La théorie est bien décrite dans la documentation PostgreSQL - Row Security Policies . Vous trouverez ci-dessous une mise en œuvre pratique d'une petite tâche commerciale spécifique - masquer les données supprimées. Une étude sur la mise en œuvre du modèle de rôle à l'aide de RLS est présentée séparément.
L'article n'est pas nouveau, il n'y a pas de sens caché et de connaissance secrète. Juste une esquisse sur la mise en œuvre pratique d'une idée théorique. Si quelqu'un est intéressé, lisez la suite. Qui n'est pas intéressé - ne perdez pas votre temps.
Formulation du problème
Sans entrer dans le sujet, brièvement, la tâche peut être formulée comme suit: il existe un tableau qui implémente une certaine entité commerciale. Les lignes du tableau peuvent être supprimées, mais vous ne pouvez pas supprimer physiquement les lignes, vous devez les masquer.
Car il est dit: «Ne supprimez rien, renommez-le simplement. L'Internet stocke TOUT «
En cours de route, il est conseillé de ne pas réécrire les fonctions stockées déjà existantes travaillant avec cette entité.
Pour implémenter ce concept, la table a l'attribut is_deleted . Ensuite, tout est simple - vous devez faire en sorte que le client ne puisse voir que les lignes dans lesquelles l'attribut is_deleted est faux. Pour quoi le mécanisme de sécurité au niveau des lignes est utilisé .
la mise en oeuvre
Créer un rôle et un schéma séparés
CREATE ROLE repos;
CREATE SCHEMA repos;
Créer la table cible
CREATE TABLE repos.file
(
...
is_del BOOLEAN DEFAULT FALSE
);
CREATE SCHEMA repos
Activer la sécurité au niveau des lignes
ALTER TABLE repos.file ENABLE ROW LEVEL SECURITY ;
CREATE POLICY file_invisible_deleted ON repos.file FOR ALL TO dba_role USING ( NOT is_deleted );
GRANT ALL ON TABLE repos.file to dba_role ;
GRANT USAGE ON SCHEMA repos TO dba_role ;
Fonction de service - suppression d'une ligne dans une table
CREATE OR REPLACE repos.delete( curr_id repos.file.id%TYPE)
RETURNS integer AS $$
BEGIN
...
UPDATE repos.file
SET is_del = TRUE
WHERE id = curr_id ;
...
END
$$ LANGUAGE plpgsql SECURITY DEFINER;
Fonction commerciale - suppression de documents
CREATE OR REPLACE business_functions.deleteDoc( doc_for_delete JSON )
RETURNS JSON AS $$
BEGIN
...
PERFORM repos.delete( doc_id ) ;
...
END
$$ LANGUAGE plpgsql SECURITY DEFINER;
résultats
Le client supprime le document
SELECT business_functions.delCFile( (SELECT json_build_object( 'CId', 3 )) );
Après suppression, le client ne voit pas le document
SELECT business_functions.getCFile"( (SELECT json_build_object( 'CId', 3 )) ) ;
-----------------
(0 rows)
Mais le document n'a pas été supprimé de la base de données, seul l'attribut is_del a été modifié
psql -d my_db
SELECT id, name , is_del FROM repos.file ;
id | name | is_del
--+---------+------------
1 | test_1 | t
(1 row)
C'est ce qui était nécessaire pour formuler le problème.
Résultat
Si le sujet est intéressant, dans l'étude suivante, vous pouvez montrer un exemple d'implémentation d'un modèle basé sur les rôles pour partager l'accès aux données à l'aide de la sécurité au niveau des lignes.