web-dev-qa-db-fra.com

PostgreSQL 9.3.13, comment puis-je rafraîchir les vues matérialisées avec différents utilisateurs?

[Je pense que la cause première de ce problème est que je ne comprends pas les autorisations et les privilèges ...]

Donc, pour définir la scène, la configuration que j'ai est une dB, appelez-la mydb.

J'ai deux utilisateurs, SPU1 et 1, SPU1 est une superutilisateur et 1 un utilisateur "régulier". Le propriétaire de mydb est SPU1. Je pense que je devrais aussi dire que 1 a créé des bases de données et créer des privilèges de rôle comme hérité d'un rôle de groupe.

J'ai un schéma SCH1, qui est un schéma défini par l'utilisateur.

Dans ce schéma, j'ai une table, appelez-le -TBL1 et une vue matérialisée, appelez-la MVW1.

Le propriétaire TBL1 est le SPU1, le propriétaire MVW1 est 1.


Le problème:

Dans la configuration actuelle, comme décrit ci-dessus, je ne peux pas rafraîchir MVW1 comme 1 ou SPU1. J'obtiens simplement l'erreur de plaisir ci-dessous (ce que j'ai beaucoup googlé mais que je n'ai rien trouvé qui résout tout à fait pour ma configuration ..).

ERROR:  permission denied for relation tbl1
********** Error **********

ERROR: permission denied for relation tbl1
SQL state: 42501

J'ai découvert que

  1. Changer le propriétaire de MVW1 au SPU1, me permet d'actualiser comme SPU1.
  2. Courir ci-dessous me permet d'actualiser MVW1 comme 1.

J'essaie de savoir quel (s) permission (s) manquant (s) (idéalement le minimum requis), j'ai besoin d'accorder à l'utilisateur ordinaire, 1, afin que je puisse rafraîchir cette vue lorsqu'elle est connectée.

La première option, tout en souhaitant savoir, ne résout pas mon problème. La deuxième option semble que je suis en vigueur accordant des autorisations superutilisantes à un non-superutilisateur, ou plutôt accorder des privilèges plus importants que nécessaire.

Si quelqu'un peut m'expliquer, ce qui se passe exactement ici (ou soulignez quelles informations que j'ai manquées dans la description de mon problème nécessaire pour le résoudre), et laissez-moi savoir si ma deuxième option est en fait la voie à suivre ou d'une meilleure alternative?

Merci beaucoup!

3
Alex

Vous pouvez le faire avec une fonction qui fonctionne dans le contexte de sécurité de son propriétaire.

Fonction qui rafraîchit la vue (Créez-la avec l'utilisateur qui possède le MV/Table):

CREATE OR REPLACE FUNCTION refresh_mvw1()
RETURNS void
SECURITY DEFINER
AS $$
BEGIN
REFRESH MATERIALIZED VIEW mvw1 with data;
RETURN;
END;
$$ LANGUAGE plpgsql;

Grant exécuter sur la fonction à tout utilisateur que vous souhaitez pouvoir rafraîchir la vue:

-- Users have 'execute' permissions by default on functions!
revoke all on function refresh_mvw1() from public;
grant execute on function refresh_mvw1() to u1;

Rafraîchir:

select refresh_mvw1();

Du Postgres Docs :

Sécurité Définisseur Spécifie que la fonction doit être exécutée avec les privilèges de l'utilisateur qui l'a créée.

Version prenant en charge un paramètre:

CREATE OR REPLACE FUNCTION refresh_mv_xxx(table_name text)
RETURNS void
SECURITY DEFINER
AS $$
DECLARE sql text; 
BEGIN
sql := 'REFRESH MATERIALIZED VIEW ' || table_name || ' with data';
EXECUTE sql;
RETURN;
END;
$$ LANGUAGE plpgsql;

... Mais je ne suis pas sûr si Dynamic SQL exécutera toujours comme le défini.

12
Philᵀᴹ

Une autre option consiste à créer un rôle de groupe (non superutilisateur) auxquels SPU1 et U1 appartiennent à/hériter de (par exemple les "rafraîchisseurs") et attribuent ce rôle de groupe en tant que propriétaire de la vue matérialisée.

1
Dologan