Skip to content

Commit

Permalink
admin: improve permissions managment
Browse files Browse the repository at this point in the history
  • Loading branch information
bouttier committed Apr 20, 2023
1 parent bf66b78 commit 556c4b7
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 4 deletions.
20 changes: 20 additions & 0 deletions backend/geonature/core/admin/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from functools import partial

from flask import g
from werkzeug.exceptions import Unauthorized

Expand Down Expand Up @@ -33,3 +35,21 @@ def can_delete(self):
@property
def can_export(self):
return self._can_action("E")


# https://github.com/flask-admin/flask-admin/issues/1807
# https://stackoverflow.com/questions/54638047/correct-way-to-register-flask-admin-views-with-application-factory
class ReloadingIterator:
def __init__(self, iterator_factory):
self.iterator_factory = iterator_factory

def __iter__(self):
return self.iterator_factory()


class DynamicOptionsMixin:
def get_dynamic_options(self, view):
raise NotImplementedError

def get_options(self, view):
return ReloadingIterator(partial(self.get_dynamic_options, view))
87 changes: 83 additions & 4 deletions backend/geonature/core/gn_permissions/admin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
from flask import has_app_context, Markup
from flask_admin.contrib.sqla import ModelView
from flask_admin.contrib.sqla.filters import FilterEqual

from geonature.utils.env import db
from geonature.core.admin.admin import admin
from geonature.core.admin.utils import CruvedProtectedMixin
from geonature.core.gn_permissions.models import PermObject, Permission, PermissionAvailable
from geonature.core.admin.utils import CruvedProtectedMixin, DynamicOptionsMixin
from geonature.core.gn_permissions.models import (
PermObject,
PermAction,
PermScope,
Permission,
PermissionAvailable,
)
from geonature.core.gn_commons.models.base import TModules

from pypnusershub.db.models import User


class ObjectAdmin(CruvedProtectedMixin, ModelView):
Expand All @@ -21,20 +32,88 @@ class ObjectAdmin(CruvedProtectedMixin, ModelView):
can_delete = False


class RoleFilter(DynamicOptionsMixin, FilterEqual):
def get_dynamic_options(self, view):
if has_app_context():
yield from [(u.id_role, u.nom_complet) for u in User.query.all()]


class ModuleFilter(DynamicOptionsMixin, FilterEqual):
def get_dynamic_options(self, view):
if has_app_context():
yield from [(m.id_module, m.module_code) for m in TModules.query.all()]


class ObjectFilter(DynamicOptionsMixin, FilterEqual):
def get_dynamic_options(self, view):
if has_app_context():
yield from [(o.id_object, o.code_object) for o in PermObject.query.all()]


class ActionFilter(DynamicOptionsMixin, FilterEqual):
def get_dynamic_options(self, view):
if has_app_context():
yield from [(a.id_action, a.code_action) for a in PermAction.query.all()]


class ScopeFilter(DynamicOptionsMixin, FilterEqual):
def apply(self, query, value, alias=None):
column = self.get_column(alias)
if value:
return query.filter(column == value)
else:
return query.filter(column.is_(None))

def get_dynamic_options(self, view):
if has_app_context():
yield (None, "Sans restriction")
yield from [(a.value, a.label) for a in PermScope.query.all()]


class PermissionAdmin(CruvedProtectedMixin, ModelView):
module_code = "ADMIN"
object_code = "PERMISSIONS"

column_list = ("role", "module", "object", "action", "scope")
column_list = ("role", "module", "object", "action", "label", "filters")
column_labels = {
"role": "Rôle",
"scope": "Porté",
"filters": "Restrictions",
"object": "Objet",
"role.identifiant": "identifiant du rôle",
"role.nom_complet": "nom du rôle",
"availability": "Permission disponible",
}
column_searchable_list = ("role.identifiant", "role.nom_complet")
column_formatters = {
"role": lambda v, c, m, p: Markup("<b>{}</b>".format(Markup.escape(m.role.nom_role)))
if m.role.groupe
else m.role.nom_complet,
"module": lambda v, c, m, p: m.module.module_code,
"object": lambda v, c, m, p: m.object.code_object,
"label": lambda v, c, m, p: m.availability.label if m.availability else None,
"filters": lambda v, c, m, p: m.scope.label if m.scope else None,
}
column_filters = (
RoleFilter(column=Permission.id_role, name="Rôle"),
ModuleFilter(column=Permission.id_module, name="Module"),
ObjectFilter(column=Permission.id_object, name="Objet"),
ActionFilter(column=Permission.id_action, name="Action"),
ScopeFilter(column=Permission.scope_value, name="Scope"),
)
named_filter_urls = True
column_sortable_list = (
("role", "role.nom_complet"),
("module", "module.module_code"),
("object", "object.code_object"),
("action", "action.code_action"),
)
column_default_sort = [
("role.nom_complet", True),
("module.module_code", True),
("object.code_object", True),
("action.code_action", True),
]
form_columns = ("role", "module", "object", "action", "scope")


class PermissionAvailableAdmin(CruvedProtectedMixin, ModelView):
Expand Down

0 comments on commit 556c4b7

Please sign in to comment.