Skip to content

Commit

Permalink
introduce readonly notion on profil from SIAP habilitation (#1463)
Browse files Browse the repository at this point in the history
  • Loading branch information
kolok authored Aug 6, 2024
1 parent 14c3319 commit 4d73731
Show file tree
Hide file tree
Showing 41 changed files with 685 additions and 316 deletions.
39 changes: 35 additions & 4 deletions conventions/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,55 @@
from conventions.models.convention import Convention


def has_campaign_permission(permission):
def currentrole_permission_required(permission):
def has_permission(function):
def wrapper(request, *args, **kwargs):
_check_currentrole_permission(request, None, permission)
return function(request, *args, **kwargs)

return wrapper

return has_permission


def currentrole_permission_required_view_function(permission):
def has_permission(function):
def wrapper(view, request, *args, **kwargs):
_check_currentrole_permission(request, None, permission)
return function(view, request, *args, **kwargs)

return wrapper

return has_permission


def currentrole_campaign_permission_required(permission):
def has_permission(function):
def wrapper(view, request, **kwargs):
request.user.check_perm(permission, view.convention)
_check_currentrole_permission(request, view.convention, permission)
return function(view, request, **kwargs)

return wrapper

return has_permission


def has_campaign_permission_view_function(permission):
def currentrole_campaign_permission_required_view_function(permission):
def has_permission(function):
def wrapper(request, convention_uuid, **kwargs):
convention = Convention.objects.get(uuid=convention_uuid)
request.user.check_perm(permission, convention)
_check_currentrole_permission(request, convention, permission)
return function(request, convention_uuid, **kwargs)

return wrapper

return has_permission


def _check_currentrole_permission(request, convention, permission):
role_id = (
request.session["role"]["id"]
if "role" in request.session and "id" in request.session["role"]
else None
)
request.user.check_perm(permission, obj=convention, role_id=role_id)
24 changes: 0 additions & 24 deletions conventions/services/conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from conventions.forms.convention_form_resiliation import ConventionResiliationForm
from conventions.models import Convention, ConventionStatut
from conventions.services import utils
from conventions.services.file import ConventionFileService
from conventions.services.search import AvenantListSearchService
from core.request import AuthenticatedHttpRequest

Expand Down Expand Up @@ -44,29 +43,6 @@ def save(self):
pass


def convention_sent(request, convention_uuid):
convention = Convention.objects.get(uuid=convention_uuid)
result_status = None
if request.method == "POST":
upform = UploadForm(request.POST, request.FILES)
if upform.is_valid():
ConventionFileService.upload_convention_file(
convention, request.FILES["file"]
)
result_status = utils.ReturnStatus.SUCCESS
else:
upform = UploadForm()

return {
"success": result_status,
"convention": convention,
"upform": upform, # Obsolète: cette approche sera dépréciée dans le futur, au profit de extra_forms.
"extra_forms": {
"upform": upform,
},
}


def convention_post_action(request, convention_uuid):
convention = Convention.objects.get(uuid=convention_uuid)
result_status = None
Expand Down
36 changes: 36 additions & 0 deletions conventions/services/recapitulatif.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from conventions.forms.notification import NotificationForm
from conventions.forms.programme_number import ProgrammeNumberForm
from conventions.forms.type1and2 import ConventionType1and2Form
from conventions.forms.upload import UploadForm
from conventions.models.choices import ConventionStatut
from conventions.models.convention import Convention
from conventions.models.convention_history import ConventionHistory
Expand Down Expand Up @@ -571,3 +572,38 @@ def convention_resiliation_validate(request, convention_uuid):
"success": result_status,
"convention": convention,
}


# FIXME to be tested
class ConventionSentService(ConventionService):
# convention: Convention
# request: HttpRequest
# upform: UploadForm = UploadForm()
# return_status: utils.ReturnStatus = utils.ReturnStatus.ERROR

def get(self):
upform = UploadForm()
return {
"convention": self.convention,
"upform": upform,
"extra_forms": {
"upform": upform,
},
}

def save(self):
upform = UploadForm(self.request.POST, self.request.FILES)
if upform.is_valid():
ConventionFileService.upload_convention_file(
self.convention, self.request.FILES["file"]
)
self.result_status = utils.ReturnStatus.SUCCESS

return {
"success": self.result_status,
"convention": self.convention,
"upform": upform,
"extra_forms": {
"upform": upform,
},
}
2 changes: 2 additions & 0 deletions conventions/services/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ def base_convention_response_error(request, convention):


def editable_convention(request: HttpRequest, convention: Convention):
if "readonly" in request.session and request.session["readonly"]:
return False
if is_instructeur(request):
if "is_expert" in request.session and request.session["is_expert"] is True:
return True
Expand Down
8 changes: 8 additions & 0 deletions conventions/templatetags/custom_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ def is_instructeur(request: HttpRequest) -> bool:
return request.user.is_instructeur()


@register.filter
def is_readonly(request: HttpRequest) -> bool:
# Manage is_staff exception
if "readonly" in request.session:
return request.session["readonly"]
return False


@register.filter
def current_administration(request: HttpRequest) -> None | int:
if is_instructeur(request) and request.session.get("administration"):
Expand Down
10 changes: 1 addition & 9 deletions conventions/tests/services/test_conventions_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
from django.test import RequestFactory, TestCase

from conventions.models import Convention
from conventions.services.conventions import (
ConventionService,
convention_post_action,
convention_sent,
)
from conventions.services.conventions import ConventionService, convention_post_action
from users.models import User


Expand Down Expand Up @@ -46,10 +42,6 @@ def test_convention_service_basic(self):
self.assertEqual(self.convention, service.convention)
self.assertEqual(self.request, service.request)

def test_convention_sent_basic(self):
result = convention_sent(self.request, self.convention.uuid)
self.assertEqual(result["convention"], self.convention)

def test_convention_post_action_basic(self):
self.request.POST = QueryDict()
result = convention_post_action(self.request, self.convention.uuid)
Expand Down
55 changes: 37 additions & 18 deletions conventions/tests/views/test_finalisation.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import pytest
from django.conf import settings
from django.core.management import call_command
from django.urls import reverse
from pytest_django.asserts import assertTemplateUsed
from waffle.testutils import override_flag

from conventions.forms.convention_form_finalisation import (
FinalisationCerfaForm,
FinalisationNumeroForm,
)
from conventions.models.choices import ConventionStatut
from conventions.tests.factories import ConventionFactory
from users.tests.factories import GroupFactory, RoleFactory, UserFactory
from users.type_models import TypeRole


@pytest.fixture(scope="session")
def django_db_setup(django_db_blocker):
with django_db_blocker.unblock():
call_command("loaddata", "auth.json")


@pytest.fixture
Expand All @@ -22,20 +29,39 @@ def convention():
)


@pytest.fixture
def logged_in_user(client, convention):
user = UserFactory()
role = RoleFactory(
user=user,
administration=convention.programme.administration,
typologie=TypeRole.INSTRUCTEUR.label,
group=GroupFactory(name="instructeur"),
)
client.force_login(user)

# Définir manuellement les données de session
session = client.session
session["role"] = {"id": role.id}
session.save()

return user


@pytest.fixture
def avenant(convention):
return ConventionFactory(
statut=ConventionStatut.INSTRUCTION.label,
numero="3456",
parent_id=convention.id,
programme=convention.programme,
fichier_override_cerfa='{"files": {"705e2175-4a1d-4670-b9d0-de8f3c4a5432": {"uuid": "705e2175-4a1d-4670-b9d0-'
'de8f3c4a5432", "size": 345913, "filename": "Cerfa.docx"}}, "text": ""}',
)


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_get_numero(client, convention):
def test_get_numero(client, convention, logged_in_user):
url = reverse("conventions:finalisation_numero", args=[convention.uuid])
response = client.get(url)
assert response.status_code == 200
Expand All @@ -49,8 +75,7 @@ def test_get_numero(client, convention):


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_get_numero_avenant(client, avenant):
def test_get_numero_avenant(client, avenant, logged_in_user):
url = reverse("conventions:finalisation_numero", args=[avenant.uuid])
response = client.get(url)
assert response.status_code == 200
Expand All @@ -64,8 +89,7 @@ def test_get_numero_avenant(client, avenant):


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_post_numero_fail(client, convention):
def test_post_numero_fail(client, convention, logged_in_user):
url = reverse("conventions:finalisation_numero", args=[convention.uuid])
data = {"numero": ""}
response = client.post(url, data)
Expand All @@ -75,8 +99,7 @@ def test_post_numero_fail(client, convention):


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_post_numero_success(client, convention):
def test_post_numero_success(client, convention, logged_in_user):
url = reverse("conventions:finalisation_numero", args=[convention.uuid])
data = {"numero": "1234567"}
response = client.post(url, data)
Expand All @@ -89,8 +112,7 @@ def test_post_numero_success(client, convention):


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_get_cerfa(client, convention):
def test_get_cerfa(client, convention, logged_in_user):
url = reverse("conventions:finalisation_cerfa", args=[convention.uuid])
response = client.get(url)
assert response.status_code == 200
Expand All @@ -100,8 +122,7 @@ def test_get_cerfa(client, convention):


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_post_cerfa(client, convention):
def test_post_cerfa(client, convention, logged_in_user):
url = reverse("conventions:finalisation_cerfa", args=[convention.uuid])
data = {}
response = client.post(url, data)
Expand All @@ -114,8 +135,7 @@ def test_post_cerfa(client, convention):


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_get_validation(client, convention):
def test_get_validation(client, convention, logged_in_user):
url = reverse("conventions:finalisation_validation", args=[convention.uuid])
response = client.get(url)
assert response.status_code == 200
Expand All @@ -127,8 +147,7 @@ def test_get_validation(client, convention):


@pytest.mark.django_db
@override_flag(settings.FLAG_OVERRIDE_CERFA, active=True)
def test_get_validation_avenant(client, avenant):
def test_get_validation_avenant(client, avenant, logged_in_user):
url = reverse("conventions:finalisation_validation", args=[avenant.uuid])
response = client.get(url)
assert response.status_code == 200
Expand Down
21 changes: 6 additions & 15 deletions conventions/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from django.contrib.auth.decorators import permission_required
from django.urls import path
from django.views.generic import RedirectView, TemplateView

Expand Down Expand Up @@ -30,7 +29,7 @@
),
path(
"post_action/<convention_uuid>",
views.post_action,
views.ActionsPostValidation.as_view(),
name="post_action",
),
path(
Expand All @@ -51,16 +50,12 @@
),
path(
"from_operation/add_convention/<numero_operation>",
permission_required("convention.add_convention")(
views.AddConventionView.as_view()
),
views.AddConventionView.as_view(),
name="from_operation_add_convention",
),
path(
"from_operation/add_avenants/<uuid:convention_uuid>",
permission_required("convention.add_convention")(
views.AddAvenantsView.as_view()
),
views.AddAvenantsView.as_view(),
name="from_operation_add_avenants",
),
# Pages pour la finalisation d'une convention par un instructeur
Expand All @@ -87,9 +82,7 @@
),
path(
"new_convention_anru",
permission_required("convention.add_convention")(
views.NewConventionAnruView.as_view()
),
views.NewConventionAnruView.as_view(),
name="new_convention_anru",
),
path(
Expand Down Expand Up @@ -275,7 +268,7 @@
),
path(
"sent/<convention_uuid>",
views.sent,
views.ConventionSentView.as_view(),
name="sent",
),
path(
Expand Down Expand Up @@ -317,9 +310,7 @@
),
path(
"search_for_avenant",
permission_required("convention.add_convention")(
views.SearchForAvenantResultView.as_view()
),
views.SearchForAvenantResultView.as_view(),
name="search_for_avenant",
),
path(
Expand Down
Loading

0 comments on commit 4d73731

Please sign in to comment.