diff --git a/.gitignore b/.gitignore index 3a3acf00b..fe31849bb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,15 @@ config/conf_gn_module.toml config/monitoring/* !config/monitoring/generic frontend/assets/*.jpg + + +# Node +.npm +node_modules +npm-debug.log +coverage/ +node_modules/ +tmp/ +npm-debug.log* +yarn-error.log* +.ng_pkg_build/ diff --git a/README.rst b/README.rst index 8d2bbdf4d..1a9f852b2 100644 --- a/README.rst +++ b/README.rst @@ -4,8 +4,8 @@ Module GeoNature de suivis génériques Module générique de gestion des données de protocoles de type suivis ******************************************************************** -Ce module permet de gérer de façon générique des données de protocoles "simples" articulés en 3 niveaux : -des sites (nom, type, localisation) dans lesquels on fait des visites (dates, observateurs) +Ce module permet de gérer de façon générique des données de protocoles "simples" articulés en 3 niveaux : +des sites (nom, type, localisation) dans lesquels on fait des visites (dates, observateurs) dans lesquelles on peut faire des observations (espèces). Ces 3 niveaux peuvent être complétés des données spécifiques à chaque protocole, qui sont stockées dynamiquement dans la base de données sous forme de jsonb. @@ -33,6 +33,8 @@ Sommaire * `Documentation technique `_ * `Création d'un sous-module `_ * `Mise à jour du module `_ +* `Liste des commandes `_ +* `Permissions`_ Installation ************ @@ -116,11 +118,11 @@ Lancer la commande d'installation du sous-module flask monitorings install -- Par défaut la commande d'installation extrait le code du module depuis le chemin. +- Par défaut la commande d'installation extrait le code du module depuis le chemin. - Par exemple ``/contrib/test/`` donnera la valeur ``test`` à ``module_code``. - Le caractère ``/`` à la fin de ```` est optionnel. -Si la commande précise que le module est déjà installé (test sur le ``module_code``) on peut préciser une valeur différente pour ``module_code`` avec la commande : +Si la commande précise que le module est déjà installé (test sur le ``module_code``) on peut préciser une valeur différente pour ``module_code`` avec la commande : :: @@ -159,9 +161,9 @@ Cliquez sur le bouton ``Éditer`` -------------------------------- Le formulaire d'édition du module s'affiche et vous pouvez choisir les variable suivantes : - + - Jeux de données *(obligatoire)* : - + - Un module peut concerner plusieurs jeux de données, le choix sera ensuite proposé au niveau de chaque visite. - Liste des observateurs *(obligatoire)*: @@ -176,9 +178,9 @@ Le formulaire d'édition du module s'affiche et vous pouvez choisir les variable - Activer la synthèse *(non obligatoire, désactivée par défaut)* ? - Si on décide d'intégrer les données du sous-module dans la synthèse de GeoNature. - + - Affichage des taxons *(obligatoire)* ? - + - Définit comment sont affichés les taxons dans le module : - ``lb_nom`` : Nom latin, @@ -191,7 +193,7 @@ Le formulaire d'édition du module s'affiche et vous pouvez choisir les variable - Options spécifiques du sous-module : - - Un sous-module peut présenter des options qui lui sont propres et définies dans les paramètres spécifiques du sous-module. + - Un sous-module peut présenter des options qui lui sont propres et définies dans les paramètres spécifiques du sous-module. Exemples de sous-modules ======================== @@ -201,3 +203,20 @@ D'autres exemples de sous-modules sont disponibles sur le dépôt https://github * Protocole de suivi des oedicnèmes, * Protocole de suivi des mâles chanteurs de l'espèce chevêche d'Athena; * Protocole Suivi Temporel des Oiseaux de Montagne (STOM) + + +Permissions +************ + +Les permissions ne sont implémentées que partiellement, la notion de portée (mes données, les données de mon organisme, toutes les données) n'est pas prise en compte. Si un utilisateur à le droit de réaliser une action sur un type d'objet, il peut le faire sur l'ensemble des données. + +La gestion des permissions pour les rôles (utilisateur ou groupe) se réalise au niveau de l'interface d'administration des permissions de GeoNature. + +Il est possible de spéficier les permissions pour chaque type d'objet (groupes de sites, sites, visites et observations). + +Si aucune permission n'est associé à l'objet, les permissions auront comme valeurs celles associées au module qui lui même hérite des permissions du supermodule Monitoring qui lui même hérite de GéoNature. + + + +Par défaut, dès qu'un utilisateur à un droit suppérieur à 0 pour une action (c-a-d aucune portée) il peut réaliser cette action. Il est possible de surcharger les paramètres au niveau des fichiers de configuration des objets du module. (cf configuration des sous-modules). + diff --git a/VERSION b/VERSION index 0c62199f1..6710fa219 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.1 +0.2.2dev diff --git a/backend/command/cmd_install.py b/backend/command/cmd_install.py index 0c14d04f8..07ff98e10 100644 --- a/backend/command/cmd_install.py +++ b/backend/command/cmd_install.py @@ -10,8 +10,10 @@ from sqlalchemy import and_ from sqlalchemy.sql import text from sqlalchemy.exc import IntegrityError +from sqlalchemy.orm.exc import NoResultFound from geonature.utils.env import DB +from geonature.core.gn_permissions.models import CorObjectModule, TObjects from pypnnomenclature.models import TNomenclatures, BibNomenclaturesTypes from ..monitoring.models import TMonitoringModules @@ -42,10 +44,10 @@ def install_monitoring_module(module_config_dir_path, module_code, build): # on enleve le '/' de la fin de module_config_dir_path if module_config_dir_path[-1] == '/': - module_config_dir_path = module_config_dir_path[:-1] - + module_config_dir_path = module_config_dir_path[:-1] + module_code = module_code or module_config_dir_path.split('/')[-1] - + print('Install module {}'.format(module_code)) module_monitoring = get_simple_module('module_code', 'MONITORINGS') @@ -115,6 +117,10 @@ def install_monitoring_module(module_config_dir_path, module_code, build): DB.session.add(module) DB.session.commit() + # Insert permission object + if "permission_objects" in config: + id_module = module.id_module + insert_permission_object(id_module, config) #  run specific sql if os.path.exists(module_config_dir_path + '/synthese.sql'): @@ -174,6 +180,75 @@ def install_monitoring_module(module_config_dir_path, module_code, build): return +def insert_permission_object(id_module, permissions): + """ Insertion de l'association permission object + + Args: + id_module ([type]): id du module + permissions ([type]): liste des permissions à associer au module + + Raises: + e: [description] + """ + for perm in permissions: + print(f"Insert perm {perm}") + #load object + try: + object = DB.session.query(TObjects).filter(TObjects.code_object==perm).one() + # save + obj_mod = CorObjectModule(id_module=id_module, id_object = object.id_object) + + try: + DB.session.add(obj_mod) + DB.session.commit() + print(f" Ok") + except IntegrityError: + DB.session.rollback() + print(f" Impossible d'insérer la permission {perm} pour des raisons d'intégrités") + except NoResultFound as e: + print(f" Permission {perm} does'nt exists") + except Exception as e: + print(f" Impossible d'insérer la permission {perm} :{e}") + + + +@monitorings_cli.command('update_permission_objects') +@click.argument('module_code') +@with_appcontext +def update_perm_module_cmd(module_code): + """ + Mise à jour (uniquement insertion) des objets permissions associés au module + Défini par le paramètre permission_objects du fichier module.json + + Args: + module_code ([string]): code du sous module + + """ + try: + module = get_module('module_code', module_code) + except Exception: + print("le module n'existe pas") + return + path_module = CONFIG_PATH + '/' + module_code + '/module.json' + + if not os.path.exists(path_module): + print(f"Il n'y a pas de fichier {path_module} pour ce module") + return + config_module = json_from_file(path_module, None) + if not config_module: + print('Il y a un problème avec le fichier {}'.format(path_module)) + return + + print(f"Insertion des objets de permissions pour le module {module_code}") + # Insert permission object + if "permission_objects" in config_module: + id_module = module.id_module + insert_permission_object(id_module, config_module["permission_objects"]) + else: + print("no permission") + + + @monitorings_cli.command('remove') @click.argument('module_code') @with_appcontext diff --git a/backend/monitoring/base.py b/backend/monitoring/base.py index a93964406..a65434b01 100644 --- a/backend/monitoring/base.py +++ b/backend/monitoring/base.py @@ -137,7 +137,7 @@ def config_value(self, param_name): field_name = self.config_param(param_name) return self.get_value(field_name) - def parent_type(self): + def parent_type(self): ''' on renvoie le premier de la liste ''' @@ -191,8 +191,8 @@ def id_parent(self): return getattr(self._model, self.id_parent_fied_name()) - def get_cruved(self): - return cruved_scope_for_user_in_monitoring_module(self._module_code) + def get_cruved(self, object_type=None): + return cruved_scope_for_user_in_monitoring_module(self._module_code, object_type) def cond_filters(self): filters = self.config_param('filters') @@ -201,7 +201,7 @@ def cond_filters(self): return True print('filters', filters, self) - cond = True + cond = True for key in filters: cond = cond and self.get_value(key) == filters[key] diff --git a/backend/monitoring/serializer.py b/backend/monitoring/serializer.py index 994bbffb4..059a9e8ca 100644 --- a/backend/monitoring/serializer.py +++ b/backend/monitoring/serializer.py @@ -19,7 +19,7 @@ def get_parent(self): return if not self._parent: - self._parent = ( + self._parent = ( monitoring_definitions .monitoring_object_instance( self._module_code, @@ -161,6 +161,12 @@ def serialize(self, depth=1): if self._object_type == 'module': monitoring_object_dict['cruved'] = self.get_cruved() + monitoring_object_dict['cruved_objects'] = {} + monitoring_object_dict['cruved_objects']['site'] = self.get_cruved("GNM_SITES") + monitoring_object_dict['cruved_objects']['sites_group'] = self.get_cruved("GNM_GRP_SITES") + monitoring_object_dict['cruved_objects']['visite'] = self.get_cruved("GNM_VISITES") + monitoring_object_dict['cruved_objects']['observation'] = self.get_cruved("GNM_OBSERVATIONS") + properties['id_parent'] = to_int(self.id_parent()) if(children): diff --git a/backend/routes/decorators.py b/backend/routes/decorators.py index a19713eb3..01fdd1635 100644 --- a/backend/routes/decorators.py +++ b/backend/routes/decorators.py @@ -8,7 +8,7 @@ from geonature.core.gn_permissions.tools import ( get_user_from_token_and_raise, - cruved_scope_for_user_in_module + cruved_scope_for_user_in_module, ) from ..modules.repositories import get_module @@ -27,17 +27,10 @@ def to_int_cruved(cruved): return cruved -def cruved_scope_for_user_in_monitoring_module(module_code=None): +def cruved_scope_for_user_in_monitoring_module(module_code=None, object_code=None): user = get_user_from_token_and_raise(request) - cruved_module = { - 'C': '0', - 'R': '0', - 'U': '0', - 'V': '0', - 'E': '0', - 'D': '0' - } + cruved_module = {"C": "0", "R": "0", "U": "0", "V": "0", "E": "0", "D": "0"} # If user not a dict: its a token issue # return the appropriate Response @@ -48,51 +41,50 @@ def cruved_scope_for_user_in_monitoring_module(module_code=None): module = None herited = False - if module_code and module_code != 'null': - module = get_module('module_code', module_code) - if module: - cruved_module, herited = cruved_scope_for_user_in_module(user['id_role'], module.module_code, 'ALL') - if not herited: - return to_int_cruved(cruved_module) + if module_code and module_code != "null": + module = get_module("module_code", module_code) + module_code = module.module_code + append = {10: ["MONOTORINGS", object_code], 25: ["MONOTORINGS", "ALL"]} + else: + module_code = "MONITORINGS" + append = {} - cruved_monitorings, herited = cruved_scope_for_user_in_module(user['id_role'], 'MONITORINGS', 'ALL') - if not herited: - return to_int_cruved(cruved_monitorings) - - # return cruved_0, user - return to_int_cruved(cruved_monitorings) + cruved_module, herited = cruved_scope_for_user_in_module( + id_role=user["id_role"], + module_code=module_code, + object_code=object_code, + append_to_select=append, + ) + return to_int_cruved(cruved_module) def check_cruved_scope_monitoring( - action, - droit_min=1, - redirect_on_expiration=None, - redirect_on_invalid_token=None + action, droit_min=1, redirect_on_expiration=None, redirect_on_invalid_token=None ): """ - Decorateur qui verifie si un utilisateur a des droit sur un module de suivi - (reférencé dans la route comme module_code) - - Prend en compte le droit maximum entre le module MONITORINGS et le module spécifique - autorise l'acces a la route si ce droit est supérieur ou égal à droit_min - - :params action: type d'action CRUVED - :param droit min: droit minimum pour acceder a la route - :param redirect_on_expiration: url en cas d'expiration - :param redirect_on_invalid_token: url en cas de token invalid - :param return_module: si vrai rajoute le module en parametre de route - :type action: str - :type droit: int - :type redirect_on_expiration: str - :type redirect_on_invalid_token: str - :type return_module: bool + Decorateur qui verifie si un utilisateur a des droit sur un module de suivi + (reférencé dans la route comme module_code) + + Prend en compte le droit maximum entre le module MONITORINGS et le module spécifique + autorise l'acces a la route si ce droit est supérieur ou égal à droit_min + + :params action: type d'action CRUVED + :param droit min: droit minimum pour acceder a la route + :param redirect_on_expiration: url en cas d'expiration + :param redirect_on_invalid_token: url en cas de token invalid + :param return_module: si vrai rajoute le module en parametre de route + :type action: str + :type droit: int + :type redirect_on_expiration: str + :type redirect_on_invalid_token: str + :type return_module: bool """ def _check_cruved_scope_monitoring(fn): @wraps(fn) def __check_cruved_scope_monitoring(*args, **kwargs): - module_code = kwargs.get('module_code') + module_code = kwargs.get("module_code") cruved = cruved_scope_for_user_in_monitoring_module(module_code) user = get_user_from_token_and_raise(request) @@ -100,14 +92,14 @@ def __check_cruved_scope_monitoring(*args, **kwargs): if not permission or permission < droit_min: raise InsufficientRightsError( - '''User {} with permission level {} for action {} \ + """User {} with permission level {} for action {} \ is not allowed to use this route for module {}, \ -min permission level is {}'''.format( - user['id_role'], +min permission level is {}""".format( + user["id_role"], permission, action, - module_code or 'monitorings', - droit_min + module_code or "monitorings", + droit_min, ), 403, ) diff --git a/backend/routes/modules.py b/backend/routes/modules.py index 12e60ea57..04459a0a6 100644 --- a/backend/routes/modules.py +++ b/backend/routes/modules.py @@ -53,6 +53,7 @@ def get_modules_api(): for module in modules: module_out = module.as_dict(depth=depth) module_out['cruved'] = cruved_scope_for_user_in_monitoring_module(module.module_code) + modules_out.append(module_out) return modules_out diff --git a/backend/routes/monitoring.py b/backend/routes/monitoring.py index b6aa8dd89..9842c3d88 100644 --- a/backend/routes/monitoring.py +++ b/backend/routes/monitoring.py @@ -50,11 +50,10 @@ def get_monitoring_object_api(module_code, object_type, id): # field_name = param.get('field_name') # value = module_code if object_type == 'module' - get_config(module_code, verification_date=True) - depth = to_int(request.args.get('depth', 1)) + return ( monitoring_definitions .monitoring_object_instance(module_code, object_type, id) @@ -141,7 +140,7 @@ def delete_object_api(module_code, object_type, id): # breadcrumbs @blueprint.route('breadcrumbs///', methods=['GET']) -@blueprint.route('breadcrumbs//', +@blueprint.route('breadcrumbs//', defaults={'id': None}, methods=['GET'] ) diff --git a/config/monitoring/generic/site.json b/config/monitoring/generic/site.json index 4893000a1..befa15d6c 100644 --- a/config/monitoring/generic/site.json +++ b/config/monitoring/generic/site.json @@ -39,14 +39,14 @@ "attribut_label": "ID Module", "hidden": true }, - "base_site_name": { + "base_site_code": { "type_widget": "text", - "attribut_label": "Nom", + "attribut_label": "Code", "required": true }, - "base_site_code": { + "base_site_name": { "type_widget": "text", - "attribut_label": "Code", + "attribut_label": "Nom", "required": true }, "base_site_description": { @@ -113,6 +113,5 @@ "attribut_label": "Médias", "schema_dot_table": "gn_monitoring.t_base_sites" } - } + } } - \ No newline at end of file diff --git a/data/migration/exemple_cruved.sql b/data/migration/exemple_cruved.sql new file mode 100644 index 000000000..309c2458d --- /dev/null +++ b/data/migration/exemple_cruved.sql @@ -0,0 +1,16 @@ +INSERT INTO gn_permissions.t_objects (code_object, description_object) +VALUES +('GNM_SITES', 'Permissions sur les sites'), +('GNM_VISITES', 'Permissions sur les visites'), +('GNM_OBSERVATIONS', 'Permissions sur les observation'), +('GNM_GRP_SITES', 'Permissions sur les groupes de sites') +; + + +INSERT INTO gn_permissions.cor_object_module (id_object, id_module) +SELECT id_object, id_module +FROM ( +SELECT id_module +FROM gn_commons.t_modules tm WHERE module_code = 'cheveches' +) AS m, gn_permissions.t_objects o +WHERE o.code_object ILIKE 'GNM_%'; diff --git a/data/migration/migration_0.2.1_0.2.2.sql b/data/migration/migration_0.2.1_0.2.2.sql new file mode 100644 index 000000000..fb2306d0a --- /dev/null +++ b/data/migration/migration_0.2.1_0.2.2.sql @@ -0,0 +1,7 @@ +INSERT INTO gn_permissions.t_objects (code_object, description_object) +VALUES +('GNM_SITES', 'Permissions sur les sites'), +('GNM_VISITES', 'Permissions sur les visites'), +('GNM_OBSERVATIONS', 'Permissions sur les observation'), +('GNM_GRP_SITES', 'Permissions sur les groupes de sites') +; diff --git a/data/monitoring.sql b/data/monitoring.sql index 5b7c86e0a..4ebb69c9f 100644 --- a/data/monitoring.sql +++ b/data/monitoring.sql @@ -1,14 +1,14 @@ -- schema qui complete gn_monitoring pour le module monitoring CREATE TABLE IF NOT EXISTS gn_monitoring.t_module_complements ( - + id_module SERIAL NOT NULL, - uuid_module_complement UUID DEFAULT uuid_generate_v4() NOT NULL, - + uuid_module_complement UUID DEFAULT uuid_generate_v4() NOT NULL, + id_list_observer INTEGER, id_list_taxonomy INTEGER, b_synthese BOOLEAN DEFAULT TRUE, - taxonomy_display_field_name CHARACTER VARYING DEFAULT 'nom_vern,lb_nom', + taxonomy_display_field_name CHARACTER VARYING DEFAULT 'nom_vern,lb_nom', data JSONB, @@ -112,7 +112,7 @@ CREATE TABLE IF NOT EXISTS gn_monitoring.t_module_complements ( -- champs en complément de t_observation: relation 1-1 CREATE TABLE IF NOT EXISTS gn_monitoring.t_observation_complements ( - + id_observation INTEGER NOT NULL, data JSONB, @@ -149,4 +149,17 @@ CREATE TABLE IF NOT EXISTS gn_monitoring.t_module_complements ( -- on evite de mettre 2 fois le meme couple (shema_name, table_name) ON CONFLICT(schema_name, table_name) DO NOTHING; +-- Ajout contrainte sur la table des objets de permission +-- Devrait être dans GN2 +-- TODO supprimer ces deux lignes une fois présentes dans GN2 +ALTER TABLE gn_permissions.t_objects DROP CONSTRAINT IF EXISTS unique_t_objects; +ALTER TABLE gn_permissions.t_objects ADD CONSTRAINT unique_t_objects UNIQUE (code_object); + +INSERT INTO gn_permissions.t_objects (code_object, description_object) +VALUES +('GNM_SITES', 'Permissions sur les sites'), +('GNM_VISITES', 'Permissions sur les visites'), +('GNM_OBSERVATIONS', 'Permissions sur les observation'), +('GNM_GRP_SITES', 'Permissions sur les groupes de sites') + ON CONFLICT(code_object) DO NOTHING; diff --git a/docs/changelog.rst b/docs/changelog.rst index a5305c5bc..7ed97bd68 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,36 @@ CHANGELOG ========= +0.2.2 (unrelease) +======= + +* Version minimale de GeoNature nécessaire : 2.5.5 + +**🚀 Nouveautés** + +* Gestion des permissions par objet (site, groupe de site, visite, observation) +* Interaction carte liste pour les groupes de site + +**🐛 Corrections** + +* Affichage des tooltips pour les objets cachés #76 + + +**⚠️ Notes de version** + +Si vous mettez à jour le module : + +* Pour mettre à jour la base de données, il faut exécuter le fichier ``data/migration/migration_0.2.1_0.2.2.sql`` +* Suivez la procédure classique de mise à jour du module (``docs/MAJ.rst``) +* Nettoyer des résidus liées à l'ancienne versions : + +:: + + cd /home/`whoami`/geonature/frontend + npm uninstall test + npm ci /home/`whoami`/gn_module_monitoring/frontend/ --no-save + + 0.2.1 (2021-01-14) ======= ------------------ @@ -73,9 +103,9 @@ Nécessite la version 2.5.2 de GeoNature minimum. Si vous mettez à jour le module depuis la version 0.1.0 : -* Les fichiers ``custom.json`` ne sont plus utiles (la configuration spécifique à une installation (liste utilisateurs, etc..) +* Les fichiers ``custom.json`` ne sont plus utiles (la configuration spécifique à une installation (liste utilisateurs, etc..) est désormais gérée dans la base de données, dans la table ``gn_monitoring.t_module_complements``) -* Dans les fichiers ``config.json``, la variable ``data`` (pour précharger les données (nomenclatures, etc..)) est désormais calculée depuis la configuration. +* Dans les fichiers ``config.json``, la variable ``data`` (pour précharger les données (nomenclatures, etc..)) est désormais calculée depuis la configuration. * Pour mettre à jour la base de données, il faut exécuter le fichier ``data/migration/migration_0.1.0_0.2.0.sql`` * Suivez la procédure classique de mise à jour du module (``docs/MAJ.rst``) diff --git a/docs/commandes.rst b/docs/commandes.rst new file mode 100644 index 000000000..e8a6dc83b --- /dev/null +++ b/docs/commandes.rst @@ -0,0 +1,48 @@ +Commandes disponibles +######################### + +:Important: + Pour pouvoir lancer les commandes il faut s'assurer d'être à la racine de l'application ``GeoNature`` et que le virtualenv soit activé + ``source backend/venv/bin/activate`` + + + +========================= +Installer un module +========================= + +.. code-block:: bash + + flask monitorings install + + +=============================== +Mettre à jour la nommenclature +=============================== + + +.. code-block:: bash + + flask monitorings add_module_nomenclature + +============================================= +Mettre à jour les objets de permissions +============================================= +La mise à jour correspond pour le moment uniquement à un ajout d'objet de permission. +Les suppressions doivent être réalisées manuellement + + +.. code-block:: bash + + flask monitorings update_permission_objects + + +========================= +Supprimer un module +========================= +La suppression d'un module n'est possible qu'en cas d'absence de données associées. + + +.. code-block:: bash + + flask monitorings remove diff --git a/docs/sous_module.rst b/docs/sous_module.rst index 79b6742a4..e22cfd362 100644 --- a/docs/sous_module.rst +++ b/docs/sous_module.rst @@ -27,7 +27,7 @@ Structure d'un module Pour chaque fichier, les valeurs prises par défaut sont celles du fichier de même nom présent dans le répertoire ``config/monitoring/generic``. Le fichier ``img.jpg`` servira de vignette du sous-module sur la page d'accueil du module Monitorings. -Pour chacune un lien symbolique est créé automatiquement dans le répertoire ``frontend/src/external_assets/monitorings`` de GeoNature. +Pour chacune un lien symbolique est créé automatiquement dans le répertoire ``frontend/src/external_assets/monitorings`` de GeoNature. Pour que l'image soit prise en compte, lors de l'installation du module ou si on la modifie, il faut relancer une compilation de GeoNature (avec la commande ``geonature frontend_build`` par exemple). @@ -63,6 +63,10 @@ Dans le fichier ``module.json``, deux variables doivent obligatoirement être d * ``module_code``: un nom cours, en minuscule et simple, par exemple ``cheveches`` ou ``oedic`` pour les protocoles chevêches ou oedicnèmes. * ``module_desc``: une description succinte du module. +Une variable optionnelle permet de configurer les objets faisant l'objet de permission: + +* ``permission_objects``: liste des objets permissions à associer au module. Elle peut contenir les valeurs suivantes ``["GNM_GRP_SITES", "GNM_SITES", "GNM_VISITES", "GNM_OBSERVATIONS"]`` + Dans le cas général (``module.json``, ``site.json``, ``visit.json``, ``observation.json``) on peut redéfinir au besoin certaines variables. * ``label`` : permet de nommer les objets, par exemple ``"Site"`` pour site, @@ -163,7 +167,7 @@ Pour définir une nouvelle variable ou aussi redéfinir une caractéristique d'u "min": 1, "max": 2 } - + * **utilisateur** : choix de plusieurs noms d'utilisateurs dans une liste .. code-block:: JSON @@ -243,7 +247,7 @@ On rajoutera cet élément dans notre variable ``specific`` et cet élément ser * Changer le label d'un élément et le rendre visible et obligatoire .. code-block:: JSON - + "visit_date_max": { "attribut_label": "Date de fin de visite", "hidden": false, @@ -279,7 +283,7 @@ Pour renseigner la valeur de la nomenclature, on spécifie : Pour pouvoir faire des composants de type select à partir d'une API, on peut utiliser le composant ``datalist``. -Les options supplémentaires pour ce widget : +Les options supplémentaires pour ce widget : - ``api`` : API qui fournira la liste - ``application`` : ``GeoNature`` ou ``TaxHub`` permet de préfixer l'API avec l'URL de l'API de l'application @@ -376,7 +380,7 @@ La valeur de ce paramètre est alors une chaîne de caractère qui définie une * ``value``: les valeur du formulaire * ``attribut_name``: du composant concerné -* ``meta``: un dictionnaire de données additionelles, et fourni au composant dynamicFormGenerator, il peut contenir des données sur +* ``meta``: un dictionnaire de données additionelles, et fourni au composant dynamicFormGenerator, il peut contenir des données sur * la nomenclature (pour avoir les valeurs des nomenclature à partir des id, ici un dictionnaire avec ``id_nomenclature`` comme clés. * ``bChainInput`` si on enchaine les releves * etc.. à redéfinir selon les besoin @@ -385,7 +389,7 @@ La chaine de caractère qui décrit la fonction doit être de la forme suivante: .. code-block:: JSON -"hidden": "({value, attribut_name, }) => { return value.id == 't' }" + "hidden": "({value, attribut_name, }) => { return value.id == 't' }" Le format JSON ne permet pas les saut de ligne dans les chaines de caractère, @@ -394,11 +398,11 @@ et pour avoir plus de lisibilité, quand la fonction est plus complexe, on peut .. code-block:: JSON -"hidden": [ - "({value, attribut_name, }) => {", - "return value.id == 't'", - "}" -] + "hidden": [ + "({value, attribut_name, }) => {", + "return value.id == 't'", + "}" + ] Le lignes seront coléés entre elle avec l'ajout de saut de lignes (caractère `\n`. @@ -416,13 +420,13 @@ Exemples: "test": { "type_widget": "text", "attribut_label": "Test" - }, + }, "test2": { "type_widget": "text", "attribut_label": "Test 2", "hidden": "({value}) => value.test != 't'", "required": "({value}) => value.test != 't'" - } + } } * Ajouter un champs pour renseigner la profondeur d'une grotte si le type de site est une grotte @@ -496,7 +500,7 @@ Nomenclature ------------ Le fichier ``nomenclature.json`` permet de renseigner les nomenclatures spécifiques à chaque sous-module. -Elles seront insérées dans la base de données lors de l'installation du sous-module (si elles n'existent pas déjà). +Elles seront insérées dans la base de données lors de l'installation du sous-module (si elles n'existent pas déjà). Exemple de fichier : @@ -535,10 +539,22 @@ Exemple de fichier : Gestion des droits ------------------ -Actuellement le CRUVED est implémenté de manière partielle au niveau du module MONITORINGS. +Actuellement le CRUVED est implémenté de manière partielle au niveau du module MONITORINGS : Il n'y a actuellement pas de vérification des portées, les droits s'appliquent sur toutes les données + +Si on définit un CRUVED sur un sous-module, alors cela surcouche pour ce sous-module le CRUVED définit au niveau de tout le module Monitorings. +Par défaut les valeurs définies du cruved sont : + +- `site_group.json` : "cruved": {"C":1, "U":1, "D": 1}, +- `site.json` : "cruved": {"C":1, "U":1, "D": 1}, +- `visit.son` : "cruved": {"C":1, "U":1, "D": 1}, +- `observation.json` : "cruved": {"C":1, "U":1, "D": 1}, + + +Pour surcoucher les permissions il faut rajouter la variable cruved dans les fichiers de configuration du module (site_group.json, site.json, ...) + +.. code-block:: JSON + "cruved": {"C": 3, "U": 3, "D": 3}, + -- Si on définit un CRUVED sur un sous-module, alors cela surcouche pour ce sous-module le CRUVED définit au niveau de tout le module Monitorings. - Pour pouvoir modifier les paramètres d'un module, il faut que le CRUVED de l'utilisateur ait un U=3 pour ce sous-module. -- Pour pouvoir créer des objets dans un sous-module, il faut un C>=1 -- Pour pouvoir supprimer un média sur un objet, il faut un D>=1 -- Il n'y a actuellement pas de vérification des portées, les droits s'appliquent sur toutes les données + diff --git a/frontend/app/class/monitoring-object-base.ts b/frontend/app/class/monitoring-object-base.ts index 81e11a87f..78b8b9738 100644 --- a/frontend/app/class/monitoring-object-base.ts +++ b/frontend/app/class/monitoring-object-base.ts @@ -13,6 +13,7 @@ export class MonitoringObjectBase { parentsPath = []; userCruved; + userCruvedObject; deleted = false; idTableLocation; @@ -125,6 +126,7 @@ export class MonitoringObjectBase { setData(data) { this.userCruved = data.cruved; + this.userCruvedObject = data.cruved_objects; this.properties = data.properties; this.geometry = data.geometry; this.id = this.id || this.properties[this.configParam("id_field_name")]; @@ -292,7 +294,7 @@ export class MonitoringObjectBase { ? `Modification ${this.labelDu()} ${description}` : `Création d'${this.labelArtUndef(true)}` : `Détails ${this.labelDu()} ${description}` ; - + return text.trim(); } @@ -324,7 +326,7 @@ export class MonitoringObjectBase { ? `Modification ${this.labelDu()} ${description}` : `Création d'${this.labelArtUndef(true)}` : `Détails ${this.labelDu()} ${description}` ; - + return text.trim(); } diff --git a/frontend/app/components/monitoring-form/monitoring-form.component.html b/frontend/app/components/monitoring-form/monitoring-form.component.html index fe9dafbdd..6d78b5b55 100644 --- a/frontend/app/components/monitoring-form/monitoring-form.component.html +++ b/frontend/app/components/monitoring-form/monitoring-form.component.html @@ -117,7 +117,7 @@

Attention

diff --git a/frontend/app/components/monitoring-lists/monitoring-lists.component.html b/frontend/app/components/monitoring-lists/monitoring-lists.component.html index 23a61319c..add430e5b 100644 --- a/frontend/app/components/monitoring-lists/monitoring-lists.component.html +++ b/frontend/app/components/monitoring-lists/monitoring-lists.component.html @@ -12,40 +12,40 @@ role="tab" attr.aria-controls="nav-{{ child0.objectType }}" aria-selected="true" + (click)="changeActiveTab(child0.objectType)" >{{ child0.template["label_list"] }} {{displayNumber(child0.objectType)}} -