SET ROLE dbo;
DROP SCHEMA IF EXISTS vmreports CASCADE;
CREATE SCHEMA IF NOT EXISTS vmreports AUTHORIZATION dbo;

GRANT USAGE ON SCHEMA vmreports TO appserver;
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO appserver;
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO appserver;

GRANT USAGE ON SCHEMA vmreports TO nifi,analytics,analyst;
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO nifi,analytics,analyst;
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO nifi,analytics,analyst;

/*
конструкция осложняется тем, что
нужен один пользователь-владелец и второй читатель
Это вызывает множество телодвижений при создании.
Необходимость указывать пароль при локальном коннекте не очень радует 
(ведь пользователь локальный, прописан на этом же сервере)
*/

--DROP FOREIGN TABLE IF EXISTS host;
--CREATE FOREIGN TABLE vmreports.host () SERVER billing OPTIONS (schema_name 'vmreports', table_name 'host'); -- вместо этого лучше импортировать схему
DROP SERVER IF EXISTS billing CASCADE;
CREATE SERVER billing
    FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host 'localhost', port '5432', dbname 'billing', updatable 'false');
-- для импорта схемы мы создаем маппинг владельцу 
DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER billing;
CREATE USER MAPPING FOR PUBLIC SERVER billing OPTIONS (user 'appserver', password '***');

IMPORT FOREIGN SCHEMA vmreports FROM SERVER billing INTO vmreports;
--GRANT SELECT ON vmreports.host to appserver;
--DROP USER MAPPING IF EXISTS FOR dbo SERVER billing; -- мы импортировали схему, маппинг больше не нужен. 
-- Но нам все равно пришлось указать пароль дважды


--DROP USER MAPPING IF EXISTS FOR appserver SERVER billing;
--CREATE USER MAPPING FOR appserver SERVER billing OPTIONS (user 'nifi', password '***');
--проверка
--set role appserver; select  * from vmreports.host;

-- это если интересно, не разрешен ли локальный коннект
--SELECT * FROM pg_hba_file_rules;

/*
Довольно тонкий нюанс, легко ускользающий
ALTER DEFAULT PRIVILEGES FOR ROLE target_creator_role 
IN SCHEMA schema_name 
GRANT privilege_type ON TABLES TO recipient_role;
Recommended Strategy for "Any User"Because there is no "FOR ALL ROLES" option, the best practice is to have all users create objects as a shared group role.Create a group role (e.g., schema_owner_role).Grant that role to all relevant users.Instruct users to run SET ROLE schema_owner_role; before creating objects.Run ALTER DEFAULT PRIVILEGES FOR ROLE schema_owner_role ... once to cover all objects created under that role.
*/
/*
Best Practices for Role Owners:Dedicated Schema Owner: Create a dedicated, non-login role for managing database schema objects (DDL) and make it the owner of the database/schemas.Separation of Duties: Separate the application user (DML - SELECT, INSERT, UPDATE) from the owner role (DDL - CREATE, ALTER, DROP).Use ALTER DEFAULT PRIVILEGES: Set up default privileges for new objects to ensure that user roles automatically gain access to new tables or functions created by the owner role.Leverage Role Hierarchy: Create group roles (e.g., app_reader, app_writer) and grant these to individual user roles for easier permission management.Avoid Public Schema: Create specific schemas and revoke CREATE privileges on the public schema to prevent accidental object creation.Secure SUPERUSER Usage: Only use the default postgres superuser role for initial setup and critical administrative tasks. Never use it for applications.Example Implementation:sql-- Create a schema owner
CREATE ROLE ddl_user NOLOGIN;
-- Create an app user
CREATE ROLE dml_user LOGIN PASSWORD 'secure_password';

-- Assign ownership
ALTER DATABASE mydb OWNER TO ddl_user;
ALTER SCHEMA public OWNER TO ddl_user;

-- Grant future access
ALTER DEFAULT PRIVILEGES FOR ROLE ddl_user IN SCHEMA public 
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO dml_user;
*/