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

IA-3893 Extract plugins permissions from main codebase #1947

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Generated by Django 4.2.17 on 2025-01-29 15:38

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("menupermissions", "0068_alter_custompermissionsupport_options"),
]

operations = [
migrations.AlterModelOptions(
name="custompermissionsupport",
options={
"managed": False,
"permissions": (
("iaso_forms", "Formulaires"),
("iaso_forms_stats", "Statistiques pour les formulaires"),
("iaso_mappings", "Correspondances avec DHIS2"),
("iaso_modules", "modules"),
("iaso_completeness", "Complétude des données"),
("iaso_org_units", "Unités d'organisations"),
("iaso_org_units_read", "Lire les unités d'organisations"),
("iaso_registry_write", "Editer le Registre"),
("iaso_registry_read", "Lire le Registre"),
("iaso_links", "Correspondances sources"),
("iaso_users", "Users"),
("iaso_users_managed", "Users managed"),
("iaso_pages", "Pages"),
("iaso_projects", "Projets"),
("iaso_sources", "Sources"),
("iaso_data_tasks", "Tâches"),
("iaso_submissions", "Soumissions"),
("iaso_update_submission", "Editer soumissions"),
("iaso_planning_write", "Editer le planning"),
("iaso_planning_read", "Lire le planning"),
("iaso_reports", "Reports"),
("iaso_teams", "Equipes"),
("iaso_assignments", "Attributions"),
("iaso_entities", "Entities"),
("iaso_entity_type_write", "Write entity type"),
("iaso_storages", "Storages"),
("iaso_completeness_stats", "Completeness stats"),
("iaso_workflows", "Workflows"),
("iaso_entity_duplicates_read", "Read Entity duplicates"),
("iaso_entity_duplicates_write", "Write Entity duplicates"),
("iaso_user_roles", "Manage user roles"),
("iaso_datastore_read", "Read data store"),
("iaso_datastore_write", "Write data store"),
("iaso_org_unit_types", "Org unit types"),
("iaso_org_unit_groups", "Org unit groups"),
("iaso_org_unit_change_request_review", "Org unit change request review"),
("iaso_org_unit_change_request_configurations", "Org unit change request configurations"),
("iaso_write_sources", "Write data source"),
("iaso_page_write", "Write page"),
("iaso_payments", "Payments page"),
("iaso_mobile_app_offline_setup", "Mobile app offline setup"),
("iaso_trypelim_anonymous", "Anonymisation des patients"),
("iaso_trypelim_management_areas", "Areas"),
("iaso_trypelim_management_edit_areas", "Edit areas"),
("iaso_trypelim_management_edit_shape_areas", "Edit areas shapes"),
("iaso_trypelim_case_cases", "Cases"),
("iaso_trypelim_case_analysis", "Cases analysis"),
("iaso_trypelim_management_coordinations", "Coordinations"),
("iaso_trypelim_management_devices", "Devices"),
("iaso_trypelim_datas_download", "Téléchargement de données"),
("iaso_trypelim_duplicates", "Doublons"),
("iaso_trypelim_datas_patient_edition", "Edition d'un patient"),
("iaso_trypelim_management_health_structures", "Health facilities"),
("iaso_trypelim_lab", "Labo"),
("iaso_trypelim_labupload", "Labo import"),
("iaso_trypelim_locator", "Locator"),
("iaso_trypelim_plannings_macroplanning", "Macroplanning"),
("iaso_trypelim_plannings_microplanning", "Microplanning"),
("iaso_trypelim_modifications", "Modifications"),
("iaso_trypelim_management_plannings", "Plannings"),
("iaso_trypelim_management_plannings_template", "Plannings template"),
("iaso_trypelim_qualitycontrol", "Quality control"),
("iaso_trypelim_case_reconciliation", "Reconciliation"),
("iaso_trypelim_plannings_routes", "Routes"),
("iaso_trypelim_stats_graphs", "Graphs"),
("iaso_trypelim_stats_reports", "Reports"),
("iaso_trypelim_datasets_datauploads", "Upload of cases files"),
("iaso_trypelim_datasets_villageuploads", "Upload of villages files"),
("iaso_trypelim_management_teams", "Teams"),
("iaso_trypelim_management_users", "Users"),
("iaso_trypelim_vectorcontrol", "Vector control"),
("iaso_trypelim_vectorcontrolupload", "Vector control import Gpx"),
("iaso_trypelim_management_villages", "Villages"),
("iaso_trypelim_management_workzones", "Work zones"),
("iaso_trypelim_management_zones", "Zones"),
("iaso_trypelim_management_edit_zones", "Edit zones"),
("iaso_trypelim_management_edit_shape_zones", "Edit zones shapes"),
),
},
),
]
74 changes: 25 additions & 49 deletions hat/menupermissions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
`/api/permissions/` endpoint
"""

from django.conf import LazySettings
from django.conf import settings, LazySettings
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.translation import gettext_lazy as _
from rest_framework.exceptions import PermissionDenied
from importlib import import_module


_ASSIGNMENTS = "iaso_assignments"
_COMPLETENESS = "iaso_completeness"
Expand Down Expand Up @@ -65,20 +67,6 @@
_USERS_ROLES = "iaso_user_roles"
_WORKFLOW = "iaso_workflows"

# Polio
_POLIO = "iaso_polio"
_POLIO_BUDGET = "iaso_polio_budget"
_POLIO_BUDGET_ADMIN = "iaso_polio_budget_admin"
_POLIO_CONFIG = "iaso_polio_config"
_POLIO_CHRONOGRAM = "iaso_polio_chronogram"
_POLIO_CHRONOGRAM_RESTRICTED_WRITE = "iaso_polio_chronogram_restricted_write"
_POLIO_NOTIFICATIONS = "iaso_polio_notifications"
_POLIO_VACCINE_AUTHORIZATIONS_ADMIN = "iaso_polio_vaccine_authorizations_admin"
_POLIO_VACCINE_AUTHORIZATIONS_READ_ONLY = "iaso_polio_vaccine_authorizations_read_only"
_POLIO_VACCINE_SUPPLY_CHAIN_READ = "iaso_polio_vaccine_supply_chain_read"
_POLIO_VACCINE_SUPPLY_CHAIN_WRITE = "iaso_polio_vaccine_supply_chain_write"
_POLIO_VACCINE_STOCK_MANAGEMENT_READ = "iaso_polio_vaccine_stock_management_read"
_POLIO_VACCINE_STOCK_MANAGEMENT_WRITE = "iaso_polio_vaccine_stock_management_write"

# Trypelim
_ANONYMOUS_VIEW = "iaso_trypelim_anonymous"
Expand Down Expand Up @@ -146,19 +134,18 @@
PAGE_WRITE = _PREFIX + _PAGE_WRITE
PLANNING_WRITE = _PREFIX + _PLANNING_WRITE
PLANNING_READ = _PREFIX + _PLANNING_READ
POLIO = _PREFIX + _POLIO
POLIO_BUDGET = _PREFIX + _POLIO_BUDGET
POLIO_BUDGET_ADMIN = _PREFIX + _POLIO_BUDGET_ADMIN
POLIO_CHRONOGRAM = _PREFIX + _POLIO_CHRONOGRAM
POLIO_CHRONOGRAM_RESTRICTED_WRITE = _PREFIX + _POLIO_CHRONOGRAM_RESTRICTED_WRITE
POLIO_CONFIG = _PREFIX + _POLIO_CONFIG
POLIO_NOTIFICATIONS = _PREFIX + _POLIO_NOTIFICATIONS
POLIO_VACCINE_AUTHORIZATIONS_ADMIN = _PREFIX + _POLIO_VACCINE_AUTHORIZATIONS_ADMIN
POLIO_VACCINE_AUTHORIZATIONS_READ_ONLY = _PREFIX + _POLIO_VACCINE_AUTHORIZATIONS_READ_ONLY
POLIO_VACCINE_STOCK_MANAGEMENT_READ = _PREFIX + _POLIO_VACCINE_STOCK_MANAGEMENT_READ
POLIO_VACCINE_STOCK_MANAGEMENT_WRITE = _PREFIX + _POLIO_VACCINE_STOCK_MANAGEMENT_WRITE
POLIO_VACCINE_SUPPLY_CHAIN_READ = _PREFIX + _POLIO_VACCINE_SUPPLY_CHAIN_READ
POLIO_VACCINE_SUPPLY_CHAIN_WRITE = _PREFIX + _POLIO_VACCINE_SUPPLY_CHAIN_WRITE


# Import from plugins
for plugin in settings.PLUGINS:
try:
exported_permissions = import_module(f"plugins.{plugin}.permissions").exported_permissions
for permission_name, permission_value in exported_permissions.items():
globals()[permission_name] = permission_value
except ImportError:
print(f"{plugin} plugin has no permission support")


PROJECTS = _PREFIX + _PROJECTS
REGISTRY_WRITE = _PREFIX + _REGISTRY_WRITE
REGISTRY_READ = _PREFIX + _REGISTRY_READ
Expand Down Expand Up @@ -263,13 +250,11 @@ class Meta:
(_REPORTS, _("Reports")),
(_TEAMS, _("Equipes")),
(_ASSIGNMENTS, _("Attributions")),
(_POLIO_BUDGET, _("Budget Polio")),
(_ENTITIES, _("Entities")),
(_ENTITY_TYPE_WRITE, _("Write entity type")),
(_STORAGE, _("Storages")),
(_COMPLETENESS_STATS, _("Completeness stats")),
(_WORKFLOW, _("Workflows")),
(_POLIO_BUDGET_ADMIN, _("Budget Polio Admin")),
(_ENTITIES_DUPLICATE_READ, _("Read Entity duplicates")),
(_ENTITIES_DUPLICATE_WRITE, _("Write Entity duplicates")),
(_USERS_ROLES, _("Manage user roles")),
Expand All @@ -283,18 +268,6 @@ class Meta:
(_PAGE_WRITE, _("Write page")),
(_PAYMENTS, _("Payments page")),
(_MOBILE_APP_OFFLINE_SETUP, ("Mobile app offline setup")),
# Polio
(_POLIO, _("Polio")),
(_POLIO_CONFIG, _("Polio config")),
(_POLIO_CHRONOGRAM, _("Polio chronogram")),
(_POLIO_CHRONOGRAM_RESTRICTED_WRITE, _("Polio chronogram user (restricted write)")),
(_POLIO_NOTIFICATIONS, _("Polio notifications")),
(_POLIO_VACCINE_AUTHORIZATIONS_READ_ONLY, _("Polio Vaccine Authorizations Read Only")),
(_POLIO_VACCINE_AUTHORIZATIONS_ADMIN, _("Polio Vaccine Authorizations Admin")),
(_POLIO_VACCINE_SUPPLY_CHAIN_READ, _("Polio Vaccine Supply Chain Read")),
(_POLIO_VACCINE_SUPPLY_CHAIN_WRITE, _("Polio Vaccine Supply Chain Write")),
(_POLIO_VACCINE_STOCK_MANAGEMENT_READ, _("Polio Vaccine Stock Management Read")),
(_POLIO_VACCINE_STOCK_MANAGEMENT_WRITE, _("Polio Vaccine Stock Management Write")),
# Trypelim
(_ANONYMOUS_VIEW, "Anonymisation des patients"),
(_AREAS, _("Areas")),
Expand Down Expand Up @@ -336,20 +309,23 @@ class Meta:

@staticmethod
def filter_permissions(permissions, modules_permissions, settings: LazySettings):
content_type = ContentType.objects.get_for_model(CustomPermissionSupport)
content_types = [ContentType.objects.get_for_model(CustomPermissionSupport)]

for plugin in settings.PLUGINS:
try:
permission_model = import_module(f"plugins.{plugin}.permissions").permission_model
content_types.append(ContentType.objects.get_for_model(permission_model))
except ImportError:
print(f"{plugin} plugin has no permission support")

permissions = (
permissions.filter(content_type=content_type)
permissions.filter(content_type__in=content_types)
.filter(codename__startswith="iaso_")
.filter(codename__in=modules_permissions)
.exclude(codename__contains="datastore")
.exclude(codename__contains="iaso_beneficiaries")
.order_by("id")
)
# in future filter this on a feature flags, so we can disable it by account
if "polio" not in settings.PLUGINS:
permissions = permissions.exclude(codename__startswith="iaso_polio")
if "trypelim" not in settings.PLUGINS:
permissions = permissions.exclude(codename__startswith="iaso_trypelim")

return permissions

Expand Down
27 changes: 19 additions & 8 deletions iaso/test.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import importlib
import typing
from importlib import import_module
from unittest import mock

from rest_framework.test import APITestCase as BaseAPITestCase, APIClient
from django.contrib.auth.models import AnonymousUser

from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.files import File
from django.http import StreamingHttpResponse, HttpResponse
from django.http import HttpResponse, StreamingHttpResponse
from django.test import TestCase as BaseTestCase
from django.urls import clear_url_caches
from django.utils import timezone
from rest_framework.test import APIClient
from rest_framework.test import APITestCase as BaseAPITestCase

from hat.menupermissions.models import CustomPermissionSupport
from hat.api_import.models import APIImport
from hat.menupermissions.models import CustomPermissionSupport
from iaso import models as m


Expand All @@ -38,8 +39,18 @@ def create_user_with_profile(
m.Profile.objects.create(user=user, account=account)

if permissions is not None:
content_type = ContentType.objects.get_for_model(CustomPermissionSupport)
user.user_permissions.set(Permission.objects.filter(codename__in=permissions, content_type=content_type))
content_types = [ContentType.objects.get_for_model(CustomPermissionSupport)]

for plugin in settings.PLUGINS:
try:
permission_model = import_module(f"plugins.{plugin}.permissions").permission_model
content_types.append(ContentType.objects.get_for_model(permission_model))
except ImportError:
pass

user.user_permissions.set(
Permission.objects.filter(codename__in=permissions, content_type__in=content_types)
)

if org_units is not None:
user.iaso_profile.org_units.set(org_units)
Expand Down
37 changes: 37 additions & 0 deletions plugins/polio/migrations/0218_poliopermissionsupport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 4.2.17 on 2025-01-29 15:23

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("polio", "0217_round_is_test"),
]

operations = [
migrations.CreateModel(
name="PolioPermissionSupport",
fields=[
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
],
options={
"permissions": (
("iaso_polio", "Polio"),
("iaso_polio_budget", "Budget Polio"),
("iaso_polio_budget_admin", "Budget Polio Admin"),
("iaso_polio_config", "Polio config"),
("iaso_polio_chronogram", "Polio chronogram"),
("iaso_polio_chronogram_restricted_write", "Polio chronogram user (restricted write)"),
("iaso_polio_notifications", "Polio notifications"),
("iaso_polio_vaccine_authorizations_admin", "Polio Vaccine Authorizations Admin"),
("iaso_polio_vaccine_authorizations_read_only", "Polio Vaccine Authorizations Read Only"),
("iaso_polio_vaccine_supply_chain_read", "Polio Vaccine Supply Chain Read"),
("iaso_polio_vaccine_supply_chain_write", "Polio Vaccine Supply Chain Write"),
("iaso_polio_vaccine_stock_management_read", "Polio Vaccine Stock Management Read"),
("iaso_polio_vaccine_stock_management_write", "Polio Vaccine Stock Management Write"),
),
"managed": False,
"default_permissions": [],
},
),
]
Loading
Loading