Projet

Général

Profil

Evolution #315 » asgard_4_fonctions_utilitaires_v10.sql

Leslie Lemaire, 31/08/2020 14:00

 
1

    
2
-- v0 2020.05.07 AF
3
-- v1 2020.05.15 LL
4
-- v2 2020.05.19 LL
5
-- v3 2020.05.25 LL
6
-- v4 2020.05.27 LL
7
-- v5 2020.05.28 LL
8
-- v6 2020.05.30 LL
9
-- v7 2020.06.05/19 LL (asgard 0.7.0)
10
-- v8 2020.06.26/29 LL (asgard 0.7.1)
11
-- v9 2020.08.11 LL (asgard 1.0.0)
12
-- v10 2020.08.30 LL (asgard 1.0.0)
13
/*
14
- fonction d'import de la nomenclature : nomenclature
15
explicite, import pour les schémas existants dans la base,
16
fonctionnalité de mise à jour.
17
- simplification de la structuration des remontées d'erreurs pour
18
asgard_initialisation_gestion_schema, asgard_sortie_gestion_schema,
19
asgard_nettoyage_roles, asgard_import_nomenclature et
20
asgard_initialise_schema (ajout d'un contrôle d'erreurs).
21
- ajout d'un contrôle des privilèges sur l'objet dans
22
asgard_admin_proprietaire.
23
- ajout d'une fonction de réinitialisation des droits
24
sur l'ensemble des schémas référencés ;
25
- sécurisation de la fonction asgard_initialise_schema, qui,
26
lorsqu'elle est appliquées aux schémas d'ASGARD, n'efface
27
plus les privilèges essentiels au fonctionnement d'ASGARD.
28
 */
29

    
30

    
31
-- MOT DE PASSE DE CONTRÔLE : 'x7-A;#rzo'
32
-- peut être modifié sans risque par rechercher/remplacer
33

    
34
---------------------------------------
35
------ 4 - FONCTIONS UTILITAIRES ------
36
---------------------------------------
37
/* 4.1 - LISTES DES DROITS SUR LES OBJETS D'UN SCHEMA
38
   4.2 - LISTE DES DROITS SUR UN OBJET
39
   4.3 - MODIFICATION DU PROPRIETAIRE D'UN SCHEMA ET SON CONTENU
40
   4.4 - TRANSFORMATION GRANT EN REVOKE
41
   4.5 - INITIALISATION DE GESTION_SCHEMA
42
   4.6 - DEREFERENCEMENT D'UN SCHEMA
43
   4.7 - NETTOYAGE DES RÔLES
44
   4.8 - REINITIALISATION DES PRIVILEGES SUR UN SCHEMA
45
   4.9 - REINITIALISATION DES PRIVILEGES SUR UN OBJET
46
   4.10 - DEPLACEMENT D'OBJET
47
   4.11 - OCTROI D'UN RÔLE À TOUS LES RÔLES DE CONNEXION
48
   4.12 - IMPORT DE LA NOMENCLATURE DANS GESTION_SCHEMA
49
   4.13 - REAFFECTATION DES PRIVILEGES D'UN RÔLE
50
   4.14 - REINITIALISATION DES PRIVILEGES SUR TOUS LES SCHEMAS */
51

    
52

    
53
------ 4.1 - LISTES DES DROITS SUR LES OBJETS D'UN SCHEMA ------
54

    
55
-- FUNCTION: z_asgard.asgard_synthese_role(regnamespace, regrole)
56

    
57
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_role(n_schema regnamespace, n_role regrole)
58
    RETURNS TABLE(commande text)
59
    LANGUAGE plpgsql
60
    AS $_$
61
/* OBJET : Cette fonction renvoie une table contenant une
62
           liste de commandes GRANT et REVOKE permettant de
63
           recréer les droits de "role_1" sur les objets du
64
           schéma "schema" (et le schéma lui-même).
65
ARGUMENTS :
66
- "schema" est un nom de schéma valide, casté en regnamespace ;
67
- "role_1" est un nom de rôle valide, casté en regrole.
68
SORTIE : Une table avec un unique champ nommé "commande". */
69
DECLARE
70
    n_role_trans text := n_role::text ;
71
BEGIN
72
    ------ SCHEMAS ------
73
    -- privilèges attribués (hors propriétaire) :
74
    RETURN QUERY
75
        WITH t_acl AS (
76
        SELECT unnest(nspacl)::text AS acl
77
            FROM pg_catalog.pg_namespace
78
            WHERE oid = n_schema::oid
79
                AND nspacl IS NOT NULL
80
                AND NOT n_role::oid = nspowner
81
        )
82
        SELECT 'GRANT ' || privilege || ' ON SCHEMA ' || n_schema::text || ' TO %I'
83
            FROM t_acl, unnest(ARRAY['USAGE', 'CREATE'], ARRAY['U', 'C']) AS l (privilege, prvlg)
84
            WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
85
    -- privilèges révoqués du propriétaire :
86
    RETURN QUERY
87
        WITH t_acl AS (
88
        SELECT oid, unnest(CASE WHEN nspacl::text[] = ARRAY[]::text[]
89
                               OR NOT array_to_string(nspacl, ',') ~ ('^' || n_role_trans || '[=]')
90
                                   AND NOT array_to_string(nspacl, ',') ~ ('[,]' || n_role_trans || '[=]')
91
                           THEN ARRAY[NULL]::text[]
92
                           ELSE nspacl::text[] END) AS acl
93
            FROM pg_catalog.pg_namespace
94
            WHERE oid = n_schema::oid
95
                AND n_role::oid = nspowner
96
                AND nspacl IS NOT NULL
97
        )
98
        SELECT 'REVOKE ' || privilege || ' ON SCHEMA ' || n_schema::text || ' FROM %I'
99
            FROM t_acl, unnest(ARRAY['USAGE', 'CREATE'], ARRAY['U', 'C']) AS l (privilege, prvlg)
100
            WHERE (acl ~ ('^' || n_role_trans || '[=]')
101
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
102
    ------ TABLES ------
103
    -- inclut les vues, vues matérialisées, tables étrangères et partitions
104
    -- privilèges attribués (hors propriétaire) :
105
    RETURN QUERY
106
        WITH t_acl AS (
107
        SELECT oid, unnest(relacl)::text AS acl
108
            FROM pg_catalog.pg_class
109
            WHERE relnamespace = n_schema
110
                AND relkind IN ('r', 'v', 'm', 'f', 'p')
111
                AND relacl IS NOT NULL
112
                AND NOT n_role::oid = relowner
113
        )
114
        SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
115
            FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
116
                                     'TRUNCATE', 'REFERENCES', 'TRIGGER'],
117
                               ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
118
            WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
119
    -- privilèges révoqués du propriétaire :
120
    RETURN QUERY
121
        WITH t_acl AS (
122
        SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
123
                               OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
124
                                   AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
125
                           THEN ARRAY[NULL]::text[]
126
                           ELSE relacl::text[] END) AS acl
127
            FROM pg_catalog.pg_class
128
            WHERE relnamespace = n_schema
129
                AND relacl IS NOT NULL
130
                AND relkind IN ('r', 'v', 'm', 'f', 'p')
131
                AND n_role::oid = relowner
132
        )
133
        SELECT 'REVOKE ' || privilege || ' ON TABLE ' || oid::regclass::text || ' FROM %I'
134
            FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
135
                                     'TRUNCATE', 'REFERENCES', 'TRIGGER'],
136
                               ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
137
            WHERE (acl ~ ('^' || n_role_trans || '[=]')
138
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
139
    ------ SEQUENCES ------
140
    -- privilèges attribués (hors propriétaire) :
141
    RETURN QUERY
142
        WITH t_acl AS (
143
        SELECT oid, unnest(relacl)::text AS acl
144
            FROM pg_catalog.pg_class
145
            WHERE relnamespace = n_schema
146
                AND relkind = 'S'
147
                AND relacl IS NOT NULL
148
                AND NOT n_role::oid = relowner
149
        )
150
        SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
151
            FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
152
                               ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
153
            WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
154
    -- privilèges révoqués du propriétaire :
155
    RETURN QUERY
156
        WITH t_acl AS (
157
        SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
158
                               OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
159
                                   AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
160
                           THEN ARRAY[NULL]::text[]
161
                           ELSE relacl::text[] END) AS acl
162
            FROM pg_catalog.pg_class
163
            WHERE relnamespace = n_schema
164
                AND relacl IS NOT NULL
165
                AND relkind = 'S'
166
                AND n_role::oid = relowner
167
        )
168
        SELECT 'REVOKE ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' FROM %I'
169
            FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
170
                               ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
171
            WHERE (acl ~ ('^' || n_role_trans || '[=]')
172
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
173
    ------ COLONNES ------
174
    -- privilèges attribués :
175
    RETURN QUERY
176
        WITH t_acl AS (
177
        SELECT attname, attrelid, unnest(attacl)::text AS acl
178
            FROM pg_catalog.pg_class JOIN pg_catalog.pg_attribute
179
                     ON pg_class.oid = pg_attribute.attrelid
180
            WHERE relnamespace = n_schema
181
                AND attacl IS NOT NULL
182
        )
183
        SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
184
                || attrelid::regclass::text || ' TO %I'
185
            FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
186
                               ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
187
            WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
188
    ------ FONCTIONS ------
189
    -- inclut les fonctions d'agrégation
190
    -- privilèges attribués (hors propriétaire) :
191
    RETURN QUERY
192
        WITH t_acl AS (
193
        SELECT oid, unnest(proacl)::text AS acl
194
            FROM pg_catalog.pg_proc
195
            WHERE pronamespace = n_schema
196
                AND proacl IS NOT NULL
197
                AND NOT n_role::oid = proowner
198
        )
199
        SELECT 'GRANT ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' TO %I'
200
            FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
201
            WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
202
    -- privilèges révoqués du propriétaire :
203
    RETURN QUERY
204
        WITH t_acl AS (
205
        SELECT oid, unnest(CASE WHEN proacl::text[] = ARRAY[]::text[]
206
                               OR NOT array_to_string(proacl, ',') ~ ('^' || n_role_trans || '[=]')
207
                                   AND NOT array_to_string(proacl, ',') ~ ('[,]' || n_role_trans || '[=]')
208
                           THEN ARRAY[NULL]::text[]
209
                           ELSE proacl::text[] END) AS acl
210
            FROM pg_catalog.pg_proc
211
            WHERE pronamespace = n_schema
212
                AND n_role::oid = proowner
213
                AND proacl IS NOT NULL
214
        )
215
        SELECT 'REVOKE ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' FROM %I'
216
            FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
217
            WHERE (acl ~ ('^' || n_role_trans || '[=]')
218
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
219
    ------ TYPES ------
220
    -- inclut les domaines
221
    -- privilèges attribués (hors propriétaire) :
222
    RETURN QUERY
223
        WITH t_acl AS (
224
        SELECT oid, unnest(typacl)::text AS acl
225
            FROM pg_catalog.pg_type
226
            WHERE typnamespace = n_schema
227
                AND typacl IS NOT NULL
228
                AND NOT n_role::oid = typowner
229
        )
230
        SELECT 'GRANT ' || privilege || ' ON TYPE ' || oid::regtype::text || ' TO %I'
231
            FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
232
            WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
233
    -- privilèges révoqués du propriétaire :
234
    RETURN QUERY
235
        WITH t_acl AS (
236
        SELECT oid, unnest(CASE WHEN typacl::text[] = ARRAY[]::text[]
237
                               OR NOT array_to_string(typacl, ',') ~ ('^' || n_role_trans || '[=]')
238
                                   AND NOT array_to_string(typacl, ',') ~ ('[,]' || n_role_trans || '[=]')
239
                           THEN ARRAY[NULL]::text[]
240
                           ELSE typacl::text[] END) AS acl
241
            FROM pg_catalog.pg_type
242
            WHERE typnamespace = n_schema
243
                AND n_role::oid = typowner
244
                AND typacl IS NOT NULL
245
        )
246
        SELECT 'REVOKE ' || privilege || ' ON TYPE ' || oid::regtype::text || ' FROM %I'
247
            FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
248
            WHERE (acl ~ ('^' || n_role_trans || '[=]')
249
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
250
END
251
$_$;
252

    
253
ALTER FUNCTION z_asgard.asgard_synthese_role(regnamespace, regrole)
254
    OWNER TO g_admin_ext ;
255

    
256
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.' ;
257

    
258

    
259
-- FUNCTION: z_asgard.asgard_synthese_public(regnamespace)
260

    
261
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_public(n_schema regnamespace)
262
    RETURNS TABLE(commande text)
263
    LANGUAGE plpgsql
264
    AS $_$
265
/* OBJET : Cette fonction renvoie une table contenant une
266
           liste de commandes GRANT et REVOKE permettant de
267
           recréer les droits de public sur les objets du
268
           schéma "schema" (et le schéma lui-même).
269
REMARQUE : La fonction ne s'intéresse pas aux objets de type
270
fonction (dont agrégats) et type (dont domaines), sur lesquels
271
public reçoit des droits par défaut qu'il n'est pas judicieux
272
de reproduire sur un autre rôle, ni de révoquer lors d'un
273
changement de lecteur/éditeur. Si des privilèges par défaut ont
274
été révoqués pour public, la révocation restera valable pour les
275
futurs lecteur/éditeurs puisqu'il n'y a pas d'attribution
276
de privilèges supplémentaires pour les lecteurs/éditeurs sur
277
ces objets.
278
ARGUMENT : "schema" est un nom de schéma valide, casté en
279
regnamespace.
280
SORTIE : Une table avec un unique champ nommé "commande". */
281
BEGIN
282
    ------ SCHEMAS ------
283
    RETURN QUERY
284
        WITH t_acl AS (
285
        SELECT unnest(nspacl)::text AS acl
286
            FROM pg_catalog.pg_namespace
287
            WHERE oid = n_schema::oid
288
                AND nspacl IS NOT NULL
289
        )
290
        SELECT 'GRANT ' || privilege || ' ON SCHEMA ' || n_schema::text || ' TO %I'
291
            FROM t_acl, unnest(ARRAY['USAGE', 'CREATE'], ARRAY['U', 'C']) AS l (privilege, prvlg)
292
            WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
293
    ------ TABLES ------
294
    -- inclut les vues, vues matérialisées, tables étrangères et partitions
295
    RETURN QUERY
296
        WITH t_acl AS (
297
        SELECT oid, unnest(relacl)::text AS acl
298
            FROM pg_catalog.pg_class
299
            WHERE relnamespace = n_schema
300
                AND relkind IN ('r', 'v', 'm', 'f', 'p')
301
                AND relacl IS NOT NULL
302
        )
303
        SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
304
            FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
305
                                     'TRUNCATE', 'REFERENCES', 'TRIGGER'],
306
                               ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
307
            WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
308
    ------ SEQUENCES ------
309
    RETURN QUERY
310
        WITH t_acl AS (
311
        SELECT oid, unnest(relacl)::text AS acl
312
            FROM pg_catalog.pg_class
313
            WHERE relnamespace = n_schema
314
                AND relkind = 'S'
315
                AND relacl IS NOT NULL
316
        )
317
        SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
318
            FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
319
                               ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
320
            WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
321
    ------ COLONNES ------
322
    RETURN QUERY
323
        WITH t_acl AS (
324
        SELECT attname, attrelid, unnest(attacl)::text AS acl
325
            FROM pg_catalog.pg_class JOIN pg_catalog.pg_attribute
326
                     ON pg_class.oid = pg_attribute.attrelid
327
            WHERE relnamespace = n_schema
328
                AND attacl IS NOT NULL
329
        )
330
        SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
331
                || attrelid::regclass::text || ' TO %I'
332
            FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
333
                               ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
334
            WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
335
END
336
$_$;
337

    
338
ALTER FUNCTION z_asgard.asgard_synthese_public(regnamespace)
339
    OWNER TO g_admin_ext ;
340

    
341
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.' ;
342

    
343

    
344

    
345

    
346
------ 4.2 - LISTE DES DROITS SUR UN OBJET ------
347

    
348
-- FUNCTION: z_asgard.asgard_synthese_role_obj(oid, text, regrole)
349

    
350
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_role_obj(obj_oid oid, obj_type text, n_role regrole)
351
    RETURNS TABLE(commande text)
352
    LANGUAGE plpgsql
353
    AS $_$
354
/* OBJET : Cette fonction renvoie une table contenant une
355
           liste de commandes GRANT et REVOKE permettant de
356
           recréer les droits de "role_1" sur un objet de type
357
		   table, table étrangère, partition de table, vue,
358
           vue matérialisée, séquence, fonction (dont fonctions
359
           d'agrégations), type (dont domaines).
360
ARGUMENTS :
361
- "obj_oid" est l'identifiant interne de l'objet ;
362
- "obj_type" est le type de l'objet au format text ('table',
363
'view', 'materialized view', 'sequence', 'function', 'type',
364
'domain', 'foreign table', 'partitioned table', 'aggregate') ;
365
- "role_1" est un nom de rôle valide, casté en regrole.
366
SORTIE : Une table avec un unique champ nommé "commande". */
367
DECLARE
368
    n_role_trans text := n_role::text ;
369
BEGIN
370
    ------ TABLE, VUE, VUE MATERIALISEE ------
371
    IF obj_type IN ('table', 'view', 'materialized view', 'foreign table', 'partitioned table')
372
    THEN
373
        -- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
374
        RETURN QUERY
375
            WITH t_acl AS (
376
            SELECT oid, unnest(relacl)::text AS acl
377
                FROM pg_catalog.pg_class
378
                WHERE oid = obj_oid
379
                    AND relacl IS NOT NULL
380
                    AND NOT n_role::oid = relowner
381
            )
382
            SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
383
                FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
384
                                         'TRUNCATE', 'REFERENCES', 'TRIGGER'],
385
                                   ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
386
                WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
387
        -- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
388
        RETURN QUERY
389
            WITH t_acl AS (
390
            SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
391
                                   OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
392
                                       AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
393
                               THEN ARRAY[NULL]::text[]
394
                               ELSE relacl::text[] END) AS acl
395
                FROM pg_catalog.pg_class
396
                WHERE oid = obj_oid
397
                    AND relacl IS NOT NULL
398
                    AND n_role::oid = relowner
399
            )
400
            SELECT 'REVOKE ' || privilege || ' ON TABLE ' || oid::regclass::text || ' FROM %I'
401
                FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
402
                                         'TRUNCATE', 'REFERENCES', 'TRIGGER'],
403
                                   ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
404
                WHERE (acl ~ ('^' || n_role_trans || '[=]')
405
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
406
        ------ COLONNES ------
407
        -- privilèges attribués :
408
        RETURN QUERY
409
            WITH t_acl AS (
410
            SELECT attname, attrelid, unnest(attacl)::text AS acl
411
                FROM pg_catalog.pg_attribute
412
                WHERE pg_attribute.attrelid = obj_oid
413
                    AND attacl IS NOT NULL
414
            )
415
            SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
416
                    || attrelid::regclass::text || ' TO %I'
417
                FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
418
                                   ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
419
                WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
420
    ------ SEQUENCES ------
421
    ELSIF obj_type = 'sequence'
422
    THEN
423
        -- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
424
        RETURN QUERY
425
            WITH t_acl AS (
426
            SELECT oid, unnest(relacl)::text AS acl
427
                FROM pg_catalog.pg_class
428
                WHERE oid = obj_oid
429
                    AND relacl IS NOT NULL
430
                    AND NOT n_role::oid = relowner
431
            )
432
            SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
433
                FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
434
                                   ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
435
                WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
436
        -- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
437
        RETURN QUERY
438
            WITH t_acl AS (
439
            SELECT oid, unnest(CASE WHEN relacl::text[] = ARRAY[]::text[]
440
                                   OR NOT array_to_string(relacl, ',') ~ ('^' || n_role_trans || '[=]')
441
                                       AND NOT array_to_string(relacl, ',') ~ ('[,]' || n_role_trans || '[=]')
442
                               THEN ARRAY[NULL]::text[]
443
                               ELSE relacl::text[] END) AS acl
444
                FROM pg_catalog.pg_class
445
                WHERE oid = obj_oid
446
                    AND relacl IS NOT NULL
447
                    AND n_role::oid = relowner
448
            )
449
            SELECT 'REVOKE ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' FROM %I'
450
                FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
451
                                   ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
452
                WHERE (acl ~ ('^' || n_role_trans || '[=]')
453
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
454
    ------ FONCTIONS ------
455
    -- inclut les fonctions d'agrégation
456
    ELSIF obj_type IN ('function', 'aggregate')
457
    THEN
458
        -- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
459
        RETURN QUERY
460
            WITH t_acl AS (
461
            SELECT oid, unnest(proacl)::text AS acl
462
                FROM pg_catalog.pg_proc
463
                WHERE oid = obj_oid
464
                    AND proacl IS NOT NULL
465
                    AND NOT n_role::oid = proowner
466
            )
467
            SELECT 'GRANT ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' TO %I'
468
                FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
469
                WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
470
        -- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
471
        RETURN QUERY
472
            WITH t_acl AS (
473
            SELECT oid, unnest(CASE WHEN proacl::text[] = ARRAY[]::text[]
474
                                   OR NOT array_to_string(proacl, ',') ~ ('^' || n_role_trans || '[=]')
475
                                       AND NOT array_to_string(proacl, ',') ~ ('[,]' || n_role_trans || '[=]')
476
                               THEN ARRAY[NULL]::text[]
477
                               ELSE proacl::text[] END) AS acl
478
                FROM pg_catalog.pg_proc
479
                WHERE oid = obj_oid
480
                    AND n_role::oid = proowner
481
                    AND proacl IS NOT NULL
482
            )
483
            SELECT 'REVOKE ' || privilege || ' ON FUNCTION ' || oid::regprocedure::text || ' FROM %I'
484
                FROM t_acl, unnest(ARRAY['EXECUTE'], ARRAY['X']) AS l (privilege, prvlg)
485
                WHERE (acl ~ ('^' || n_role_trans || '[=]')
486
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
487
    ------ TYPES ------
488
    -- inclut les domaines
489
    ELSIF obj_type IN ('type', 'domain')
490
    THEN
491
        -- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
492
        RETURN QUERY
493
            WITH t_acl AS (
494
            SELECT oid, unnest(typacl)::text AS acl
495
                FROM pg_catalog.pg_type
496
                WHERE oid = obj_oid
497
                    AND typacl IS NOT NULL
498
                    AND NOT n_role::oid = typowner
499
            )
500
            SELECT 'GRANT ' || privilege || ' ON TYPE ' || oid::regtype::text || ' TO %I'
501
                FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
502
                WHERE acl ~ ('^' || n_role_trans || '[=].*' || prvlg || '.*[/]') ;
503
        -- privilèges révoqués du propriétaire (si n_role est le propriétaire de l'objet) :
504
        RETURN QUERY
505
            WITH t_acl AS (
506
            SELECT oid, unnest(CASE WHEN typacl::text[] = ARRAY[]::text[]
507
                                   OR NOT array_to_string(typacl, ',') ~ ('^' || n_role_trans || '[=]')
508
                                       AND NOT array_to_string(typacl, ',') ~ ('[,]' || n_role_trans || '[=]')
509
                               THEN ARRAY[NULL]::text[]
510
                               ELSE typacl::text[] END) AS acl
511
                FROM pg_catalog.pg_type
512
                WHERE oid = obj_oid
513
                    AND n_role::oid = typowner
514
                    AND typacl IS NOT NULL
515
            )
516
            SELECT 'REVOKE ' || privilege || ' ON TYPE ' || oid::regtype::text || ' FROM %I'
517
                FROM t_acl, unnest(ARRAY['USAGE'], ARRAY['U']) AS l (privilege, prvlg)
518
                WHERE (acl ~ ('^' || n_role_trans || '[=]')
519
                    AND NOT acl ~ ( '[=].*' || prvlg || '.*[/]')) OR acl IS NULL ;
520
    ELSE
521
       RAISE EXCEPTION 'FSS0. Le type d''objet % n''est pas pris en charge', obj_type ;
522
    END IF ;
523
END
524
$_$;
525

    
526
ALTER FUNCTION z_asgard.asgard_synthese_role_obj(oid, text, regrole)
527
    OWNER TO g_admin_ext ;
528

    
529
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.' ;
530

    
531

    
532

    
533
-- FUNCTION: z_asgard.asgard_synthese_public_obj(oid, text)
534

    
535
CREATE OR REPLACE FUNCTION z_asgard.asgard_synthese_public_obj(obj_oid oid, obj_type text)
536
    RETURNS TABLE(commande text)
537
    LANGUAGE plpgsql
538
    AS $_$
539
/* OBJET : Cette fonction renvoie une table contenant une
540
           liste de commandes GRANT et REVOKE permettant de
541
           recréer les droits de public sur un objet de type
542
		   table, table étrangère, partition de table, vue,
543
           vue matérialisée ou séquence.
544
REMARQUE : La fonction ne s'intéresse pas aux objets de type
545
fonction (dont agrégats) et type (dont domaines), sur lesquels
546
public reçoit des droits par défaut qu'il n'est pas judicieux
547
de reproduire sur un autre rôle, ni de révoquer lors d'un
548
changement de lecteur/éditeur. Si des privilèges par défaut ont
549
été révoqués pour public, la révocation restera valable pour les
550
futurs lecteur/éditeurs puisqu'il n'y a pas d'attribution
551
de privilèges supplémentaires pour les lecteurs/éditeurs sur
552
ces objets.
553
ARGUMENTS :
554
- "obj_oid" est l'identifiant interne de l'objet ;
555
- "obj_type" est le type de l'objet au format text ('table',
556
'view', 'materialized view', 'sequence', 'foreign table',
557
'partitioned table').
558
SORTIE : Une table avec un unique champ nommé "commande". */
559
BEGIN
560
    ------ TABLE, VUE, VUE MATERIALISEE ------
561
    IF obj_type IN ('table', 'view', 'materialized view', 'foreign table', 'partitioned table')
562
    THEN
563
        -- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
564
        RETURN QUERY
565
            WITH t_acl AS (
566
            SELECT oid, unnest(relacl)::text AS acl
567
                FROM pg_catalog.pg_class
568
                WHERE oid = obj_oid
569
                    AND relacl IS NOT NULL
570
            )
571
            SELECT 'GRANT ' || privilege || ' ON TABLE ' || oid::regclass::text || ' TO %I'
572
                FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
573
                                         'TRUNCATE', 'REFERENCES', 'TRIGGER'],
574
                                   ARRAY['r', 'a', 'w', 'd', 'D', 'x', 't']) AS l (privilege, prvlg)
575
                WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
576
        ------ COLONNES ------
577
        -- privilèges attribués :
578
        RETURN QUERY
579
            WITH t_acl AS (
580
            SELECT attname, attrelid, unnest(attacl)::text AS acl
581
                FROM pg_catalog.pg_attribute
582
                WHERE pg_attribute.attrelid = obj_oid
583
                    AND attacl IS NOT NULL
584
            )
585
            SELECT 'GRANT ' || privilege || ' (' || attname::text || ') ON TABLE '
586
                    || attrelid::regclass::text || ' TO %I'
587
                FROM t_acl, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'REFERENCES'],
588
                                   ARRAY['r', 'a', 'w', 'x']) AS l (privilege, prvlg)
589
                WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
590
    ------ SEQUENCES ------
591
    ELSIF obj_type = 'sequence'
592
    THEN
593
        -- privilèges attribués (si n_role n'est pas le propriétaire de l'objet) :
594
        RETURN QUERY
595
            WITH t_acl AS (
596
            SELECT oid, unnest(relacl)::text AS acl
597
                FROM pg_catalog.pg_class
598
                WHERE oid = obj_oid
599
                    AND relacl IS NOT NULL
600
            )
601
            SELECT 'GRANT ' || privilege || ' ON SEQUENCE ' || oid::regclass::text || ' TO %I'
602
                FROM t_acl, unnest(ARRAY['SELECT', 'USAGE', 'UPDATE'],
603
                                   ARRAY['r', 'U', 'w']) AS l (privilege, prvlg)
604
                WHERE acl ~ ('^[=].*' || prvlg || '.*[/]') ;
605
    ELSE
606
       RAISE EXCEPTION 'FSS0. Le type d''objet % n''est pas pris en charge', obj_type ;
607
    END IF ;
608
END
609
$_$;
610

    
611
ALTER FUNCTION z_asgard.asgard_synthese_public_obj(oid, text)
612
    OWNER TO g_admin_ext ;
613

    
614
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.' ;
615

    
616

    
617

    
618

    
619

    
620
------ 4.3 - MODIFICATION DU PROPRIETAIRE D'UN SCHEMA ET SON CONTENU ------
621

    
622
-- FUNCTION: z_asgard.asgard_admin_proprietaire(text, text, boolean)
623

    
624
CREATE OR REPLACE FUNCTION z_asgard.asgard_admin_proprietaire(
625
                           n_schema text, n_owner text, b_setschema boolean DEFAULT True
626
                           )
627
    RETURNS int
628
    LANGUAGE plpgsql
629
    AS $_$
630
/* OBJET : Gestion des droits. Cette fonction permet d''attribuer
631
           un schéma et tous les objets qu'il contient à un [nouveau]
632
           propriétaire.
633
AVERTISSEMENT : Les objets de type operator class, operator family
634
et extended planner statistic ne sont pas pris en charge pour l'heure.
635
ARGUMENTS :
636
- "n_schema" est une chaîne de caractères correspondant au nom du
637
  schéma à considérer ;
638
- "n_owner" est une chaîne de caractères correspondant au nom du
639
  rôle (rôle de groupe ou rôle de connexion) qui doit être
640
  propriétaire des objets ;
641
- "b_setschema" est un paramètre booléen optionnel (vrai par défaut)
642
  qui indique si la fonction doit changer le propriétaire du schéma
643
  ou seulement des objets qu'il contient.
644
RESULTAT : la fonction renvoie un entier correspondant au nombre
645
d''objets effectivement traités. Les commandes lancées sont notifiées
646
au fur et à mesure. */
647
DECLARE
648
    item record ;
649
    k int := 0 ;
650
    o_owner oid ;
651
    s_owner text ;
652
BEGIN
653
    ------ TESTS PREALABLES ------
654
    SELECT nspowner::regrole::text
655
        INTO s_owner
656
        FROM pg_catalog.pg_namespace
657
        WHERE nspname = n_schema ;
658
    
659
    -- non existance du schémas
660
    IF NOT FOUND
661
    THEN
662
        RAISE EXCEPTION 'FAP1. Le schéma % n''existe pas.', n_schema ;
663
    END IF ;
664
    
665
    -- absence de permission sur le propriétaire courant du schéma
666
    IF NOT pg_has_role(s_owner::regrole::oid, 'USAGE')
667
    THEN
668
        RAISE EXCEPTION 'FAP5. Vous n''êtes pas habilité à modifier le propriétaire du schéma %.', n_schema
669
                USING DETAIL = 'Propriétaire courant : ' || s_owner || '.' ;  
670
    END IF ;
671
    
672
    -- le propriétaire désigné n'existe pas
673
    IF NOT n_owner IN (SELECT rolname::text FROM pg_catalog.pg_roles)
674
    THEN
675
        RAISE EXCEPTION 'FAP2. Le rôle % n''existe pas.', n_owner ;
676
    -- absence de permission sur le propriétaire désigné
677
    ELSIF NOT pg_has_role(n_owner, 'USAGE')
678
    THEN
679
        RAISE EXCEPTION 'FAP6. Vous n''avez pas la permission d''utiliser le rôle %.', n_owner ;  
680
    ELSE
681
        o_owner := quote_ident(n_owner)::regrole::oid ;
682
    END IF ;
683
    
684
    -- le propriétaire désigné n'est pas le propriétaire courant et la fonction
685
    -- a été lancée avec la variante qui ne traite pas le schéma
686
    IF NOT b_setschema
687
            AND NOT quote_ident(n_owner) = s_owner
688
    THEN
689
        RAISE EXCEPTION 'FAP3. Le rôle % n''est pas propriétaire du schéma.', n_owner
690
            USING HINT = 'Lancez asgard_admin_proprietaire(' || quote_literal(n_schema)
691
                         || ', ' || quote_literal(n_owner) || ') pour changer également le propriétaire du schéma.' ;
692
    END IF ;
693
    
694
    ------ PROPRIÉTAIRE DU SCHEMA ------
695
    IF b_setschema
696
    THEN
697
        EXECUTE 'ALTER SCHEMA ' || quote_ident(n_schema) || ' OWNER TO ' || quote_ident(n_owner) ;
698
        RAISE NOTICE '> %', 'ALTER SCHEMA ' || quote_ident(n_schema) || ' OWNER TO ' || quote_ident(n_owner) ;
699
        k := k + 1 ;
700
    END IF ;
701
    
702
    ------ PROPRIETAIRES DES OBJETS ------
703
    -- uniquement ceux qui n'appartiennent pas déjà
704
    -- au rôle identifié
705
    FOR item IN
706
        -- tables, tables étrangères, vues, vues matérialisées,
707
        -- partitions, séquences :
708
        SELECT
709
            relname::text AS n_objet,
710
            relowner AS obj_owner,
711
            relkind IN ('r', 'f', 'p', 'm') AS b, -- servira à assurer que les tables
712
                                                  -- soient listées avant les objets qui
713
                                                  -- en dépendent
714
            'ALTER ' || kind_lg || ' ' || pg_class.oid::regclass || ' OWNER TO '
715
                || quote_ident(n_owner) AS commande
716
            FROM pg_catalog.pg_class,
717
                unnest(ARRAY['r', 'p', 'v', 'm', 'f', 'S'],
718
                       ARRAY['TABLE', 'TABLE', 'VIEW', 'MATERIALIZED VIEW', 'FOREIGN TABLE', 'SEQUENCE']) AS l (kind_crt, kind_lg)
719
            WHERE relnamespace = quote_ident(n_schema)::regnamespace
720
                AND relkind IN ('S', 'r', 'p', 'v', 'm', 'f')
721
                AND kind_crt = relkind
722
                AND NOT relowner = o_owner
723
        UNION
724
        -- fonctions et agrégats :
725
        SELECT
726
            proname::text AS n_objet,
727
            proowner AS obj_owner,
728
            False AS b,
729
            'ALTER FUNCTION ' || pg_proc.oid::regprocedure || ' OWNER TO '
730
                || quote_ident(n_owner) AS commande
731
            FROM pg_catalog.pg_proc
732
            WHERE pronamespace = quote_ident(n_schema)::regnamespace
733
                AND NOT proowner = o_owner
734
            -- à noter que les agrégats (proisagg vaut True) ont
735
            -- leur propre commande ALTER AGGREGATE OWNER TO, mais
736
            -- ALTER FUNCTION OWNER TO fonctionne également, on ne
737
            -- fait donc pas de distinction pour l'heure
738
        UNION
739
        -- types et domaines :
740
        SELECT
741
            typname::text AS n_objet,
742
            typowner AS obj_owner,
743
            False AS b,
744
            'ALTER ' || kind_lg || ' ' || typnamespace::regnamespace::text || '.'
745
                || quote_ident(typname) || ' OWNER TO '
746
                || quote_ident(n_owner) AS commande
747
            FROM unnest(ARRAY['true', 'false'],
748
                       ARRAY['DOMAIN', 'TYPE']) AS l (kind_crt, kind_lg),
749
                pg_catalog.pg_type LEFT JOIN pg_catalog.pg_class ON typrelid = pg_class.oid
750
            WHERE typnamespace = quote_ident(n_schema)::regnamespace
751
                AND kind_crt::boolean = (typtype = 'd')
752
                AND NOT (typelem > 0 AND typname ~ '^_')
753
                -- exclusion des types array générés automatiquement
754
                -- leur propriétaire est lié à celui du type source
755
                -- et ne peut être modifié directement
756
                AND (NOT typtype = 'c' OR relkind = 'c')
757
                -- idem pour les types "ligne de table", dont
758
                -- le propriétaire est lié à celui de la table
759
                AND NOT typowner = o_owner
760
        UNION
761
        -- conversions :
762
        SELECT
763
            conname::text AS n_objet,
764
            conowner AS obj_owner,
765
            False AS b,
766
            'ALTER CONVERSION ' || connamespace::regnamespace::text || '.'
767
                || quote_ident(conname) || ' OWNER TO '
768
                || quote_ident(n_owner) AS commande
769
            FROM pg_catalog.pg_conversion
770
            WHERE connamespace = quote_ident(n_schema)::regnamespace
771
                AND NOT conowner = o_owner
772
        UNION
773
        -- opérateurs :
774
        SELECT
775
            oprname::text AS n_objet,
776
            oprowner AS obj_owner,
777
            False AS b,
778
            'ALTER OPERATOR ' || pg_operator.oid::regoperator || ' OWNER TO '
779
                || quote_ident(n_owner) AS commande
780
            FROM pg_catalog.pg_operator
781
            WHERE oprnamespace = quote_ident(n_schema)::regnamespace
782
                AND NOT oprowner = o_owner
783
        UNION
784
        -- collations :
785
        SELECT
786
            collname::text AS n_objet,
787
            collowner AS obj_owner,
788
            False AS b,
789
            'ALTER COLLATION ' || collnamespace::regnamespace::text || '.'
790
                || quote_ident(collname) || ' OWNER TO '
791
                || quote_ident(n_owner) AS commande
792
            FROM pg_catalog.pg_collation
793
            WHERE collnamespace = quote_ident(n_schema)::regnamespace
794
                AND NOT collowner = o_owner
795
        UNION
796
        -- text search dictionary :
797
        SELECT
798
            dictname::text AS n_objet,
799
            dictowner AS obj_owner,
800
            False AS b,
801
            'ALTER TEXT SEARCH DICTIONARY ' || pg_ts_dict.oid::regdictionary || ' OWNER TO '
802
                || quote_ident(n_owner) AS commande
803
            FROM pg_catalog.pg_ts_dict
804
            WHERE dictnamespace = quote_ident(n_schema)::regnamespace
805
                AND NOT dictowner = o_owner
806
        UNION
807
        -- text search configuration :
808
        SELECT
809
            cfgname::text AS n_objet,
810
            cfgowner AS obj_owner,
811
            False AS b,
812
            'ALTER TEXT SEARCH CONFIGURATION ' || pg_ts_config.oid::regconfig || ' OWNER TO '
813
                || quote_ident(n_owner) AS commande
814
            FROM pg_catalog.pg_ts_config
815
            WHERE cfgnamespace = quote_ident(n_schema)::regnamespace
816
                AND NOT cfgowner = o_owner
817
            ORDER BY b DESC
818
    LOOP
819
        IF pg_has_role(item.obj_owner, 'USAGE')
820
        THEN
821
            EXECUTE item.commande ;
822
            RAISE NOTICE '> %', item.commande ;
823
            k := k + 1 ;
824
        ELSE
825
            RAISE EXCEPTION 'FAP4. Vous n''êtes pas habilité à modifier le propriétaire de l''objet %.', item.n_objet
826
                USING DETAIL = 'Propriétaire courant : ' || item.obj_owner::regrole::text || '.' ;    
827
        END IF ;
828
    END LOOP ;
829
    ------ RESULTAT ------
830
    RETURN k ;
831
END
832
$_$ ;
833

    
834
ALTER FUNCTION z_asgard.asgard_admin_proprietaire(text, text, boolean)
835
    OWNER TO g_admin_ext ;
836

    
837

    
838
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.' ;
839

    
840

    
841

    
842
------ 4.4 - TRANSFORMATION GRANT EN REVOKE ------
843

    
844
-- FUNCTION: z_asgard.asgard_grant_to_revoke(text)
845

    
846
CREATE OR REPLACE FUNCTION z_asgard.asgard_grant_to_revoke(c_grant text)
847
    RETURNS text
848
    LANGUAGE plpgsql
849
    AS $_$
850
/* OBJET : Cette fonction transforme une commande de type GRANT en
851
           son équivalent REVOKE, ou l'inverse.
852
AVERTISSEMENT : La fonction ne reconnaîtra que les mots clés écrits
853
en majuscules.
854
ARGUMENT : une commande de type GRANT/REVOKE présumée valide (chaîne de caractères).
855
SORTIE : une commande de type REVOKE/GRANT (chaîne de caractères). */
856
DECLARE
857
    c_revoke text ;
858
BEGIN
859
    IF c_grant ~ '^GRANT'
860
    THEN
861
        c_revoke := regexp_replace(c_grant, '^GRANT', 'REVOKE') ;
862
        c_revoke := regexp_replace(c_revoke, '[[:space:]]TO[[:space:]]', ' FROM ') ;
863
    ELSIF c_grant ~ '^REVOKE'
864
    THEN
865
        c_revoke := regexp_replace(c_grant, '^REVOKE', 'GRANT') ;
866
        c_revoke := regexp_replace(c_revoke, '[[:space:]]FROM[[:space:]]', ' TO ') ;
867
    ELSE
868
        RAISE EXCEPTION 'FGR1. Commande GRANT/REVOKE invalide.' ;
869
    END IF ;
870
    RETURN c_revoke ;
871
END
872
$_$;
873

    
874
ALTER FUNCTION z_asgard.asgard_grant_to_revoke(text)
875
    OWNER TO g_admin_ext ;
876

    
877
COMMENT ON FUNCTION z_asgard.asgard_grant_to_revoke(text) IS 'ASGARD. Fonction qui transforme une commande GRANT en commande REVOKE.' ;
878

    
879

    
880
------ 4.5 - INITIALISATION DE GESTION_SCHEMA ------
881

    
882
-- FUNCTION: z_asgard_admin.asgard_initialisation_gestion_schema(text[], boolean)
883

    
884
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_initialisation_gestion_schema(
885
                           exceptions text[] default NULL::text[], b_gs boolean default False
886
                           )
887
    RETURNS text
888
    LANGUAGE plpgsql
889
    AS $_$
890
/* OBJET : Cette fonction intègre à la table de gestion des droits
891
           gestion_schema l'ensemble des schémas existants, hors
892
           schémas système et ceux qui sont (optionnellement) listés
893
           en argument.
894
ARGUMENTS :
895
- exceptions (optionnel) : un tableau text[] contenant les noms des schémas
896
à omettre, le cas échéant ;
897
- b_gs (optionnel) : un booléen indiquant si, dans l'hypothèse où un schéma
898
serait déjà référencé - nécessairement comme non créé - dans la table de gestion,
899
c'est le propriétaire du schéma qui doit devenir le "producteur" du schéma
900
(False) ou le producteur pré-renseigné dans la table de gestion qui doit
901
devenir le propriétaire du schéma (True). False par défaut.
902
SORTIE : '__ FIN INTIALISATION.' si la requête s'est exécutée normalement. */
903
DECLARE
904
    item record ;
905
    e_mssg text ;
906
    e_detl text ;
907
    e_hint text ;
908
    b_creation boolean ;
909
BEGIN
910

    
911
    FOR item IN SELECT nspname, nspowner FROM pg_catalog.pg_namespace
912
                    WHERE NOT nspname ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
913
                                            '^public$', '^information_schema$', '^topology$'])
914
                        AND (exceptions IS NULL OR NOT nspname = ANY(exceptions))
915
    LOOP
916
        SELECT creation INTO b_creation
917
            FROM z_asgard.gestion_schema_usr
918
            WHERE item.nspname::text = nom_schema ;
919
        IF b_creation IS NULL
920
        -- schéma non référencé dans gestion_schema
921
        THEN
922
            INSERT INTO z_asgard.gestion_schema_usr (nom_schema, producteur, creation)
923
                VALUES (item.nspname::text, replace(item.nspowner::regrole::text, '"', ''), true) ;
924
            RAISE NOTICE '... Schéma % enregistré dans la table de gestion.', item.nspname::text ;
925
        ELSIF NOT b_creation
926
        -- schéma pré-référencé dans gestion_schema
927
        THEN
928
            IF NOT b_gs
929
            THEN
930
                UPDATE z_asgard.gestion_schema_usr
931
                    SET creation = true,
932
                        producteur = replace(item.nspowner::regrole::text, '"', '')
933
                    WHERE item.nspname::text = nom_schema ;
934
            ELSE
935
                UPDATE z_asgard.gestion_schema_usr
936
                    SET creation = true
937
                    WHERE item.nspname::text = nom_schema ;
938
            END IF ;
939
            RAISE NOTICE '... Schéma % marqué comme créé dans la table de gestion.', item.nspname::text ;
940
        END IF ;
941
    END LOOP ;
942

    
943
    RETURN '__ FIN INITALISATION.' ;
944

    
945
EXCEPTION WHEN OTHERS THEN
946
    GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
947
                            e_hint = PG_EXCEPTION_HINT,
948
                            e_detl = PG_EXCEPTION_DETAIL ;           
949
    RAISE EXCEPTION 'FIG0 > %', e_mssg
950
        USING DETAIL = e_detl,
951
            HINT = e_hint ;
952

    
953
END
954
$_$;
955

    
956
ALTER FUNCTION z_asgard_admin.asgard_initialisation_gestion_schema(text[], boolean)
957
    OWNER TO g_admin ;
958

    
959
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.' ;
960

    
961

    
962

    
963
------ 4.6 - DEREFERENCEMENT D'UN SCHEMA ------
964

    
965
-- FUNCTION: z_asgard_admin.asgard_sortie_gestion_schema(text)
966

    
967
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_sortie_gestion_schema(n_schema text)
968
    RETURNS text
969
    LANGUAGE plpgsql
970
    AS $_$
971
/* OBJET : Cette fonction permet de supprimer de la table de gestion un
972
           schéma existant (qui échappera alors aux mécanismes de
973
           gestion des droits), en outrepassant les règles qui veulent
974
           que seules les lignes avec creation valant false puisse
975
           être ciblées par des DELETE et que creation ne puisse être
976
           mis à false si le schéma existe.
977
ARGUMENTS :
978
- n_schema : nom d'un schéma présumé référencé dans le champ
979
             nom_schema de la table de gestion (sinon la fonction n'aura
980
             pas d'effet).
981
SORTIE : '__ DEREFERENCEMENT REUSSI.' si la requête s'est exécutée normalement. */
982
DECLARE
983
    e_mssg text ;
984
    e_detl text ;
985
    e_hint text ;
986
BEGIN
987

    
988
    UPDATE z_asgard.gestion_schema_etr
989
        SET ctrl = ARRAY['EXIT', 'x7-A;#rzo']
990
        WHERE nom_schema = n_schema ;
991
        
992
    DELETE FROM z_asgard.gestion_schema_etr
993
        WHERE nom_schema = n_schema ;
994

    
995
    RETURN '__ DEREFERENCEMENT REUSSI.' ;
996

    
997
EXCEPTION WHEN OTHERS THEN
998
    GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
999
                            e_hint = PG_EXCEPTION_HINT,
1000
                            e_detl = PG_EXCEPTION_DETAIL ;
1001
    RAISE EXCEPTION 'FSG0 > %', e_mssg
1002
        USING DETAIL = e_detl,
1003
            HINT = e_hint ;
1004

    
1005
END
1006
$_$;
1007

    
1008
ALTER FUNCTION z_asgard_admin.asgard_sortie_gestion_schema(text)
1009
    OWNER TO g_admin ;
1010

    
1011
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.' ;
1012

    
1013

    
1014

    
1015
------ 4.7 - NETTOYAGE DES RÔLES ------
1016

    
1017
-- FUNCTION: z_asgard.asgard_nettoyage_roles()
1018

    
1019
CREATE OR REPLACE FUNCTION z_asgard.asgard_nettoyage_roles()
1020
    RETURNS text
1021
    LANGUAGE plpgsql
1022
    AS $_$
1023
/* OBJET : Cette fonction active la mise à jour des noms des rôles
1024
           désignés dans la table de gestion comme producteur, éditeur et
1025
           lecteur, pour prendre en compte les changements de nom
1026
           ou suppression qui auraient pu avoir eu lieu.
1027
ARGUMENTS : néant.
1028
SORTIE : '__ NETTOYAGE REUSSI.' si la requête s'est exécutée normalement. */
1029
DECLARE
1030
    e_mssg text ;
1031
    e_detl text ;
1032
    e_hint text ;
1033
BEGIN
1034

    
1035
    UPDATE z_asgard.gestion_schema_usr
1036
        SET producteur = producteur,
1037
            editeur = editeur,
1038
            lecteur = lecteur ;
1039

    
1040
    RETURN '__ NETTOYAGE REUSSI.' ;
1041

    
1042
EXCEPTION WHEN OTHERS THEN
1043
    GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
1044
                            e_hint = PG_EXCEPTION_HINT,
1045
                            e_detl = PG_EXCEPTION_DETAIL ;
1046
    RAISE EXCEPTION 'FNR0 > %', e_mssg
1047
        USING DETAIL = e_detl,
1048
            HINT = e_hint ;
1049

    
1050
END
1051
$_$;
1052

    
1053
ALTER FUNCTION z_asgard.asgard_nettoyage_roles()
1054
    OWNER TO g_admin_ext ;
1055

    
1056
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.' ;
1057

    
1058

    
1059

    
1060
------ 4.8 - REINITIALISATION DES PRIVILEGES SUR UN SCHEMA ------
1061

    
1062
-- FUNCTION: z_asgard.asgard_initialise_schema(text, boolean, boolean)
1063

    
1064
CREATE OR REPLACE FUNCTION z_asgard.asgard_initialise_schema(
1065
                              n_schema text,
1066
                              b_preserve boolean DEFAULT False,
1067
                              b_gs boolean default False
1068
                              )
1069
    RETURNS text
1070
    LANGUAGE plpgsql
1071
    AS $_$
1072
/* OBJET : Cette fonction permet de réinitialiser les droits
1073
           sur un schéma selon les privilèges standards associés
1074
           aux rôles désignés dans la table de gestion.
1075
           Si elle est appliquée à un schéma existant non référencé
1076
           dans la table de gestion, elle l'ajoute avec son
1077
           propriétaire courant. Elle échoue si le schéma n'existe
1078
           pas.
1079
ARGUMENTS :
1080
- n_schema : nom d'un schéma présumé existant ;
1081
- b_preserve (optionnel) : un paramètre booléen. Pour un schéma encore
1082
non référencé (ou pré-référencé comme non-créé) dans la table de gestion une valeur
1083
True signifie que les privilèges des rôles lecteur et éditeur doivent être
1084
ajoutés par dessus les droits actuels. Avec la valeur par défaut False,
1085
les privilèges sont réinitialisés. Ce paramètre est ignoré pour un schéma déjà
1086
référencé comme créé (et les privilèges sont réinitialisés) ;
1087
- b_gs (optionnel) : un booléen indiquant si, dans l'hypothèse où un schéma
1088
serait déjà référencé - nécessairement comme non créé - dans la table de gestion,
1089
c'est le propriétaire du schéma qui doit devenir le "producteur" (False) ou le
1090
producteur de la table de gestion qui doit devenir le propriétaire
1091
du schéma (True). False par défaut. Ce paramètre est ignoré pour un schéma déjà
1092
créé.
1093
SORTIE : '__ REINITIALISATION REUSSIE.' (ou '__INITIALISATION REUSSIE.' pour
1094
un schéma non référencé comme créé avec b_preserve = True) si la requête
1095
s'est exécutée normalement. */
1096
DECLARE
1097
    roles record ;
1098
    r record ;
1099
    c record ;
1100
    n_owner text ;
1101
    k int := 0 ;
1102
    n int ;
1103
    e_mssg text ;
1104
    e_detl text ;
1105
    e_hint text ;
1106
BEGIN
1107
    ------ TESTS PREALABLES ------
1108
    -- schéma système
1109
    IF n_schema ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
1110
                            '^public$', '^information_schema$', '^topology$'])
1111
    THEN
1112
        RAISE EXCEPTION 'FIS1. Opération interdite. Le schéma % est un schéma système.', n_schema ;
1113
    END IF ;
1114
    
1115
    -- existence du schéma
1116
    SELECT replace(nspowner::regrole::text, '"', '') INTO n_owner
1117
        FROM pg_catalog.pg_namespace
1118
        WHERE n_schema = nspname::text ;
1119
    IF NOT FOUND
1120
    THEN
1121
        RAISE EXCEPTION 'FIS2. Echec. Le schéma % n''existe pas.', n_schema ;
1122
    END IF ;
1123
    
1124
    -- permission sur le propriétaire
1125
    IF NOT pg_has_role(n_owner, 'USAGE')
1126
    THEN
1127
        RAISE EXCEPTION 'FIS3. Echec. Vous ne disposez pas des permissions nécessaires sur le schéma % pour réaliser cette opération.', n_schema
1128
            USING HINT = 'Il vous faut être membre du rôle propriétaire ' || n_owner || '.' ;
1129
    END IF ;
1130
    
1131
    ------ RECUPERATION DES ROLES ------
1132
    SELECT
1133
        r1.rolname AS producteur,
1134
        CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
1135
        CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
1136
        creation INTO roles
1137
        FROM z_asgard.gestion_schema_etr
1138
            LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
1139
            LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
1140
            LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
1141
        WHERE nom_schema = n_schema ;
1142
    
1143
    ------ SCHEMA NON REFERENCE ------
1144
    -- ajouté à gestion_schema
1145
    -- le reste est pris en charge par le trigger
1146
    -- on_modify_gestion_schema_after
1147
    IF NOT FOUND
1148
    THEN
1149
        INSERT INTO z_asgard.gestion_schema_usr (nom_schema, producteur, creation)
1150
            VALUES (n_schema, n_owner, true) ;
1151
        RAISE NOTICE '... Le schéma % a été enregistré dans la table de gestion.', n_schema ;
1152
        
1153
        IF b_preserve
1154
        THEN
1155
            RETURN '__ INITIALISATION REUSSIE.' ;
1156
        END IF ;
1157
        
1158
    ------- SCHEMA PRE-REFERENCE ------
1159
    -- présent dans gestion_schema avec creation valant
1160
    -- False.
1161
    ELSIF NOT roles.creation
1162
    THEN
1163
        IF NOT b_gs
1164
        THEN
1165
            UPDATE z_asgard.gestion_schema_usr
1166
                SET creation = true,
1167
                    producteur = n_owner
1168
                WHERE n_schema = nom_schema ;
1169
        ELSE
1170
            UPDATE z_asgard.gestion_schema_usr
1171
                SET creation = true
1172
                WHERE n_schema = nom_schema ;
1173
        END IF ;
1174
        RAISE NOTICE '... Le schéma % a été marqué comme créé dans la table de gestion.', item.nspname::text ;
1175
        
1176
        IF b_preserve
1177
        THEN
1178
            RETURN '__ INITIALISATION REUSSIE.' ;
1179
        END IF ;
1180
        
1181
    ------ REMISE A PLAT DES PROPRIETAIRES ------
1182
    -- uniquement pour les schémas qui étaient déjà
1183
    -- référencés dans gestion_schema (pour les autres, pris en charge
1184
    -- par le trigger on_modify_gestion_schema_after)
1185
    
1186
    -- schéma dont le propriétaire ne serait pas le producteur
1187
    ELSIF NOT roles.producteur = n_owner
1188
    THEN
1189
        -- permission sur le producteur
1190
        IF NOT pg_has_role(roles.producteur, 'USAGE')
1191
        THEN
1192
            RAISE EXCEPTION 'FIS4. Echec. Vous ne disposez pas des permissions nécessaires sur le schéma % pour réaliser cette opération.', n_schema
1193
                USING HINT = 'Il vous faut être membre du rôle producteur ' || roles.producteur || '.' ;
1194
        END IF ;
1195
        -- propriétaire du schéma + contenu
1196
        RAISE NOTICE '(ré)attribution de la propriété du schéma et des objets au rôle producteur du schéma :' ;
1197
        PERFORM z_asgard.asgard_admin_proprietaire(n_schema, roles.producteur) ;
1198
    
1199
    -- schema dont le propriétaire est le producteur
1200
    ELSE
1201
        -- reprise uniquement des propriétaires du contenu
1202
        RAISE NOTICE '(ré)attribution de la propriété des objets au rôle producteur du schéma :' ;
1203
        SELECT z_asgard.asgard_admin_proprietaire(n_schema, roles.producteur, False) INTO n ;
1204
        IF n = 0
1205
        THEN
1206
            RAISE NOTICE '> néant' ;
1207
        END IF ;        
1208
    END IF ;
1209
    
1210
    ------ DESTRUCTION DES PRIVILEGES ACTUELS ------
1211
    -- hors privilèges par défaut (définis par ALTER DEFAULT PRIVILEGE)
1212
    -- et hors révocations des privilèges par défaut de public sur
1213
    -- les types et les fonctions
1214
    -- pour le propriétaire, ces commandes ont pour effet
1215
    -- de remettre les privilèges par défaut supprimés
1216
    
1217
    -- public
1218
    RAISE NOTICE 'remise à zéro des privilèges manuels du pseudo-rôle public :' ;
1219
    FOR c IN (SELECT * FROM z_asgard.asgard_synthese_public(
1220
                    quote_ident(n_schema)::regnamespace))
1221
    LOOP
1222
        EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
1223
        RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
1224
    END LOOP ;
1225
    IF NOT FOUND
1226
    THEN
1227
        RAISE NOTICE '> néant' ;
1228
    END IF ;
1229
    
1230
    -- autres rôles
1231
    RAISE NOTICE 'remise à zéro des privilèges des autres rôles (pour le producteur, les éventuels privilèges manquants sont réattribués) :' ;
1232
    FOR r IN (SELECT rolname FROM pg_roles)
1233
    LOOP
1234
        FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role(
1235
                       quote_ident(n_schema)::regnamespace, quote_ident(r.rolname)::regrole))
1236
        LOOP
1237
            EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
1238
            RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
1239
            k := k + 1 ;
1240
        END LOOP ;        
1241
    END LOOP ;
1242
    IF NOT FOUND OR k = 0
1243
    THEN
1244
        RAISE NOTICE '> néant' ;
1245
    END IF ;
1246

    
1247
    ------ RECREATION DES PRIVILEGES DE L'EDITEUR ------
1248
    IF roles.editeur IS NOT NULL
1249
    THEN
1250
        RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
1251
        
1252
        EXECUTE 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
1253
        RAISE NOTICE '> %', 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
1254
        
1255
        EXECUTE 'GRANT SELECT, UPDATE, DELETE, INSERT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
1256
        RAISE NOTICE '> %', 'GRANT SELECT, UPDATE, DELETE, INSERT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
1257
        
1258
        EXECUTE 'GRANT SELECT, USAGE ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
1259
        RAISE NOTICE '> %', 'GRANT SELECT, USAGE ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.editeur) ;
1260
    END IF ;
1261
    
1262
    ------ RECREATION DES PRIVILEGES DU LECTEUR ------
1263
    IF roles.lecteur IS NOT NULL
1264
    THEN
1265
        RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
1266
        
1267
        EXECUTE 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
1268
        RAISE NOTICE '> %', 'GRANT USAGE ON SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
1269
        
1270
        EXECUTE 'GRANT SELECT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
1271
        RAISE NOTICE '> %', 'GRANT SELECT ON ALL TABLES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
1272
        
1273
        EXECUTE 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
1274
        RAISE NOTICE '> %', 'GRANT SELECT ON ALL SEQUENCES IN SCHEMA ' || quote_ident(n_schema) || ' TO ' || quote_ident(roles.lecteur) ;
1275
    END IF ;
1276
    
1277
    ------ RECREATION DES PRIVILEGES SUR LES SCHEMAS D'ASGARD ------
1278
    IF n_schema = 'z_asgard' AND (roles.lecteur IS NULL OR NOT roles.lecteur = 'g_consult')
1279
    THEN
1280
        -- rétablissement des droits de g_consult
1281
        RAISE NOTICE 'rétablissement des privilèges attendus pour g_consult :' ;
1282
        
1283
        GRANT USAGE ON SCHEMA z_asgard TO g_consult ;
1284
        RAISE NOTICE '> GRANT USAGE ON SCHEMA z_asgard TO g_consult' ;
1285
        
1286
        GRANT SELECT ON TABLE z_asgard.gestion_schema_usr TO g_consult ;
1287
        RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard.gestion_schema_usr TO g_consult' ;
1288
        
1289
        GRANT SELECT ON TABLE z_asgard.gestion_schema_etr TO g_consult ;
1290
        RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard.gestion_schema_etr TO g_consult' ;
1291
        
1292
        GRANT SELECT ON TABLE z_asgard.qgis_menubuilder_metadata TO g_consult ;
1293
        RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard.qgis_menubuilder_metadata TO g_consult' ;
1294
    
1295
    ELSIF n_schema = 'z_asgard_admin'
1296
    THEN
1297
        -- rétablissement des droits de g_admin_ext
1298
        RAISE NOTICE 'rétablissement des privilèges attendus pour g_admin_ext :' ;
1299
        
1300
        GRANT USAGE ON SCHEMA z_asgard_admin TO g_admin_ext ;
1301
        RAISE NOTICE '> GRANT USAGE ON SCHEMA z_asgard_admin TO g_admin_ext' ;
1302
        
1303
        GRANT INSERT, SELECT, UPDATE, DELETE ON TABLE z_asgard_admin.gestion_schema TO g_admin_ext ;
1304
        RAISE NOTICE '> GRANT INSERT, SELECT, UPDATE, DELETE ON TABLE z_asgard_admin.gestion_schema TO g_admin_ext' ;
1305
        
1306
        GRANT SELECT ON TABLE z_asgard_admin.asgard_parametre TO g_admin_ext ;
1307
        RAISE NOTICE '> GRANT SELECT ON TABLE z_asgard_admin.asgard_parametre TO g_admin_ext' ;
1308
        
1309
    END IF ;
1310
                
1311
    RETURN '__ REINITIALISATION REUSSIE.' ;
1312
    
1313
EXCEPTION WHEN OTHERS THEN
1314
    GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
1315
                            e_hint = PG_EXCEPTION_HINT,
1316
                            e_detl = PG_EXCEPTION_DETAIL ;
1317
    RAISE EXCEPTION 'FIS0 > %', e_mssg
1318
        USING DETAIL = e_detl,
1319
            HINT = e_hint ;
1320
    
1321
END
1322
$_$;
1323

    
1324
ALTER FUNCTION z_asgard.asgard_initialise_schema(text, boolean, boolean)
1325
    OWNER TO g_admin_ext ;
1326

    
1327
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à).' ;
1328

    
1329

    
1330
------ 4.9 - REINITIALISATION DES PRIVILEGES SUR UN OBJET ------
1331

    
1332
-- FUNCTION: z_asgard.asgard_initialise_obj(text, text, text)
1333

    
1334
CREATE OR REPLACE FUNCTION z_asgard.asgard_initialise_obj(
1335
                              obj_schema text,
1336
                              obj_nom text,
1337
                              obj_typ text
1338
                              )
1339
    RETURNS text
1340
    LANGUAGE plpgsql
1341
    AS $_$
1342
/* OBJET : Cette fonction permet de réinitialiser les droits
1343
           sur un objet selon les privilèges standards associés
1344
           aux rôles désignés dans la table de gestion pour son schéma.
1345

    
1346
ARGUMENTS :
1347
- "obj_schema" est le nom du schéma contenant l'objet, au format
1348
texte et sans guillemets ;
1349
- "obj_nom" est le nom de l'objet, au format texte et sans
1350
guillemets ;
1351
- "obj_typ" est le type de l'objet au format text ('table',
1352
'partitioned table' (assimilé à 'table'), 'view', 'materialized view',
1353
'foreign table', 'sequence', 'function', 'aggregate', 'type', 'domain').
1354
SORTIE : '__ REINITIALISATION REUSSIE.' si la requête s'est exécutée
1355
normalement. */
1356
DECLARE
1357
    class_info record ;
1358
    roles record ;
1359
    obj record ;
1360
    r record ;
1361
    c record ;
1362
    l text ;
1363
    k int := 0 ;
1364
BEGIN
1365

    
1366
    -- pour la suite, on assimile les partitions à des tables
1367
    IF obj_typ = 'partitioned table'
1368
    THEN
1369
        obj_typ := 'table' ;
1370
    END IF ;
1371

    
1372
    ------ TESTS PREALABLES ------
1373
    -- schéma système
1374
    IF obj_schema ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
1375
                            '^public$', '^information_schema$', '^topology$'])
1376
    THEN
1377
        RAISE EXCEPTION 'FIO1. Opération interdite. Le schéma % est un schéma système.', obj_schema ;
1378
    END IF ;
1379
    
1380
    -- schéma non référencé
1381
    IF NOT obj_schema IN (SELECT nom_schema FROM z_asgard.gestion_schema_usr WHERE creation)
1382
    THEN
1383
        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 ;
1384
    END IF ;
1385
    
1386
    -- type invalide + récupération des informations sur le catalogue contenant l'objet
1387
    SELECT
1388
        xtyp, xclass, xprefix || 'name' AS xname, xprefix || 'owner' AS xowner,
1389
        xprefix || 'namespace' AS xschema
1390
        INTO class_info
1391
        FROM unnest(ARRAY['table', 'foreign table', 'view', 'materialized view',
1392
                        'sequence', 'type', 'domain', 'function', 'aggregate'],
1393
                    ARRAY['pg_class', 'pg_class', 'pg_class', 'pg_class',
1394
                        'pg_class', 'pg_type', 'pg_type', 'pg_proc', 'pg_proc'],
1395
                    ARRAY['rel', 'rel', 'rel', 'rel', 'rel', 'typ', 'typ',
1396
                        'pro', 'pro']) AS typ (xtyp, xclass, xprefix)
1397
            WHERE typ.xtyp = obj_typ ;
1398
            
1399
    IF NOT FOUND
1400
    THEN
1401
        RAISE EXCEPTION 'FIO3. Echec. Le type % n''existe pas ou n''est pas pris en charge.', obj_typ
1402
            USING HINT = 'Types acceptés : ''table'', ''partitioned table'' (assimilé à ''table''), ''view'', ''materialized view'', ''foreign table'', ''sequence'', ''function'', ''aggregate'', ''type'', ''domain''.' ;
1403
    END IF ;
1404
        
1405
    -- objet inexistant + récupération du propriétaire
1406
    EXECUTE 'SELECT ' || class_info.xowner || '::regrole::text AS prop, '
1407
            || class_info.xclass || '.oid FROM pg_catalog.' || class_info.xclass
1408
            || ' WHERE ' || class_info.xname || ' = ' || quote_literal(obj_nom) 
1409
            || ' AND ' || class_info.xschema || '::regnamespace::text = quote_ident('
1410
            || quote_literal(obj_schema) || ')'
1411
        INTO obj ;
1412
            
1413
    IF obj.prop IS NULL
1414
    THEN
1415
        RAISE EXCEPTION 'FIO4. Echec. L''objet % n''existe pas.', obj_nom ;
1416
    END IF ;    
1417
    
1418
    ------ RECUPERATION DES ROLES ------
1419
    SELECT
1420
        r1.rolname AS producteur,
1421
        CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
1422
        CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
1423
        creation INTO roles
1424
        FROM z_asgard.gestion_schema_etr
1425
            LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
1426
            LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
1427
            LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
1428
        WHERE nom_schema = obj_schema ;
1429
            
1430
    -- permission sur le producteur
1431
    IF NOT pg_has_role(roles.producteur, 'USAGE')
1432
    THEN
1433
        RAISE EXCEPTION 'FIO5. Echec. Vous ne disposez pas des permissions nécessaires sur le schéma % pour réaliser cette opération.', obj_schema
1434
            USING HINT = 'Il vous faut être membre du rôle producteur ' || roles.producteur || '.' ;
1435
    END IF ;
1436
    
1437
    ------ REMISE A PLAT DU PROPRIETAIRE ------
1438
    IF NOT obj.prop = roles.producteur
1439
    THEN
1440
        -- permission sur le propriétaire de l'objet
1441
        IF NOT pg_has_role(obj.prop, 'USAGE')
1442
        THEN
1443
            RAISE EXCEPTION 'FIO6. Echec. Vous ne disposez pas des permissions nécessaires sur l''objet % pour réaliser cette opération.', obj_nom
1444
                USING HINT = 'Il vous faut être membre du rôle propriétaire de l''objet (' || obj.prop || ').' ;
1445
        END IF ;
1446
        
1447
        RAISE NOTICE 'réattribution de la propriété de % au rôle producteur du schéma :', obj_nom ;
1448
        l := 'ALTER ' || obj_typ || ' ' || quote_ident(obj_schema) || '.' || quote_ident(obj_nom)||
1449
                ' OWNER TO '  || quote_ident(roles.producteur) ;
1450
        EXECUTE l ;
1451
        RAISE NOTICE '> %', l ;
1452
    END IF ;    
1453
    
1454
    ------ DESTRUCTION DES PRIVILEGES ACTUELS ------
1455
    -- hors privilèges par défaut (définis par ALTER DEFAULT PRIVILEGE)
1456
    -- et hors révocations des privilèges par défaut de public sur
1457
    -- les types et les fonctions
1458
    -- pour le propriétaire, ces commandes ont pour effet
1459
    -- de remettre les privilèges par défaut supprimés
1460
    
1461
    -- public
1462
    RAISE NOTICE 'remise à zéro des privilèges manuels du pseudo-rôle public :' ;
1463
    FOR c IN (SELECT * FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ))
1464
    LOOP
1465
        EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
1466
        RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), 'public') ;
1467
    END LOOP ;
1468
    IF NOT FOUND
1469
    THEN
1470
        RAISE NOTICE '> néant' ;
1471
    END IF ;
1472

    
1473
    -- autres rôles
1474
    RAISE NOTICE 'remise à zéro des privilèges des autres rôles (pour le producteur, les éventuels privilèges manquants sont réattribués) :' ;
1475
    FOR r IN (SELECT rolname FROM pg_roles)
1476
    LOOP
1477
        FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role_obj(
1478
                        obj.oid, obj_typ, quote_ident(r.rolname)::regrole))
1479
        LOOP
1480
            EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
1481
            RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), r.rolname) ;
1482
            k := k + 1 ;
1483
        END LOOP ;        
1484
    END LOOP ;
1485
    IF NOT FOUND OR k = 0
1486
    THEN
1487
        RAISE NOTICE '> néant' ;
1488
    END IF ;
1489

    
1490
    ------ RECREATION DES PRIVILEGES DE L'EDITEUR ------
1491
    IF roles.editeur IS NOT NULL
1492
    THEN
1493
        -- sur les tables :
1494
        IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
1495
        THEN
1496
            RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
1497
            l := 'GRANT SELECT, UPDATE, DELETE, INSERT ON TABLE '
1498
                    || quote_ident(obj_schema) || '.' || quote_ident(obj_nom) ||
1499
                    ' TO ' || quote_ident(roles.editeur) ;
1500
            EXECUTE l ;
1501
            RAISE NOTICE '> %', l ;
1502
        -- sur les séquences :
1503
        ELSIF obj_typ IN ('sequence')
1504
        THEN
1505
            RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
1506
            l := 'GRANT SELECT, USAGE ON SEQUENCE '
1507
                    || quote_ident(obj_schema) || '.' || quote_ident(obj_nom) ||
1508
                    ' TO ' || quote_ident(roles.editeur) ;
1509
            EXECUTE l ;
1510
            RAISE NOTICE '> %', l ;
1511
        END IF ;        
1512
    END IF ;
1513
    
1514
    ------ RECREATION DES PRIVILEGES DU LECTEUR ------
1515
    IF roles.lecteur IS NOT NULL
1516
    THEN
1517
        -- sur les tables :
1518
        IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
1519
        THEN
1520
            RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
1521
            l := 'GRANT SELECT ON TABLE ' || quote_ident(obj_schema) || '.'
1522
                    || quote_ident(obj_nom) ||
1523
                    ' TO ' || quote_ident(roles.lecteur) ;
1524
            EXECUTE l ;
1525
            RAISE NOTICE '> %', l ;
1526
        -- sur les séquences :
1527
        ELSIF obj_typ IN ('sequence')
1528
        THEN
1529
            RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
1530
            l := 'GRANT SELECT ON SEQUENCE ' || quote_ident(obj_schema) || '.'
1531
                    || quote_ident(obj_nom) ||
1532
                    ' TO ' || quote_ident(roles.lecteur) ;
1533
            EXECUTE l ;
1534
            RAISE NOTICE '> %', l ;
1535
        END IF ;
1536
    END IF ;
1537
                
1538
    RETURN '__ REINITIALISATION REUSSIE.' ;
1539
END
1540
$_$;
1541

    
1542
ALTER FUNCTION z_asgard.asgard_initialise_obj(text, text, text)
1543
    OWNER TO g_admin_ext ;
1544

    
1545
COMMENT ON FUNCTION z_asgard.asgard_initialise_obj(text, text, text) IS 'ASGARD. Fonction qui réinitialise les privilèges sur un objet.' ;
1546

    
1547

    
1548
------ 4.10 - DEPLACEMENT D'OBJET ------
1549

    
1550
-- FUNCTION: z_asgard.asgard_deplace_obj(text, text, text, text, int)
1551

    
1552
CREATE OR REPLACE FUNCTION z_asgard.asgard_deplace_obj(
1553
                                obj_schema text,
1554
                                obj_nom text,
1555
                                obj_typ text,
1556
                                schema_cible text,
1557
                                variante int DEFAULT 1
1558
                                )
1559
    RETURNS text
1560
    LANGUAGE plpgsql
1561
    AS $_$
1562
/* OBJET : Cette fonction permet de déplacer un objet vers un nouveau
1563
           schéma en spécifiant la gestion voulue sur les droits de
1564
           l'objet : transfert ou réinitialisation des privilèges.
1565
           Dans le cas d'une table avec un ou plusieurs champs de
1566
           type serial, elle prend aussi en charge les privilèges
1567
           sur les séquences associées.
1568
ARGUMENTS :
1569
- "obj_schema" est le nom du schéma contenant l'objet, au format
1570
texte et sans guillemets ;
1571
- "obj_nom" est le nom de l'objet, au format texte et sans
1572
guillemets ;
1573
- "obj_typ" est le type de l'objet au format text ('table',
1574
'partitioned table' (assimilé à 'table'), 'view', 'materialized view',
1575
'foreign table', 'sequence', 'function', 'aggregate', 'type', 'domain') ;
1576
- "schema_cible" est le nom du schéma où doit être déplacé l'objet,
1577
au format texte et sans guillemets ;
1578
- "variante" [optionnel] est un entier qui définit le comportement
1579
attendu par l'utilisateur vis à vis des privilèges :
1580
    - 1 (valeur par défaut) | TRANSFERT COMPLET + CONSERVATION :
1581
    les privilèges des rôles producteur, éditeur et lecteur de
1582
    l'ancien schéma sont transférés sur ceux du nouveau. Si un
1583
    éditeur ou lecteur a été désigné pour le nouveau schéma mais
1584
    qu'aucun n'était défini pour l'ancien, le rôle reçoit les
1585
    privilèges standards pour sa fonction. Le cas échéant,
1586
    les privilèges des autres rôles sont conservés ;
1587
    - 2 | REINITIALISATION COMPLETE : les nouveaux
1588
    producteur, éditeur et lecteur reçoivent les privilèges
1589
    standard. Les privilèges des autres rôles sont supprimés ;
1590
    - 3 | TRANSFERT COMPLET + NETTOYAGE : les privilèges des rôles
1591
    producteur, éditeur et lecteur de l'ancien schéma sont transférés
1592
    sur ceux du nouveau. Si un éditeur ou lecteur a été désigné pour
1593
    le nouveau schéma mais qu'aucun n'était défini pour l'ancien,
1594
    le rôle reçoit les privilèges standards pour sa fonction.
1595
    Les privilèges des autres rôles sont supprimés ;
1596
    - 4 | TRANSFERT PRODUCTEUR + CONSERVATION : les privilèges de
1597
    l'ancien producteur sont transférés sur le nouveau. Les privilèges
1598
    des autres rôles sont conservés tels quels. C'est le comportement
1599
    d'une commande ALTER [...] SET SCHEMA (interceptée par l'event
1600
    trigger asgard_on_alter_objet) ;
1601
    - 5 | TRANSFERT PRODUCTEUR + REINITIALISATION : les privilèges
1602
    de l'ancien producteur sont transférés sur le nouveau. Les
1603
    nouveaux éditeur et lecteur reçoivent les privilèges standards.
1604
    Les privilèges des autres rôles sont supprimés ;
1605
    - 6 | REINITIALISATION PARTIELLE : les nouveaux
1606
    producteur, éditeur et lecteur reçoivent les privilèges
1607
    standard. Les privilèges des autres rôles sont conservés.
1608
SORTIE : '__ DEPLACEMENT REUSSI.' si la requête s'est exécutée normalement. */
1609
DECLARE
1610
    class_info record ;
1611
    roles record ;
1612
    roles_cible record ;
1613
    obj record ;
1614
    r record ;
1615
    c record ;
1616
    l text ;
1617
    c_lecteur text[] ;
1618
    c_editeur text[] ;
1619
    c_producteur text[] ;
1620
    c_n_lecteur text[] ;
1621
    c_n_editeur text[] ;
1622
    c_autres text[] ;
1623
    seq_liste oid[] ;
1624
    a text[] ;
1625
    s record ;
1626
    o oid ;
1627
BEGIN
1628

    
1629
    -- pour la suite, on assimile les partitions à des tables
1630
    IF obj_typ = 'partitioned table'
1631
    THEN
1632
        obj_typ := 'table' ;
1633
    END IF ;
1634

    
1635
    ------ TESTS PREALABLES ------
1636
    -- schéma système
1637
    IF obj_schema ~ ANY(ARRAY['^pg_toast', '^pg_temp', '^pg_catalog$',
1638
                            '^public$', '^information_schema$', '^topology$'])
1639
    THEN
1640
        RAISE EXCEPTION 'FDO1. Opération interdite. Le schéma % est un schéma système.', obj_schema ;
1641
    END IF ;
1642
    
1643
    -- schéma de départ non référencé
1644
    IF NOT obj_schema IN (SELECT nom_schema FROM z_asgard.gestion_schema_usr WHERE creation)
1645
    THEN
1646
        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 ;
1647
    END IF ;
1648
    
1649
    -- schéma cible non référencé
1650
    IF NOT schema_cible IN (SELECT nom_schema FROM z_asgard.gestion_schema_usr WHERE creation)
1651
    THEN
1652
        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 ;
1653
    END IF ;
1654
    
1655
    -- type invalide + récupération des informations sur le catalogue contenant l'objet
1656
    SELECT
1657
        xtyp, xclass, xprefix || 'name' AS xname, xprefix || 'owner' AS xowner,
1658
        xprefix || 'namespace' AS xschema
1659
        INTO class_info
1660
        FROM unnest(ARRAY['table', 'foreign table', 'view', 'materialized view',
1661
                        'sequence', 'type', 'domain', 'function', 'aggregate'],
1662
                    ARRAY['pg_class', 'pg_class', 'pg_class', 'pg_class',
1663
                        'pg_class', 'pg_type', 'pg_type', 'pg_proc', 'pg_proc'],
1664
                    ARRAY['rel', 'rel', 'rel', 'rel', 'rel', 'typ', 'typ',
1665
                        'pro', 'pro']) AS typ (xtyp, xclass, xprefix)
1666
            WHERE typ.xtyp = obj_typ ;
1667
            
1668
    IF NOT FOUND
1669
    THEN
1670
        RAISE EXCEPTION 'FDO4. Echec. Le type % n''existe pas ou n''est pas pris en charge.', obj_typ
1671
            USING HINT = 'Types acceptés : ''table'', ''partitioned table'' (assimilé à ''table''), ''view'', ''materialized view'', ''foreign table'', ''sequence'', ''function'', ''aggregate'', ''type'', ''domain''.' ;
1672
    END IF ;
1673
        
1674
    -- objet inexistant + récupération du propriétaire
1675
    EXECUTE 'SELECT ' || class_info.xowner || '::regrole::text AS prop, '
1676
            || class_info.xclass || '.oid FROM pg_catalog.' || class_info.xclass
1677
            || ' WHERE ' || class_info.xname || ' = ' || quote_literal(obj_nom) 
1678
            || ' AND ' || class_info.xschema || '::regnamespace::text = quote_ident('
1679
            || quote_literal(obj_schema) || ')'
1680
        INTO obj ;
1681
            
1682
    IF obj.prop IS NULL
1683
    THEN
1684
        RAISE EXCEPTION 'FDO5. Echec. L''objet % n''existe pas.', obj_nom ;
1685
    END IF ;
1686
    
1687
    ------ RECUPERATION DES ROLES ------
1688
    -- schéma de départ :
1689
    SELECT
1690
        r1.rolname AS producteur,
1691
        CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
1692
        CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
1693
        creation INTO roles
1694
        FROM z_asgard.gestion_schema_etr
1695
            LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
1696
            LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
1697
            LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
1698
        WHERE nom_schema = obj_schema ;
1699
        
1700
    -- schéma cible :
1701
    SELECT
1702
        r1.rolname AS producteur,
1703
        CASE WHEN editeur = 'public' THEN 'public' ELSE r2.rolname END AS editeur,
1704
        CASE WHEN lecteur = 'public' THEN 'public' ELSE r3.rolname END AS lecteur,
1705
        creation INTO roles_cible
1706
        FROM z_asgard.gestion_schema_etr
1707
            LEFT JOIN pg_catalog.pg_roles AS r1 ON r1.oid = oid_producteur
1708
            LEFT JOIN pg_catalog.pg_roles AS r2 ON r2.oid = oid_editeur
1709
            LEFT JOIN pg_catalog.pg_roles AS r3 ON r3.oid = oid_lecteur
1710
        WHERE nom_schema = schema_cible ;
1711
            
1712
    -- permission sur le producteur du schéma cible
1713
    IF NOT pg_has_role(roles_cible.producteur, 'USAGE')
1714
    THEN
1715
        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
1716
            USING HINT = 'Il vous faut être membre du rôle producteur ' || roles_cible.producteur || '.' ;
1717
    END IF ;
1718
    
1719
    -- permission sur le propriétaire de l'objet
1720
    IF NOT pg_has_role(obj.prop, 'USAGE')
1721
    THEN
1722
        RAISE EXCEPTION 'FDO7. Echec. Vous ne disposez pas des permissions nécessaires sur l''objet % pour réaliser cette opération.', obj_nom
1723
            USING HINT = 'Il vous faut être membre du rôle propriétaire de l''objet (' || obj.prop || ').' ;
1724
    END IF ;
1725
    
1726
    ------ MEMORISATION DES PRIVILEGES ACTUELS ------
1727
    -- ancien producteur :
1728
    SELECT array_agg(commande) INTO c_producteur
1729
        FROM z_asgard.asgard_synthese_role_obj(
1730
                obj.oid, obj_typ, quote_ident(roles.producteur)::regrole) ;
1731
    
1732
    -- ancien éditeur :
1733
    IF roles.editeur = 'public'
1734
    THEN
1735
        SELECT array_agg(commande) INTO c_editeur
1736
            FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
1737
    ELSIF roles.editeur IS NOT NULL
1738
    THEN
1739
        SELECT array_agg(commande) INTO c_editeur
1740
            FROM z_asgard.asgard_synthese_role_obj(
1741
                    obj.oid, obj_typ, quote_ident(roles.editeur)::regrole) ;
1742
    END IF ;
1743
                
1744
    -- ancien lecteur :
1745
    IF roles.lecteur = 'public'
1746
    THEN
1747
        SELECT array_agg(commande) INTO c_lecteur
1748
            FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
1749
    ELSIF roles.lecteur IS NOT NULL
1750
    THEN
1751
        SELECT array_agg(commande) INTO c_lecteur
1752
            FROM z_asgard.asgard_synthese_role_obj(
1753
                    obj.oid, obj_typ, quote_ident(roles.lecteur)::regrole) ;
1754
    END IF ;
1755
    
1756
    -- nouvel éditeur :
1757
    IF roles_cible.editeur = 'public'
1758
    THEN
1759
        SELECT array_agg(commande) INTO c_n_editeur
1760
            FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
1761
    ELSIF roles_cible.editeur IS NOT NULL
1762
    THEN
1763
        SELECT array_agg(commande) INTO c_n_editeur
1764
            FROM z_asgard.asgard_synthese_role_obj(
1765
                    obj.oid, obj_typ, quote_ident(roles_cible.editeur)::regrole) ;
1766
    END IF ;
1767
                
1768
    -- nouveau lecteur :
1769
    IF roles_cible.lecteur = 'public'
1770
    THEN
1771
        SELECT array_agg(commande) INTO c_n_lecteur
1772
            FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
1773
    ELSIF roles_cible.lecteur IS NOT NULL
1774
    THEN
1775
        SELECT array_agg(commande) INTO c_n_lecteur
1776
            FROM z_asgard.asgard_synthese_role_obj(
1777
                    obj.oid, obj_typ, quote_ident(roles_cible.lecteur)::regrole) ;
1778
    END IF ;
1779
    
1780
    -- autres rôles :
1781
    -- pour ces commandes, contrairement aux précédentes, le rôle
1782
    -- est inséré dès maintenant (avec "format")
1783
    -- public
1784
    IF NOT 'public' = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
1785
            roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL))
1786
    THEN
1787
        SELECT array_agg(format(commande, 'public')) INTO c_autres
1788
            FROM z_asgard.asgard_synthese_public_obj(obj.oid, obj_typ) ;
1789
    END IF ;
1790
    -- et le reste
1791
    FOR r IN (SELECT rolname FROM pg_roles
1792
            WHERE NOT rolname = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
1793
                roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL)))
1794
    LOOP
1795
        SELECT array_agg(format(commande, r.rolname::text)) INTO a
1796
            FROM z_asgard.asgard_synthese_role_obj(
1797
                    obj.oid, obj_typ, quote_ident(r.rolname)::regrole) ;
1798
        IF FOUND
1799
        THEN
1800
            c_autres := array_cat(c_autres, a) ;
1801
            a := NULL ;
1802
        END IF ;
1803
    END LOOP ;
1804
    
1805
    ------ PRIVILEGES SUR LES SEQUENCES ASSOCIEES ------
1806
    IF obj_typ = 'table'
1807
    THEN
1808
        -- dans le cas d'une table, on recherche les séquences
1809
        -- utilisées par ses éventuels champs de type serial.
1810
        -- elles sont repérées par le fait qu'il existe
1811
        -- une dépendance de type "DEPENDENCY_AUTO" entre
1812
        -- la séquence et un champ de la table
1813
        FOR s IN (
1814
            SELECT
1815
                pg_class.oid
1816
                FROM pg_catalog.pg_depend LEFT JOIN pg_catalog.pg_class
1817
                    ON pg_class.oid = pg_depend.objid
1818
                WHERE pg_depend.classid = 'pg_catalog.pg_class'::regclass::oid
1819
                    AND pg_depend.refclassid = 'pg_catalog.pg_class'::regclass::oid
1820
                    AND pg_depend.refobjid = obj.oid
1821
                    AND pg_depend.refobjsubid > 0
1822
                    AND pg_depend.deptype = 'a'
1823
                    AND pg_class.relkind = 'S'
1824
            )
1825
        LOOP
1826
            -- liste des séquences
1827
            seq_liste := array_append(seq_liste, s.oid) ;
1828
            
1829
            -- récupération des privilèges
1830
            -- ancien producteur :
1831
            SELECT array_agg(commande) INTO a
1832
                FROM z_asgard.asgard_synthese_role_obj(
1833
                        s.oid, 'sequence', quote_ident(roles.producteur)::regrole) ;
1834
            IF FOUND
1835
            THEN
1836
                c_producteur := array_cat(c_producteur, a) ;
1837
                a := NULL ;
1838
            END IF ;
1839
        
1840
            -- ancien éditeur :
1841
            IF roles.editeur = 'public'
1842
            THEN
1843
                SELECT array_agg(commande) INTO a
1844
                    FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
1845
            ELSIF roles.editeur IS NOT NULL
1846
            THEN
1847
                SELECT array_agg(commande) INTO a
1848
                    FROM z_asgard.asgard_synthese_role_obj(
1849
                            s.oid, 'sequence'::text, quote_ident(roles.editeur)::regrole) ;
1850
            END IF ;
1851
            IF a IS NOT NULL
1852
            THEN
1853
                c_editeur := array_cat(c_editeur, a) ;
1854
                a := NULL ;
1855
            END IF ;
1856
                        
1857
            -- ancien lecteur :
1858
            IF roles.lecteur = 'public'
1859
            THEN
1860
                SELECT array_agg(commande) INTO a
1861
                    FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
1862
            ELSIF roles.lecteur IS NOT NULL
1863
            THEN
1864
                SELECT array_agg(commande) INTO a
1865
                    FROM z_asgard.asgard_synthese_role_obj(
1866
                            s.oid, 'sequence'::text, quote_ident(roles.lecteur)::regrole) ;
1867
            END IF ;
1868
            IF a IS NOT NULL
1869
            THEN
1870
                c_lecteur := array_cat(c_lecteur, a) ;
1871
                a := NULL ;
1872
            END IF ;
1873
            
1874
            -- nouvel éditeur :
1875
            IF roles_cible.editeur = 'public'
1876
            THEN
1877
                SELECT array_agg(commande) INTO a
1878
                    FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
1879
            ELSIF roles_cible.editeur IS NOT NULL
1880
            THEN
1881
                SELECT array_agg(commande) INTO a
1882
                    FROM z_asgard.asgard_synthese_role_obj(
1883
                            s.oid, 'sequence'::text, quote_ident(roles_cible.editeur)::regrole) ;
1884
            END IF ;
1885
            IF a IS NOT NULL
1886
            THEN
1887
                c_n_editeur := array_cat(c_n_editeur, a) ;
1888
                a := NULL ;
1889
            END IF ;
1890
                        
1891
            -- nouveau lecteur :
1892
            IF roles_cible.lecteur = 'public'
1893
            THEN
1894
                SELECT array_agg(commande) INTO a
1895
                    FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
1896
            ELSIF roles_cible.lecteur IS NOT NULL
1897
            THEN
1898
                SELECT array_agg(commande) INTO a
1899
                    FROM z_asgard.asgard_synthese_role_obj(
1900
                            s.oid, 'sequence'::text, quote_ident(roles_cible.lecteur)::regrole) ;
1901
            END IF ;
1902
            IF a IS NOT NULL
1903
            THEN
1904
                c_n_lecteur := array_cat(c_n_lecteur, a) ;
1905
                a := NULL ;
1906
            END IF ;
1907
            
1908
            -- autres rôles :
1909
            -- public
1910
            IF NOT 'public' = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
1911
                    roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL))
1912
            THEN
1913
                SELECT array_agg(format(commande, 'public')) INTO a
1914
                    FROM z_asgard.asgard_synthese_public_obj(s.oid, 'sequence'::text) ;
1915
                IF FOUND
1916
                THEN
1917
                    c_autres := array_cat(c_autres, a) ;
1918
                    a := NULL ;
1919
                END IF ;
1920
            END IF ;
1921
            -- et le reste
1922
            FOR r IN (SELECT rolname FROM pg_roles
1923
                    WHERE NOT rolname = ANY (array_remove(ARRAY[roles.producteur, roles.lecteur, roles.editeur,
1924
                        roles_cible.producteur, roles_cible.lecteur, roles_cible.editeur], NULL)))
1925
            LOOP
1926
                SELECT array_agg(format(commande, r.rolname::text)) INTO a
1927
                    FROM z_asgard.asgard_synthese_role_obj(
1928
                            s.oid, 'sequence'::text, quote_ident(r.rolname)::regrole) ;
1929
                IF FOUND
1930
                THEN
1931
                    c_autres := array_cat(c_autres, a) ;
1932
                    a := NULL ;
1933
                END IF ;
1934
            END LOOP ;
1935
        END LOOP ;
1936
    END IF ;
1937
    
1938
    ------ DEPLACEMENT DE L'OBJET ------
1939
    EXECUTE 'ALTER ' || obj_typ || ' ' || quote_ident(obj_schema) || '.' || quote_ident(obj_nom)||
1940
                ' SET SCHEMA '  || quote_ident(schema_cible) ;
1941
                
1942
    RAISE NOTICE '... Objet déplacé dans le schéma %.', schema_cible ;
1943
  
1944
    ------ PRIVILEGES DU PRODUCTEUR ------
1945
    -- par défaut, ils ont été transférés
1946
    -- lors du changement de propriétaire, il
1947
    -- n'y a donc qu'à réinitialiser pour les
1948
    -- variantes 2 et 6
1949
    
1950
    -- objet, réinitialisation pour 2 et 6
1951
    IF variante IN (2, 6) AND (c_producteur IS NOT NULL)
1952
    THEN
1953
        RAISE NOTICE 'réinitialisation des privilèges du nouveau producteur, % :', roles_cible.producteur ;
1954
        FOREACH l IN ARRAY c_producteur
1955
        LOOP
1956
            l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
1957
            EXECUTE format(l, roles_cible.producteur) ;
1958
            RAISE NOTICE '> %', format(l, roles_cible.producteur) ;
1959
        END LOOP ;
1960
    END IF ;
1961
    
1962
    ------- PRIVILEGES EDITEUR ------
1963
    -- révocation des privilèges du nouvel éditeur
1964
    IF roles_cible.editeur IS NOT NULL
1965
            AND (roles.editeur IS NULL OR NOT roles.editeur = roles_cible.editeur)
1966
            AND NOT roles.producteur = roles_cible.editeur
1967
            AND NOT variante = 4
1968
            AND c_n_editeur IS NOT NULL
1969
    THEN
1970
        RAISE NOTICE 'suppression des privilèges pré-existants du nouvel éditeur, % :', roles_cible.editeur ;
1971
        FOREACH l IN ARRAY c_n_editeur
1972
        LOOP
1973
            l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
1974
            EXECUTE format(l, roles_cible.editeur) ;
1975
            RAISE NOTICE '> %', format(l, roles_cible.editeur) ;  
1976
        END LOOP ;
1977
    END IF ;
1978
    
1979
    -- révocation des privilèges de l'ancien éditeur
1980
    IF roles.editeur IS NOT NULL AND NOT roles.editeur = roles_cible.producteur
1981
            AND (roles_cible.editeur IS NULL OR NOT roles.editeur = roles_cible.editeur OR NOT variante IN (1,3))
1982
            AND NOT variante = 4
1983
            AND c_editeur IS NOT NULL
1984
    THEN
1985
        RAISE NOTICE 'suppression des privilèges de l''ancien éditeur, % :', roles.editeur ;
1986
        FOREACH l IN ARRAY c_editeur
1987
        LOOP
1988
            l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
1989
            EXECUTE format(l, roles.editeur) ;
1990
            RAISE NOTICE '> %', format(l, roles.editeur) ;  
1991
        END LOOP ;
1992
    END IF ;
1993
    
1994
    -- reproduction sur le nouvel éditeur pour les variantes 1 et 3
1995
    IF roles.editeur IS NOT NULL
1996
            AND roles_cible.editeur IS NOT NULL
1997
            AND variante IN (1, 3)
1998
            AND c_editeur IS NOT NULL
1999
            AND NOT roles.editeur = roles_cible.editeur
2000
    THEN
2001
        RAISE NOTICE 'transfert des privilèges de l''ancien éditeur vers le nouvel éditeur, % :', roles_cible.editeur ;
2002
        FOREACH l IN ARRAY c_editeur
2003
        LOOP
2004
            l := replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.') ;
2005
            EXECUTE format(l, roles_cible.editeur) ;
2006
            RAISE NOTICE '> %', format(l, roles_cible.editeur) ;  
2007
        END LOOP ;
2008
    END IF ;
2009
    
2010
    -- attribution des privilèges standard au nouvel éditeur
2011
    -- pour les variantes 2, 5, 6
2012
    -- ou s'il n'y avait pas de lecteur sur l'ancien schéma
2013
    IF roles_cible.editeur IS NOT NULL
2014
          AND (variante IN (2, 5, 6) OR roles.editeur IS NULL)
2015
          AND NOT variante = 4
2016
    THEN
2017
        -- sur les tables :
2018
        IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
2019
        THEN
2020
            RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
2021
            l := 'GRANT SELECT, UPDATE, DELETE, INSERT ON TABLE '
2022
                    || quote_ident(schema_cible) || '.' || quote_ident(obj_nom) ||
2023
                    ' TO ' || quote_ident(roles_cible.editeur) ;
2024
            EXECUTE l ;
2025
            RAISE NOTICE '> %', l ;
2026
        -- sur les séquences libres :
2027
        ELSIF obj_typ IN ('sequence')
2028
        THEN
2029
            RAISE NOTICE 'application des privilèges standards pour le rôle éditeur du schéma :' ;
2030
            l := 'GRANT SELECT, USAGE ON SEQUENCE '
2031
                    || quote_ident(schema_cible) || '.' || quote_ident(obj_nom) ||
2032
                    ' TO ' || quote_ident(roles_cible.editeur) ;
2033
            EXECUTE l ;
2034
            RAISE NOTICE '> %', l ;
2035
        END IF ;
2036
        -- sur les séquences des champs serial :
2037
        IF seq_liste IS NOT NULL
2038
        THEN
2039
            FOREACH o IN ARRAY seq_liste
2040
            LOOP
2041
                l := 'GRANT SELECT, USAGE ON SEQUENCE '
2042
                    || o::regclass::text || ' TO ' || quote_ident(roles_cible.editeur) ;
2043
                EXECUTE l ;
2044
                RAISE NOTICE '> %', l ;
2045
            END LOOP ;
2046
        END IF ;
2047
    END IF ;
2048
    
2049
    ------- PRIVILEGES LECTEUR ------
2050
    -- révocation des privilèges du nouveau lecteur
2051
    IF roles_cible.lecteur IS NOT NULL
2052
            AND (roles.lecteur IS NULL OR NOT roles.lecteur = roles_cible.lecteur)
2053
            AND NOT roles.producteur = roles_cible.lecteur
2054
            AND (roles.editeur IS NULL OR NOT roles.editeur = roles_cible.lecteur)
2055
            AND NOT variante = 4
2056
            AND c_n_lecteur IS NOT NULL
2057
    THEN
2058
        RAISE NOTICE 'suppression des privilèges pré-existants du nouveau lecteur, % :', roles_cible.lecteur ;
2059
        FOREACH l IN ARRAY c_n_lecteur
2060
        LOOP
2061
            l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
2062
            EXECUTE format(l, roles_cible.lecteur) ;
2063
            RAISE NOTICE '> %', format(l, roles_cible.lecteur) ;  
2064
        END LOOP ;
2065
    END IF ;
2066
    
2067
    -- révocation des privilèges de l'ancien lecteur
2068
    IF roles.lecteur IS NOT NULL AND NOT roles.lecteur = roles_cible.producteur
2069
           AND (roles_cible.editeur IS NULL OR NOT roles.lecteur = roles_cible.editeur)
2070
           AND (roles_cible.lecteur IS NULL OR NOT roles.lecteur = roles_cible.lecteur OR NOT variante IN (1,3))
2071
           AND NOT variante = 4
2072
           AND c_lecteur IS NOT NULL
2073
    THEN
2074
        RAISE NOTICE 'suppression des privilèges de l''ancien lecteur, % :', roles.lecteur ;
2075
        FOREACH l IN ARRAY c_lecteur
2076
        LOOP
2077
            l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
2078
            EXECUTE format(l, roles.lecteur) ;
2079
            RAISE NOTICE '> %', format(l, roles.lecteur) ;  
2080
        END LOOP ;
2081
    END IF ;
2082
    
2083
    -- reproduction sur le nouveau lecteur pour les variantes 1 et 3
2084
    IF roles.lecteur IS NOT NULL
2085
            AND roles_cible.lecteur IS NOT NULL
2086
            AND variante IN (1, 3)
2087
            AND c_lecteur IS NOT NULL
2088
            AND NOT roles.lecteur = roles_cible.lecteur
2089
    THEN
2090
        RAISE NOTICE 'transfert des privilèges de l''ancien lecteur vers le nouveau lecteur, % :', roles_cible.lecteur ;
2091
        FOREACH l IN ARRAY c_lecteur
2092
        LOOP
2093
            l := replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.') ;
2094
            EXECUTE format(l, roles_cible.lecteur) ;
2095
            RAISE NOTICE '> %', format(l, roles_cible.lecteur) ;  
2096
        END LOOP ;
2097
    END IF ;
2098
    
2099
    -- attribution des privilèges standard au nouveau lecteur
2100
    -- pour les variantes 2, 5, 6
2101
    -- ou s'il n'y avait pas de lecteur sur l'ancien schéma
2102
    IF roles_cible.lecteur IS NOT NULL
2103
          AND (variante IN (2, 5, 6) OR roles.lecteur IS NULL)
2104
          AND NOT variante = 4
2105
    THEN
2106
        -- sur les tables :
2107
        IF obj_typ IN ('table', 'view', 'materialized view', 'foreign table')
2108
        THEN
2109
            RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
2110
            l := 'GRANT SELECT ON TABLE ' || quote_ident(schema_cible) || '.'
2111
                    || quote_ident(obj_nom) ||
2112
                    ' TO ' || quote_ident(roles_cible.lecteur) ;
2113
            EXECUTE l ;
2114
            RAISE NOTICE '> %', l ;
2115
        -- sur les séquences libres :
2116
        ELSIF obj_typ IN ('sequence')
2117
        THEN
2118
            RAISE NOTICE 'application des privilèges standards pour le rôle lecteur du schéma :' ;
2119
            l := 'GRANT SELECT ON SEQUENCE ' || quote_ident(schema_cible) || '.'
2120
                    || quote_ident(obj_nom) ||
2121
                    ' TO ' || quote_ident(roles_cible.lecteur) ;
2122
            EXECUTE l ;
2123
            RAISE NOTICE '> %', l ;
2124
        END IF ; 
2125
        -- sur les séquences des champs serial :
2126
        IF seq_liste IS NOT NULL
2127
        THEN
2128
            FOREACH o IN ARRAY seq_liste
2129
            LOOP
2130
                l := 'GRANT SELECT ON SEQUENCE '
2131
                    || o::regclass::text || ' TO ' || quote_ident(roles_cible.lecteur) ;
2132
                EXECUTE l ;
2133
                RAISE NOTICE '> %', l ;
2134
            END LOOP ;
2135
        END IF ;
2136
    END IF ;
2137
    
2138
    ------ AUTRES ROLES ------
2139
    -- pour les variantes 2, 3, 5, remise à zéro
2140
    IF variante IN (2, 3, 5)
2141
        AND c_autres IS NOT NULL
2142
    THEN
2143
        RAISE NOTICE 'remise à zéro des privilèges des autres rôles :' ;
2144
        FOREACH l IN ARRAY c_autres
2145
        LOOP
2146
            l := z_asgard.asgard_grant_to_revoke(replace(l, quote_ident(obj_schema) || '.', quote_ident(schema_cible) || '.')) ;
2147
            EXECUTE l ;
2148
            RAISE NOTICE '> %', l ;  
2149
        END LOOP ;    
2150
    END IF ;
2151

    
2152
    RETURN '__ DEPLACEMENT REUSSI.' ;
2153
END
2154
$_$;
2155

    
2156
ALTER FUNCTION z_asgard.asgard_deplace_obj(text, text, text, text, int)
2157
    OWNER TO g_admin_ext ;
2158

    
2159
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.' ;
2160

    
2161

    
2162

    
2163
------ 4.11 - OCTROI D'UN RÔLE À TOUS LES RÔLES DE CONNEXION ------
2164

    
2165
-- FUNCTION: z_asgard_admin.asgard_all_login_grant_role(text, boolean)
2166

    
2167
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_all_login_grant_role(n_role text, b boolean DEFAULT True)
2168
    RETURNS int
2169
    LANGUAGE plpgsql
2170
    AS $_$
2171
/* OBJET : Cette fonction confère à tous les rôles de connexion du
2172
           serveur l'appartenance au rôle donné en argument.
2173
ARGUMENTS :
2174
- n_role : une chaîne de caractères présumée correspondre à un nom de
2175
  rôle valide ;
2176
- b : [optionnel] un booléen. Si b vaut False et qu'un rôle de connexion est
2177
déjà membre du rôle considéré par héritage, la fonction ne fait rien. Si
2178
b vaut True (défaut), la fonction ne passera un rôle de connexion que s'il est
2179
lui-même membre du rôle considéré.
2180
SORTIE : un entier correspondant au nombre de rôles pour lesquels
2181
la permission a été accordée. */
2182
DECLARE
2183
    roles record ;
2184
    attributeur text ;
2185
    utilisateur text := current_user ;
2186
    c text ;
2187
    n int := 0 ;
2188
BEGIN
2189
    ------ TESTS PREALABLES -----
2190
    -- existance du rôle
2191
    IF NOT n_role IN (SELECT rolname FROM pg_catalog.pg_roles)
2192
    THEN
2193
        RAISE EXCEPTION 'FLG1. Echec. Le rôle % n''existe pas', n_role ;
2194
    END IF ;
2195
    
2196
    -- on cherche un rôle dont l'utilisateur est
2197
    -- membre et qui, soit a l'attribut CREATEROLE
2198
    -- soit a ADMIN OPTION sur le rôle
2199
    SELECT rolname INTO attributeur
2200
        FROM pg_roles
2201
        WHERE pg_has_role(rolname, 'MEMBER') AND rolcreaterole
2202
        ORDER BY rolname = current_user DESC ;
2203
    IF NOT FOUND
2204
    THEN
2205
        SELECT grantee INTO attributeur
2206
            FROM information_schema.applicable_roles
2207
            WHERE is_grantable = 'YES' AND role_name = n_role ;
2208
        IF NOT FOUND
2209
        THEN
2210
            RAISE EXCEPTION 'FLG2. Opération interdite. Permissions insuffisantes pour le rôle %.', n_role
2211
                USING HINT = 'Votre rôle doit être membre de ' || n_role
2212
                            || ' avec admin option ou disposer de l''attribut CREATEROLE pour réaliser cette opération.' ;
2213
        END IF ;
2214
    END IF ;
2215
    
2216
    EXECUTE 'SET ROLE ' || quote_ident(attributeur) ;
2217
    
2218
    IF b
2219
    THEN
2220
        FOR roles IN SELECT rolname
2221
                        FROM pg_roles LEFT JOIN pg_auth_members
2222
                                ON member = pg_roles.oid AND roleid = n_role::regrole::oid
2223
                        WHERE rolcanlogin AND member IS NULL
2224
                            AND NOT rolsuper
2225
        LOOP
2226
            c := 'GRANT ' || quote_ident(n_role) || ' TO ' || quote_ident(roles.rolname) ;
2227
            EXECUTE c ;
2228
            RAISE NOTICE '> %', c ;
2229
            n := n + 1 ;
2230
        END LOOP ;
2231
    ELSE
2232
        FOR roles IN SELECT rolname FROM pg_roles
2233
                        WHERE rolcanlogin AND NOT pg_has_role(rolname, n_role, 'MEMBER')
2234
        LOOP
2235
            c := 'GRANT ' || quote_ident(n_role) || ' TO ' || quote_ident(roles.rolname) ;
2236
            EXECUTE c ;
2237
            RAISE NOTICE '> %', c ;
2238
            n := n + 1 ;
2239
        END LOOP ;
2240
    END IF ;
2241
    
2242
    EXECUTE 'SET ROLE ' || quote_ident(utilisateur) ;
2243
    
2244
    RETURN n ;
2245
END
2246
$_$;
2247

    
2248
ALTER FUNCTION z_asgard_admin.asgard_all_login_grant_role(text, boolean)
2249
    OWNER TO g_admin ;
2250

    
2251
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.' ;
2252

    
2253

    
2254

    
2255
------ 4.12 - IMPORT DE LA NOMENCLATURE DANS GESTION_SCHEMA ------
2256

    
2257
-- FUNCTION: z_asgard_admin.asgard_import_nomenclature(text[])
2258

    
2259
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_import_nomenclature(
2260
                           domaines text[] default NULL::text[]
2261
                           )
2262
    RETURNS text
2263
    LANGUAGE plpgsql
2264
    AS $_$
2265
/* OBJET : Fonction qui importe dans la table de gestion les schémas manquants
2266
           de la nomenclature nationale - ou de certains domaines
2267
           de la nomenclature nationale listés en argument - toujours avec
2268
           creation valant False, même si le schéma existe (mais n'a pas été
2269
           référencé).
2270
           Des messages informent l'opérateur des schémas effectivement ajoutés.
2271
           Lorsque le schéma est déjà référencé dans la table de gestion, réappliquer
2272
           la fonction a pour effet de mettre à jour les champs relatifs à la
2273
           nomenclature.
2274
ARGUMENT : domaines (optionnel) : un tableau text[] contenant les noms des
2275
domaines à importer, soit le "niveau 1"/niv1 ou niv1_abr des schémas. Si non renseigné,
2276
toute la nomenclature est importée (hors schémas déjà référencés).
2277
SORTIE : '__ FIN IMPORT NOMENCLATURE.' si la requête s'est exécutée normalement. */
2278
DECLARE
2279
    item record ;
2280
    e_mssg text ;
2281
    e_detl text ;
2282
    e_hint text ;
2283
BEGIN
2284
    FOR item IN SELECT * FROM (
2285
            VALUES
2286
                ('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'),
2287
                ('c', true, 'Données génériques', 'donnees_generique', 'Démographie', 'demographie', 'c_don_gen_demographie', false, 'g_admin', NULL, 'g_consult'),
2288
                ('c', true, 'Données génériques', 'donnees_generique', 'Habillage des cartes', 'habillage', 'c_don_gen_habillage', false, 'g_admin', NULL, 'g_consult'),
2289
                ('c', true, 'Données génériques', 'donnees_generique', 'Intercommunalité', 'intercommunalite', 'c_don_gen_intercommunalite', false, 'g_admin', NULL, 'g_consult'),
2290
                ('c', true, 'Données génériques', 'donnees_generique', 'Milieu physique', 'milieu_physique', 'c_don_gen_milieu_physique', false, 'g_admin', NULL, 'g_consult'),
2291
                ('c', true, 'Eau', 'eau', 'Alimentation en eau potable', 'aep', 'c_eau_aep', false, 'g_admin', NULL, 'g_consult'),
2292
                ('c', true, 'Eau', 'eau', 'Assainissement', 'assainissement', 'c_eau_assainissement', false, 'g_admin', NULL, 'g_consult'),
2293
                ('c', true, 'Eau', 'eau', 'Masses d’eau', 'masse_eau', 'c_eau_masse_eau', false, 'g_admin', NULL, 'g_consult'),
2294
                ('c', true, 'Eau', 'eau', 'Ouvrages', 'ouvrage', 'c_eau_ouvrage', false, 'g_admin', NULL, 'g_consult'),
2295
                ('c', true, 'Eau', 'eau', 'Pêche', 'peche', 'c_eau_peche', false, 'g_admin', NULL, 'g_consult'),
2296
                ('c', true, 'Eau', 'eau', 'Surveillance', 'surveillance', 'c_eau_surveillance', false, 'g_admin', NULL, 'g_consult'),
2297
                ('c', true, 'Agriculture', 'agriculture', 'Environnement', 'agri_environnement', 'c_agri_environnement', false, 'g_admin', NULL, 'g_consult'),
2298
                ('c', true, 'Agriculture', 'agriculture', 'Agro-alimentaire', 'agro_alimentaire', 'c_agri_agroalimentaire', false, 'g_admin', NULL, 'g_consult'),
2299
                ('c', true, 'Agriculture', 'agriculture', 'Exploitation & élevage', 'exploitation_elevage', 'c_agri_exploi_elevage', false, 'g_admin', NULL, 'g_consult'),
2300
                ('c', true, 'Agriculture', 'agriculture', 'Parcellaire agricole', 'parcellaire_agricole', 'c_agri_parcellaire_agricole', false, 'g_admin', NULL, 'g_consult'),
2301
                ('c', true, 'Agriculture', 'agriculture', 'Santé animale', 'sante_animale', 'c_agri_sante_animale', false, 'g_admin', NULL, 'g_consult'),
2302
                ('c', true, 'Agriculture', 'agriculture', 'Santé végétale', 'sante_vegetale', 'c_agri_sante_vegetale', false, 'g_admin', NULL, 'g_consult'),
2303
                ('c', true, 'Risques', 'risque', 'Séismes', 'seisme', 'c_risque_seisme', false, 'g_admin', NULL, 'g_consult'),
2304
                ('c', true, 'Agriculture', 'agriculture', 'Zonages agricoles', 'zonages_agricoles', 'c_agri_zonages_agricoles', false, 'g_admin', NULL, 'g_consult'),
2305
                ('c', true, 'Air & climat', 'air_climat', 'Changement climatique', 'changement_climatique', 'c_air_clim_changement', false, 'g_admin', NULL, 'g_consult'),
2306
                ('c', true, 'Air & climat', 'air_climat', 'Météorologie', 'meteo', 'c_air_clim_meteo', false, 'g_admin', NULL, 'g_consult'),
2307
                ('c', true, 'Air & climat', 'air_climat', 'Qualité de l’air & pollution', 'qualité_pollution', 'c_air_clim_qual_polu', false, 'g_admin', NULL, 'g_consult'),
2308
                ('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Assiettes des servitudes', 'assiette_servitude', 'c_amgt_urb_servitude', false, 'g_admin', NULL, 'g_consult'),
2309
                ('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Politique européenne', 'politique_europeenne', 'c_amgt_urb_pol_euro', false, 'g_admin', NULL, 'g_consult'),
2310
                ('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Zonages d’aménagement', 'zonages_amenagement', 'c_amgt_urb_zon_amgt', false, 'g_admin', NULL, 'g_consult'),
2311
                ('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Zonages d’études', 'zonages_etudes', 'c_amgt_urb_zon_etudes', false, 'g_admin', NULL, 'g_consult'),
2312
                ('c', true, 'Aménagement & urbanisme', 'amenagement_urbanisme', 'Zonages de planification', 'zonages_planification', 'c_amgt_urb_zon_plan', false, 'g_admin', NULL, 'g_consult'),
2313
                ('c', true, 'Culture, société & services', 'culture_societe_service', 'Enseignement', 'enseignement', 'c_cult_soc_ser_enseignement', false, 'g_admin', NULL, 'g_consult'),
2314
                ('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'),
2315
                ('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'),
2316
                ('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'),
2317
                ('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'),
2318
                ('c', true, 'Culture, société & services', 'culture_societe_service', 'Tourisme', 'tourisme', 'c_cult_soc_ser_tourisme', false, 'g_admin', NULL, 'g_consult'),
2319
                ('c', true, 'Données génériques', 'donnees_generique', 'Action publique', 'action_publique', 'c_don_gen_action_publique', false, 'g_admin', NULL, 'g_consult'),
2320
                ('c', true, 'Données génériques', 'donnees_generique', 'Découpage administratif', 'administratif', 'c_don_gen_administratif', false, 'g_admin', NULL, 'g_consult'),
2321
                ('c', true, 'Eau', 'eau', 'Travaux & entretien', 'travail_action', 'c_eau_travail_action', false, 'g_admin', NULL, 'g_consult'),
2322
                ('c', true, 'Eau', 'eau', 'Autres utilisations', 'utilisation_autre', 'c_eau_utilisation_autre', false, 'g_admin', NULL, 'g_consult'),
2323
                ('c', true, 'Eau', 'eau', 'Zonages eau', 'zonages_eau', 'c_eau_zonages', false, 'g_admin', NULL, 'g_consult'),
2324
                ('c', true, 'Foncier & sol', 'foncier_sol', 'Foncier agricole', 'foncier_agricole', 'c_fon_sol_agricole', false, 'g_admin', NULL, 'g_consult'),
2325
                ('c', true, 'Foncier & sol', 'foncier_sol', 'Mutations foncières', 'mutation_fonciere', 'c_fon_sol_mutation', false, 'g_admin', NULL, 'g_consult'),
2326
                ('c', true, 'Foncier & sol', 'foncier_sol', 'Occupation du sol', 'occupation_sol', 'c_fon_sol_occupation', false, 'g_admin', NULL, 'g_consult'),
2327
                ('c', true, 'Foncier & sol', 'foncier_sol', 'Propriétés foncières', 'propriete_fonciere', 'c_fon_sol_propriete', false, 'g_admin', NULL, 'g_consult'),
2328
                ('c', true, 'Forêt', 'foret', 'Description', 'description', 'c_foret_description', false, 'g_admin', NULL, 'g_consult'),
2329
                ('c', true, 'Forêt', 'foret', 'Défense de la forêt contre les incendies', 'dfci', 'c_foret_dfci', false, 'g_admin', NULL, 'g_consult'),
2330
                ('c', true, 'Forêt', 'foret', 'Gestion', 'gestion', 'c_foret_gestion', false, 'g_admin', NULL, 'g_consult'),
2331
                ('c', true, 'Forêt', 'foret', 'Règlement', 'reglement', 'c_foret_reglement', false, 'g_admin', NULL, 'g_consult'),
2332
                ('c', true, 'Forêt', 'foret', 'Transformation', 'transformation', 'c_foret_transformation', false, 'g_admin', NULL, 'g_consult'),
2333
                ('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'),
2334
                ('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'),
2335
                ('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Construction', 'construction', 'c_hab_vil_construction', false, 'g_admin', NULL, 'g_consult'),
2336
                ('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'),
2337
                ('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'),
2338
                ('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'),
2339
                ('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'),
2340
                ('c', true, 'Habitat & politique de la ville', 'habitat_politique_de_la_ville', 'Politique', 'politique', 'c_hab_vil_politique', false, 'g_admin', NULL, 'g_consult'),
2341
                ('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'),
2342
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Autres activités', 'autres_activites', 'c_mer_litt_autres_activites', false, 'g_admin', NULL, 'g_consult'),
2343
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Chasse maritime', 'chasse_maritime', 'c_mer_litt_chasse_maritime', false, 'g_admin', NULL, 'g_consult'),
2344
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Culture marine', 'culture_marine', 'c_mer_litt_culture_marine', false, 'g_admin', NULL, 'g_consult'),
2345
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Écologie du littoral', 'ecologie_littoral', 'c_mer_litt_ecol_littoral', false, 'g_admin', NULL, 'g_consult'),
2346
                ('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'),
2347
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Lutte anti-pollution', 'lutte_anti_pollution', 'c_mer_litt_lutte_anti_pollu', false, 'g_admin', NULL, 'g_consult'),
2348
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Navigation maritime', 'navigation_maritime', 'c_mer_litt_nav_maritime', false, 'g_admin', NULL, 'g_consult'),
2349
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Pêche maritime', 'peche_maritime', 'c_mer_litt_peche_maritime', false, 'g_admin', NULL, 'g_consult'),
2350
                ('c', true, 'Mer & littoral', 'mer_littoral', 'Topographie', 'topographie', 'c_mer_litt_topographie', false, 'g_admin', NULL, 'g_consult'),
2351
                ('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Chasse', 'chasse', 'c_nat_pays_bio_chasse', false, 'g_admin', NULL, 'g_consult'),
2352
                ('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'),
2353
                ('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Inventaires paysages', 'inventaire_paysage', 'c_nat_pays_bio_invent_pays', false, 'g_admin', NULL, 'g_consult'),
2354
                ('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Zonages nature', 'zonage_nature', 'c_nat_pays_bio_zonage_nat', false, 'g_admin', NULL, 'g_consult'),
2355
                ('c', true, 'Nature, paysage & biodiversité', 'nature_paysage_biodiversite', 'Zonages paysages', 'zonage_paysage', 'c_nat_pays_bio_zonage_pays', false, 'g_admin', NULL, 'g_consult'),
2356
                ('c', true, 'Nuisances', 'nuisance', 'Bruit', 'bruit', 'c_nuis_bruit', false, 'g_admin', NULL, 'g_consult'),
2357
                ('c', true, 'Nuisances', 'nuisance', 'Déchets', 'dechet', 'c_nuis_dechet', false, 'g_admin', NULL, 'g_consult'),
2358
                ('c', true, 'Nuisances', 'nuisance', 'Nuisances électromagnétiques', 'nuisance_electromagnetique', 'c_nuis_electromag', false, 'g_admin', NULL, 'g_consult'),
2359
                ('c', true, 'Nuisances', 'nuisance', 'Pollution des sols', 'pollution_sol', 'c_nuis_pollu_sol', false, 'g_admin', NULL, 'g_consult'),
2360
                ('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'),
2361
                ('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Autre', 'autre', 'c_res_energ_autre', false, 'g_admin', NULL, 'g_consult'),
2362
                ('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Électricité', 'electricite', 'c_res_energ_electricite', false, 'g_admin', NULL, 'g_consult'),
2363
                ('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Hydrocarbures', 'hydrocarbure', 'c_res_energ_hydrocarbure', false, 'g_admin', NULL, 'g_consult'),
2364
                ('c', true, 'Réseaux & énergie', 'reseau_energie_divers', 'Télécommunications', 'telecommunication', 'c_res_energ_telecom', false, 'g_admin', NULL, 'g_consult'),
2365
                ('c', true, 'Risques', 'risque', 'Avalanche', 'avalanche', 'c_risque_avalanche', false, 'g_admin', NULL, 'g_consult'),
2366
                ('c', true, 'Risques', 'risque', 'Éruptions volcaniques', 'eruption_volcanique', 'c_risque_eruption_volcanique', false, 'g_admin', NULL, 'g_consult'),
2367
                ('c', true, 'Risques', 'risque', 'Gestion des risques', 'gestion_risque', 'c_risque_gestion_risque', false, 'g_admin', NULL, 'g_consult'),
2368
                ('c', true, 'Risques', 'risque', 'Inondations', 'inondation', 'c_risque_inondation', false, 'g_admin', NULL, 'g_consult'),
2369
                ('c', true, 'Risques', 'risque', 'Mouvements de terrain', 'mouvement_terrain', 'c_risque_mouvement_terrain', false, 'g_admin', NULL, 'g_consult'),
2370
                ('c', true, 'Risques', 'risque', 'Radon', 'radon', 'c_risque_radon', false, 'g_admin', NULL, 'g_consult'),
2371
                ('c', true, 'Risques', 'risque', 'Risques miniers', 'risque_minier', 'c_risque_minier', false, 'g_admin', NULL, 'g_consult'),
2372
                ('c', true, 'Risques', 'risque', 'Risques technologiques', 'risque_technologique', 'c_risque_techno', false, 'g_admin', NULL, 'g_consult'),
2373
                ('c', true, 'Risques', 'risque', 'Zonages risques naturels', 'zonages_risque_naturel', 'c_risque_zonages_naturel', false, 'g_admin', NULL, 'g_consult'),
2374
                ('c', true, 'Risques', 'risque', 'Zonages risques technologiques', 'zonages_risque_technologique', 'c_risque_zonages_techno', false, 'g_admin', NULL, 'g_consult'),
2375
                ('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'),
2376
                ('c', true, 'Sites industriels & production', 'site_industriel_production', 'Sites éoliens', 'site_eolien', 'c_indus_prod_eolien', false, 'g_admin', NULL, 'g_consult'),
2377
                ('c', true, 'Sites industriels & production', 'site_industriel_production', 'Sites industriels', 'site_industriel', 'c_indus_prod_industriel', false, 'g_admin', NULL, 'g_consult'),
2378
                ('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'),
2379
                ('c', true, 'Socio-économie', 'socio_economie', ' ', ' ', 'c_socio_eco_', false, 'g_admin', NULL, 'g_consult'),
2380
                ('c', true, 'Déplacements', 'transport_deplacement', 'Sécurité routière', 'securite_routiere', 'c_tr_depl_securite_routiere', false, 'g_admin', NULL, 'g_consult'),
2381
                ('c', true, 'Déplacements', 'transport_deplacement', 'Transport collectif', 'tr_collectif', 'c_tr_depl_collectif', false, 'g_admin', NULL, 'g_consult'),
2382
                ('c', true, 'Déplacements', 'transport_deplacement', 'Transport exceptionnel', 'tr_exceptionnel', 'c_tr_depl_exceptionnel', false, 'g_admin', NULL, 'g_consult'),
2383
                ('c', true, 'Déplacements', 'transport_deplacement', 'Transport de marchandises', 'tr_marchandise', 'c_tr_depl_marchandise', false, 'g_admin', NULL, 'g_consult'),
2384
                ('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'),
2385
                ('c', true, 'Déplacements', 'transport_deplacement', 'Trafic', 'trafic', 'c_tr_depl_trafic', false, 'g_admin', NULL, 'g_consult'),
2386
                ('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Aérien', 'aerien', 'c_tr_infra_aerien', false, 'g_admin', NULL, 'g_consult'),
2387
                ('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Circulation douce', 'circulation_douce', 'c_tr_infra_circulation_douce', false, 'g_admin', NULL, 'g_consult'),
2388
                ('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Ferroviaire', 'ferroviaire', 'c_tr_infra_ferroviaire', false, 'g_admin', NULL, 'g_consult'),
2389
                ('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Fluvial', 'fluvial', 'c_tr_infra_fluvial', false, 'g_admin', NULL, 'g_consult'),
2390
                ('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Maritime', 'maritime', 'c_tr_infra_maritime', false, 'g_admin', NULL, 'g_consult'),
2391
                ('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Plateformes multimodales', 'plateforme_multimodale', 'c_tr_infra_plateforme_multimod', false, 'g_admin', NULL, 'g_consult'),
2392
                ('c', true, 'Infrastructures de transport', 'transport_infrastructure', 'Routier', 'routier', 'c_tr_infra_routier', false, 'g_admin', NULL, 'g_consult')
2393
            ) AS t (bloc, nomenclature, niv1, niv1_abr, niv2, niv2_abr, nom_schema, creation, producteur, editeur, lecteur)
2394
            WHERE domaines IS NULL OR niv1 = ANY(domaines) OR niv1_abr = ANY(domaines)
2395
    LOOP
2396
        -- si le schéma n'était pas déjà référencé, il est ajouté
2397
        -- (toujours comme non créé, même s'il existe par ailleurs dans la base)
2398
        IF NOT item.nom_schema IN (SELECT gestion_schema_usr.nom_schema FROM z_asgard.gestion_schema_usr)
2399
        THEN
2400
            INSERT INTO z_asgard.gestion_schema_usr
2401
                (bloc, nomenclature, niv1, niv1_abr, niv2, niv2_abr, nom_schema, creation, producteur, editeur, lecteur) VALUES
2402
                (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) ;
2403
            RAISE NOTICE 'Le schéma % a été ajouté à la table de gestion.', item.nom_schema ;
2404
        
2405
        -- sinon les champs de la nomenclature sont simplement mis à jour, le cas échéant
2406
        ELSIF item.nom_schema IN (SELECT gestion_schema_usr.nom_schema FROM z_asgard.gestion_schema_usr)
2407
        THEN
2408
            UPDATE z_asgard.gestion_schema_usr
2409
                SET nomenclature = item.nomenclature,
2410
                    niv1 = item.niv1,
2411
                    niv1_abr = item.niv1_abr,
2412
                    niv2 = item.niv2,
2413
                    niv2_abr = item.niv2_abr
2414
                WHERE gestion_schema_usr.nom_schema = item.nom_schema
2415
                    AND (NOT nomenclature = item.nomenclature
2416
                        OR NOT coalesce(gestion_schema_usr.niv1, '') = coalesce(item.niv1, '')
2417
                        OR NOT coalesce(gestion_schema_usr.niv1_abr, '') = coalesce(item.niv1_abr, '')
2418
                        OR NOT coalesce(gestion_schema_usr.niv2, '') = coalesce(item.niv2, '')
2419
                        OR NOT coalesce(gestion_schema_usr.niv2_abr, '') = coalesce(item.niv2_abr, '')) ;
2420
            IF FOUND
2421
            THEN
2422
                RAISE NOTICE 'Les champs de la nomenclature ont été mis à jour pour le schéma %.', item.nom_schema ;
2423
            END IF ;
2424
    
2425
        END IF ;
2426
    END LOOP ;
2427

    
2428
    RETURN '__ FIN IMPORT NOMENCLATURE.' ;
2429

    
2430
EXCEPTION WHEN OTHERS THEN
2431
    GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
2432
                            e_hint = PG_EXCEPTION_HINT,
2433
                            e_detl = PG_EXCEPTION_DETAIL ;
2434
    RAISE EXCEPTION 'FIN0 > %', e_mssg
2435
        USING DETAIL = e_detl,
2436
            HINT = e_hint ;
2437
    
2438

    
2439
END
2440
$_$;
2441

    
2442
ALTER FUNCTION z_asgard_admin.asgard_import_nomenclature(text[])
2443
    OWNER TO g_admin ;
2444

    
2445
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.' ;
2446

    
2447

    
2448
------ 4.13 - REAFFECTATION DES PRIVILEGES D'UN RÔLE ------
2449

    
2450
-- FUNCTION: z_asgard_admin.asgard_reaffecte_role(text, text, boolean, boolean)
2451

    
2452
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_reaffecte_role(
2453
                                n_role text,
2454
                                n_role_cible text DEFAULT NULL,
2455
                                b_hors_asgard boolean DEFAULT False,
2456
                                b_privileges boolean DEFAULT True)
2457
    RETURNS text
2458
    LANGUAGE plpgsql
2459
    AS $_$
2460
/* OBJET : Cette fonction transfère tous les privilèges d'un rôle
2461
           à un autre, et en premier lieu ses fonctions de producteur,
2462
           éditeur et lecteur. Si aucun rôle cible n'est spécifié, les
2463
           privilèges sont simplement supprimés et g_admin devient
2464
           producteur des schémas, le cas échéant.
2465
ARGUMENTS :
2466
- n_role : une chaîne de caractères présumée correspondre à un nom de
2467
  rôle valide ;
2468
- n_role_cible : une chaîne de caractères présumée correspondre à un
2469
  nom de rôle valide ;
2470
- b_hors_asgard : un booléen, valeur par défaut False. Si ce paramètre
2471
  vaut True, la propriété et les privilèges sur les objets des schémas
2472
  non gérés par ASGARD ou hors schémas (par ex la base), sont pris en
2473
  compte. La propriété des objets reviendra à g_admin si aucun
2474
  rôle cible n'est spécifié ;
2475
- b_privileges : un booléen, valeur par défaut True. Indique si, dans
2476
  l'hypothèse où le rôle cible est spécifié, celui-ci doit recevoir
2477
  les privilèges et propriétés du rôle (True) ou seulement ses propriétés
2478
  (False).
2479
SORTIE : '__ REAFFECTATION REUSSIE' si la fonction s'est exécutée sans
2480
erreur. */
2481
DECLARE
2482
    item record ;
2483
    n_producteur_cible text := coalesce(n_role_cible, 'g_admin') ;
2484
    c record ;
2485
    k int ;
2486
BEGIN
2487

    
2488
    ------ TESTS PREALABLES -----
2489
    -- existance du rôle
2490
    IF NOT n_role IN (SELECT rolname FROM pg_catalog.pg_roles)
2491
    THEN
2492
        RAISE EXCEPTION 'FRR1. Echec. Le rôle % n''existe pas', n_role ;
2493
    END IF ;
2494
    
2495
    -- existance du rôle cible
2496
    IF n_role_cible IS NOT NULL AND NOT n_role_cible IN (SELECT rolname FROM pg_catalog.pg_roles)
2497
    THEN
2498
        RAISE EXCEPTION 'FRR2. Echec. Le rôle % n''existe pas', n_role_cible ;
2499
    END IF ;
2500
    
2501
    
2502
    IF NOT b_privileges
2503
    THEN
2504
        n_role_cible := NULL ;
2505
    END IF ;
2506
    
2507
    ------ FONCTION DE PRODUCTEUR ------
2508
    FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE producteur = n_role)
2509
    LOOP
2510
        IF item.editeur = n_producteur_cible
2511
        THEN
2512
            UPDATE z_asgard.gestion_schema_usr
2513
                SET editeur = NULL
2514
                WHERE nom_schema = item.nom_schema ;
2515
            RAISE NOTICE '... L''éditeur du schéma % a été supprimé.', item.nom_schema ;
2516
        END IF ;
2517
        
2518
        IF item.lecteur = n_producteur_cible
2519
        THEN
2520
            UPDATE z_asgard.gestion_schema_usr
2521
                SET lecteur = NULL
2522
                WHERE nom_schema = item.nom_schema ;
2523
            RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
2524
        END IF ;
2525
        
2526
        UPDATE z_asgard.gestion_schema_usr
2527
            SET producteur = n_role_cible
2528
            WHERE nom_schema = item.nom_schema ;
2529
            RAISE NOTICE '... Le producteur du schéma % a été redéfini.', item.nom_schema ;
2530
    END LOOP ;
2531
    
2532
    ------ FONCTION D'EDITEUR ------
2533
    -- seulement si le rôle cible n'est pas déjà producteur du schéma
2534
    FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE editeur = n_role)
2535
    LOOP
2536
        IF item.producteur = n_role_cible
2537
        THEN
2538
            RAISE NOTICE 'Le rôle cible est actuellement producteur du schéma %.', item.nom_schema ;
2539
            UPDATE z_asgard.gestion_schema_usr
2540
                SET editeur = NULL
2541
                WHERE nom_schema = item.nom_schema ;
2542
            RAISE NOTICE '... L''éditeur du schéma % a été supprimé.', item.nom_schema ;
2543
        ELSE
2544
        
2545
            IF item.lecteur = n_role_cible
2546
                THEN
2547
                UPDATE z_asgard.gestion_schema_usr
2548
                    SET lecteur = NULL
2549
                    WHERE nom_schema = item.nom_schema ;
2550
                RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
2551
            END IF ;
2552
            
2553
            UPDATE z_asgard.gestion_schema_usr
2554
                SET editeur = n_role_cible
2555
                WHERE nom_schema = item.nom_schema ;
2556
                RAISE NOTICE '... L''éditeur du schéma % a été redéfini.', item.nom_schema ;
2557
        
2558
        END IF ;
2559
    END LOOP ;
2560
    
2561
    ------ FONCTION DE LECTEUR ------
2562
    -- seulement si le rôle cible n'est pas déjà producteur ou éditeur du schéma
2563
    FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE lecteur = n_role)
2564
    LOOP
2565
        IF item.producteur = n_role_cible
2566
        THEN
2567
            RAISE NOTICE 'Le rôle cible est actuellement producteur du schéma %.', item.nom_schema ;
2568
            UPDATE z_asgard.gestion_schema_usr
2569
                SET lecteur = NULL
2570
                WHERE nom_schema = item.nom_schema ;
2571
            RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
2572
        ELSIF item.editeur = n_role_cible
2573
        THEN
2574
            RAISE NOTICE 'Le rôle cible est actuellement éditeur du schéma %.', item.nom_schema ;
2575
            UPDATE z_asgard.gestion_schema_usr
2576
                SET lecteur = NULL
2577
                WHERE nom_schema = item.nom_schema ;
2578
            RAISE NOTICE '... Le lecteur du schéma % a été supprimé.', item.nom_schema ;
2579
        ELSE
2580
            
2581
            UPDATE z_asgard.gestion_schema_usr
2582
                SET lecteur = n_role_cible
2583
                WHERE nom_schema = item.nom_schema ;
2584
                RAISE NOTICE '... Le lecteur du schéma % a été redéfini.', item.nom_schema ;
2585
        
2586
        END IF ;
2587
    END LOOP ;
2588
    
2589
    ------ PROPRIETES HORS ASGARD ------
2590
    IF b_hors_asgard
2591
    THEN
2592
        EXECUTE 'REASSIGN OWNED BY ' || quote_ident(n_role) || ' TO ' || quote_ident(n_producteur_cible) ;
2593
        RAISE NOTICE '> %', 'REASSIGN OWNED BY ' || quote_ident(n_role) || ' TO ' || quote_ident(n_producteur_cible) ;
2594
        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.' ;
2595
    END IF ;
2596
    
2597
    ------ PRIVILEGES RESIDUELS SUR LES SCHEMAS D'ASGARD -------
2598
    k := 0 ;
2599
    FOR item IN (SELECT * FROM z_asgard.gestion_schema_usr WHERE creation)
2600
    LOOP
2601
        FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role(
2602
                       quote_ident(item.nom_schema)::regnamespace, quote_ident(n_role)::regrole))
2603
        LOOP
2604
            EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
2605
            RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
2606
            
2607
            IF n_role_cible IS NOT NULL
2608
            THEN
2609
                EXECUTE format(c.commande, n_role_cible) ;
2610
                RAISE NOTICE '> %', format(c.commande, n_role_cible) ;
2611
            END IF ;
2612
            
2613
            k := k + 1 ;
2614
        END LOOP ;        
2615
    END LOOP ;
2616
    IF k > 0
2617
    THEN
2618
        IF n_role_cible IS NULL
2619
        THEN
2620
            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 ;
2621
        ELSE
2622
            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 ;
2623
        END IF ;
2624
    END IF ;
2625
    
2626
    ------ PRIVILEGES RESIDUELS SUR LES SCHEMAS HORS ASGARD ------
2627
    IF b_hors_asgard
2628
    THEN
2629
        k := 0 ;
2630
        FOR item IN (SELECT * FROM pg_catalog.pg_namespace
2631
                         LEFT JOIN z_asgard.gestion_schema_usr
2632
                             ON nspname::text = nom_schema AND creation
2633
                         WHERE nom_schema IS NULL)
2634
        LOOP
2635
            FOR c IN (SELECT * FROM z_asgard.asgard_synthese_role(
2636
                           quote_ident(item.nspname::text)::regnamespace, quote_ident(n_role)::regrole))
2637
            LOOP
2638
                EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
2639
                RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
2640
                
2641
                IF n_role_cible IS NOT NULL
2642
                THEN
2643
                    EXECUTE format(c.commande, n_role_cible) ;
2644
                    RAISE NOTICE '> %', format(c.commande, n_role_cible) ;
2645
                END IF ;
2646
                
2647
                k := k + 1 ;
2648
            END LOOP ;        
2649
        END LOOP ;
2650
        IF k > 0
2651
        THEN
2652
            IF n_role_cible IS NULL
2653
        THEN
2654
            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 ;
2655
        ELSE
2656
            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 ;
2657
        END IF ;
2658
        END IF ;
2659
    END IF ;
2660
    
2661
    ------- OBJETS HORS SCHEMAS ------
2662
    IF b_hors_asgard
2663
    THEN
2664
        k := 0 ;
2665
        FOR c IN (
2666
            WITH t_acl AS (
2667
            -- bases de données
2668
            SELECT 'DATABASE'::text AS type_obj, datname::text AS n_obj, unnest(datacl)::text AS acl
2669
                FROM pg_catalog.pg_database
2670
                WHERE datacl IS NOT NULL
2671
            UNION
2672
            -- tablespaces
2673
            SELECT 'TABLESPACE'::text AS type_obj, spcname::text AS n_obj, unnest(spcacl)::text AS acl
2674
                FROM pg_catalog.pg_tablespace
2675
                WHERE spcacl IS NOT NULL
2676
            UNION
2677
            -- foreign data wrappers
2678
            SELECT 'FOREIGN DATA WRAPPER'::text AS type_obj, fdwname::text AS n_obj, unnest(fdwacl)::text AS acl
2679
                FROM pg_catalog.pg_foreign_data_wrapper
2680
                WHERE fdwacl IS NOT NULL
2681
            UNION
2682
            -- foreign servers
2683
            SELECT 'FOREIGN SERVER'::text AS type_obj, srvname::text AS n_obj, unnest(srvacl)::text AS acl
2684
                FROM pg_catalog.pg_foreign_server
2685
                WHERE srvacl IS NOT NULL
2686
            UNION
2687
            -- langages
2688
            SELECT 'LANGUAGE'::text AS type_obj, lanname::text AS n_obj, unnest(lanacl)::text AS acl
2689
                FROM pg_catalog.pg_language
2690
                WHERE lanacl IS NOT NULL
2691
            UNION            
2692
            -- large objects
2693
            SELECT 'LARGE OBJECT'::text AS type_obj, pg_largeobject_metadata.oid::text AS n_obj, unnest(lomacl)::text AS acl
2694
                FROM pg_catalog.pg_largeobject_metadata
2695
                WHERE lomacl IS NOT NULL           
2696
            )
2697
            SELECT 'GRANT ' || privilege || ' ON ' || type_obj || ' ' || quote_ident(n_obj) || ' TO %I' AS commande
2698
                FROM t_acl, unnest(ARRAY['CREATE', 'CONNECT', 'TEMPORARY', 'USAGE', 'SELECT', 'UPDATE'],
2699
                                   ARRAY['C', 'c', 'T', 'U', 'r', 'w']) AS l (privilege, prvlg)
2700
                WHERE acl ~ ('^' || quote_ident(n_role)::regrole::text || '[=].*' || prvlg || '.*[/]')
2701
        ) LOOP
2702
            EXECUTE format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
2703
            RAISE NOTICE '> %', format(z_asgard.asgard_grant_to_revoke(c.commande), n_role) ;
2704
            
2705
            IF n_role_cible IS NOT NULL
2706
            THEN
2707
                EXECUTE format(c.commande, n_role_cible) ;
2708
                RAISE NOTICE '> %', format(c.commande, n_role_cible) ;
2709
            END IF ;
2710
            
2711
            k := k + 1 ;
2712
        END LOOP ;
2713
        IF k > 0
2714
        THEN
2715
            IF n_role_cible IS NULL
2716
            THEN
2717
                RAISE NOTICE '... Les privilèges résiduels du rôle % sur les objets hors schémas ont été révoqués.', n_role ;
2718
            ELSE
2719
                RAISE NOTICE '... Les privilèges résiduels du rôle % sur les objets hors schémas ont été réaffectés.', n_role ;
2720
            END IF ;
2721
        END IF ;
2722
    END IF ;
2723

    
2724
    RETURN '__ REAFFECTATION REUSSIE' ;
2725
END
2726
$_$;
2727

    
2728
ALTER FUNCTION z_asgard_admin.asgard_reaffecte_role(text, text, boolean, boolean)
2729
    OWNER TO g_admin ;
2730

    
2731
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.' ;
2732

    
2733

    
2734
------ 4.14 - REINITIALISATION DES PRIVILEGES SUR TOUS LES SCHEMAS ------
2735

    
2736
-- FUNCTION: z_asgard_admin.asgard_initialise_all_schemas(integer)
2737

    
2738
CREATE OR REPLACE FUNCTION z_asgard_admin.asgard_initialise_all_schemas(variante integer DEFAULT 0)
2739
    RETURNS varchar[]
2740
    LANGUAGE plpgsql
2741
    AS $_$
2742
/* OBJET : Cette fonction réinitialise les privilèges sur tous les
2743
           schémas référencés par ASGARD en une seule commande.
2744
           Pour les schémas d'ASGARD, même s'ils n'ont pas été référencés,
2745
           les droits nécessaires au bon fonctionnement du système seront
2746
           rétablis. 
2747
ARGUMENTS : un entier optionnel - 0 par défaut.
2748
Si 1, la fonction ne fera que s'assurer que tous les objets appartiennent
2749
au propriétaire du schéma. Si 2, la fonction ne s'exécutera que sur les
2750
schémas d'ASGARD. 
2751
SORTIE : NULL si la requête s'est exécutée normalement, sinon la liste
2752
des schémas qui n'ont pas pu être traités. Se reporter dans ce cas à
2753
l'onglet des messages pour le détail des erreurs. */
2754
DECLARE
2755
    s record ;
2756
    l varchar[] ;
2757
    b boolean ;
2758
    k integer ;
2759
    e_mssg text ;
2760
    e_detl text ;
2761
    e_hint text ;
2762
    utilisateur text := current_user::text ;
2763
    v_prop oid ;
2764
    t text ;
2765
BEGIN
2766

    
2767
    ------ CONTROLES PREALABLES ------
2768
    -- la fonction est dans z_asgard_admin, donc seuls les membres de
2769
    -- g_admin devraient pouvoir y accéder, mais au cas où :
2770
    IF NOT pg_has_role('g_admin', 'USAGE')
2771
    THEN
2772
        RAISE EXCEPTION 'FAS1. Opération interdite. Vous devez être membre de g_admin pour exécuter cette fonction.' ;
2773
    END IF ;
2774
    
2775
    IF NOT utilisateur IN (SELECT rolname FROM pg_catalog.pg_roles WHERE rolsuper)
2776
    THEN
2777
        SET ROLE g_admin ;
2778
    END IF ;
2779
    
2780
    -- permission manquante du propriétaire de la vue gestion_schema_usr
2781
    -- (en principe g_admin_ext) sur le schéma z_asgard_admin ou la table
2782
    -- gestion_schema :
2783
    SELECT relowner INTO v_prop
2784
        FROM pg_catalog.pg_class
2785
        WHERE relname = 'gestion_schema_usr' AND relnamespace = 'z_asgard'::regnamespace::oid ;
2786
        
2787
    IF NOT FOUND
2788
    THEN
2789
        RAISE EXCEPTION 'FAS2. Echec. La vue gestion_schema_usr est introuvable.' ;
2790
    END IF ;
2791
    
2792
    IF NOT has_schema_privilege(v_prop, 'z_asgard_admin', 'USAGE')
2793
            OR NOT has_table_privilege(v_prop, 'z_asgard_admin.gestion_schema', 'SELECT')
2794
    THEN
2795
        RAISE NOTICE '(temporaire) droits a minima pour le propriétaire de la vue gestion_schema_usr :' ;
2796
    
2797
        IF NOT has_schema_privilege(v_prop, 'z_asgard_admin', 'USAGE')
2798
        THEN
2799
            t := 'GRANT USAGE ON SCHEMA z_asgard_admin TO ' || v_prop::regrole::text ;
2800
            EXECUTE t ;
2801
            RAISE NOTICE '> %', t ;
2802
        END IF ;
2803
        
2804
        IF NOT has_table_privilege(v_prop, 'z_asgard_admin.gestion_schema', 'SELECT')
2805
        THEN
2806
            t := 'GRANT SELECT ON TABLE z_asgard_admin.gestion_schema TO ' || v_prop::regrole::text ;
2807
            EXECUTE t ;
2808
            RAISE NOTICE '> %', t ;
2809
        END IF ;
2810
        
2811
        RAISE NOTICE '---------------------------------' ;
2812
    END IF ;
2813
    
2814
    ------ NETTOYAGE ------
2815
    FOR s IN (
2816
            SELECT 2 AS n, nom_schema, producteur
2817
                FROM z_asgard.gestion_schema_usr
2818
                WHERE creation AND NOT nom_schema IN ('z_asgard', 'z_asgard_admin')
2819
            UNION VALUES (1, 'z_asgard', 'g_admin_ext'), (0, 'z_asgard_admin', 'g_admin')
2820
            ORDER BY n, nom_schema
2821
            )
2822
    LOOP
2823
        b := True ;
2824
        
2825
        IF s.n < 2 OR variante < 2
2826
        THEN
2827
        
2828
            ------ CONTROLE DES PRIVILEGES DE G_ADMIN SUR LE PRODUCTEUR ------
2829
            -- si g_admin n'est pas membre du producteur, alors on l'en rend
2830
            -- membre, sous réserve que ce ne soit pas un super-utilisateur ou
2831
            -- un rôle de connexion (ce dernier cas n'étant pas supposé arriver,
2832
            -- sauf désactivation temporaire de triggers ou à avoir donné
2833
            -- LOGIN au rôle après l'avoir désigné comme producteur).
2834
            IF NOT pg_has_role(s.producteur, 'USAGE')
2835
            THEN
2836
                -- propriétaire super-utilisateur
2837
                IF s.producteur IN (SELECT rolname FROM pg_catalog.pg_roles WHERE rolsuper)
2838
                THEN
2839
                    RAISE NOTICE '... ECHEC. Schéma % non traité.', s.nom_schema
2840
                        USING DETAIL = 'Seul un super-utilisateur est habilité à intervenir sur ce schéma. Producteur : ' || s.producteur || '.',
2841
                            HINT = 'Veuillez relancer la fonction en tant que super-utilisateur.' ;
2842
                    b := False ;
2843
                    l := array_append(l, s.nom_schema) ;
2844
                
2845
                -- propriétaire rôle de connexion
2846
                ELSIF s.producteur IN (SELECT rolname FROM pg_catalog.pg_roles WHERE rolcanlogin)
2847
                THEN
2848
                    RAISE NOTICE '... ECHEC. Schéma % non traité.', s.nom_schema
2849
                        USING DETAIL = 'Le producteur du schéma est un rôle de connexion. Producteur : ' || s.producteur || '.',
2850
                            HINT = 'Veuillez relancer la fonction en tant que super-utilisateur ou après avoir désigné un rôle de groupe comme producteur.' ;
2851
                    b := False ;
2852
                    l := array_append(l, s.nom_schema) ;
2853
                    
2854
                -- rôle de groupe lambda sur lequel g_admin n'a pas de permission
2855
                -- on la lui donne et on continue
2856
                ELSE            
2857
                    EXECUTE 'GRANT ' || quote_ident(s.producteur) || ' TO g_admin' ;
2858
                    RAISE NOTICE '... Permission accordée à g_admin sur le rôle %.', s.producteur ;
2859
                END IF ;
2860
            END IF ;
2861
            
2862
            IF b
2863
            THEN             
2864
                BEGIN
2865
                    IF variante = 1
2866
                    THEN
2867
                        -- lancement de la fonction de nettoyage des propriétaires
2868
                        IF quote_ident(s.producteur) IN (SELECT nspowner::regrole::text FROM pg_catalog.pg_namespace WHERE nspname = s.nom_schema)
2869
                        THEN
2870
                            -- version objets seuls si le propriétaire du schéma est bon
2871
                            RAISE NOTICE '(ré)attribution de la propriété des objets au rôle producteur du schéma :' ;
2872
                            SELECT z_asgard.asgard_admin_proprietaire(s.nom_schema, s.producteur, False) INTO k ;
2873
                            IF k = 0
2874
                            THEN
2875
                                RAISE NOTICE '> néant' ;
2876
                            END IF ;
2877
                        ELSE
2878
                            -- version schéma + objets sinon
2879
                            RAISE NOTICE '(ré)attribution de la propriété du schéma et des objets au rôle producteur du schéma :' ;
2880
                            PERFORM z_asgard.asgard_admin_proprietaire(s.nom_schema, s.producteur) ;
2881
                        END IF ;
2882
                            
2883
                    ELSE
2884
                        -- lancement de la fonction de réinitialisation des droits
2885
                        PERFORM z_asgard.asgard_initialise_schema(s.nom_schema) ;
2886
                            
2887
                    END IF ;
2888
                    
2889
                    RAISE NOTICE '... Le schéma % a été traité', s.nom_schema ;
2890
                    
2891
                EXCEPTION WHEN OTHERS THEN
2892
                    GET STACKED DIAGNOSTICS e_mssg = MESSAGE_TEXT,
2893
                                            e_hint = PG_EXCEPTION_HINT,
2894
                                            e_detl = PG_EXCEPTION_DETAIL ;
2895
                    RAISE NOTICE '... ECHEC. Schéma % non traité.', s.nom_schema ;
2896
                    RAISE NOTICE 'FAS0 > %', e_mssg
2897
                        USING DETAIL = e_detl,
2898
                            HINT = e_hint ;
2899
                    l := array_append(l, s.nom_schema) ;
2900
                END ;
2901
            END IF ;    
2902
        
2903
        RAISE NOTICE '---------------------------------' ;
2904
    END IF ;
2905
    
2906
    END LOOP ;
2907
    
2908
    EXECUTE 'SET ROLE ' || quote_ident(utilisateur) ;
2909
    
2910
    ------ RESULTAT ------
2911
    RETURN l ;
2912

    
2913
END
2914
$_$;
2915

    
2916
ALTER FUNCTION z_asgard_admin.asgard_initialise_all_schemas(integer)
2917
    OWNER TO g_admin ;
2918

    
2919
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.' ;
2920

    
    (1-1/1)