Authorizations
Les autorisations doivent évoluer et pour cela plusieurs travaux sont nécessaires.
réécrire les authorizations actuelles afin de remplacer les boutons radios par des cases à cocher
- localizationscope pouvoir choisir plusieurs scope, ne garder que les noeuds de plus haut niveau (tous les enfants sélectionnés) et concaténer l'information dans une seule requête (par exemple VARIADIC ARRAY[where 'localization'::text] )::ltree ? array[E'theix.theix__11', E'laqueuille.*', E'estreesmons.estreesmons__a06']::lquery[] )
- datagroup choix 0, n datagroups (@>)
- choix de plusieurs timescopes
- mise en place d'index gist sur ces colonnes
présentation des droits:
Les droits sont posés par types de données. Cependant on peut imaginer rajouter le type de données dans l'arborescence.
En ce cas on créerait autant d'autorisations qu'il y a de type de données.
A noter cependant que les localizationscopes peuvent différer d'un type de données à l'autre
- dérouler dans une treetable le ltree des localisationscope avec possibilité de dérouler un dernier niveau datagroup à chaque niveau cases à cocher. avec possibilité de fixer une période.
localisationscope | admin | dépôt | publication | extraction | date de début | date de fin |
---|---|---|---|---|---|---|
monprojet |
||||||
└───monsite |
||||||
└───maparcelle |
La requête correspondante contiendrait des or. Chaque ligne étant un cas where (utilisation éventuelle des @>). On ne garde que les premiers noeuds ayant une case cochées; les noeuds enfants (y compris ceux à venir) sont cochés.
- Choisir une combinaison de localisationscopes, datagroups et timeranges pour une requête du type where [localisationscopes] @> ... and [datagroups] @>... and [timerange] @>... C'est ce qui est actuellement présenté (mais avec des cases à cocher vs boutons radio)
web service et base de données:
Il est possible qu'une configuration d'interface (une case cachée) soit enregistrée dans plusieurs tables et correspondre à plusieurs policies.
-
admin : délégation de droits.
- Tout d'abord possibilité de déléguer un rôle en ajoutant un utilisateur dans un groupe que l'on possède. A priori, la clause admin de create role permet cette délégation de rôle. (Ce qui éviterait d'avoir un privilège createrole potentiellement faille de sécurité). On pourrait créer un nouveau rôle contenant tous les rôles de l'utilisateur avec la clause admin.
- ensuite la possibilité de créer une nouvelle autorisation qui est forcément une sous partie des rôle que l'on a. Logiciellement ce n'est peut-être pas compliqué mais qu'en est-il de cette possibilité sur la base de données. Peut-être un check à l'enregistrement du rôle qui vérifie que la nouvelle autorisation est inclusive d'une autorisation existante pour l'utilisateur. On peut aussi se contenter de limiter admin à la délégation d'une autorisation existente et limiter la création d'autorisations aux seules administrateurs de l'application.
-
dépôt il s'agit du droit de déposer un fichier(table binaryfile) en ajoutant une policy sur cette table.
-
publication il s'agit d'une policy sur la table data en ecriture
-
extraction : il s'agit d'une policy sur la table data en lecture
-
dates de début et de fin actuellement que pour la lecture, mais on pourrait rajouter cela pour le dépôt (il s'agit là de l'interval de date des données) ou pour l'administration (période de validité du droit)
données de référence
Dans la v1 pas de découpage fin de la données de référence. Cependant on pourrait s'appuyer soit sur les clés hiérarchique soit sur les références pour limiter la création d'une données de référence à un domaine (une policy en lecture ou écriture sur la table référence qui vérifie que la ligne insérée ou lue respecte bien un certain pattern)
graph LR
CreateAuthorisation -- store --> authorization
CreateAuthorisation -- role -->siOrerole
role -- herits<br />+admin <br />+ R/W<br />__ --> siOrerole
subgraph FrontEnd
Interface
end
subgraph BackEnd
Interface[Interface] --> Service
Interface[Interface] --> Service
Interface[Interface] --> Service
Service{Service} -.-> CreateAuthorisation
CreateAuthorisation o--o Utilisateur
Utilisateur o--o role
end
subgraph DataBase
authorization[(Authorization)] --> Policy((Policy))
siOrerole[(SiOrerole)] --> Policy
Policy ==> References[(References)]
Policy ==> Data[(Data)]
Policy ==> BinaryFile[(BinaryFile)]
end
style BackEnd fill:#ffccff,stroke:#333,stroke-width:4px
style FrontEnd fill:#ccffcc,stroke:#333,stroke-width:4px
style DataBase fill:#99ccff,stroke:#333,stroke-width:4px
style Policy fill:#80bfff,stroke:#004080,stroke-width:4px
style CreateAuthorisation fill:#ffb3ff,stroke:#ff00ff,stroke-width:4px
style Service fill:#ff6666,stroke:#800000,stroke-width:4px
base de données et policies
- pour chaque schema, on crée deux types
requiredauthorization
etauthorization
CREATE TYPE mons.requiredauthorizations AS
(
projet ltree,
localisation ltree
);
CREATE TYPE mons."authorization" AS
(
requiredauthorizations mons.requiredauthorizations,
datagroup text[],
timescope tsrange
);
Il est a noté que les champs pour le type `requiredauthorizations` dépende des type de données.
On peut créer un `requiredauthorizations` pour chaque type de données ou bien un `requiredauthorizations` qui comprends comme champs tous les champs `requiredauthorizations` de tous les types de données.
Un `requiredauthorizations` unique fonctionne puisque pour un type de données un champs non rempli accepte tout.
On peut commencer à créer `requiredauthorization` sans attribut et à chaque ajout d'un datatype ajouter les attribut correspondants aux noms des requiredAuthorizations de ce datatype.
ALTER TYPE requiredauthorization ADD ATTRIBUTE toto ltree
-
on utilise ce type pour remplacer
requiredauthorization
, datagroup, timescope deoresiauthorization
parauthorization
de typeschema.authorization
-
on crée une fonction
shema.isAuthorized
CREATE OR REPLACE FUNCTION mons.isAuthorized("authorization" mons."authorization", "authorizedArray" mons."authorization"[])
RETURNS BOOLEAN AS
as
$$
DECLARE
result TEXT;create or replace function isauthorized("authorization" mons."authorization", "authorizedArray" mons."authorization"[]) returns boolean
language plpgsql
as
$$
DECLARE
result TEXT;
BEGIN
select exists(select 1
into result
from unnest("authorizedArray") authorized
where
(
(
authorized).requiredauthorizations.projet is null or
(
COALESCE((authorized).requiredauthorizations.projet, ''::ltree) <@
COALESCE(("authorization").requiredauthorizations.projet, ''::ltree)
)
)
AND
(
(
authorized).requiredauthorizations.localization is null or
(
COALESCE((authorized).requiredauthorizations.localization, ''::ltree) <@
COALESCE(("authorization").requiredauthorizations.localization, ''::ltree)
)
)
AND
(
("authorized").datagroup= array[]::TEXT[] or
(
(authorized).datagroup @> COALESCE(("authorization").datagroup, array[]::TEXT[])
)
)
and (
("authorized").timescope = '(,)'::tsrange ) or
(
(authorized).timescope @> COALESCE(("authorization").timescope, '[,]'::tsrange)
)
);
return result;
END;
$$;
- pour en faciliter l'usage, on crée un operator ? pour comparer une authorization à un tableau d'authorization
CREATE OPERATOR ? (
LEFTARG = mons."authorization",
RIGHTARG = mons."authorization"[],
FUNCTION = mons.isAuthorized
);
- il suffit alors de tester créer la policy avec la règle
authorization ? authorizations
, oùauthorizations
est le tableau des authorizations pour un type donné
example de test sur mon soere
select "authorization"
from mons."data"
where "authorization" ? ARRAY[
(('projet_atlantique','oir')::mons.requiredauthorizations,
array['referentiel','qualitatif'],
'["1984-01-03 00:00:00","1984-01-05 00:00:00")'::tsRange
)::mons.authorization,
(('projet_manche','')::mons.requiredauthorizations,
array['referentiel'],
'["1984-01-01 00:00:00","1984-01-02 00:00:00")'::tsRange
)::mons.authorization
]