Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
amandine-sahl committed Dec 5, 2023
2 parents 2e97e65 + 0f67fa3 commit b24a584
Show file tree
Hide file tree
Showing 33 changed files with 629 additions and 207 deletions.
120 changes: 120 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
name: pytest

on:
push:
branches:
- master
- hotfixes
- develop
- workshop
pull_request:
branches:
- master
- hotfixes
- develop
- workshop

jobs:
build:

runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
include:
- name: "Debian 10"
python-version: "3.7"
postgres-version: 11
postgis-version: 2.5
- name: "Debian 11"
python-version: "3.9"
postgres-version: 13
postgis-version: 3.2

name: ${{ matrix.name }}

services:
postgres:
image: postgis/postgis:${{ matrix.postgres-version }}-${{ matrix.postgis-version }}
env:
POSTGRES_DB: geonature2db
POSTGRES_PASSWORD: geonatpasswd
POSTGRES_USER: geonatadmin
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Add postgis_raster database extension
if: ${{ matrix.postgis-version >= 3 }}
run: |
psql -h localhost -U geonatadmin -d geonature2db -tc 'CREATE EXTENSION "postgis_raster";'
env:
PGPASSWORD: geonatpasswd
- name: Add database extensions
run: |
psql -h localhost -U geonatadmin -d geonature2db -tc 'CREATE EXTENSION "hstore";'
psql -h localhost -U geonatadmin -d geonature2db -tc 'CREATE EXTENSION "uuid-ossp";'
psql -h localhost -U geonatadmin -d geonature2db -tc 'CREATE EXTENSION "pg_trgm";'
psql -h localhost -U geonatadmin -d geonature2db -tc 'CREATE EXTENSION "unaccent";'
env:
PGPASSWORD: geonatpasswd
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install GDAL
run: |
sudo apt update
sudo apt install -y libgdal-dev
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install \
-e ..[tests] \
-r requirements-dev.txt
working-directory: ./dependencies/GeoNature/backend
- name: Install database
run: |
geonature db upgrade geonature@head -x local-srid=2154
geonature db autoupgrade -x local-srid=2154
geonature taxref import-v15 --skip-bdc-statuts
geonature db upgrade geonature-samples@head
geonature db upgrade nomenclatures_taxonomie_data@head
geonature db upgrade ref_geo_fr_departments@head
geonature db upgrade ref_geo_fr_municipalities@head
geonature db upgrade ref_geo_inpn_grids_10@head
env:
GEONATURE_CONFIG_FILE: dependencies/GeoNature/config/test_config.toml
- name: Install monitoring module database
run: |
geonature upgrade-modules-db MONITORINGS
env:
GEONATURE_CONFIG_FILE: dependencies/GeoNature/config/test_config.toml
- name: Test with pytest
run: |
pytest -v --cov --cov-report xml
env:
GEONATURE_CONFIG_FILE: dependencies/GeoNature/config/test_config.toml
- name: Upload coverage to Codecov
if: ${{ matrix.name == 'Debian 11' }}
uses: codecov/codecov-action@v2
with:
flags: pytest
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "dependencies/GeoNature"]
path = dependencies/GeoNature
url = [email protected]:PnX-SI/GeoNature.git
branch = develop
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,15 @@ Les permissions ne sont implémentées que partiellement. La notion de portée (

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écifier les permissions pour chaque type d'objet (groupes de sites, sites, visites et observations).
Les permissions sont définis pour chaque type d'objet (modules, groupes de sites, sites, visites et observations) :
* MONITORINGS_MODULES - R : permet a l'utilisateur d'accéder au module, de le voir dans la liste des modules
* MONITORINGS_MODULES - U : action administrateur qui permet de configurer le module et de synchroniser la synthèse
* MONITORINGS_MODULES - E : action qui permet aux utilisateurs d'exporter les données (si défini par le module)
* MONITORINGS_GRP_SITES - CRUD : action de lire, créer, modifier, supprimer un groupe de site
* MONITORINGS_SITES - CRUD : action de lire, créer, modifier, supprimer un site
* MONITORINGS_VISITES - CRUD : action de lire, créer, modifier, supprimer les visites, observations, observations détails

Si aucune permission n'est associée à l'objet, les permissions auront comme valeur celles associées au sous-module.
Par défaut, dès qu'un utilisateur a un droit supérieur à 0 pour une action (c-a-d aucune portée) il peut réaliser cette action.

Par défaut, dès qu'un utilisateur a un droit supé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 doc de configuration des sous-modules).

Il est possible de mettre à jour les permissions disponibles pour un module en utilisant la commande `update_module_available_permissions`
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.7.0
0.7.1
10 changes: 7 additions & 3 deletions backend/gn_module_monitoring/command/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ def cmd_install_monitoring_module(module_code):
DB.session.commit()

# Ajouter les permissions disponibles
process_available_permissions(module_code)
process_available_permissions(module_code, session=DB.session)
DB.session.commit()

#  run specific sql
if (module_config_dir_path / "synthese.sql").exists:
Expand Down Expand Up @@ -196,10 +197,13 @@ def cmd_process_available_permission_module(module_code):
"""

if module_code:
return process_available_permissions(module_code)
process_available_permissions(module_code, session=DB.session)
DB.session.commit()
return

for module in installed_modules():
process_available_permissions(module["module_code"])
process_available_permissions(module["module_code"], session=DB.session)
DB.session.commit()


@click.command("remove")
Expand Down
117 changes: 69 additions & 48 deletions backend/gn_module_monitoring/command/utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import os
from pathlib import Path

from flask import current_app
from sqlalchemy import and_, text
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.exc import NoResultFound

from geonature.utils.env import DB, BACKEND_DIR
from geonature.core.gn_permissions.models import PermObject
from geonature.core.gn_permissions.models import PermObject, PermissionAvailable, PermAction
from geonature.core.gn_commons.models import TModules

from pypnnomenclature.models import TNomenclatures, BibNomenclaturesTypes
Expand All @@ -16,13 +18,30 @@

from ..modules.repositories import get_module, get_source_by_code, get_modules


"""
utils.py
fonctions pour les commandes du module monitoring
"""


PERMISSION_LABEL = {
"MONITORINGS_MODULES": {"label": "modules", "actions": ["R", "U", "E"]},
"MONITORINGS_GRP_SITES": {"label": "groupes de sites", "actions": ["C", "R", "U", "D"]},
"MONITORINGS_SITES": {"label": "sites", "actions": ["C", "R", "U", "D"]},
"MONITORINGS_VISITES": {"label": "visites", "actions": ["C", "R", "U", "D"]},
}

ACTION_LABEL = {
"C": "Créer des",
"R": "Voir les",
"U": "Modifier les",
"D": "Supprimer des",
"E": "Exporter les",
}


def process_for_all_module(process_func):
"""
boucle sur les répertoire des module
Expand All @@ -34,12 +53,6 @@ def process_for_all_module(process_func):
return


def getMonitoringPermissionObjectLabel_dict():
return __import__(
"gn_module_monitoring"
).monitoring.definitions.MonitoringPermissionObjectLabel_dict


def process_export_csv(module_code=None):
"""
fonction qui va chercher les fichier sql de exports/csv et qui les joue
Expand Down Expand Up @@ -73,7 +86,7 @@ def process_export_csv(module_code=None):
print("{} - export csv erreur dans le script {} : {}".format(module_code, f, e))


def process_available_permissions(module_code):
def process_available_permissions(module_code, session):
try:
module = get_module("module_code", module_code)
except Exception:
Expand All @@ -85,33 +98,36 @@ def process_available_permissions(module_code):
print(f"Il y a un problème de configuration pour le module {module_code}")
return

insert_module_available_permissions(module_code, "ALL")
tree = config.get("tree", [])

# Insert permission object
for permission_object_code in config.get("permission_objects", []):
insert_module_available_permissions(module_code, permission_object_code)
module_objects = [k for k in extract_keys(tree, keys=[])]

permission_level = current_app.config["MONITORINGS"].get("PERMISSION_LEVEL", {})

# Insert permission object
for permission_object_code in module_objects:
print(f"Création des permissions pour {module_code} : {permission_object_code}")
insert_module_available_permissions(
module_code, permission_level[permission_object_code], session=session
)

def insert_module_available_permissions(module_code, perm_object_code):
print(
f"process permissions for (module_code, perm_object)= ({module_code},{perm_object_code})"
)

object_label = getMonitoringPermissionObjectLabel_dict().get(perm_object_code)
def insert_module_available_permissions(module_code, perm_object_code, session):
object_label = PERMISSION_LABEL.get(perm_object_code)["label"]

if not object_label:
print(f"L'object {perm_object_code} n'est pas traité")

try:
module = TModules.query.filter_by(module_code=module_code).one()
module = session.query(TModules).filter_by(module_code=module_code).one()
except NoResultFound:
print("Le module {module_code} n'est pas présent")
print(f"Le module {module_code} n'est pas présent")
return

try:
perm_object = PermObject.query.filter_by(code_object=perm_object_code).one()
perm_object = session.query(PermObject).filter_by(code_object=perm_object_code).one()
except NoResultFound:
print("L'object de permission {module_code} n'est pas présent")
print(f"L'object de permission {perm_object_code} n'est pas présent")
return

txt_cor_object_module = f"""
Expand All @@ -122,33 +138,27 @@ def insert_module_available_permissions(module_code, perm_object_code):
VALUES({module.id_module}, {perm_object.id_object})
ON CONFLICT DO NOTHING
"""
DB.engine.execution_options(autocommit=True).execute(txt_cor_object_module)

txt_perm_available = f"""
INSERT INTO gn_permissions.t_permissions_available (
id_module,
id_object,
id_action,
label,
scope_filter)
SELECT
{module.id_module},
{perm_object.id_object},
a.id_action,
v.label,
true
FROM
( VALUES
('C', 'Créer des {object_label}'),
('R', 'Voir les {object_label}'),
('U', 'Modifier les {object_label}'),
('D', 'Supprimer des {object_label}'),
('E', 'Exporter les {object_label}')
) AS v (action_code, label)
JOIN gn_permissions.bib_actions a ON v.action_code = a.code_action
ON CONFLICT DO NOTHING
"""
DB.engine.execution_options(autocommit=True).execute(txt_perm_available)
session.execute(txt_cor_object_module)

# Création d'une permission disponible pour chaque action
object_actions = PERMISSION_LABEL.get(perm_object_code)["actions"]
for action in object_actions:
permaction = session.query(PermAction).filter_by(code_action=action).one()
try:
perm = (
session.query(PermissionAvailable)
.filter_by(module=module, object=perm_object, action=permaction)
.one()
)
except NoResultFound:
perm = PermissionAvailable(
module=module,
object=perm_object,
action=permaction,
label=f"{ACTION_LABEL[action]} {object_label}",
scope_filter=True,
)
session.add(perm)


def remove_monitoring_module(module_code):
Expand Down Expand Up @@ -313,3 +323,14 @@ def available_modules():
available_modules_.append({**module, "module_code": d})
break
return available_modules_


def extract_keys(test_dict, keys=[]):
"""
FOnction permettant d'extraire de façon récursive les clés d'un dictionnaire
"""
for key, val in test_dict.items():
keys.append(key)
if isinstance(val, dict):
extract_keys(val, keys)
return keys
15 changes: 14 additions & 1 deletion backend/gn_module_monitoring/conf_schema_toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,21 @@
from marshmallow import Schema, fields, validates_schema, ValidationError


# Permissions associés à chaque objet monitoring
PERMISSION_LEVEL_DEFAULT = {
"module": "MONITORINGS_MODULES",
"site": "MONITORINGS_SITES",
"sites_group": "MONITORINGS_GRP_SITES",
"visit": "MONITORINGS_VISITES",
"observation": "MONITORINGS_VISITES",
"observation_detail": "MONITORINGS_VISITES",
}


class GnModuleSchemaConf(Schema):
pass
PERMISSION_LEVEL = fields.Dict(
keys=fields.Str(), values=fields.Str(), load_default=PERMISSION_LEVEL_DEFAULT
)


# AREA_TYPE = fields.List(fields.String(), missing=["COM", "M1", "M5", "M10"])
Expand Down
1 change: 0 additions & 1 deletion backend/gn_module_monitoring/config/generic/module.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"cruved": {"C":4, "U":3, "D": 4},
"id_field_name": "id_module",
"description_field_name": "module_label",
"label": "Module",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"cruved": {"C":1, "U":1, "D": 1},
"id_field_name": "id_observation",
"description_field_name": "id_observation",
"chained": true,
Expand Down
Loading

0 comments on commit b24a584

Please sign in to comment.