Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permissions : filtre taxonomique #3100

Open
bouttier opened this issue Jun 14, 2024 · 4 comments
Open

Permissions : filtre taxonomique #3100

bouttier opened this issue Jun 14, 2024 · 4 comments

Comments

@bouttier
Copy link
Contributor

bouttier commented Jun 14, 2024

Il est souhaité de rajouter aux permissions un filtre taxonomique permettant de restreindre une permission à certains taxons uniquement (#3097).

On souhaite pouvoir donner l’accès à plusieurs taxons, qui ne sont pas nécessairement des espèces (ceci dit je ne suis pas très convaincu qu’il soit bien souvent utile de donner accès à plusieurs taxons lorsque l’on peut donner l’accès à une branche de l’arbre taxonomique ?).
Même remarque que pour les filtres géographiques, on préférera pouvoir associer plusieurs taxons à une permissions plutôt que de devoir créer plusieurs permissions distinctes.

Pour mettre en place ce filtre, il faut :

  • Rajouter une table cor_permission_taxref au schéma gn_permissions avec une colonne FK vers gn_permissions.t_permissions.id_permission et une colonne FK vers taxonomie.taxref.cd_ref.
  • Modifier les modèles en conséquence, notamment en rajoutant une relationship taxons_filter sur le modèle Permission contenant la liste des taxons alloués par la permission.
  • Rajouter une colonne booléenne taxons_filter dans la table t_permissions_available
  • Rajouter dans Permission.filters_fields une entrée "TAXO": taxons_filter.
  • Il faut adapter la property Permission.filters de sorte qu’elle continue lorsque la liste taxons_filter est vide (cas d’un filtre de type liste non existant jusque là – tâche commune avec les filtres géographiques).
  • Il faut compléter PermFilter.__str__ pour l’affichage de la permission dans l’interface d’admin :
        elif self.name == "TAXO":
            if self.value:
                taxons_names = ','.join([t.lb_nom for t in self.value])
                return f"""<i class="fa fa-tree" aria-hidden="true"></i>  {taxons_names}"""
            else:
                return """<i class="fa fa-universal-access" aria-hidden="true"></i>  le vivant"""
  • Compléter PermissionAdmin et PermissionAvailableAdmin et notamment le filters_formatter

Pour prendre en compte le filtre dans la synthèse, il faut l’implémenter deux fois :

  • En python pour la vérification unitaire de l’accès à une observation lors de l’accès à la route get_one_synthese
  • En SQL pour le filtrage des observations à récupérer lors de l’accès à la route get_observations_for_web
    Puis il faut passer la colonne taxons_filter à TRUE dans la table t_permissions_available pour le R (et le E) de la synthèse.

Pour la vérification unitaire, à implémenter dans Synthese._has_permission_grant :

  • rajouter TAXO à if perm.has_other_filters_than(...)
  • rajouter un bloc if perm.taxons_filter: vérifiant si l’observation appartient à une partie autorisé de l’arbre taxonomique.
    Il faut probablement interroger la vue d’union récursive des taxons par cd_sup.

Pour le filtrage d’une liste d’observation, à implémenter dans SyntheseQuery.build_permissions_filter :

  • rajouter TAXO à if perm.has_other_filters_than(...)
  • rajouter un bloc if perm.taxons_filter:

Toute la difficulté de l’implémentation de ses filtres réside dans la détermination de l’ensemble des observations concernés par un filtre taxonomique alors que celui-ci porte sur une branche de l’arbre taxonomique.

Ce problème se pose de manière identique pour les règles de sensibilité, celle-ci pouvant porter également sur une branche de l’arbre taxonomique. La solution apporté pour la sensibilité consiste à dupliquer les règles de sensibilité pour chaque ramification de la branche sur laquelle porte la règle original. Ceci est effectué au moyen d’une vue matérialisé récursive sur le cd_sub :

-- Vues des règles actives
CREATE MATERIALIZED VIEW gn_sensitivity.t_sensitivity_rules_cd_ref AS
WITH RECURSIVE r(cd_ref) AS (
SELECT t.cd_ref,
r.id_sensitivity, r.cd_nom, r.nom_cite, r.id_nomenclature_sensitivity,
r.sensitivity_duration, r.sensitivity_territory, r.id_territory,
COALESCE(r.date_min, '1900-01-01'::date) AS date_min,
COALESCE(r.date_max, '1900-12-31'::date) AS date_max,
r.active, r.comments, r.meta_create_date, r.meta_update_date
FROM gn_sensitivity.t_sensitivity_rules r
JOIN taxonomie.taxref t ON t.cd_nom = r.cd_nom
WHERE r.active = true
UNION ALL
SELECT t.cd_ref , r.id_sensitivity, t.cd_nom, r.nom_cite, r.id_nomenclature_sensitivity,
r.sensitivity_duration, r.sensitivity_territory, r.id_territory, r.date_min,
r.date_max, r.active, r.comments, r.meta_create_date, r.meta_update_date
FROM taxonomie.taxref t, r
WHERE cd_taxsup = r.cd_ref
)
SELECT r.*
FROM r
WITH DATA;
Cependant, il apparaît peu opportun de dupliquer les permissions de la même manière (problème de performance, qui a d’ailleurs déjà pu être constaté lors de la duplication des règles pour les membres des groupes).

La piste privilégié consiste à rajouter dans taxref le chemin complet dans l’arbre taxonomique pour tous les taxons comme décrit ici : PnX-SI/TaxHub#354 Le filtrage est alors immédiat. Il semble très pertinent de finaliser cette fonctionnalité avant de rajouter les filtres taxonomiques. Il reste toutefois possible de mettre en place les filtres taxonomiques sans attendre en effectuant des requêtes WITH RECURSIVE, mais avec certainement de très mauvaise performance, notamment pour le filtrage de la synthèse.

@jpm-cbna
Copy link
Contributor

La piste privilégié consiste à rajouter dans taxref le chemin complet dans l’arbre taxonomique pour tous les taxons comme décrit ici : PnX-SI/TaxHub#354 Le filtrage est alors immédiat. Il semble très pertinent de finaliser cette fonctionnalité avant de rajouter les filtres taxonomiques.

Oui, cela semble nécessaire de finaliser la fonctionnalité en question si sa performance a pu être confirmée. Sur la branche feat/sinp, c'est la fonction Postgresl find_all_taxon_children() qui est utilisé et ce n'est pas assez performant.

@jpm-cbna
Copy link
Contributor

Une autre piste pour améliorer les performance de filtre serait d'utiliser les valeurs des colonnes regne, phylum, classe, ordre, famille, sous_famille, tribu, groupe1_inpn, groupe2_inpn et/ou groupe3_inpn.

En effet, je pense qu'il y a très peu de demande de permissions avec un filtre taxonomique au niveau du rang "genre" ou inférieur. Nous pourrions donc peut être nous en passer.

Ceci dit cette solution est plus restrictive et demande surement à dénormaliser le modèle de la base de données...

@jpm-cbna
Copy link
Contributor

ceci dit je ne suis pas très convaincu qu’il soit bien souvent utile de donner accès à plusieurs taxons lorsque l’on peut donner l’accès à une branche de l’arbre taxonomique ?

Oui, c'est bien le cas. Si un utilisateur sélectionne tous les enfants d'un nœud de l'arbre taxonomique, il faudrait automatiquement définir une seule permission en utilisant le nœud.

Ceci dit, ce n'est surement pas simple à mettre en place. Par ailleurs, je pense que dans la majorité des cas, les utilisateurs se simplifient la vie en demandant des permissions sur un seul niveau taxonomique englobant leurs besoins, quand c'est possible.

Un problème par exemple, c'est la sélection des "invertébrés". A priori, cela demande la sélection de plusieurs taxons sauf si on utilise le champ groupe3_inpn.

@bouttier
Copy link
Contributor Author

Il me semble que les filtres regne, phylum, classe, ordre, famille, sous_famille et tribu sont équivalent à un filtre sur le bon cd_ref, je me trompe ? Si c’est bien le cas, la différence serait donc de filtrer via un index ltree vs un index textuel sur les colonnes en questions. Je dirais qu’implémenter des filtres spécifiques pour ces colonnes ne serait à faire que si ltree ne suffit pas en terme de performance (donc à tester en premier lieu).

Les filtres sur les groupes INPN sont assez intéressants pour plusieurs raisons :

  • ils résument simplement des filtres portant sur plusieurs cd_ref
  • certaines personnes sont habituées à les utiliser plutôt que des cd_ref
  • le filtrage est à priori plus simple qu’une liste de cd_ref (mais vérifier les perfs de ltree sur une liste de taxons, qui, si elles sont suffisantes, peuvent permettre de s’affranchir d’une spécificité groupes INPN)

À réfléchir comment les filtres de groupes INPN s’articulent avec les filtres taxonomiques. Peut-être deux types de filtres distincts ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants