|
|
|
-- v0 2020.05.07 AF
|
|
-- v1 2020.05.15 LL
|
|
-- v2 2020.05.19 LL
|
|
-- v3 2020.05.25 LL
|
|
-- v4 2020.05.27 LL
|
|
-- v5 2020.05.28 LL
|
|
-- v6 2020.05.30 LL
|
|
-- v7 2020.06.05/19 LL (asgard 0.7.0)
|
|
-- v8 2020.06.26/29 LL (asgard 0.7.1)
|
|
-- v9 2020.08.11 LL (asgard 1.0.0)
|
|
-- v10 2020.08.30 LL (asgard 1.0.0)
|
|
/*
|
|
- fonction d'import de la nomenclature : nomenclature
|
|
explicite, import pour les schémas existants dans la base,
|
|
fonctionnalité de mise à jour.
|
|
- simplification de la structuration des remontées d'erreurs pour
|
|
asgard_initialisation_gestion_schema, asgard_sortie_gestion_schema,
|
|
asgard_nettoyage_roles, asgard_import_nomenclature et
|
|
asgard_initialise_schema (ajout d'un contrôle d'erreurs).
|
|
- ajout d'un contrôle des privilèges sur l'objet dans
|
|
asgard_admin_proprietaire.
|
|
- ajout d'une fonction de réinitialisation des droits
|
|
sur l'ensemble des schémas référencés ;
|
|
- sécurisation de la fonction asgard_initialise_schema, qui,
|
|
lorsqu'elle est appliquées aux schémas d'ASGARD, n'efface
|
|
plus les privilèges essentiels au fonctionnement d'ASGARD.
|
|
*/
|
|
|
|
|
|
-- MOT DE PASSE DE CONTRÔLE : 'x7-A;#rzo'
|
|
-- peut être modifié sans risque par rechercher/remplacer
|
|
|
|
---------------------------------------
|
|
------ 4 - FONCTIONS UTILITAIRES ------
|
|
---------------------------------------
|
|
/* 4.1 - LISTES DES DROITS SUR LES OBJETS D'UN SCHEMA
|
|
4.2 - LISTE DES DROITS SUR UN OBJET
|
|
4.3 - MODIFICATION DU PROPRIETAIRE D'UN SCHEMA ET SON CONTENU
|
|
4.4 - TRANSFORMATION GRANT EN REVOKE
|
|
4.5 - INITIALISATION DE GESTION_SCHEMA
|
|
4.6 - DEREFERENCEMENT D'UN SCHEMA
|
|
4.7 - NETTOYAGE DES RÔLES
|
|
4.8 - REINITIALISATION DES PRIVILEGES SUR UN SCHEMA
|
|
4.9 - REINITIALISATION DES PRIVILEGES SUR UN OBJET
|
|
4.10 - DEPLACEMENT D'OBJET
|
|
4.11 - OCTROI D'UN RÔLE À TOUS LES RÔLES DE CONNEXION
|
|
4.12 - IMPORT DE LA NOMENCLATURE DANS GESTION_SCHEMA
|
|
4.13 - REAFFECTATION DES PRIVILEGES D'UN RÔLE
|
|
4.14 - REINITIALISATION DES PRIVILEGES SUR TOUS LES SCHEMAS */
|
|
|
|
|
|
------ 4.1 - LISTES DES DROITS SUR LES OBJETS D'UN SCHEMA ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_synthese_role(regnamespace, regrole)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_role(n_schema regnamespace, n_role regrole)
|
|
RETURNS TABLE(commande text)
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction renvoie une table contenant une
|
|
liste de commandes GRANT et REVOKE permettant de
|
|
recréer les droits de "role_1" sur les objets du
|
|
schéma "schema" (et le schéma lui-même).
|
|
ARGUMENTS :
|
|
- "schema" est un nom de schéma valide, casté en regnamespace ;
|
|
- "role_1" est un nom de rôle valide, casté en regrole.
|
|
SORTIE : Une table avec un unique champ nommé "commande". */
|
|
DECLARE
|
|
n_role_trans text := n_role::text ;
|
|
BEGIN
|
|
------ SCHEMAS ------
|
|
-- privilèges attribués (hors propriétaire) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT unnest(nspacl)::text AS acl
|
|
FROM pg_catalog.pg_namespace
|
|
WHERE oid = n_schema::oid
|
|
AND nspacl IS NOT NULL
|
|
AND NOT n_role::oid = nspowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON SCHEMA ' || n_schema::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['USAGE', 'CREATE'], ARRAY['U', 'C']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN nspacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(nspacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(nspacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE nspacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_namespace
|
|
WHERE oid = n_schema::oid
|
|
AND n_role::oid = nspowner
|
|
AND nspacl IS NOT NULL
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON SCHEMA ' || n_schema::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['USAGE', 'CREATE'], ARRAY['U', 'C']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
------ TABLES ------
|
|
-- inclut les vues, vues matérialisées, tables étrangères et partitions
|
|
-- privilèges attribués (hors propriétaire) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE relnamespace = n_schema
|
|
AND relkind IN ('r', 'v', 'm', 'f', 'p')
|
|
AND relacl IS NOT NULL
|
|
AND NOT n_role::oid = relowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
|
|
'TRUNCATE', 'REFERENCES', 'TRIGGER'],
|
|
ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE relacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE relnamespace = n_schema
|
|
AND relacl IS NOT NULL
|
|
AND relkind IN ('r', 'v', 'm', 'f', 'p')
|
|
AND n_role::oid = relowner
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON TABLE ' || oid::regclass::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
|
|
'TRUNCATE', 'REFERENCES', 'TRIGGER'],
|
|
ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
------ SEQUENCES ------
|
|
-- privilèges attribués (hors propriétaire) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE relnamespace = n_schema
|
|
AND relkind = 'S'
|
|
AND relacl IS NOT NULL
|
|
AND NOT n_role::oid = relowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
|
|
ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE relacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE relnamespace = n_schema
|
|
AND relacl IS NOT NULL
|
|
AND relkind = 'S'
|
|
AND n_role::oid = relowner
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
|
|
ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
------ COLONNES ------
|
|
-- privilèges attribués :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT attname, attrelid, unnest(attacl)::text AS acl
|
|
FROM pg_catalog.pg_class JOIN pg_catalog.pg_attribute
|
|
ON pg_class.oid = pg_attribute.attrelid
|
|
WHERE relnamespace = n_schema
|
|
AND attacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
|
|
|| attrelid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
|
|
ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
------ FONCTIONS ------
|
|
-- inclut les fonctions d'agrégation
|
|
-- privilèges attribués (hors propriétaire) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(proacl)::text AS acl
|
|
FROM pg_catalog.pg_proc
|
|
WHERE pronamespace = n_schema
|
|
AND proacl IS NOT NULL
|
|
AND NOT n_role::oid = proowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN proacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(proacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(proacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE proacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_proc
|
|
WHERE pronamespace = n_schema
|
|
AND n_role::oid = proowner
|
|
AND proacl IS NOT NULL
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
------ TYPES ------
|
|
-- inclut les domaines
|
|
-- privilèges attribués (hors propriétaire) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(typacl)::text AS acl
|
|
FROM pg_catalog.pg_type
|
|
WHERE typnamespace = n_schema
|
|
AND typacl IS NOT NULL
|
|
AND NOT n_role::oid = typowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON TYPE ' || oid::regtype::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN typacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(typacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(typacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE typacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_type
|
|
WHERE typnamespace = n_schema
|
|
AND n_role::oid = typowner
|
|
AND typacl IS NOT NULL
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON TYPE ' || oid::regtype::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_synthese_role(regnamespace, regrole)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_synthese_role(regnamespace, regrole) IS 'ASGARD. Fonction qui liste les commandes permettant de reproduire les droits d''un rôle sur les objets d''un schéma.' ;
|
|
|
|
|
|
-- FUNCTION: z_asgard.asgard_synthese_public(regnamespace)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_public(n_schema regnamespace)
|
|
RETURNS TABLE(commande text)
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction renvoie une table contenant une
|
|
liste de commandes GRANT et REVOKE permettant de
|
|
recréer les droits de public sur les objets du
|
|
schéma "schema" (et le schéma lui-même).
|
|
REMARQUE : La fonction ne s'intéresse pas aux objets de type
|
|
fonction (dont agrégats) et type (dont domaines), sur lesquels
|
|
public reçoit des droits par défaut qu'il n'est pas judicieux
|
|
de reproduire sur un autre rôle, ni de révoquer lors d'un
|
|
changement de lecteur/éditeur. Si des privilèges par défaut ont
|
|
été révoqués pour public, la révocation restera valable pour les
|
|
futurs lecteur/éditeurs puisqu'il n'y a pas d'attribution
|
|
de privilèges supplémentaires pour les lecteurs/éditeurs sur
|
|
ces objets.
|
|
ARGUMENT : "schema" est un nom de schéma valide, casté en
|
|
regnamespace.
|
|
SORTIE : Une table avec un unique champ nommé "commande". */
|
|
BEGIN
|
|
------ SCHEMAS ------
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT unnest(nspacl)::text AS acl
|
|
FROM pg_catalog.pg_namespace
|
|
WHERE oid = n_schema::oid
|
|
AND nspacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON SCHEMA ' || n_schema::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['USAGE', 'CREATE'], ARRAY['U', 'C']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
|
|
------ TABLES ------
|
|
-- inclut les vues, vues matérialisées, tables étrangères et partitions
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE relnamespace = n_schema
|
|
AND relkind IN ('r', 'v', 'm', 'f', 'p')
|
|
AND relacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
|
|
'TRUNCATE', 'REFERENCES', 'TRIGGER'],
|
|
ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
|
|
------ SEQUENCES ------
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE relnamespace = n_schema
|
|
AND relkind = 'S'
|
|
AND relacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
|
|
ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
|
|
------ COLONNES ------
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT attname, attrelid, unnest(attacl)::text AS acl
|
|
FROM pg_catalog.pg_class JOIN pg_catalog.pg_attribute
|
|
ON pg_class.oid = pg_attribute.attrelid
|
|
WHERE relnamespace = n_schema
|
|
AND attacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
|
|
|| attrelid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
|
|
ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_synthese_public(regnamespace)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_synthese_public(regnamespace) IS 'ASGARD. Fonction qui liste les commandes permettant de reproduire les droits de public sur les objets d''un schéma.' ;
|
|
|
|
|
|
|
|
|
|
------ 4.2 - LISTE DES DROITS SUR UN OBJET ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_synthese_role_obj(oid, text, regrole)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_role_obj(obj_oid oid, obj_type text, n_role regrole)
|
|
RETURNS TABLE(commande text)
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction renvoie une table contenant une
|
|
liste de commandes GRANT et REVOKE permettant de
|
|
recréer les droits de "role_1" sur un objet de type
|
|
table, table étrangère, partition de table, vue,
|
|
vue matérialisée, séquence, fonction (dont fonctions
|
|
d'agrégations), type (dont domaines).
|
|
ARGUMENTS :
|
|
- "obj_oid" est l'identifiant interne de l'objet ;
|
|
- "obj_type" est le type de l'objet au format text ('table',
|
|
'view', 'materialized view', 'sequence', 'function', 'type',
|
|
'domain', 'foreign table', 'partitioned table', 'aggregate') ;
|
|
- "role_1" est un nom de rôle valide, casté en regrole.
|
|
SORTIE : Une table avec un unique champ nommé "commande". */
|
|
DECLARE
|
|
n_role_trans text := n_role::text ;
|
|
BEGIN
|
|
------ TABLE, VUE, VUE MATERIALISEE ------
|
|
IF obj_type IN ('table', 'view', 'materialized view', 'foreign table', 'partitioned table')
|
|
THEN
|
|
-- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE oid = obj_oid
|
|
AND relacl IS NOT NULL
|
|
AND NOT n_role::oid = relowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
|
|
'TRUNCATE', 'REFERENCES', 'TRIGGER'],
|
|
ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE relacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE oid = obj_oid
|
|
AND relacl IS NOT NULL
|
|
AND n_role::oid = relowner
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON TABLE ' || oid::regclass::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
|
|
'TRUNCATE', 'REFERENCES', 'TRIGGER'],
|
|
ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
------ COLONNES ------
|
|
-- privilèges attribués :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT attname, attrelid, unnest(attacl)::text AS acl
|
|
FROM pg_catalog.pg_attribute
|
|
WHERE pg_attribute.attrelid = obj_oid
|
|
AND attacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
|
|
|| attrelid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
|
|
ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
------ SEQUENCES ------
|
|
ELSIF obj_type = 'sequence'
|
|
THEN
|
|
-- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE oid = obj_oid
|
|
AND relacl IS NOT NULL
|
|
AND NOT n_role::oid = relowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
|
|
ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE relacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE oid = obj_oid
|
|
AND relacl IS NOT NULL
|
|
AND n_role::oid = relowner
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
|
|
ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
------ FONCTIONS ------
|
|
-- inclut les fonctions d'agrégation
|
|
ELSIF obj_type IN ('function', 'aggregate')
|
|
THEN
|
|
-- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(proacl)::text AS acl
|
|
FROM pg_catalog.pg_proc
|
|
WHERE oid = obj_oid
|
|
AND proacl IS NOT NULL
|
|
AND NOT n_role::oid = proowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN proacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(proacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(proacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE proacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_proc
|
|
WHERE oid = obj_oid
|
|
AND n_role::oid = proowner
|
|
AND proacl IS NOT NULL
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
------ TYPES ------
|
|
-- inclut les domaines
|
|
ELSIF obj_type IN ('type', 'domain')
|
|
THEN
|
|
-- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(typacl)::text AS acl
|
|
FROM pg_catalog.pg_type
|
|
WHERE oid = obj_oid
|
|
AND typacl IS NOT NULL
|
|
AND NOT n_role::oid = typowner
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON TYPE ' || oid::regtype::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
|
|
-- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(CASE WHEN typacl::text[] = ARRAY[]::text[]
|
|
OR NOT array_to_string(typacl, ',') ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT array_to_string(typacl, ',') ~ ('[,]' || n_role_trans || '[=]')
|
|
THEN ARRAY[NULL]::text[]
|
|
ELSE typacl::text[] END) AS acl
|
|
FROM pg_catalog.pg_type
|
|
WHERE oid = obj_oid
|
|
AND n_role::oid = typowner
|
|
AND typacl IS NOT NULL
|
|
)
|
|
SELECT 'REVOKE ' || privilege || ' ON TYPE ' || oid::regtype::text || ' FROM %I'
|
|
FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
|
|
WHERE (acl ~ ('^' || n_role_trans || '[=]')
|
|
AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
|
|
ELSE
|
|
RAISE EXCEPTION 'FSS0. Le type d''objet % n''est pas pris en charge', obj_type ;
|
|
END IF ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_synthese_role_obj(oid, text, regrole)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_synthese_role_obj(oid, text, regrole) IS 'ASGARD. Fonction qui liste les commandes permettant de reproduire les droits d''un rôle sur un objet.' ;
|
|
|
|
|
|
|
|
-- FUNCTION: z_asgard.asgard_synthese_public_obj(oid, text)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_public_obj(obj_oid oid, obj_type text)
|
|
RETURNS TABLE(commande text)
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction renvoie une table contenant une
|
|
liste de commandes GRANT et REVOKE permettant de
|
|
recréer les droits de public sur un objet de type
|
|
table, table étrangère, partition de table, vue,
|
|
vue matérialisée ou séquence.
|
|
REMARQUE : La fonction ne s'intéresse pas aux objets de type
|
|
fonction (dont agrégats) et type (dont domaines), sur lesquels
|
|
public reçoit des droits par défaut qu'il n'est pas judicieux
|
|
de reproduire sur un autre rôle, ni de révoquer lors d'un
|
|
changement de lecteur/éditeur. Si des privilèges par défaut ont
|
|
été révoqués pour public, la révocation restera valable pour les
|
|
futurs lecteur/éditeurs puisqu'il n'y a pas d'attribution
|
|
de privilèges supplémentaires pour les lecteurs/éditeurs sur
|
|
ces objets.
|
|
ARGUMENTS :
|
|
- "obj_oid" est l'identifiant interne de l'objet ;
|
|
- "obj_type" est le type de l'objet au format text ('table',
|
|
'view', 'materialized view', 'sequence', 'foreign table',
|
|
'partitioned table').
|
|
SORTIE : Une table avec un unique champ nommé "commande". */
|
|
BEGIN
|
|
------ TABLE, VUE, VUE MATERIALISEE ------
|
|
IF obj_type IN ('table', 'view', 'materialized view', 'foreign table', 'partitioned table')
|
|
THEN
|
|
-- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE oid = obj_oid
|
|
AND relacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
|
|
'TRUNCATE', 'REFERENCES', 'TRIGGER'],
|
|
ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
|
|
------ COLONNES ------
|
|
-- privilèges attribués :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT attname, attrelid, unnest(attacl)::text AS acl
|
|
FROM pg_catalog.pg_attribute
|
|
WHERE pg_attribute.attrelid = obj_oid
|
|
AND attacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
|
|
|| attrelid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
|
|
ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
|
|
------ SEQUENCES ------
|
|
ELSIF obj_type = 'sequence'
|
|
THEN
|
|
-- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
|
|
RETURN QUERY
|
|
WITH t_acl AS (
|
|
SELECT oid, unnest(relacl)::text AS acl
|
|
FROM pg_catalog.pg_class
|
|
WHERE oid = obj_oid
|
|
AND relacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
|
|
FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
|
|
ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
|
|
ELSE
|
|
RAISE EXCEPTION 'FSS0. Le type d''objet % n''est pas pris en charge', obj_type ;
|
|
END IF ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_synthese_public_obj(oid, text)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_synthese_public_obj(oid, text) IS 'ASGARD. Fonction qui liste les commandes permettant de reproduire les droits de public sur un objet.' ;
|
|
|
|
|
|
|
|
|
|
|
|
------ 4.3 - MODIFICATION DU PROPRIETAIRE D'UN SCHEMA ET SON CONTENU ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_admin_proprietaire(text, text, boolean)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_admin_proprietaire(
|
|
n_schema text, n_owner text, b_setschema boolean DEFAULT True
|
|
)
|
|
RETURNS int
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Gestion des droits. Cette fonction permet d''attribuer
|
|
un schéma et tous les objets qu'il contient à un [nouveau]
|
|
propriétaire.
|
|
AVERTISSEMENT : Les objets de type operator class, operator family
|
|
et extended planner statistic ne sont pas pris en charge pour l'heure.
|
|
ARGUMENTS :
|
|
- "n_schema" est une chaîne de caractères correspondant au nom du
|
|
schéma à considérer ;
|
|
- "n_owner" est une chaîne de caractères correspondant au nom du
|
|
rôle (rôle de groupe ou rôle de connexion) qui doit être
|
|
propriétaire des objets ;
|
|
- "b_setschema" est un paramètre booléen optionnel (vrai par défaut)
|
|
qui indique si la fonction doit changer le propriétaire du schéma
|
|
ou seulement des objets qu'il contient.
|
|
RESULTAT : la fonction renvoie un entier correspondant au nombre
|
|
d''objets effectivement traités. Les commandes lancées sont notifiées
|
|
au fur et à mesure. */
|
|
DECLARE
|
|
item record ;
|
|
k int := 0 ;
|
|
o_owner oid ;
|
|
s_owner text ;
|
|
BEGIN
|
|
------ TESTS PREALABLES ------
|
|
SELECT nspowner::regrole::text
|
|
INTO s_owner
|
|
FROM pg_catalog.pg_namespace
|
|
WHERE nspname = n_schema ;
|
|
|
|
-- non existance du schémas
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE EXCEPTION 'FAP1. Le schéma % n''existe pas.', n_schema ;
|
|
END IF ;
|
|
|
|
-- absence de permission sur le propriétaire courant du schéma
|
|
IF NOT pg_has_role(s_owner::regrole::oid, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FAP5. Vous n''êtes pas habilité à modifier le propriétaire du schéma %.', n_schema
|
|
USING DETAIL = 'Propriétaire courant : ' || s_owner || '.' ;
|
|
END IF ;
|
|
|
|
-- le propriétaire désigné n'existe pas
|
|
IF NOT n_owner IN (SELECT rolname::text FROM pg_catalog.pg_roles)
|
|
THEN
|
|
RAISE EXCEPTION 'FAP2. Le rôle % n''existe pas.', n_owner ;
|
|
-- absence de permission sur le propriétaire désigné
|
|
ELSIF NOT pg_has_role(n_owner, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FAP6. Vous n''avez pas la permission d''utiliser le rôle %.', n_owner ;
|
|
ELSE
|
|
o_owner := quote_ident(n_owner)::regrole::oid ;
|
|
END IF ;
|
|
|
|
-- le propriétaire désigné n'est pas le propriétaire courant et la fonction
|
|
-- a été lancée avec la variante qui ne traite pas le schéma
|
|
IF NOT b_setschema
|
|
AND NOT quote_ident(n_owner) = s_owner
|
|
THEN
|
|
RAISE EXCEPTION 'FAP3. Le rôle % n''est pas propriétaire du schéma.', n_owner
|
|
USING HINT = 'Lancez asgard_admin_proprietaire(' || quote_literal(n_schema)
|
|
|| ', ' || quote_literal(n_owner) || ') pour changer également le propriétaire du schéma.' ;
|
|
END IF ;
|
|
|
|
------ PROPRIÉTAIRE DU SCHEMA ------
|
|
IF b_setschema
|
|
THEN
|
|
EXECUTE 'ALTER SCHEMA ' || quote_ident(n_schema) || ' OWNER TO ' || quote_ident(n_owner) ;
|
|
RAISE NOTICE '> %', 'ALTER SCHEMA ' || quote_ident(n_schema) || ' OWNER TO ' || quote_ident(n_owner) ;
|
|
k := k + 1 ;
|
|
END IF ;
|
|
|
|
------ PROPRIETAIRES DES OBJETS ------
|
|
-- uniquement ceux qui n'appartiennent pas déjà
|
|
-- au rôle identifié
|
|
FOR item IN
|
|
-- tables, tables étrangères, vues, vues matérialisées,
|
|
-- partitions, séquences :
|
|
SELECT
|
|
relname::text AS n_objet,
|
|
relowner AS obj_owner,
|
|
relkind IN ('r', 'f', 'p', 'm') AS b, -- servira à assurer que les tables
|
|
-- soient listées avant les objets qui
|
|
-- en dépendent
|
|
'ALTER ' || kind_lg || ' ' || pg_class.oid::regclass || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM pg_catalog.pg_class,
|
|
unnest(ARRAY['r', 'p', 'v', 'm', 'f', 'S'],
|
|
ARRAY['TABLE', 'TABLE', 'VIEW', 'MATERIALIZED VIEW', 'FOREIGN TABLE', 'SEQUENCE']) AS l (kind_crt, kind_lg)
|
|
WHERE relnamespace = quote_ident(n_schema)::regnamespace
|
|
AND relkind IN ('S', 'r', 'p', 'v', 'm', 'f')
|
|
AND kind_crt = relkind
|
|
AND NOT relowner = o_owner
|
|
UNION
|
|
-- fonctions et agrégats :
|
|
SELECT
|
|
proname::text AS n_objet,
|
|
proowner AS obj_owner,
|
|
False AS b,
|
|
'ALTER FUNCTION ' || pg_proc.oid::regprocedure || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM pg_catalog.pg_proc
|
|
WHERE pronamespace = quote_ident(n_schema)::regnamespace
|
|
AND NOT proowner = o_owner
|
|
-- à noter que les agrégats (proisagg vaut True) ont
|
|
-- leur propre commande ALTER AGGREGATE OWNER TO, mais
|
|
-- ALTER FUNCTION OWNER TO fonctionne également, on ne
|
|
-- fait donc pas de distinction pour l'heure
|
|
UNION
|
|
-- types et domaines :
|
|
SELECT
|
|
typname::text AS n_objet,
|
|
typowner AS obj_owner,
|
|
False AS b,
|
|
'ALTER ' || kind_lg || ' ' || typnamespace::regnamespace::text || '.'
|
|
|| quote_ident(typname) || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM unnest(ARRAY['true', 'false'],
|
|
ARRAY['DOMAIN', 'TYPE']) AS l (kind_crt, kind_lg),
|
|
pg_catalog.pg_type LEFT JOIN pg_catalog.pg_class ON typrelid = pg_class.oid
|
|
WHERE typnamespace = quote_ident(n_schema)::regnamespace
|
|
AND kind_crt::boolean = (typtype = 'd')
|
|
AND NOT (typelem > 0 AND typname ~ '^_')
|
|
-- exclusion des types array générés automatiquement
|
|
-- leur propriétaire est lié à celui du type source
|
|
-- et ne peut être modifié directement
|
|
AND (NOT typtype = 'c' OR relkind = 'c')
|
|
-- idem pour les types "ligne de table", dont
|
|
-- le propriétaire est lié à celui de la table
|
|
AND NOT typowner = o_owner
|
|
UNION
|
|
-- conversions :
|
|
SELECT
|
|
conname::text AS n_objet,
|
|
conowner AS obj_owner,
|
|
False AS b,
|
|
'ALTER CONVERSION ' || connamespace::regnamespace::text || '.'
|
|
|| quote_ident(conname) || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM pg_catalog.pg_conversion
|
|
WHERE connamespace = quote_ident(n_schema)::regnamespace
|
|
AND NOT conowner = o_owner
|
|
UNION
|
|
-- opérateurs :
|
|
SELECT
|
|
oprname::text AS n_objet,
|
|
oprowner AS obj_owner,
|
|
False AS b,
|
|
'ALTER OPERATOR ' || pg_operator.oid::regoperator || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM pg_catalog.pg_operator
|
|
WHERE oprnamespace = quote_ident(n_schema)::regnamespace
|
|
AND NOT oprowner = o_owner
|
|
UNION
|
|
-- collations :
|
|
SELECT
|
|
collname::text AS n_objet,
|
|
collowner AS obj_owner,
|
|
False AS b,
|
|
'ALTER COLLATION ' || collnamespace::regnamespace::text || '.'
|
|
|| quote_ident(collname) || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM pg_catalog.pg_collation
|
|
WHERE collnamespace = quote_ident(n_schema)::regnamespace
|
|
AND NOT collowner = o_owner
|
|
UNION
|
|
-- text search dictionary :
|
|
SELECT
|
|
dictname::text AS n_objet,
|
|
dictowner AS obj_owner,
|
|
False AS b,
|
|
'ALTER TEXT SEARCH DICTIONARY ' || pg_ts_dict.oid::regdictionary || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM pg_catalog.pg_ts_dict
|
|
WHERE dictnamespace = quote_ident(n_schema)::regnamespace
|
|
AND NOT dictowner = o_owner
|
|
UNION
|
|
-- text search configuration :
|
|
SELECT
|
|
cfgname::text AS n_objet,
|
|
cfgowner AS obj_owner,
|
|
False AS b,
|
|
'ALTER TEXT SEARCH CONFIGURATION ' || pg_ts_config.oid::regconfig || ' OWNER TO '
|
|
|| quote_ident(n_owner) AS commande
|
|
FROM pg_catalog.pg_ts_config
|
|
WHERE cfgnamespace = quote_ident(n_schema)::regnamespace
|
|
AND NOT cfgowner = o_owner
|
|
ORDER BY b DESC
|
|
LOOP
|
|
IF pg_has_role(item.obj_owner, 'USAGE')
|
|
THEN
|
|
EXECUTE item.commande ;
|
|
RAISE NOTICE '> %', item.commande ;
|
|
k := k + 1 ;
|
|
ELSE
|
|
RAISE EXCEPTION 'FAP4. Vous n''êtes pas habilité à modifier le propriétaire de l''objet %.', item.n_objet
|
|
USING DETAIL = 'Propriétaire courant : ' || item.obj_owner::regrole::text || '.' ;
|
|
END IF ;
|
|
END LOOP ;
|
|
------ RESULTAT ------
|
|
RETURN k ;
|
|
END
|
|
$_$ ;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_admin_proprietaire(text, text, boolean)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_admin_proprietaire(text, text, boolean) IS 'ASGARD. Fonction qui modifie le propriétaire d''un schéma et de tous les objets qu''il contient.' ;
|
|
|
|
|
|
|
|
------ 4.4 - TRANSFORMATION GRANT EN REVOKE ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_grant_to_revoke(text)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_grant_to_revoke(c_grant text)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction transforme une commande de type GRANT en
|
|
son équivalent REVOKE, ou l'inverse.
|
|
AVERTISSEMENT : La fonction ne reconnaîtra que les mots clés écrits
|
|
en majuscules.
|
|
ARGUMENT : une commande de type GRANT/REVOKE présumée valide (chaîne de caractères).
|
|
SORTIE : une commande de type REVOKE/GRANT (chaîne de caractères). */
|
|
DECLARE
|
|
c_revoke text ;
|
|
BEGIN
|
|
IF c_grant ~ '^GRANT'
|
|
THEN
|
|
c_revoke := regexp_replace(c_grant, '^GRANT', 'REVOKE') ;
|
|
c_revoke := regexp_replace(c_revoke, '[[:space:]]TO[[:space:]]', ' FROM ') ;
|
|
ELSIF c_grant ~ '^REVOKE'
|
|
THEN
|
|
c_revoke := regexp_replace(c_grant, '^REVOKE', 'GRANT') ;
|
|
c_revoke := regexp_replace(c_revoke, '[[:space:]]FROM[[:space:]]', ' TO ') ;
|
|
ELSE
|
|
RAISE EXCEPTION 'FGR1. Commande GRANT/REVOKE invalide.' ;
|
|
END IF ;
|
|
RETURN c_revoke ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_grant_to_revoke(text)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_grant_to_revoke(text) IS 'ASGARD. Fonction qui transforme une commande GRANT en commande REVOKE.' ;
|
|
|
|
|
|
------ 4.5 - INITIALISATION DE GESTION_SCHEMA ------
|
|
|
|
-- FUNCTION: z_asgard_admin.asgard_initialisation_gestion_schema(text[], boolean)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_initialisation_gestion_schema(
|
|
exceptions text[] default NULL::text[], b_gs boolean default False
|
|
)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction intègre à la table de gestion des droits
|
|
gestion_schema l'ensemble des schémas existants, hors
|
|
schémas système et ceux qui sont (optionnellement) listés
|
|
en argument.
|
|
ARGUMENTS :
|
|
- exceptions (optionnel) : un tableau text[] contenant les noms des schémas
|
|
à omettre, le cas échéant ;
|
|
- b_gs (optionnel) : un booléen indiquant si, dans l'hypothèse où un schéma
|
|
serait déjà référencé - nécessairement comme non créé - dans la table de gestion,
|
|
c'est le propriétaire du schéma qui doit devenir le "producteur" du schéma
|
|
(False) ou le producteur pré-renseigné dans la table de gestion qui doit
|
|
devenir le propriétaire du schéma (True). False par défaut.
|
|
SORTIE : '__ FIN INTIALISATION.' si la requête s'est exécutée normalement. */
|
|
DECLARE
|
|
item record ;
|
|
e_mssg text ;
|
|
e_detl text ;
|
|
e_hint text ;
|
|
b_creation boolean ;
|
|
BEGIN
|
|
|
|
FOR item IN SELECT nspname, nspowner FROM pg_catalog.pg_namespace
|
|
WHERE NOT nspname ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
|
|
'^public$', '^information_schema$', '^topology$'])
|
|
AND (exceptions IS NULL OR NOT nspname = ANY(exceptions))
|
|
LOOP
|
|
SELECT creation INTO b_creation
|
|
FROM z_asgard.gestion_schema_usr
|
|
WHERE item.nspname::text = nom_schema ;
|
|
IF b_creation IS NULL
|
|
-- schéma non référencé dans gestion_schema
|
|
THEN
|
|
INSERT INTO z_asgard.gestion_schema_usr (nom_schema, producteur, creation)
|
|
VALUES (item.nspname::text, replace(item.nspowner::regrole::text, '"', ''), true) ;
|
|
RAISE NOTICE '... Schéma % enregistré dans la table de gestion.', item.nspname::text ;
|
|
ELSIF NOT b_creation
|
|
-- schéma pré-référencé dans gestion_schema
|
|
THEN
|
|
IF NOT b_gs
|
|
THEN
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET creation = true,
|
|
producteur = replace(item.nspowner::regrole::text, '"', '')
|
|
WHERE item.nspname::text = nom_schema ;
|
|
ELSE
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET creation = true
|
|
WHERE item.nspname::text = nom_schema ;
|
|
END IF ;
|
|
RAISE NOTICE '... Schéma % marqué comme créé dans la table de gestion.', item.nspname::text ;
|
|
END IF ;
|
|
END LOOP ;
|
|
|
|
RETURN '__ FIN INITALISATION.' ;
|
|
|
|
EXCEPTION WHEN OTHERS THEN
|
|
GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
|
|
e_hint = PG_EXCEPTION_HINT,
|
|
e_detl = PG_EXCEPTION_DETAIL ;
|
|
RAISE EXCEPTION 'FIG0 > %', e_mssg
|
|
USING DETAIL = e_detl,
|
|
HINT = e_hint ;
|
|
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard_admin.asgard_initialisation_gestion_schema(text[], boolean)
|
|
OWNER TO g_admin ;
|
|
|
|
COMMENT ON FUNCTION z_asgard_admin.asgard_initialisation_gestion_schema(text[], boolean) IS 'ASGARD. Fonction qui initialise la table de gestion à partir des schémas existants.' ;
|
|
|
|
|
|
|
|
------ 4.6 - DEREFERENCEMENT D'UN SCHEMA ------
|
|
|
|
-- FUNCTION: z_asgard_admin.asgard_sortie_gestion_schema(text)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_sortie_gestion_schema(n_schema text)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction permet de supprimer de la table de gestion un
|
|
schéma existant (qui échappera alors aux mécanismes de
|
|
gestion des droits), en outrepassant les règles qui veulent
|
|
que seules les lignes avec creation valant false puisse
|
|
être ciblées par des DELETE et que creation ne puisse être
|
|
mis à false si le schéma existe.
|
|
ARGUMENTS :
|
|
- n_schema : nom d'un schéma présumé référencé dans le champ
|
|
nom_schema de la table de gestion (sinon la fonction n'aura
|
|
pas d'effet).
|
|
SORTIE : '__ DEREFERENCEMENT REUSSI.' si la requête s'est exécutée normalement. */
|
|
DECLARE
|
|
e_mssg text ;
|
|
e_detl text ;
|
|
e_hint text ;
|
|
BEGIN
|
|
|
|
UPDATE z_asgard.gestion_schema_etr
|
|
SET ctrl = ARRAY['EXIT', 'x7-A;#rzo']
|
|
WHERE nom_schema = n_schema ;
|
|
|
|
DELETE FROM z_asgard.gestion_schema_etr
|
|
WHERE nom_schema = n_schema ;
|
|
|
|
RETURN '__ DEREFERENCEMENT REUSSI.' ;
|
|
|
|
EXCEPTION WHEN OTHERS THEN
|
|
GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
|
|
e_hint = PG_EXCEPTION_HINT,
|
|
e_detl = PG_EXCEPTION_DETAIL ;
|
|
RAISE EXCEPTION 'FSG0 > %', e_mssg
|
|
USING DETAIL = e_detl,
|
|
HINT = e_hint ;
|
|
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard_admin.asgard_sortie_gestion_schema(text)
|
|
OWNER TO g_admin ;
|
|
|
|
COMMENT ON FUNCTION z_asgard_admin.asgard_sortie_gestion_schema(text) IS 'ASGARD. Fonction qui déréférence un schéma existant de la table de gestion.' ;
|
|
|
|
|
|
|
|
------ 4.7 - NETTOYAGE DES RÔLES ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_nettoyage_roles()
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_nettoyage_roles()
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction active la mise à jour des noms des rôles
|
|
désignés dans la table de gestion comme producteur, éditeur et
|
|
lecteur, pour prendre en compte les changements de nom
|
|
ou suppression qui auraient pu avoir eu lieu.
|
|
ARGUMENTS : néant.
|
|
SORTIE : '__ NETTOYAGE REUSSI.' si la requête s'est exécutée normalement. */
|
|
DECLARE
|
|
e_mssg text ;
|
|
e_detl text ;
|
|
e_hint text ;
|
|
BEGIN
|
|
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET producteur = producteur,
|
|
editeur = editeur,
|
|
lecteur = lecteur ;
|
|
|
|
RETURN '__ NETTOYAGE REUSSI.' ;
|
|
|
|
EXCEPTION WHEN OTHERS THEN
|
|
GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
|
|
e_hint = PG_EXCEPTION_HINT,
|
|
e_detl = PG_EXCEPTION_DETAIL ;
|
|
RAISE EXCEPTION 'FNR0 > %', e_mssg
|
|
USING DETAIL = e_detl,
|
|
HINT = e_hint ;
|
|
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_nettoyage_roles()
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_nettoyage_roles() IS 'ASGARD. Fonction qui met à jour les noms des rôles référencés dans la table de gestion.' ;
|
|
|
|
|
|
|
|
------ 4.8 - REINITIALISATION DES PRIVILEGES SUR UN SCHEMA ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_initialise_schema(text, boolean, boolean)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_initialise_schema(
|
|
n_schema text,
|
|
b_preserve boolean DEFAULT False,
|
|
b_gs boolean default False
|
|
)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction permet de réinitialiser les droits
|
|
sur un schéma selon les privilèges standards associés
|
|
aux rôles désignés dans la table de gestion.
|
|
Si elle est appliquée à un schéma existant non référencé
|
|
dans la table de gestion, elle l'ajoute avec son
|
|
propriétaire courant. Elle échoue si le schéma n'existe
|
|
pas.
|
|
ARGUMENTS :
|
|
- n_schema : nom d'un schéma présumé existant ;
|
|
- b_preserve (optionnel) : un paramètre booléen. Pour un schéma encore
|
|
non référencé (ou pré-référencé comme non-créé) dans la table de gestion une valeur
|
|
True signifie que les privilèges des rôles lecteur et éditeur doivent être
|
|
ajoutés par dessus les droits actuels. Avec la valeur par défaut False,
|
|
les privilèges sont réinitialisés. Ce paramètre est ignoré pour un schéma déjà
|
|
référencé comme créé (et les privilèges sont réinitialisés) ;
|
|
- b_gs (optionnel) : un booléen indiquant si, dans l'hypothèse où un schéma
|
|
serait déjà référencé - nécessairement comme non créé - dans la table de gestion,
|
|
c'est le propriétaire du schéma qui doit devenir le "producteur" (False) ou le
|
|
producteur de la table de gestion qui doit devenir le propriétaire
|
|
du schéma (True). False par défaut. Ce paramètre est ignoré pour un schéma déjà
|
|
créé.
|
|
SORTIE : '__ REINITIALISATION REUSSIE.' (ou '__INITIALISATION REUSSIE.' pour
|
|
un schéma non référencé comme créé avec b_preserve = True) si la requête
|
|
s'est exécutée normalement. */
|
|
DECLARE
|
|
roles record ;
|
|
r record ;
|
|
c record ;
|
|
n_owner text ;
|
|
k int := 0 ;
|
|
n int ;
|
|
e_mssg text ;
|
|
e_detl text ;
|
|
e_hint text ;
|
|
BEGIN
|
|
------ TESTS PREALABLES ------
|
|
-- schéma système
|
|
IF n_schema ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
|
|
'^public$', '^information_schema$', '^topology$'])
|
|
THEN
|
|
RAISE EXCEPTION 'FIS1. Opération interdite. Le schéma % est un schéma système.', n_schema ;
|
|
END IF ;
|
|
|
|
-- existence du schéma
|
|
SELECT replace(nspowner::regrole::text, '"', '') INTO n_owner
|
|
FROM pg_catalog.pg_namespace
|
|
WHERE n_schema = nspname::text ;
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE EXCEPTION 'FIS2. Echec. Le schéma % n''existe pas.', n_schema ;
|
|
END IF ;
|
|
|
|
-- permission sur le propriétaire
|
|
IF NOT pg_has_role(n_owner, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FIS3. Echec. Vous ne disposez pas des permissions nécessaires sur le schéma % pour réaliser cette opération.', n_schema
|
|
USING HINT = 'Il vous faut être membre du rôle propriétaire ' || n_owner || '.' ;
|
|
END IF ;
|
|
|
|
------ RECUPERATION DES ROLES ------
|
|
SELECT
|
|
r1.rolname AS producteur,
|
|
CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
|
|
CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
|
|
creation INTO roles
|
|
FROM z_asgard.gestion_schema_etr
|
|
LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
|
|
LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
|
|
LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
|
|
WHERE nom_schema = n_schema ;
|
|
|
|
------ SCHEMA NON REFERENCE ------
|
|
-- ajouté à gestion_schema
|
|
-- le reste est pris en charge par le trigger
|
|
-- on_modify_gestion_schema_after
|
|
IF NOT FOUND
|
|
THEN
|
|
INSERT INTO z_asgard.gestion_schema_usr (nom_schema, producteur, creation)
|
|
VALUES (n_schema, n_owner, true) ;
|
|
RAISE NOTICE '... Le schéma % a été enregistré dans la table de gestion.', n_schema ;
|
|
|
|
IF b_preserve
|
|
THEN
|
|
RETURN '__ INITIALISATION REUSSIE.' ;
|
|
END IF ;
|
|
|
|
------- SCHEMA PRE-REFERENCE ------
|
|
-- présent dans gestion_schema avec creation valant
|
|
-- False.
|
|
ELSIF NOT roles.creation
|
|
THEN
|
|
IF NOT b_gs
|
|
THEN
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET creation = true,
|
|
producteur = n_owner
|
|
WHERE n_schema = nom_schema ;
|
|
ELSE
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET creation = true
|
|
WHERE n_schema = nom_schema ;
|
|
END IF ;
|
|
RAISE NOTICE '... Le schéma % a été marqué comme créé dans la table de gestion.', item.nspname::text ;
|
|
|
|
IF b_preserve
|
|
THEN
|
|
RETURN '__ INITIALISATION REUSSIE.' ;
|
|
END IF ;
|
|
|
|
------ REMISE A PLAT DES PROPRIETAIRES ------
|
|
-- uniquement pour les schémas qui étaient déjà
|
|
-- référencés dans gestion_schema (pour les autres, pris en charge
|
|
-- par le trigger on_modify_gestion_schema_after)
|
|
|
|
-- schéma dont le propriétaire ne serait pas le producteur
|
|
ELSIF NOT roles.producteur = n_owner
|
|
THEN
|
|
-- permission sur le producteur
|
|
IF NOT pg_has_role(roles.producteur, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FIS4. Echec. Vous ne disposez pas des permissions nécessaires sur le schéma % pour réaliser cette opération.', n_schema
|
|
USING HINT = 'Il vous faut être membre du rôle producteur ' || roles.producteur || '.' ;
|
|
END IF ;
|
|
-- propriétaire du schéma + contenu
|
|
RAISE NOTICE '(ré)attribution de la propriété du schéma et des objets au rôle producteur du schéma :' ;
|
|
PERFORM z_asgard.asgard_admin_proprietaire(n_schema, roles.producteur) ;
|
|
|
|
-- schema dont le propriétaire est le producteur
|
|
ELSE
|
|
-- reprise uniquement des propriétaires du contenu
|
|
RAISE NOTICE '(ré)attribution de la propriété des objets au rôle producteur du schéma :' ;
|
|
SELECT z_asgard.asgard_admin_proprietaire(n_schema, roles.producteur, False) INTO n ;
|
|
IF n = 0
|
|
THEN
|
|
RAISE NOTICE '> néant' ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
------ DESTRUCTION DES PRIVILEGES ACTUELS ------
|
|
-- hors privilèges par défaut (définis par ALTER DEFAULT PRIVILEGE)
|
|
-- et hors révocations des privilèges par défaut de public sur
|
|
-- les types et les fonctions
|
|
-- pour le propriétaire, ces commandes ont pour effet
|
|
-- de remettre les privilèges par défaut supprimés
|
|
|
|
-- public
|
|
RAISE NOTICE 'remise à zéro des privilèges manuels du pseudo-rôle public :' ;
|
|
FOR c IN (SELECT * FROM z_asgard.asgard_synthese_public(
|
|
quote_ident(n_schema)::regnamespace))
|
|
LOOP
|
|
EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
|
|
RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
|
|
END LOOP ;
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE NOTICE '> néant' ;
|
|
END IF ;
|
|
|
|
-- autres rôles
|
|
RAISE NOTICE 'remise à zéro des privilèges des autres rôles (pour le producteur, les éventuels privilèges manquants sont réattribués) :' ;
|
|
FOR r IN (SELECT rolname FROM pg_roles)
|
|
LOOP
|
|
FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role(
|
|
quote_ident(n_schema)::regnamespace, quote_ident(r.rolname)::regrole))
|
|
LOOP
|
|
EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
|
|
RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
|
|
k := k + 1 ;
|
|
END LOOP ;
|
|
END LOOP ;
|
|
IF NOT FOUND OR k = 0
|
|
THEN
|
|
RAISE NOTICE '> néant' ;
|
|
END IF ;
|
|
|
|
------ RECREATION DES PRIVILEGES DE L'EDITEUR ------
|
|
IF roles.editeur IS NOT NULL
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
|
|
|
|
EXECUTE 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
|
|
RAISE NOTICE '> %', 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
|
|
|
|
EXECUTE 'GRANT SELECT, UPDATE, DELETE, INSERT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
|
|
RAISE NOTICE '> %', 'GRANT SELECT, UPDATE, DELETE, INSERT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
|
|
|
|
EXECUTE 'GRANT SELECT, USAGE ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
|
|
RAISE NOTICE '> %', 'GRANT SELECT, USAGE ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
|
|
END IF ;
|
|
|
|
------ RECREATION DES PRIVILEGES DU LECTEUR ------
|
|
IF roles.lecteur IS NOT NULL
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
|
|
|
|
EXECUTE 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
|
|
RAISE NOTICE '> %', 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
|
|
|
|
EXECUTE 'GRANT SELECT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
|
|
RAISE NOTICE '> %', 'GRANT SELECT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
|
|
|
|
EXECUTE 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
|
|
RAISE NOTICE '> %', 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
|
|
END IF ;
|
|
|
|
------ RECREATION DES PRIVILEGES SUR LES SCHEMAS D'ASGARD ------
|
|
IF n_schema = 'z_asgard' AND (roles.lecteur IS NULL OR NOT roles.lecteur = 'g_consult')
|
|
THEN
|
|
-- rétablissement des droits de g_consult
|
|
RAISE NOTICE 'rétablissement des privilèges attendus pour g_consult :' ;
|
|
|
|
GRANT USAGE ON SCHEMA z_asgard TO g_consult ;
|
|
RAISE NOTICE '> GRANT USAGE ON SCHEMA z_asgard TO g_consult' ;
|
|
|
|
GRANT SELECT ON TABLE z_asgard.gestion_schema_usr TO g_consult ;
|
|
RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard.gestion_schema_usr TO g_consult' ;
|
|
|
|
GRANT SELECT ON TABLE z_asgard.gestion_schema_etr TO g_consult ;
|
|
RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard.gestion_schema_etr TO g_consult' ;
|
|
|
|
GRANT SELECT ON TABLE z_asgard.qgis_menubuilder_metadata TO g_consult ;
|
|
RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard.qgis_menubuilder_metadata TO g_consult' ;
|
|
|
|
ELSIF n_schema = 'z_asgard_admin'
|
|
THEN
|
|
-- rétablissement des droits de g_admin_ext
|
|
RAISE NOTICE 'rétablissement des privilèges attendus pour g_admin_ext :' ;
|
|
|
|
GRANT USAGE ON SCHEMA z_asgard_admin TO g_admin_ext ;
|
|
RAISE NOTICE '> GRANT USAGE ON SCHEMA z_asgard_admin TO g_admin_ext' ;
|
|
|
|
GRANT INSERT, SELECT, UPDATE, DELETE ON TABLE z_asgard_admin.gestion_schema TO g_admin_ext ;
|
|
RAISE NOTICE '> GRANT INSERT, SELECT, UPDATE, DELETE ON TABLE z_asgard_admin.gestion_schema TO g_admin_ext' ;
|
|
|
|
GRANT SELECT ON TABLE z_asgard_admin.asgard_parametre TO g_admin_ext ;
|
|
RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard_admin.asgard_parametre TO g_admin_ext' ;
|
|
|
|
END IF ;
|
|
|
|
RETURN '__ REINITIALISATION REUSSIE.' ;
|
|
|
|
EXCEPTION WHEN OTHERS THEN
|
|
GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
|
|
e_hint = PG_EXCEPTION_HINT,
|
|
e_detl = PG_EXCEPTION_DETAIL ;
|
|
RAISE EXCEPTION 'FIS0 > %', e_mssg
|
|
USING DETAIL = e_detl,
|
|
HINT = e_hint ;
|
|
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_initialise_schema(text, boolean, boolean)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_initialise_schema(text, boolean, boolean) IS 'ASGARD. Fonction qui réinitialise les privilèges sur un schéma (et l''ajoute à la table de gestion s''il n''y est pas déjà).' ;
|
|
|
|
|
|
------ 4.9 - REINITIALISATION DES PRIVILEGES SUR UN OBJET ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_initialise_obj(text, text, text)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_initialise_obj(
|
|
obj_schema text,
|
|
obj_nom text,
|
|
obj_typ text
|
|
)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction permet de réinitialiser les droits
|
|
sur un objet selon les privilèges standards associés
|
|
aux rôles désignés dans la table de gestion pour son schéma.
|
|
|
|
ARGUMENTS :
|
|
- "obj_schema" est le nom du schéma contenant l'objet, au format
|
|
texte et sans guillemets ;
|
|
- "obj_nom" est le nom de l'objet, au format texte et sans
|
|
guillemets ;
|
|
- "obj_typ" est le type de l'objet au format text ('table',
|
|
'partitioned table' (assimilé à 'table'), 'view', 'materialized view',
|
|
'foreign table', 'sequence', 'function', 'aggregate', 'type', 'domain').
|
|
SORTIE : '__ REINITIALISATION REUSSIE.' si la requête s'est exécutée
|
|
normalement. */
|
|
DECLARE
|
|
class_info record ;
|
|
roles record ;
|
|
obj record ;
|
|
r record ;
|
|
c record ;
|
|
l text ;
|
|
k int := 0 ;
|
|
BEGIN
|
|
|
|
-- pour la suite, on assimile les partitions à des tables
|
|
IF obj_typ = 'partitioned table'
|
|
THEN
|
|
obj_typ := 'table' ;
|
|
END IF ;
|
|
|
|
------ TESTS PREALABLES ------
|
|
-- schéma système
|
|
IF obj_schema ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
|
|
'^public$', '^information_schema$', '^topology$'])
|
|
THEN
|
|
RAISE EXCEPTION 'FIO1. Opération interdite. Le schéma % est un schéma système.', obj_schema ;
|
|
END IF ;
|
|
|
|
-- schéma non référencé
|
|
IF NOT obj_schema IN (SELECT nom_schema FROM z_asgard.gestion_schema_usr WHERE creation)
|
|
THEN
|
|
RAISE EXCEPTION 'FIO2. Echec. Le schéma % n''est pas référencé dans la table de gestion (ou marqué comme non créé).', obj_schema ;
|
|
END IF ;
|
|
|
|
-- type invalide + récupération des informations sur le catalogue contenant l'objet
|
|
SELECT
|
|
xtyp, xclass, xprefix || 'name' AS xname, xprefix || 'owner' AS xowner,
|
|
xprefix || 'namespace' AS xschema
|
|
INTO class_info
|
|
FROM unnest(ARRAY['table', 'foreign table', 'view', 'materialized view',
|
|
'sequence', 'type', 'domain', 'function', 'aggregate'],
|
|
ARRAY['pg_class', 'pg_class', 'pg_class', 'pg_class',
|
|
'pg_class', 'pg_type', 'pg_type', 'pg_proc', 'pg_proc'],
|
|
ARRAY['rel', 'rel', 'rel', 'rel', 'rel', 'typ', 'typ',
|
|
'pro', 'pro']) AS typ (xtyp, xclass, xprefix)
|
|
WHERE typ.xtyp = obj_typ ;
|
|
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE EXCEPTION 'FIO3. Echec. Le type % n''existe pas ou n''est pas pris en charge.', obj_typ
|
|
USING HINT = 'Types acceptés : ''table'', ''partitioned table'' (assimilé à ''table''), ''view'', ''materialized view'', ''foreign table'', ''sequence'', ''function'', ''aggregate'', ''type'', ''domain''.' ;
|
|
END IF ;
|
|
|
|
-- objet inexistant + récupération du propriétaire
|
|
EXECUTE 'SELECT ' || class_info.xowner || '::regrole::text AS prop, '
|
|
|| class_info.xclass || '.oid FROM pg_catalog.' || class_info.xclass
|
|
|| ' WHERE ' || class_info.xname || ' = ' || quote_literal(obj_nom)
|
|
|| ' AND ' || class_info.xschema || '::regnamespace::text = quote_ident('
|
|
|| quote_literal(obj_schema) || ')'
|
|
INTO obj ;
|
|
|
|
IF obj.prop IS NULL
|
|
THEN
|
|
RAISE EXCEPTION 'FIO4. Echec. L''objet % n''existe pas.', obj_nom ;
|
|
END IF ;
|
|
|
|
------ RECUPERATION DES ROLES ------
|
|
SELECT
|
|
r1.rolname AS producteur,
|
|
CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
|
|
CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
|
|
creation INTO roles
|
|
FROM z_asgard.gestion_schema_etr
|
|
LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
|
|
LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
|
|
LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
|
|
WHERE nom_schema = obj_schema ;
|
|
|
|
-- permission sur le producteur
|
|
IF NOT pg_has_role(roles.producteur, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FIO5. Echec. Vous ne disposez pas des permissions nécessaires sur le schéma % pour réaliser cette opération.', obj_schema
|
|
USING HINT = 'Il vous faut être membre du rôle producteur ' || roles.producteur || '.' ;
|
|
END IF ;
|
|
|
|
------ REMISE A PLAT DU PROPRIETAIRE ------
|
|
IF NOT obj.prop = roles.producteur
|
|
THEN
|
|
-- permission sur le propriétaire de l'objet
|
|
IF NOT pg_has_role(obj.prop, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FIO6. Echec. Vous ne disposez pas des permissions nécessaires sur l''objet % pour réaliser cette opération.', obj_nom
|
|
USING HINT = 'Il vous faut être membre du rôle propriétaire de l''objet (' || obj.prop || ').' ;
|
|
END IF ;
|
|
|
|
RAISE NOTICE 'réattribution de la propriété de % au rôle producteur du schéma :', obj_nom ;
|
|
l := 'ALTER ' || obj_typ || ' ' || quote_ident(obj_schema) || '.' || quote_ident(obj_nom)||
|
|
' OWNER TO ' || quote_ident(roles.producteur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END IF ;
|
|
|
|
------ DESTRUCTION DES PRIVILEGES ACTUELS ------
|
|
-- hors privilèges par défaut (définis par ALTER DEFAULT PRIVILEGE)
|
|
-- et hors révocations des privilèges par défaut de public sur
|
|
-- les types et les fonctions
|
|
-- pour le propriétaire, ces commandes ont pour effet
|
|
-- de remettre les privilèges par défaut supprimés
|
|
|
|
-- public
|
|
RAISE NOTICE 'remise à zéro des privilèges manuels du pseudo-rôle public :' ;
|
|
FOR c IN (SELECT * FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ))
|
|
LOOP
|
|
EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
|
|
RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
|
|
END LOOP ;
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE NOTICE '> néant' ;
|
|
END IF ;
|
|
|
|
-- autres rôles
|
|
RAISE NOTICE 'remise à zéro des privilèges des autres rôles (pour le producteur, les éventuels privilèges manquants sont réattribués) :' ;
|
|
FOR r IN (SELECT rolname FROM pg_roles)
|
|
LOOP
|
|
FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role_obj(
|
|
obj.oid, obj_typ, quote_ident(r.rolname)::regrole))
|
|
LOOP
|
|
EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
|
|
RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
|
|
k := k + 1 ;
|
|
END LOOP ;
|
|
END LOOP ;
|
|
IF NOT FOUND OR k = 0
|
|
THEN
|
|
RAISE NOTICE '> néant' ;
|
|
END IF ;
|
|
|
|
------ RECREATION DES PRIVILEGES DE L'EDITEUR ------
|
|
IF roles.editeur IS NOT NULL
|
|
THEN
|
|
-- sur les tables :
|
|
IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
|
|
l := 'GRANT SELECT, UPDATE, DELETE, INSERT ON TABLE '
|
|
|| quote_ident(obj_schema) || '.' || quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles.editeur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
-- sur les séquences :
|
|
ELSIF obj_typ IN ('sequence')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
|
|
l := 'GRANT SELECT, USAGE ON SEQUENCE '
|
|
|| quote_ident(obj_schema) || '.' || quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles.editeur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
------ RECREATION DES PRIVILEGES DU LECTEUR ------
|
|
IF roles.lecteur IS NOT NULL
|
|
THEN
|
|
-- sur les tables :
|
|
IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
|
|
l := 'GRANT SELECT ON TABLE ' || quote_ident(obj_schema) || '.'
|
|
|| quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles.lecteur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
-- sur les séquences :
|
|
ELSIF obj_typ IN ('sequence')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
|
|
l := 'GRANT SELECT ON SEQUENCE ' || quote_ident(obj_schema) || '.'
|
|
|| quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles.lecteur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
RETURN '__ REINITIALISATION REUSSIE.' ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_initialise_obj(text, text, text)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_initialise_obj(text, text, text) IS 'ASGARD. Fonction qui réinitialise les privilèges sur un objet.' ;
|
|
|
|
|
|
------ 4.10 - DEPLACEMENT D'OBJET ------
|
|
|
|
-- FUNCTION: z_asgard.asgard_deplace_obj(text, text, text, text, int)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard.asgard_deplace_obj(
|
|
obj_schema text,
|
|
obj_nom text,
|
|
obj_typ text,
|
|
schema_cible text,
|
|
variante int DEFAULT 1
|
|
)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction permet de déplacer un objet vers un nouveau
|
|
schéma en spécifiant la gestion voulue sur les droits de
|
|
l'objet : transfert ou réinitialisation des privilèges.
|
|
Dans le cas d'une table avec un ou plusieurs champs de
|
|
type serial, elle prend aussi en charge les privilèges
|
|
sur les séquences associées.
|
|
ARGUMENTS :
|
|
- "obj_schema" est le nom du schéma contenant l'objet, au format
|
|
texte et sans guillemets ;
|
|
- "obj_nom" est le nom de l'objet, au format texte et sans
|
|
guillemets ;
|
|
- "obj_typ" est le type de l'objet au format text ('table',
|
|
'partitioned table' (assimilé à 'table'), 'view', 'materialized view',
|
|
'foreign table', 'sequence', 'function', 'aggregate', 'type', 'domain') ;
|
|
- "schema_cible" est le nom du schéma où doit être déplacé l'objet,
|
|
au format texte et sans guillemets ;
|
|
- "variante" [optionnel] est un entier qui définit le comportement
|
|
attendu par l'utilisateur vis à vis des privilèges :
|
|
- 1 (valeur par défaut) | TRANSFERT COMPLET + CONSERVATION :
|
|
les privilèges des rôles producteur, éditeur et lecteur de
|
|
l'ancien schéma sont transférés sur ceux du nouveau. Si un
|
|
éditeur ou lecteur a été désigné pour le nouveau schéma mais
|
|
qu'aucun n'était défini pour l'ancien, le rôle reçoit les
|
|
privilèges standards pour sa fonction. Le cas échéant,
|
|
les privilèges des autres rôles sont conservés ;
|
|
- 2 | REINITIALISATION COMPLETE : les nouveaux
|
|
producteur, éditeur et lecteur reçoivent les privilèges
|
|
standard. Les privilèges des autres rôles sont supprimés ;
|
|
- 3 | TRANSFERT COMPLET + NETTOYAGE : les privilèges des rôles
|
|
producteur, éditeur et lecteur de l'ancien schéma sont transférés
|
|
sur ceux du nouveau. Si un éditeur ou lecteur a été désigné pour
|
|
le nouveau schéma mais qu'aucun n'était défini pour l'ancien,
|
|
le rôle reçoit les privilèges standards pour sa fonction.
|
|
Les privilèges des autres rôles sont supprimés ;
|
|
- 4 | TRANSFERT PRODUCTEUR + CONSERVATION : les privilèges de
|
|
l'ancien producteur sont transférés sur le nouveau. Les privilèges
|
|
des autres rôles sont conservés tels quels. C'est le comportement
|
|
d'une commande ALTER [...] SET SCHEMA (interceptée par l'event
|
|
trigger asgard_on_alter_objet) ;
|
|
- 5 | TRANSFERT PRODUCTEUR + REINITIALISATION : les privilèges
|
|
de l'ancien producteur sont transférés sur le nouveau. Les
|
|
nouveaux éditeur et lecteur reçoivent les privilèges standards.
|
|
Les privilèges des autres rôles sont supprimés ;
|
|
- 6 | REINITIALISATION PARTIELLE : les nouveaux
|
|
producteur, éditeur et lecteur reçoivent les privilèges
|
|
standard. Les privilèges des autres rôles sont conservés.
|
|
SORTIE : '__ DEPLACEMENT REUSSI.' si la requête s'est exécutée normalement. */
|
|
DECLARE
|
|
class_info record ;
|
|
roles record ;
|
|
roles_cible record ;
|
|
obj record ;
|
|
r record ;
|
|
c record ;
|
|
l text ;
|
|
c_lecteur text[] ;
|
|
c_editeur text[] ;
|
|
c_producteur text[] ;
|
|
c_n_lecteur text[] ;
|
|
c_n_editeur text[] ;
|
|
c_autres text[] ;
|
|
seq_liste oid[] ;
|
|
a text[] ;
|
|
s record ;
|
|
o oid ;
|
|
BEGIN
|
|
|
|
-- pour la suite, on assimile les partitions à des tables
|
|
IF obj_typ = 'partitioned table'
|
|
THEN
|
|
obj_typ := 'table' ;
|
|
END IF ;
|
|
|
|
------ TESTS PREALABLES ------
|
|
-- schéma système
|
|
IF obj_schema ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
|
|
'^public$', '^information_schema$', '^topology$'])
|
|
THEN
|
|
RAISE EXCEPTION 'FDO1. Opération interdite. Le schéma % est un schéma système.', obj_schema ;
|
|
END IF ;
|
|
|
|
-- schéma de départ non référencé
|
|
IF NOT obj_schema IN (SELECT nom_schema FROM z_asgard.gestion_schema_usr WHERE creation)
|
|
THEN
|
|
RAISE EXCEPTION 'FDO2. Echec. Le schéma % n''est pas référencé dans la table de gestion (ou marqué comme non créé).', obj_schema ;
|
|
END IF ;
|
|
|
|
-- schéma cible non référencé
|
|
IF NOT schema_cible IN (SELECT nom_schema FROM z_asgard.gestion_schema_usr WHERE creation)
|
|
THEN
|
|
RAISE EXCEPTION 'FDO3. Echec. Le schéma cible % n''est pas référencé dans la table de gestion (ou marqué comme non créé).', schema_cible ;
|
|
END IF ;
|
|
|
|
-- type invalide + récupération des informations sur le catalogue contenant l'objet
|
|
SELECT
|
|
xtyp, xclass, xprefix || 'name' AS xname, xprefix || 'owner' AS xowner,
|
|
xprefix || 'namespace' AS xschema
|
|
INTO class_info
|
|
FROM unnest(ARRAY['table', 'foreign table', 'view', 'materialized view',
|
|
'sequence', 'type', 'domain', 'function', 'aggregate'],
|
|
ARRAY['pg_class', 'pg_class', 'pg_class', 'pg_class',
|
|
'pg_class', 'pg_type', 'pg_type', 'pg_proc', 'pg_proc'],
|
|
ARRAY['rel', 'rel', 'rel', 'rel', 'rel', 'typ', 'typ',
|
|
'pro', 'pro']) AS typ (xtyp, xclass, xprefix)
|
|
WHERE typ.xtyp = obj_typ ;
|
|
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE EXCEPTION 'FDO4. Echec. Le type % n''existe pas ou n''est pas pris en charge.', obj_typ
|
|
USING HINT = 'Types acceptés : ''table'', ''partitioned table'' (assimilé à ''table''), ''view'', ''materialized view'', ''foreign table'', ''sequence'', ''function'', ''aggregate'', ''type'', ''domain''.' ;
|
|
END IF ;
|
|
|
|
-- objet inexistant + récupération du propriétaire
|
|
EXECUTE 'SELECT ' || class_info.xowner || '::regrole::text AS prop, '
|
|
|| class_info.xclass || '.oid FROM pg_catalog.' || class_info.xclass
|
|
|| ' WHERE ' || class_info.xname || ' = ' || quote_literal(obj_nom)
|
|
|| ' AND ' || class_info.xschema || '::regnamespace::text = quote_ident('
|
|
|| quote_literal(obj_schema) || ')'
|
|
INTO obj ;
|
|
|
|
IF obj.prop IS NULL
|
|
THEN
|
|
RAISE EXCEPTION 'FDO5. Echec. L''objet % n''existe pas.', obj_nom ;
|
|
END IF ;
|
|
|
|
------ RECUPERATION DES ROLES ------
|
|
-- schéma de départ :
|
|
SELECT
|
|
r1.rolname AS producteur,
|
|
CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
|
|
CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
|
|
creation INTO roles
|
|
FROM z_asgard.gestion_schema_etr
|
|
LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
|
|
LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
|
|
LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
|
|
WHERE nom_schema = obj_schema ;
|
|
|
|
-- schéma cible :
|
|
SELECT
|
|
r1.rolname AS producteur,
|
|
CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
|
|
CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
|
|
creation INTO roles_cible
|
|
FROM z_asgard.gestion_schema_etr
|
|
LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
|
|
LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
|
|
LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
|
|
WHERE nom_schema = schema_cible ;
|
|
|
|
-- permission sur le producteur du schéma cible
|
|
IF NOT pg_has_role(roles_cible.producteur, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FDO6. Echec. Vous ne disposez pas des permissions nécessaires sur le schéma cible % pour réaliser cette opération.', schema_cible
|
|
USING HINT = 'Il vous faut être membre du rôle producteur ' || roles_cible.producteur || '.' ;
|
|
END IF ;
|
|
|
|
-- permission sur le propriétaire de l'objet
|
|
IF NOT pg_has_role(obj.prop, 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FDO7. Echec. Vous ne disposez pas des permissions nécessaires sur l''objet % pour réaliser cette opération.', obj_nom
|
|
USING HINT = 'Il vous faut être membre du rôle propriétaire de l''objet (' || obj.prop || ').' ;
|
|
END IF ;
|
|
|
|
------ MEMORISATION DES PRIVILEGES ACTUELS ------
|
|
-- ancien producteur :
|
|
SELECT array_agg(commande) INTO c_producteur
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
obj.oid, obj_typ, quote_ident(roles.producteur)::regrole) ;
|
|
|
|
-- ancien éditeur :
|
|
IF roles.editeur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_editeur
|
|
FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
|
|
ELSIF roles.editeur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_editeur
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
obj.oid, obj_typ, quote_ident(roles.editeur)::regrole) ;
|
|
END IF ;
|
|
|
|
-- ancien lecteur :
|
|
IF roles.lecteur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_lecteur
|
|
FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
|
|
ELSIF roles.lecteur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_lecteur
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
obj.oid, obj_typ, quote_ident(roles.lecteur)::regrole) ;
|
|
END IF ;
|
|
|
|
-- nouvel éditeur :
|
|
IF roles_cible.editeur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_n_editeur
|
|
FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
|
|
ELSIF roles_cible.editeur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_n_editeur
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
obj.oid, obj_typ, quote_ident(roles_cible.editeur)::regrole) ;
|
|
END IF ;
|
|
|
|
-- nouveau lecteur :
|
|
IF roles_cible.lecteur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_n_lecteur
|
|
FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
|
|
ELSIF roles_cible.lecteur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO c_n_lecteur
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
obj.oid, obj_typ, quote_ident(roles_cible.lecteur)::regrole) ;
|
|
END IF ;
|
|
|
|
-- autres rôles :
|
|
-- pour ces commandes, contrairement aux précédentes, le rôle
|
|
-- est inséré dès maintenant (avec "format")
|
|
-- public
|
|
IF NOT 'public' = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
|
|
roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL))
|
|
THEN
|
|
SELECT array_agg(format(commande, 'public')) INTO c_autres
|
|
FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
|
|
END IF ;
|
|
-- et le reste
|
|
FOR r IN (SELECT rolname FROM pg_roles
|
|
WHERE NOT rolname = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
|
|
roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL)))
|
|
LOOP
|
|
SELECT array_agg(format(commande, r.rolname::text)) INTO a
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
obj.oid, obj_typ, quote_ident(r.rolname)::regrole) ;
|
|
IF FOUND
|
|
THEN
|
|
c_autres := array_cat(c_autres, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
END LOOP ;
|
|
|
|
------ PRIVILEGES SUR LES SEQUENCES ASSOCIEES ------
|
|
IF obj_typ = 'table'
|
|
THEN
|
|
-- dans le cas d'une table, on recherche les séquences
|
|
-- utilisées par ses éventuels champs de type serial.
|
|
-- elles sont repérées par le fait qu'il existe
|
|
-- une dépendance de type "DEPENDENCY_AUTO" entre
|
|
-- la séquence et un champ de la table
|
|
FOR s IN (
|
|
SELECT
|
|
pg_class.oid
|
|
FROM pg_catalog.pg_depend LEFT JOIN pg_catalog.pg_class
|
|
ON pg_class.oid = pg_depend.objid
|
|
WHERE pg_depend.classid = 'pg_catalog.pg_class'::regclass::oid
|
|
AND pg_depend.refclassid = 'pg_catalog.pg_class'::regclass::oid
|
|
AND pg_depend.refobjid = obj.oid
|
|
AND pg_depend.refobjsubid > 0
|
|
AND pg_depend.deptype = 'a'
|
|
AND pg_class.relkind = 'S'
|
|
)
|
|
LOOP
|
|
-- liste des séquences
|
|
seq_liste := array_append(seq_liste, s.oid) ;
|
|
|
|
-- récupération des privilèges
|
|
-- ancien producteur :
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
s.oid, 'sequence', quote_ident(roles.producteur)::regrole) ;
|
|
IF FOUND
|
|
THEN
|
|
c_producteur := array_cat(c_producteur, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
|
|
-- ancien éditeur :
|
|
IF roles.editeur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
|
|
ELSIF roles.editeur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
s.oid, 'sequence'::text, quote_ident(roles.editeur)::regrole) ;
|
|
END IF ;
|
|
IF a IS NOT NULL
|
|
THEN
|
|
c_editeur := array_cat(c_editeur, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
|
|
-- ancien lecteur :
|
|
IF roles.lecteur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
|
|
ELSIF roles.lecteur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
s.oid, 'sequence'::text, quote_ident(roles.lecteur)::regrole) ;
|
|
END IF ;
|
|
IF a IS NOT NULL
|
|
THEN
|
|
c_lecteur := array_cat(c_lecteur, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
|
|
-- nouvel éditeur :
|
|
IF roles_cible.editeur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
|
|
ELSIF roles_cible.editeur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
s.oid, 'sequence'::text, quote_ident(roles_cible.editeur)::regrole) ;
|
|
END IF ;
|
|
IF a IS NOT NULL
|
|
THEN
|
|
c_n_editeur := array_cat(c_n_editeur, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
|
|
-- nouveau lecteur :
|
|
IF roles_cible.lecteur = 'public'
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
|
|
ELSIF roles_cible.lecteur IS NOT NULL
|
|
THEN
|
|
SELECT array_agg(commande) INTO a
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
s.oid, 'sequence'::text, quote_ident(roles_cible.lecteur)::regrole) ;
|
|
END IF ;
|
|
IF a IS NOT NULL
|
|
THEN
|
|
c_n_lecteur := array_cat(c_n_lecteur, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
|
|
-- autres rôles :
|
|
-- public
|
|
IF NOT 'public' = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
|
|
roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL))
|
|
THEN
|
|
SELECT array_agg(format(commande, 'public')) INTO a
|
|
FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
|
|
IF FOUND
|
|
THEN
|
|
c_autres := array_cat(c_autres, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
END IF ;
|
|
-- et le reste
|
|
FOR r IN (SELECT rolname FROM pg_roles
|
|
WHERE NOT rolname = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
|
|
roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL)))
|
|
LOOP
|
|
SELECT array_agg(format(commande, r.rolname::text)) INTO a
|
|
FROM z_asgard.asgard_synthese_role_obj(
|
|
s.oid, 'sequence'::text, quote_ident(r.rolname)::regrole) ;
|
|
IF FOUND
|
|
THEN
|
|
c_autres := array_cat(c_autres, a) ;
|
|
a := NULL ;
|
|
END IF ;
|
|
END LOOP ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
------ DEPLACEMENT DE L'OBJET ------
|
|
EXECUTE 'ALTER ' || obj_typ || ' ' || quote_ident(obj_schema) || '.' || quote_ident(obj_nom)||
|
|
' SET SCHEMA ' || quote_ident(schema_cible) ;
|
|
|
|
RAISE NOTICE '... Objet déplacé dans le schéma %.', schema_cible ;
|
|
|
|
------ PRIVILEGES DU PRODUCTEUR ------
|
|
-- par défaut, ils ont été transférés
|
|
-- lors du changement de propriétaire, il
|
|
-- n'y a donc qu'à réinitialiser pour les
|
|
-- variantes 2 et 6
|
|
|
|
-- objet, réinitialisation pour 2 et 6
|
|
IF variante IN (2, 6) AND (c_producteur IS NOT NULL)
|
|
THEN
|
|
RAISE NOTICE 'réinitialisation des privilèges du nouveau producteur, % :', roles_cible.producteur ;
|
|
FOREACH l IN ARRAY c_producteur
|
|
LOOP
|
|
l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
|
|
EXECUTE format(l, roles_cible.producteur) ;
|
|
RAISE NOTICE '> %', format(l, roles_cible.producteur) ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
------- PRIVILEGES EDITEUR ------
|
|
-- révocation des privilèges du nouvel éditeur
|
|
IF roles_cible.editeur IS NOT NULL
|
|
AND (roles.editeur IS NULL OR NOT roles.editeur = roles_cible.editeur)
|
|
AND NOT roles.producteur = roles_cible.editeur
|
|
AND NOT variante = 4
|
|
AND c_n_editeur IS NOT NULL
|
|
THEN
|
|
RAISE NOTICE 'suppression des privilèges pré-existants du nouvel éditeur, % :', roles_cible.editeur ;
|
|
FOREACH l IN ARRAY c_n_editeur
|
|
LOOP
|
|
l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
|
|
EXECUTE format(l, roles_cible.editeur) ;
|
|
RAISE NOTICE '> %', format(l, roles_cible.editeur) ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
-- révocation des privilèges de l'ancien éditeur
|
|
IF roles.editeur IS NOT NULL AND NOT roles.editeur = roles_cible.producteur
|
|
AND (roles_cible.editeur IS NULL OR NOT roles.editeur = roles_cible.editeur OR NOT variante IN (1,3))
|
|
AND NOT variante = 4
|
|
AND c_editeur IS NOT NULL
|
|
THEN
|
|
RAISE NOTICE 'suppression des privilèges de l''ancien éditeur, % :', roles.editeur ;
|
|
FOREACH l IN ARRAY c_editeur
|
|
LOOP
|
|
l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
|
|
EXECUTE format(l, roles.editeur) ;
|
|
RAISE NOTICE '> %', format(l, roles.editeur) ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
-- reproduction sur le nouvel éditeur pour les variantes 1 et 3
|
|
IF roles.editeur IS NOT NULL
|
|
AND roles_cible.editeur IS NOT NULL
|
|
AND variante IN (1, 3)
|
|
AND c_editeur IS NOT NULL
|
|
AND NOT roles.editeur = roles_cible.editeur
|
|
THEN
|
|
RAISE NOTICE 'transfert des privilèges de l''ancien éditeur vers le nouvel éditeur, % :', roles_cible.editeur ;
|
|
FOREACH l IN ARRAY c_editeur
|
|
LOOP
|
|
l := replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.') ;
|
|
EXECUTE format(l, roles_cible.editeur) ;
|
|
RAISE NOTICE '> %', format(l, roles_cible.editeur) ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
-- attribution des privilèges standard au nouvel éditeur
|
|
-- pour les variantes 2, 5, 6
|
|
-- ou s'il n'y avait pas de lecteur sur l'ancien schéma
|
|
IF roles_cible.editeur IS NOT NULL
|
|
AND (variante IN (2, 5, 6) OR roles.editeur IS NULL)
|
|
AND NOT variante = 4
|
|
THEN
|
|
-- sur les tables :
|
|
IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
|
|
l := 'GRANT SELECT, UPDATE, DELETE, INSERT ON TABLE '
|
|
|| quote_ident(schema_cible) || '.' || quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles_cible.editeur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
-- sur les séquences libres :
|
|
ELSIF obj_typ IN ('sequence')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
|
|
l := 'GRANT SELECT, USAGE ON SEQUENCE '
|
|
|| quote_ident(schema_cible) || '.' || quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles_cible.editeur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END IF ;
|
|
-- sur les séquences des champs serial :
|
|
IF seq_liste IS NOT NULL
|
|
THEN
|
|
FOREACH o IN ARRAY seq_liste
|
|
LOOP
|
|
l := 'GRANT SELECT, USAGE ON SEQUENCE '
|
|
|| o::regclass::text || ' TO ' || quote_ident(roles_cible.editeur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END LOOP ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
------- PRIVILEGES LECTEUR ------
|
|
-- révocation des privilèges du nouveau lecteur
|
|
IF roles_cible.lecteur IS NOT NULL
|
|
AND (roles.lecteur IS NULL OR NOT roles.lecteur = roles_cible.lecteur)
|
|
AND NOT roles.producteur = roles_cible.lecteur
|
|
AND (roles.editeur IS NULL OR NOT roles.editeur = roles_cible.lecteur)
|
|
AND NOT variante = 4
|
|
AND c_n_lecteur IS NOT NULL
|
|
THEN
|
|
RAISE NOTICE 'suppression des privilèges pré-existants du nouveau lecteur, % :', roles_cible.lecteur ;
|
|
FOREACH l IN ARRAY c_n_lecteur
|
|
LOOP
|
|
l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
|
|
EXECUTE format(l, roles_cible.lecteur) ;
|
|
RAISE NOTICE '> %', format(l, roles_cible.lecteur) ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
-- révocation des privilèges de l'ancien lecteur
|
|
IF roles.lecteur IS NOT NULL AND NOT roles.lecteur = roles_cible.producteur
|
|
AND (roles_cible.editeur IS NULL OR NOT roles.lecteur = roles_cible.editeur)
|
|
AND (roles_cible.lecteur IS NULL OR NOT roles.lecteur = roles_cible.lecteur OR NOT variante IN (1,3))
|
|
AND NOT variante = 4
|
|
AND c_lecteur IS NOT NULL
|
|
THEN
|
|
RAISE NOTICE 'suppression des privilèges de l''ancien lecteur, % :', roles.lecteur ;
|
|
FOREACH l IN ARRAY c_lecteur
|
|
LOOP
|
|
l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
|
|
EXECUTE format(l, roles.lecteur) ;
|
|
RAISE NOTICE '> %', format(l, roles.lecteur) ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
-- reproduction sur le nouveau lecteur pour les variantes 1 et 3
|
|
IF roles.lecteur IS NOT NULL
|
|
AND roles_cible.lecteur IS NOT NULL
|
|
AND variante IN (1, 3)
|
|
AND c_lecteur IS NOT NULL
|
|
AND NOT roles.lecteur = roles_cible.lecteur
|
|
THEN
|
|
RAISE NOTICE 'transfert des privilèges de l''ancien lecteur vers le nouveau lecteur, % :', roles_cible.lecteur ;
|
|
FOREACH l IN ARRAY c_lecteur
|
|
LOOP
|
|
l := replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.') ;
|
|
EXECUTE format(l, roles_cible.lecteur) ;
|
|
RAISE NOTICE '> %', format(l, roles_cible.lecteur) ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
-- attribution des privilèges standard au nouveau lecteur
|
|
-- pour les variantes 2, 5, 6
|
|
-- ou s'il n'y avait pas de lecteur sur l'ancien schéma
|
|
IF roles_cible.lecteur IS NOT NULL
|
|
AND (variante IN (2, 5, 6) OR roles.lecteur IS NULL)
|
|
AND NOT variante = 4
|
|
THEN
|
|
-- sur les tables :
|
|
IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
|
|
l := 'GRANT SELECT ON TABLE ' || quote_ident(schema_cible) || '.'
|
|
|| quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles_cible.lecteur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
-- sur les séquences libres :
|
|
ELSIF obj_typ IN ('sequence')
|
|
THEN
|
|
RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
|
|
l := 'GRANT SELECT ON SEQUENCE ' || quote_ident(schema_cible) || '.'
|
|
|| quote_ident(obj_nom) ||
|
|
' TO ' || quote_ident(roles_cible.lecteur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END IF ;
|
|
-- sur les séquences des champs serial :
|
|
IF seq_liste IS NOT NULL
|
|
THEN
|
|
FOREACH o IN ARRAY seq_liste
|
|
LOOP
|
|
l := 'GRANT SELECT ON SEQUENCE '
|
|
|| o::regclass::text || ' TO ' || quote_ident(roles_cible.lecteur) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END LOOP ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
------ AUTRES ROLES ------
|
|
-- pour les variantes 2, 3, 5, remise à zéro
|
|
IF variante IN (2, 3, 5)
|
|
AND c_autres IS NOT NULL
|
|
THEN
|
|
RAISE NOTICE 'remise à zéro des privilèges des autres rôles :' ;
|
|
FOREACH l IN ARRAY c_autres
|
|
LOOP
|
|
l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
|
|
EXECUTE l ;
|
|
RAISE NOTICE '> %', l ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
RETURN '__ DEPLACEMENT REUSSI.' ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard.asgard_deplace_obj(text, text, text, text, int)
|
|
OWNER TO g_admin_ext ;
|
|
|
|
COMMENT ON FUNCTION z_asgard.asgard_deplace_obj(text, text, text, text, int) IS 'ASGARD. Fonction qui prend en charge le déplacement d''un objet dans un nouveau schéma, avec une gestion propre des privilèges.' ;
|
|
|
|
|
|
|
|
------ 4.11 - OCTROI D'UN RÔLE À TOUS LES RÔLES DE CONNEXION ------
|
|
|
|
-- FUNCTION: z_asgard_admin.asgard_all_login_grant_role(text, boolean)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_all_login_grant_role(n_role text, b boolean DEFAULT True)
|
|
RETURNS int
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction confère à tous les rôles de connexion du
|
|
serveur l'appartenance au rôle donné en argument.
|
|
ARGUMENTS :
|
|
- n_role : une chaîne de caractères présumée correspondre à un nom de
|
|
rôle valide ;
|
|
- b : [optionnel] un booléen. Si b vaut False et qu'un rôle de connexion est
|
|
déjà membre du rôle considéré par héritage, la fonction ne fait rien. Si
|
|
b vaut True (défaut), la fonction ne passera un rôle de connexion que s'il est
|
|
lui-même membre du rôle considéré.
|
|
SORTIE : un entier correspondant au nombre de rôles pour lesquels
|
|
la permission a été accordée. */
|
|
DECLARE
|
|
roles record ;
|
|
attributeur text ;
|
|
utilisateur text := current_user ;
|
|
c text ;
|
|
n int := 0 ;
|
|
BEGIN
|
|
------ TESTS PREALABLES -----
|
|
-- existance du rôle
|
|
IF NOT n_role IN (SELECT rolname FROM pg_catalog.pg_roles)
|
|
THEN
|
|
RAISE EXCEPTION 'FLG1. Echec. Le rôle % n''existe pas', n_role ;
|
|
END IF ;
|
|
|
|
-- on cherche un rôle dont l'utilisateur est
|
|
-- membre et qui, soit a l'attribut CREATEROLE
|
|
-- soit a ADMIN OPTION sur le rôle
|
|
SELECT rolname INTO attributeur
|
|
FROM pg_roles
|
|
WHERE pg_has_role(rolname, 'MEMBER') AND rolcreaterole
|
|
ORDER BY rolname = current_user DESC ;
|
|
IF NOT FOUND
|
|
THEN
|
|
SELECT grantee INTO attributeur
|
|
FROM information_schema.applicable_roles
|
|
WHERE is_grantable = 'YES' AND role_name = n_role ;
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE EXCEPTION 'FLG2. Opération interdite. Permissions insuffisantes pour le rôle %.', n_role
|
|
USING HINT = 'Votre rôle doit être membre de ' || n_role
|
|
|| ' avec admin option ou disposer de l''attribut CREATEROLE pour réaliser cette opération.' ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
EXECUTE 'SET ROLE ' || quote_ident(attributeur) ;
|
|
|
|
IF b
|
|
THEN
|
|
FOR roles IN SELECT rolname
|
|
FROM pg_roles LEFT JOIN pg_auth_members
|
|
ON member = pg_roles.oid AND roleid = n_role::regrole::oid
|
|
WHERE rolcanlogin AND member IS NULL
|
|
AND NOT rolsuper
|
|
LOOP
|
|
c := 'GRANT ' || quote_ident(n_role) || ' TO ' || quote_ident(roles.rolname) ;
|
|
EXECUTE c ;
|
|
RAISE NOTICE '> %', c ;
|
|
n := n + 1 ;
|
|
END LOOP ;
|
|
ELSE
|
|
FOR roles IN SELECT rolname FROM pg_roles
|
|
WHERE rolcanlogin AND NOT pg_has_role(rolname, n_role, 'MEMBER')
|
|
LOOP
|
|
c := 'GRANT ' || quote_ident(n_role) || ' TO ' || quote_ident(roles.rolname) ;
|
|
EXECUTE c ;
|
|
RAISE NOTICE '> %', c ;
|
|
n := n + 1 ;
|
|
END LOOP ;
|
|
END IF ;
|
|
|
|
EXECUTE 'SET ROLE ' || quote_ident(utilisateur) ;
|
|
|
|
RETURN n ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard_admin.asgard_all_login_grant_role(text, boolean)
|
|
OWNER TO g_admin ;
|
|
|
|
COMMENT ON FUNCTION z_asgard_admin.asgard_all_login_grant_role(text, boolean) IS 'ASGARD. Fonction qui confère à tous les rôles de connexion du serveur l''appartenance au rôle donné en argument.' ;
|
|
|
|
|
|
|
|
------ 4.12 - IMPORT DE LA NOMENCLATURE DANS GESTION_SCHEMA ------
|
|
|
|
-- FUNCTION: z_asgard_admin.asgard_import_nomenclature(text[])
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_import_nomenclature(
|
|
domaines text[] default NULL::text[]
|
|
)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Fonction qui importe dans la table de gestion les schémas manquants
|
|
de la nomenclature nationale - ou de certains domaines
|
|
de la nomenclature nationale listés en argument - toujours avec
|
|
creation valant False, même si le schéma existe (mais n'a pas été
|
|
référencé).
|
|
Des messages informent l'opérateur des schémas effectivement ajoutés.
|
|
Lorsque le schéma est déjà référencé dans la table de gestion, réappliquer
|
|
la fonction a pour effet de mettre à jour les champs relatifs à la
|
|
nomenclature.
|
|
ARGUMENT : domaines (optionnel) : un tableau text[] contenant les noms des
|
|
domaines à importer, soit le "niveau 1"/niv1 ou niv1_abr des schémas. Si non renseigné,
|
|
toute la nomenclature est importée (hors schémas déjà référencés).
|
|
SORTIE : '__ FIN IMPORT NOMENCLATURE.' si la requête s'est exécutée normalement. */
|
|
DECLARE
|
|
item record ;
|
|
e_mssg text ;
|
|
e_detl text ;
|
|
e_hint text ;
|
|
BEGIN
|
|
FOR item IN SELECT * FROM (
|
|
VALUES
|
|
('c', true, 'Données génériques', 'donnees_generique', 'Découpage électoral', 'decoupage_electoral', 'c_don_gen_decoupage_electoral', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Données génériques', 'donnees_generique', 'Démographie', 'demographie', 'c_don_gen_demographie', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Données génériques', 'donnees_generique', 'Habillage des cartes', 'habillage', 'c_don_gen_habillage', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Données génériques', 'donnees_generique', 'Intercommunalité', 'intercommunalite', 'c_don_gen_intercommunalite', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Données génériques', 'donnees_generique', 'Milieu physique', 'milieu_physique', 'c_don_gen_milieu_physique', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Alimentation en eau potable', 'aep', 'c_eau_aep', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Assainissement', 'assainissement', 'c_eau_assainissement', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Masses d’eau', 'masse_eau', 'c_eau_masse_eau', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Ouvrages', 'ouvrage', 'c_eau_ouvrage', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Pêche', 'peche', 'c_eau_peche', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Surveillance', 'surveillance', 'c_eau_surveillance', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Agriculture', 'agriculture', 'Environnement', 'agri_environnement', 'c_agri_environnement', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Agriculture', 'agriculture', 'Agro-alimentaire', 'agro_alimentaire', 'c_agri_agroalimentaire', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Agriculture', 'agriculture', 'Exploitation & élevage', 'exploitation_elevage', 'c_agri_exploi_elevage', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Agriculture', 'agriculture', 'Parcellaire agricole', 'parcellaire_agricole', 'c_agri_parcellaire_agricole', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Agriculture', 'agriculture', 'Santé animale', 'sante_animale', 'c_agri_sante_animale', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Agriculture', 'agriculture', 'Santé végétale', 'sante_vegetale', 'c_agri_sante_vegetale', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Séismes', 'seisme', 'c_risque_seisme', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Agriculture', 'agriculture', 'Zonages agricoles', 'zonages_agricoles', 'c_agri_zonages_agricoles', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Air & climat', 'air_climat', 'Changement climatique', 'changement_climatique', 'c_air_clim_changement', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Air & climat', 'air_climat', 'Météorologie', 'meteo', 'c_air_clim_meteo', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Air & climat', 'air_climat', 'Qualité de l’air & pollution', 'qualité_pollution', 'c_air_clim_qual_polu', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Assiettes des servitudes', 'assiette_servitude', 'c_amgt_urb_servitude', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Politique européenne', 'politique_europeenne', 'c_amgt_urb_pol_euro', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Zonages d’aménagement', 'zonages_amenagement', 'c_amgt_urb_zon_amgt', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Zonages d’études', 'zonages_etudes', 'c_amgt_urb_zon_etudes', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Zonages de planification', 'zonages_planification', 'c_amgt_urb_zon_plan', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Culture, société & services', 'culture_societe_service', 'Enseignement', 'enseignement', 'c_cult_soc_ser_enseignement', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Culture, société & services', 'culture_societe_service', 'Équipements sportifs et culturels', 'equipement_sportif_culturel', 'c_cult_soc_ser_equip_sport_cult', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Culture, société & services', 'culture_societe_service', 'Autres établissements', 'erp_autre', 'c_cult_soc_ser_erp_autre', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Culture, société & services', 'culture_societe_service', 'Patrimoine culturel', 'patrimoine_culturel', 'c_cult_soc_ser_patrim_cult', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Culture, société & services', 'culture_societe_service', 'Santé & social', 'sante_social', 'c_cult_soc_ser_sante_social', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Culture, société & services', 'culture_societe_service', 'Tourisme', 'tourisme', 'c_cult_soc_ser_tourisme', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Données génériques', 'donnees_generique', 'Action publique', 'action_publique', 'c_don_gen_action_publique', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Données génériques', 'donnees_generique', 'Découpage administratif', 'administratif', 'c_don_gen_administratif', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Travaux & entretien', 'travail_action', 'c_eau_travail_action', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Autres utilisations', 'utilisation_autre', 'c_eau_utilisation_autre', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Eau', 'eau', 'Zonages eau', 'zonages_eau', 'c_eau_zonages', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Foncier & sol', 'foncier_sol', 'Foncier agricole', 'foncier_agricole', 'c_fon_sol_agricole', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Foncier & sol', 'foncier_sol', 'Mutations foncières', 'mutation_fonciere', 'c_fon_sol_mutation', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Foncier & sol', 'foncier_sol', 'Occupation du sol', 'occupation_sol', 'c_fon_sol_occupation', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Foncier & sol', 'foncier_sol', 'Propriétés foncières', 'propriete_fonciere', 'c_fon_sol_propriete', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Forêt', 'foret', 'Description', 'description', 'c_foret_description', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Forêt', 'foret', 'Défense de la forêt contre les incendies', 'dfci', 'c_foret_dfci', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Forêt', 'foret', 'Gestion', 'gestion', 'c_foret_gestion', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Forêt', 'foret', 'Règlement', 'reglement', 'c_foret_reglement', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Forêt', 'foret', 'Transformation', 'transformation', 'c_foret_transformation', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Accession à la propriété', 'accession_propriete', 'c_hab_vil_access_propriete', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Besoin en logements', 'besoin_en_logement', 'c_hab_vil_besoin_logt', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Construction', 'construction', 'c_hab_vil_construction', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Habitat indigne', 'habitat_indigne', 'c_hab_vil_habitat_indigne', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Occupation des logements', 'occupation_logements', 'c_hab_vil_occupation_logt', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Parc locatif social', 'parc_locatif_social', 'c_hab_vil_parc_loc_social', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Parc de logements', 'parc_logements', 'c_hab_vil_parc_logt', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Politique', 'politique', 'c_hab_vil_politique', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Rénovation', 'renovation', 'c_hab_vil_renovation', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Autres activités', 'autres_activites', 'c_mer_litt_autres_activites', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Chasse maritime', 'chasse_maritime', 'c_mer_litt_chasse_maritime', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Culture marine', 'culture_marine', 'c_mer_litt_culture_marine', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Écologie du littoral', 'ecologie_littoral', 'c_mer_litt_ecol_littoral', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Limites administratives spéciales', 'lim_admin_speciale', 'c_mer_litt_lim_admin_spe', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Lutte anti-pollution', 'lutte_anti_pollution', 'c_mer_litt_lutte_anti_pollu', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Navigation maritime', 'navigation_maritime', 'c_mer_litt_nav_maritime', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Pêche maritime', 'peche_maritime', 'c_mer_litt_peche_maritime', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Mer & littoral', 'mer_littoral', 'Topographie', 'topographie', 'c_mer_litt_topographie', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Chasse', 'chasse', 'c_nat_pays_bio_chasse', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Inventaires nature & biodiversité', 'inventaire_nature_biodiversite', 'c_nat_pays_bio_invent_nat_bio', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Inventaires paysages', 'inventaire_paysage', 'c_nat_pays_bio_invent_pays', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Zonages nature', 'zonage_nature', 'c_nat_pays_bio_zonage_nat', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Zonages paysages', 'zonage_paysage', 'c_nat_pays_bio_zonage_pays', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nuisances', 'nuisance', 'Bruit', 'bruit', 'c_nuis_bruit', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nuisances', 'nuisance', 'Déchets', 'dechet', 'c_nuis_dechet', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nuisances', 'nuisance', 'Nuisances électromagnétiques', 'nuisance_electromagnetique', 'c_nuis_electromag', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Nuisances', 'nuisance', 'Pollution des sols', 'pollution_sol', 'c_nuis_pollu_sol', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Aménagement numérique du territoire', 'amenagement_numerique_territoire', 'c_res_energ_amgt_num_terri', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Autre', 'autre', 'c_res_energ_autre', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Électricité', 'electricite', 'c_res_energ_electricite', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Hydrocarbures', 'hydrocarbure', 'c_res_energ_hydrocarbure', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Télécommunications', 'telecommunication', 'c_res_energ_telecom', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Avalanche', 'avalanche', 'c_risque_avalanche', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Éruptions volcaniques', 'eruption_volcanique', 'c_risque_eruption_volcanique', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Gestion des risques', 'gestion_risque', 'c_risque_gestion_risque', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Inondations', 'inondation', 'c_risque_inondation', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Mouvements de terrain', 'mouvement_terrain', 'c_risque_mouvement_terrain', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Radon', 'radon', 'c_risque_radon', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Risques miniers', 'risque_minier', 'c_risque_minier', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Risques technologiques', 'risque_technologique', 'c_risque_techno', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Zonages risques naturels', 'zonages_risque_naturel', 'c_risque_zonages_naturel', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Risques', 'risque', 'Zonages risques technologiques', 'zonages_risque_technologique', 'c_risque_zonages_techno', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Sites industriels & production', 'site_industriel_production', 'Mines, carrières & granulats', 'mine_carriere_granulats', 'c_indus_prod_mine_carriere_granul', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Sites industriels & production', 'site_industriel_production', 'Sites éoliens', 'site_eolien', 'c_indus_prod_eolien', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Sites industriels & production', 'site_industriel_production', 'Sites industriels', 'site_industriel', 'c_indus_prod_industriel', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Sites industriels & production', 'site_industriel_production', 'Sites de production d’énergie', 'site_production_energie', 'c_indus_prod_prod_energ', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Socio-économie', 'socio_economie', ' ', ' ', 'c_socio_eco_', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Déplacements', 'transport_deplacement', 'Sécurité routière', 'securite_routiere', 'c_tr_depl_securite_routiere', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Déplacements', 'transport_deplacement', 'Transport collectif', 'tr_collectif', 'c_tr_depl_collectif', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Déplacements', 'transport_deplacement', 'Transport exceptionnel', 'tr_exceptionnel', 'c_tr_depl_exceptionnel', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Déplacements', 'transport_deplacement', 'Transport de marchandises', 'tr_marchandise', 'c_tr_depl_marchandise', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Déplacements', 'transport_deplacement', 'Transport de matières dangereuses', 'tr_matiere_dangereuse', 'c_tr_depl_mat_dangereuse', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Déplacements', 'transport_deplacement', 'Trafic', 'trafic', 'c_tr_depl_trafic', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Aérien', 'aerien', 'c_tr_infra_aerien', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Circulation douce', 'circulation_douce', 'c_tr_infra_circulation_douce', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Ferroviaire', 'ferroviaire', 'c_tr_infra_ferroviaire', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Fluvial', 'fluvial', 'c_tr_infra_fluvial', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Maritime', 'maritime', 'c_tr_infra_maritime', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Plateformes multimodales', 'plateforme_multimodale', 'c_tr_infra_plateforme_multimod', false, 'g_admin', NULL, 'g_consult'),
|
|
('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Routier', 'routier', 'c_tr_infra_routier', false, 'g_admin', NULL, 'g_consult')
|
|
) AS t (bloc, nomenclature, niv1, niv1_abr, niv2, niv2_abr, nom_schema, creation, producteur, editeur, lecteur)
|
|
WHERE domaines IS NULL OR niv1 = ANY(domaines) OR niv1_abr = ANY(domaines)
|
|
LOOP
|
|
-- si le schéma n'était pas déjà référencé, il est ajouté
|
|
-- (toujours comme non créé, même s'il existe par ailleurs dans la base)
|
|
IF NOT item.nom_schema IN (SELECT gestion_schema_usr.nom_schema FROM z_asgard.gestion_schema_usr)
|
|
THEN
|
|
INSERT INTO z_asgard.gestion_schema_usr
|
|
(bloc, nomenclature, niv1, niv1_abr, niv2, niv2_abr, nom_schema, creation, producteur, editeur, lecteur) VALUES
|
|
(item.bloc, item.nomenclature, item.niv1, item.niv1_abr, item.niv2, item.niv2_abr, item.nom_schema, item.creation, item.producteur, item.editeur, item.lecteur) ;
|
|
RAISE NOTICE 'Le schéma % a été ajouté à la table de gestion.', item.nom_schema ;
|
|
|
|
-- sinon les champs de la nomenclature sont simplement mis à jour, le cas échéant
|
|
ELSIF item.nom_schema IN (SELECT gestion_schema_usr.nom_schema FROM z_asgard.gestion_schema_usr)
|
|
THEN
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET nomenclature = item.nomenclature,
|
|
niv1 = item.niv1,
|
|
niv1_abr = item.niv1_abr,
|
|
niv2 = item.niv2,
|
|
niv2_abr = item.niv2_abr
|
|
WHERE gestion_schema_usr.nom_schema = item.nom_schema
|
|
AND (NOT nomenclature = item.nomenclature
|
|
OR NOT coalesce(gestion_schema_usr.niv1, '') = coalesce(item.niv1, '')
|
|
OR NOT coalesce(gestion_schema_usr.niv1_abr, '') = coalesce(item.niv1_abr, '')
|
|
OR NOT coalesce(gestion_schema_usr.niv2, '') = coalesce(item.niv2, '')
|
|
OR NOT coalesce(gestion_schema_usr.niv2_abr, '') = coalesce(item.niv2_abr, '')) ;
|
|
IF FOUND
|
|
THEN
|
|
RAISE NOTICE 'Les champs de la nomenclature ont été mis à jour pour le schéma %.', item.nom_schema ;
|
|
END IF ;
|
|
|
|
END IF ;
|
|
END LOOP ;
|
|
|
|
RETURN '__ FIN IMPORT NOMENCLATURE.' ;
|
|
|
|
EXCEPTION WHEN OTHERS THEN
|
|
GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
|
|
e_hint = PG_EXCEPTION_HINT,
|
|
e_detl = PG_EXCEPTION_DETAIL ;
|
|
RAISE EXCEPTION 'FIN0 > %', e_mssg
|
|
USING DETAIL = e_detl,
|
|
HINT = e_hint ;
|
|
|
|
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard_admin.asgard_import_nomenclature(text[])
|
|
OWNER TO g_admin ;
|
|
|
|
COMMENT ON FUNCTION z_asgard_admin.asgard_import_nomenclature(text[]) IS 'ASGARD. Fonction qui importe dans la table de gestion les schémas manquants de la nomenclature nationale - ou de certains domaines de la nomenclature nationale listés en argument.' ;
|
|
|
|
|
|
------ 4.13 - REAFFECTATION DES PRIVILEGES D'UN RÔLE ------
|
|
|
|
-- FUNCTION: z_asgard_admin.asgard_reaffecte_role(text, text, boolean, boolean)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_reaffecte_role(
|
|
n_role text,
|
|
n_role_cible text DEFAULT NULL,
|
|
b_hors_asgard boolean DEFAULT False,
|
|
b_privileges boolean DEFAULT True)
|
|
RETURNS text
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction transfère tous les privilèges d'un rôle
|
|
à un autre, et en premier lieu ses fonctions de producteur,
|
|
éditeur et lecteur. Si aucun rôle cible n'est spécifié, les
|
|
privilèges sont simplement supprimés et g_admin devient
|
|
producteur des schémas, le cas échéant.
|
|
ARGUMENTS :
|
|
- n_role : une chaîne de caractères présumée correspondre à un nom de
|
|
rôle valide ;
|
|
- n_role_cible : une chaîne de caractères présumée correspondre à un
|
|
nom de rôle valide ;
|
|
- b_hors_asgard : un booléen, valeur par défaut False. Si ce paramètre
|
|
vaut True, la propriété et les privilèges sur les objets des schémas
|
|
non gérés par ASGARD ou hors schémas (par ex la base), sont pris en
|
|
compte. La propriété des objets reviendra à g_admin si aucun
|
|
rôle cible n'est spécifié ;
|
|
- b_privileges : un booléen, valeur par défaut True. Indique si, dans
|
|
l'hypothèse où le rôle cible est spécifié, celui-ci doit recevoir
|
|
les privilèges et propriétés du rôle (True) ou seulement ses propriétés
|
|
(False).
|
|
SORTIE : '__ REAFFECTATION REUSSIE' si la fonction s'est exécutée sans
|
|
erreur. */
|
|
DECLARE
|
|
item record ;
|
|
n_producteur_cible text := coalesce(n_role_cible, 'g_admin') ;
|
|
c record ;
|
|
k int ;
|
|
BEGIN
|
|
|
|
------ TESTS PREALABLES -----
|
|
-- existance du rôle
|
|
IF NOT n_role IN (SELECT rolname FROM pg_catalog.pg_roles)
|
|
THEN
|
|
RAISE EXCEPTION 'FRR1. Echec. Le rôle % n''existe pas', n_role ;
|
|
END IF ;
|
|
|
|
-- existance du rôle cible
|
|
IF n_role_cible IS NOT NULL AND NOT n_role_cible IN (SELECT rolname FROM pg_catalog.pg_roles)
|
|
THEN
|
|
RAISE EXCEPTION 'FRR2. Echec. Le rôle % n''existe pas', n_role_cible ;
|
|
END IF ;
|
|
|
|
|
|
IF NOT b_privileges
|
|
THEN
|
|
n_role_cible := NULL ;
|
|
END IF ;
|
|
|
|
------ FONCTION DE PRODUCTEUR ------
|
|
FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE producteur = n_role)
|
|
LOOP
|
|
IF item.editeur = n_producteur_cible
|
|
THEN
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET editeur = NULL
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... L''éditeur du schéma % a été supprimé.', item.nom_schema ;
|
|
END IF ;
|
|
|
|
IF item.lecteur = n_producteur_cible
|
|
THEN
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET lecteur = NULL
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
|
|
END IF ;
|
|
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET producteur = n_role_cible
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... Le producteur du schéma % a été redéfini.', item.nom_schema ;
|
|
END LOOP ;
|
|
|
|
------ FONCTION D'EDITEUR ------
|
|
-- seulement si le rôle cible n'est pas déjà producteur du schéma
|
|
FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE editeur = n_role)
|
|
LOOP
|
|
IF item.producteur = n_role_cible
|
|
THEN
|
|
RAISE NOTICE 'Le rôle cible est actuellement producteur du schéma %.', item.nom_schema ;
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET editeur = NULL
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... L''éditeur du schéma % a été supprimé.', item.nom_schema ;
|
|
ELSE
|
|
|
|
IF item.lecteur = n_role_cible
|
|
THEN
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET lecteur = NULL
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
|
|
END IF ;
|
|
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET editeur = n_role_cible
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... L''éditeur du schéma % a été redéfini.', item.nom_schema ;
|
|
|
|
END IF ;
|
|
END LOOP ;
|
|
|
|
------ FONCTION DE LECTEUR ------
|
|
-- seulement si le rôle cible n'est pas déjà producteur ou éditeur du schéma
|
|
FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE lecteur = n_role)
|
|
LOOP
|
|
IF item.producteur = n_role_cible
|
|
THEN
|
|
RAISE NOTICE 'Le rôle cible est actuellement producteur du schéma %.', item.nom_schema ;
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET lecteur = NULL
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
|
|
ELSIF item.editeur = n_role_cible
|
|
THEN
|
|
RAISE NOTICE 'Le rôle cible est actuellement éditeur du schéma %.', item.nom_schema ;
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET lecteur = NULL
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
|
|
ELSE
|
|
|
|
UPDATE z_asgard.gestion_schema_usr
|
|
SET lecteur = n_role_cible
|
|
WHERE nom_schema = item.nom_schema ;
|
|
RAISE NOTICE '... Le lecteur du schéma % a été redéfini.', item.nom_schema ;
|
|
|
|
END IF ;
|
|
END LOOP ;
|
|
|
|
------ PROPRIETES HORS ASGARD ------
|
|
IF b_hors_asgard
|
|
THEN
|
|
EXECUTE 'REASSIGN OWNED BY ' || quote_ident(n_role) || ' TO ' || quote_ident(n_producteur_cible) ;
|
|
RAISE NOTICE '> %', 'REASSIGN OWNED BY ' || quote_ident(n_role) || ' TO ' || quote_ident(n_producteur_cible) ;
|
|
RAISE NOTICE '... Le cas échéant, la propriété des objets hors schémas référencés par ASGARD a été réaffectée.' ;
|
|
END IF ;
|
|
|
|
------ PRIVILEGES RESIDUELS SUR LES SCHEMAS D'ASGARD -------
|
|
k := 0 ;
|
|
FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE creation)
|
|
LOOP
|
|
FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role(
|
|
quote_ident(item.nom_schema)::regnamespace, quote_ident(n_role)::regrole))
|
|
LOOP
|
|
EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
|
|
RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
|
|
|
|
IF n_role_cible IS NOT NULL
|
|
THEN
|
|
EXECUTE format(c.commande, n_role_cible) ;
|
|
RAISE NOTICE '> %', format(c.commande, n_role_cible) ;
|
|
END IF ;
|
|
|
|
k := k + 1 ;
|
|
END LOOP ;
|
|
END LOOP ;
|
|
IF k > 0
|
|
THEN
|
|
IF n_role_cible IS NULL
|
|
THEN
|
|
RAISE NOTICE '... Les privilèges résiduels du rôle % sur les schémas référencés par ASGARD ont été révoqués.', n_role ;
|
|
ELSE
|
|
RAISE NOTICE '... Les privilèges résiduels du rôle % sur les schémas référencés par ASGARD ont été réaffectés.', n_role ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
------ PRIVILEGES RESIDUELS SUR LES SCHEMAS HORS ASGARD ------
|
|
IF b_hors_asgard
|
|
THEN
|
|
k := 0 ;
|
|
FOR item IN (SELECT * FROM pg_catalog.pg_namespace
|
|
LEFT JOIN z_asgard.gestion_schema_usr
|
|
ON nspname::text = nom_schema AND creation
|
|
WHERE nom_schema IS NULL)
|
|
LOOP
|
|
FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role(
|
|
quote_ident(item.nspname::text)::regnamespace, quote_ident(n_role)::regrole))
|
|
LOOP
|
|
EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
|
|
RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
|
|
|
|
IF n_role_cible IS NOT NULL
|
|
THEN
|
|
EXECUTE format(c.commande, n_role_cible) ;
|
|
RAISE NOTICE '> %', format(c.commande, n_role_cible) ;
|
|
END IF ;
|
|
|
|
k := k + 1 ;
|
|
END LOOP ;
|
|
END LOOP ;
|
|
IF k > 0
|
|
THEN
|
|
IF n_role_cible IS NULL
|
|
THEN
|
|
RAISE NOTICE '... Les privilèges résiduels du rôle % sur les schémas non référencés par ASGARD ont été révoqués.', n_role ;
|
|
ELSE
|
|
RAISE NOTICE '... Les privilèges résiduels du rôle % sur les schémas non référencés par ASGARD ont été réaffectés.', n_role ;
|
|
END IF ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
------- OBJETS HORS SCHEMAS ------
|
|
IF b_hors_asgard
|
|
THEN
|
|
k := 0 ;
|
|
FOR c IN (
|
|
WITH t_acl AS (
|
|
-- bases de données
|
|
SELECT 'DATABASE'::text AS type_obj, datname::text AS n_obj, unnest(datacl)::text AS acl
|
|
FROM pg_catalog.pg_database
|
|
WHERE datacl IS NOT NULL
|
|
UNION
|
|
-- tablespaces
|
|
SELECT 'TABLESPACE'::text AS type_obj, spcname::text AS n_obj, unnest(spcacl)::text AS acl
|
|
FROM pg_catalog.pg_tablespace
|
|
WHERE spcacl IS NOT NULL
|
|
UNION
|
|
-- foreign data wrappers
|
|
SELECT 'FOREIGN DATA WRAPPER'::text AS type_obj, fdwname::text AS n_obj, unnest(fdwacl)::text AS acl
|
|
FROM pg_catalog.pg_foreign_data_wrapper
|
|
WHERE fdwacl IS NOT NULL
|
|
UNION
|
|
-- foreign servers
|
|
SELECT 'FOREIGN SERVER'::text AS type_obj, srvname::text AS n_obj, unnest(srvacl)::text AS acl
|
|
FROM pg_catalog.pg_foreign_server
|
|
WHERE srvacl IS NOT NULL
|
|
UNION
|
|
-- langages
|
|
SELECT 'LANGUAGE'::text AS type_obj, lanname::text AS n_obj, unnest(lanacl)::text AS acl
|
|
FROM pg_catalog.pg_language
|
|
WHERE lanacl IS NOT NULL
|
|
UNION
|
|
-- large objects
|
|
SELECT 'LARGE OBJECT'::text AS type_obj, pg_largeobject_metadata.oid::text AS n_obj, unnest(lomacl)::text AS acl
|
|
FROM pg_catalog.pg_largeobject_metadata
|
|
WHERE lomacl IS NOT NULL
|
|
)
|
|
SELECT 'GRANT ' || privilege || ' ON ' || type_obj || ' ' || quote_ident(n_obj) || ' TO %I' AS commande
|
|
FROM t_acl, unnest(ARRAY['CREATE', 'CONNECT', 'TEMPORARY', 'USAGE', 'SELECT', 'UPDATE'],
|
|
ARRAY['C', 'c', 'T', 'U', 'r', 'w']) AS l (privilege, prvlg)
|
|
WHERE acl ~ ('^' || quote_ident(n_role)::regrole::text || '[=].*' || prvlg || '.*[/]')
|
|
) LOOP
|
|
EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
|
|
RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
|
|
|
|
IF n_role_cible IS NOT NULL
|
|
THEN
|
|
EXECUTE format(c.commande, n_role_cible) ;
|
|
RAISE NOTICE '> %', format(c.commande, n_role_cible) ;
|
|
END IF ;
|
|
|
|
k := k + 1 ;
|
|
END LOOP ;
|
|
IF k > 0
|
|
THEN
|
|
IF n_role_cible IS NULL
|
|
THEN
|
|
RAISE NOTICE '... Les privilèges résiduels du rôle % sur les objets hors schémas ont été révoqués.', n_role ;
|
|
ELSE
|
|
RAISE NOTICE '... Les privilèges résiduels du rôle % sur les objets hors schémas ont été réaffectés.', n_role ;
|
|
END IF ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
RETURN '__ REAFFECTATION REUSSIE' ;
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard_admin.asgard_reaffecte_role(text, text, boolean, boolean)
|
|
OWNER TO g_admin ;
|
|
|
|
COMMENT ON FUNCTION z_asgard_admin.asgard_reaffecte_role(text, text, boolean, boolean) IS 'ASGARD. Fonction qui réaffecte les privilèges et propriétés d''un rôle à un autre.' ;
|
|
|
|
|
|
------ 4.14 - REINITIALISATION DES PRIVILEGES SUR TOUS LES SCHEMAS ------
|
|
|
|
-- FUNCTION: z_asgard_admin.asgard_initialise_all_schemas(integer)
|
|
|
|
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_initialise_all_schemas(variante integer DEFAULT 0)
|
|
RETURNS varchar[]
|
|
LANGUAGE plpgsql
|
|
AS $_$
|
|
/* OBJET : Cette fonction réinitialise les privilèges sur tous les
|
|
schémas référencés par ASGARD en une seule commande.
|
|
Pour les schémas d'ASGARD, même s'ils n'ont pas été référencés,
|
|
les droits nécessaires au bon fonctionnement du système seront
|
|
rétablis.
|
|
ARGUMENTS : un entier optionnel - 0 par défaut.
|
|
Si 1, la fonction ne fera que s'assurer que tous les objets appartiennent
|
|
au propriétaire du schéma. Si 2, la fonction ne s'exécutera que sur les
|
|
schémas d'ASGARD.
|
|
SORTIE : NULL si la requête s'est exécutée normalement, sinon la liste
|
|
des schémas qui n'ont pas pu être traités. Se reporter dans ce cas à
|
|
l'onglet des messages pour le détail des erreurs. */
|
|
DECLARE
|
|
s record ;
|
|
l varchar[] ;
|
|
b boolean ;
|
|
k integer ;
|
|
e_mssg text ;
|
|
e_detl text ;
|
|
e_hint text ;
|
|
utilisateur text := current_user::text ;
|
|
v_prop oid ;
|
|
t text ;
|
|
BEGIN
|
|
|
|
------ CONTROLES PREALABLES ------
|
|
-- la fonction est dans z_asgard_admin, donc seuls les membres de
|
|
-- g_admin devraient pouvoir y accéder, mais au cas où :
|
|
IF NOT pg_has_role('g_admin', 'USAGE')
|
|
THEN
|
|
RAISE EXCEPTION 'FAS1. Opération interdite. Vous devez être membre de g_admin pour exécuter cette fonction.' ;
|
|
END IF ;
|
|
|
|
IF NOT utilisateur IN (SELECT rolname FROM pg_catalog.pg_roles WHERE rolsuper)
|
|
THEN
|
|
SET ROLE g_admin ;
|
|
END IF ;
|
|
|
|
-- permission manquante du propriétaire de la vue gestion_schema_usr
|
|
-- (en principe g_admin_ext) sur le schéma z_asgard_admin ou la table
|
|
-- gestion_schema :
|
|
SELECT relowner INTO v_prop
|
|
FROM pg_catalog.pg_class
|
|
WHERE relname = 'gestion_schema_usr' AND relnamespace = 'z_asgard'::regnamespace::oid ;
|
|
|
|
IF NOT FOUND
|
|
THEN
|
|
RAISE EXCEPTION 'FAS2. Echec. La vue gestion_schema_usr est introuvable.' ;
|
|
END IF ;
|
|
|
|
IF NOT has_schema_privilege(v_prop, 'z_asgard_admin', 'USAGE')
|
|
OR NOT has_table_privilege(v_prop, 'z_asgard_admin.gestion_schema', 'SELECT')
|
|
THEN
|
|
RAISE NOTICE '(temporaire) droits a minima pour le propriétaire de la vue gestion_schema_usr :' ;
|
|
|
|
IF NOT has_schema_privilege(v_prop, 'z_asgard_admin', 'USAGE')
|
|
THEN
|
|
t := 'GRANT USAGE ON SCHEMA z_asgard_admin TO ' || v_prop::regrole::text ;
|
|
EXECUTE t ;
|
|
RAISE NOTICE '> %', t ;
|
|
END IF ;
|
|
|
|
IF NOT has_table_privilege(v_prop, 'z_asgard_admin.gestion_schema', 'SELECT')
|
|
THEN
|
|
t := 'GRANT SELECT ON TABLE z_asgard_admin.gestion_schema TO ' || v_prop::regrole::text ;
|
|
EXECUTE t ;
|
|
RAISE NOTICE '> %', t ;
|
|
END IF ;
|
|
|
|
RAISE NOTICE '---------------------------------' ;
|
|
END IF ;
|
|
|
|
------ NETTOYAGE ------
|
|
FOR s IN (
|
|
SELECT 2 AS n, nom_schema, producteur
|
|
FROM z_asgard.gestion_schema_usr
|
|
WHERE creation AND NOT nom_schema IN ('z_asgard', 'z_asgard_admin')
|
|
UNION VALUES (1, 'z_asgard', 'g_admin_ext'), (0, 'z_asgard_admin', 'g_admin')
|
|
ORDER BY n, nom_schema
|
|
)
|
|
LOOP
|
|
b := True ;
|
|
|
|
IF s.n < 2 OR variante < 2
|
|
THEN
|
|
|
|
------ CONTROLE DES PRIVILEGES DE G_ADMIN SUR LE PRODUCTEUR ------
|
|
-- si g_admin n'est pas membre du producteur, alors on l'en rend
|
|
-- membre, sous réserve que ce ne soit pas un super-utilisateur ou
|
|
-- un rôle de connexion (ce dernier cas n'étant pas supposé arriver,
|
|
-- sauf désactivation temporaire de triggers ou à avoir donné
|
|
-- LOGIN au rôle après l'avoir désigné comme producteur).
|
|
IF NOT pg_has_role(s.producteur, 'USAGE')
|
|
THEN
|
|
-- propriétaire super-utilisateur
|
|
IF s.producteur IN (SELECT rolname FROM pg_catalog.pg_roles WHERE rolsuper)
|
|
THEN
|
|
RAISE NOTICE '... ECHEC. Schéma % non traité.', s.nom_schema
|
|
USING DETAIL = 'Seul un super-utilisateur est habilité à intervenir sur ce schéma. Producteur : ' || s.producteur || '.',
|
|
HINT = 'Veuillez relancer la fonction en tant que super-utilisateur.' ;
|
|
b := False ;
|
|
l := array_append(l, s.nom_schema) ;
|
|
|
|
-- propriétaire rôle de connexion
|
|
ELSIF s.producteur IN (SELECT rolname FROM pg_catalog.pg_roles WHERE rolcanlogin)
|
|
THEN
|
|
RAISE NOTICE '... ECHEC. Schéma % non traité.', s.nom_schema
|
|
USING DETAIL = 'Le producteur du schéma est un rôle de connexion. Producteur : ' || s.producteur || '.',
|
|
HINT = 'Veuillez relancer la fonction en tant que super-utilisateur ou après avoir désigné un rôle de groupe comme producteur.' ;
|
|
b := False ;
|
|
l := array_append(l, s.nom_schema) ;
|
|
|
|
-- rôle de groupe lambda sur lequel g_admin n'a pas de permission
|
|
-- on la lui donne et on continue
|
|
ELSE
|
|
EXECUTE 'GRANT ' || quote_ident(s.producteur) || ' TO g_admin' ;
|
|
RAISE NOTICE '... Permission accordée à g_admin sur le rôle %.', s.producteur ;
|
|
END IF ;
|
|
END IF ;
|
|
|
|
IF b
|
|
THEN
|
|
BEGIN
|
|
IF variante = 1
|
|
THEN
|
|
-- lancement de la fonction de nettoyage des propriétaires
|
|
IF quote_ident(s.producteur) IN (SELECT nspowner::regrole::text FROM pg_catalog.pg_namespace WHERE nspname = s.nom_schema)
|
|
THEN
|
|
-- version objets seuls si le propriétaire du schéma est bon
|
|
RAISE NOTICE '(ré)attribution de la propriété des objets au rôle producteur du schéma :' ;
|
|
SELECT z_asgard.asgard_admin_proprietaire(s.nom_schema, s.producteur, False) INTO k ;
|
|
IF k = 0
|
|
THEN
|
|
RAISE NOTICE '> néant' ;
|
|
END IF ;
|
|
ELSE
|
|
-- version schéma + objets sinon
|
|
RAISE NOTICE '(ré)attribution de la propriété du schéma et des objets au rôle producteur du schéma :' ;
|
|
PERFORM z_asgard.asgard_admin_proprietaire(s.nom_schema, s.producteur) ;
|
|
END IF ;
|
|
|
|
ELSE
|
|
-- lancement de la fonction de réinitialisation des droits
|
|
PERFORM z_asgard.asgard_initialise_schema(s.nom_schema) ;
|
|
|
|
END IF ;
|
|
|
|
RAISE NOTICE '... Le schéma % a été traité', s.nom_schema ;
|
|
|
|
EXCEPTION WHEN OTHERS THEN
|
|
GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
|
|
e_hint = PG_EXCEPTION_HINT,
|
|
e_detl = PG_EXCEPTION_DETAIL ;
|
|
RAISE NOTICE '... ECHEC. Schéma % non traité.', s.nom_schema ;
|
|
RAISE NOTICE 'FAS0 > %', e_mssg
|
|
USING DETAIL = e_detl,
|
|
HINT = e_hint ;
|
|
l := array_append(l, s.nom_schema) ;
|
|
END ;
|
|
END IF ;
|
|
|
|
RAISE NOTICE '---------------------------------' ;
|
|
END IF ;
|
|
|
|
END LOOP ;
|
|
|
|
EXECUTE 'SET ROLE ' || quote_ident(utilisateur) ;
|
|
|
|
------ RESULTAT ------
|
|
RETURN l ;
|
|
|
|
END
|
|
$_$;
|
|
|
|
ALTER FUNCTION z_asgard_admin.asgard_initialise_all_schemas(integer)
|
|
OWNER TO g_admin ;
|
|
|
|
COMMENT ON FUNCTION z_asgard_admin.asgard_initialise_all_schemas(integer) IS 'ASGARD. Fonction qui réinitialise les droits sur l''ensemble des schémas référencés.' ;
|
|
|