filtre et limitation d’accès sur une table¶
Il est parfois utile de limiter la visualisation d’une table pour un utilisateur particulier.
Un exemple simple est le suivant: un commercial ne souhaite voir que c’est client.
la table client est composé comme cela:
- id
- lib
- commercial
Il y a trois possiblités:
- faire un filtre à chaque requête sql la charge de travail est du côté du développeur
- utiliser une RULE: la charge de travail est limité au concepteur de la base
- utilisation de trigger
Filtre par requête¶
select id, lib from client where commercial = 'TUTU';
Utilisation de rule¶
CREATE TABLE client (
id serial CONSTRAINT key_clt PRIMARY KEY,
lib varchar(100) NOT NULL,
commercial varchar(100) NOT NULL
);
CREATE VIEW clt_view AS SELECT * FROM client WHERE commercial=current_user;
CREATE OR REPLACE RULE example_1 AS
ON INSERT TO clt_view
DO INSTEAD INSERT INTO client (lib, commercial) VALUES (new.lib, current_user);
CREATE OR REPLACE RULE example_2 AS
ON UPDATE TO clt_view
DO INSTEAD UPDATE client SET lib=new.lib, commercial= current_user where id=new.id;
CREATE OR REPLACE RULE example_3 AS
ON DELETE TO clt_view
DO INSTEAD DELETE FROM client where id=old.id and commercial= current_user;
INSERT INTO client(lib, commercial) VALUES ('client1','userA');
INSERT INTO client(lib, commercial) VALUES ('client2','userB');
INSERT INTO client(lib, commercial) VALUES ('client3','postgres');
Warning
notre filtre utilise comme utilisateur le user de connexion à la base il faut donc pour avoir un suivi fin avoir un user de connexion par utilisateur
Maintenant suivant l’utilisateur connecté le select sur la vue clt_view ramènera plus ou moins de lignes.
L’update et le delete ne prend en compte que l’utilisateur connecté (un commercial ne peut supprimer un client qui ne lui appartient pas).
Le developpeur utilise la vue clt_view et nom la table client.
INSERT INTO clt_view(lib) VALUES('fred');
UPDATE clt_view SET lib='fred2' where id=4;
DELETE FROM clt_view where id=2;
DELETE FROM clt_view where id=4;
Note
si on souhaite que l’update d’un client qui ne nous appertient pas retourne un erreur on peut utiliser le code suivant
CREATE FUNCTION updateclt_trigger(old clt, new clt) RETURNS VOID AS
$$
BEGIN
UPDATE client SET lib=new.lib, commercial= current_user where id=new.id;
IF found THEN
RETURN;
END IF;
RAISE EXCEPTION 'Le client % n\'existe pas ou vous n\'avez pas les bonnes autorisations', new.id;
END;
CREATE OR REPLACE RULE example_2 AS
ON UPDATE TO clt_view
DO INSTEAD SELECT updateclt_trigger(OLD,NEW);
utilisation de trigger¶
Dans notre exemple seul l’utilisateur postgres peut modifier la table cpte
CREATE TABLE cpte (
id serial CONSTRAINT key_cpte PRIMARY KEY,
lib varchar(100) NOT NULL,
actif boolean DEFAULT true
);
CREATE OR REPLACE FUNCTION maj_trigger() RETURNS TRIGGER AS
$BODY$
DECLARE
b boolean;
BEGIN
select into b true where 'postgres'= current_user;
IF b = true THEN
RETURN NEW;
END IF;
RAISE EXCEPTION 'vous n\'avez pas les autorisations necessaire pour creer ou modifier % ', new.lib;
END ;
$BODY$
LANGUAGE 'plpgsql' ;
CREATE TRIGGER insert BEFORE INSERT ON cpte
FOR EACH ROW EXECUTE PROCEDURE maj_trigger();
Note
dans cette dernière utilisation la gestion du select doit être réalisé par une vue
on peut imaginer de faire des triggers sur la vue cpte_view pour gérer les insert / update et delete sur la table cpte