-- Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this
-- software and associated documentation files (the "Software"), to deal in the Software
-- without restriction, including without limitation the rights to use, copy, modify,
-- merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
-- permit persons to whom the Software is furnished to do so.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

-- Load up the UUID data type
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Create a login role for the application to connect as so it is not connecting
-- as the master user and so that it is not the owner of the tables
DO $$
BEGIN
    IF NOT EXISTS(SELECT * FROM pg_roles WHERE rolname = '{{DB_APP_USER}}') THEN
        CREATE USER {{DB_APP_USER}} WITH LOGIN PASSWORD '{{DB_APP_PASS}}';
        GRANT USAGE ON SCHEMA public TO {{DB_APP_USER}};
        GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO {{DB_APP_USER}};
        ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO {{DB_APP_USER}};
        GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO {{DB_APP_USER}};
        ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE ON SEQUENCES TO {{DB_APP_USER}};
    END IF;
END
$$

-- Create a table for our tenants with indexes on the primary key and the tenant’s name
CREATE TABLE IF NOT EXISTS tenant (
    tenant_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    name VARCHAR(255) UNIQUE,
    status VARCHAR(64) CHECK (status IN ('Active', 'Suspended')),
    tier VARCHAR(64) CHECK (tier IN ('Gold', 'Silver', 'Bronze'))
);

-- Turn on RLS
ALTER TABLE tenant ENABLE ROW LEVEL SECURITY;

-- Restrict read and write actions so tenants can only see their rows
-- cast the UUID value in tenant_id to match the type current_user returns
DO $$
BEGIN
    IF NOT EXISTS (SELECT * FROM pg_policies WHERE tablename = 'tenant' AND policyname = 'tenant_isolation_policy') THEN
        CREATE POLICY tenant_isolation_policy ON tenant
        USING (tenant_id = current_setting('app.current_tenant')::UUID);
    END IF;
END
$$

-- Create a table for users of a tenant
CREATE TABLE IF NOT EXISTS tenant_user (
    user_id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    tenant_id UUID NOT NULL REFERENCES tenant (tenant_id) ON DELETE RESTRICT,
    email VARCHAR(255) NOT NULL UNIQUE,
    given_name VARCHAR(255) NOT NULL CHECK (given_name <> ''),
    family_name VARCHAR(255) NOT NULL CHECK (family_name <> '')
);

-- And apply RLS for the tenant users as we did for tenants
ALTER TABLE tenant_user ENABLE ROW LEVEL SECURITY;

DO $$
BEGIN
    IF NOT EXISTS(SELECT * FROM pg_policies WHERE tablename = 'tenant_user' AND policyname = 'tenant_user_isolation_policy') THEN
        CREATE POLICY tenant_user_isolation_policy ON tenant_user
        USING (tenant_id = current_setting('app.current_tenant')::UUID);
    END IF;
END
$$
