diff --git a/castellum/castellum_auth/fixtures/groups.json b/castellum/castellum_auth/fixtures/groups.json index 2f03370724b2e60ed45e3398f9f4806e591b30cd..bbbe6e54483045fad824a04f3d85624fe4129119 100644 --- a/castellum/castellum_auth/fixtures/groups.json +++ b/castellum/castellum_auth/fixtures/groups.json @@ -5,21 +5,6 @@ "fields": { "name": "Study coordinator", "permissions": [ - [ - "change_subjectfilter", - "recruitment", - "subjectfilter" - ], - [ - "view_subjectfilter", - "recruitment", - "subjectfilter" - ], - [ - "add_study", - "studies", - "study" - ], [ "change_study", "studies", @@ -45,29 +30,9 @@ "name": "Subject manager", "permissions": [ [ - "add_contact", - "contacts", - "contact" - ], - [ - "change_contact", - "contacts", - "contact" - ], - [ - "view_contact", - "contacts", - "contact" - ], - [ - "change_attributeset", - "recruitment", - "attributeset" - ], - [ - "view_attributeset", - "recruitment", - "attributeset" + "view_subject", + "subjects", + "subject" ], [ "change_subject", @@ -84,22 +49,7 @@ "name": "Recruiter", "permissions": [ [ - "view_contact", - "contacts", - "contact" - ], - [ - "add_participation", - "recruitment", - "participation" - ], - [ - "change_participation", - "recruitment", - "participation" - ], - [ - "view_participation", + "recruit", "recruitment", "participation" ] @@ -113,7 +63,7 @@ "name": "Study conductor", "permissions": [ [ - "view_participation_pseudonyms", + "conduct_study", "recruitment", "participation" ] @@ -127,22 +77,12 @@ "name": "Data protection coordinator", "permissions": [ [ - "view_contact", - "contacts", - "contact" - ], - [ - "delete_participation", - "recruitment", - "participation" - ], - [ - "view_participation_pseudonyms", - "recruitment", - "participation" + "view_subject", + "subjects", + "subject" ], [ - "view_subject", + "export_subject", "subjects", "subject" ], @@ -186,9 +126,14 @@ "name": "Receptionist", "permissions": [ [ - "search_execution", + "search_participations", "recruitment", "participation" + ], + [ + "view_current_appointments", + "recruitment", + "appointment" ] ] } diff --git a/castellum/contacts/mixins.py b/castellum/contacts/mixins.py index 59e36ce09fdcc836c80f3a9ae2ea6efdff1c7769..dab5a4243fd4de253cfbf082ff8e3b2eb93afe66 100644 --- a/castellum/contacts/mixins.py +++ b/castellum/contacts/mixins.py @@ -30,7 +30,7 @@ from .models import Contact class BaseContactUpdateView(PermissionRequiredMixin, UpdateView): model = Contact form_class = ContactForm - permission_required = 'contacts.change_contact' + permission_required = 'subjects.change_subject' def get_form_kwargs(self): kwargs = super().get_form_kwargs() diff --git a/castellum/data_protection/templates/data_protection/index.html b/castellum/data_protection/templates/data_protection/index.html index deeab7994c92453906f7e7903b1ed3cc17706de9..ea0d1381f177fee3b866657218938fcfb37ad325 100644 --- a/castellum/data_protection/templates/data_protection/index.html +++ b/castellum/data_protection/templates/data_protection/index.html @@ -1,5 +1,5 @@ {% extends "base_with_breadcrumbs.html" %} -{% load i18n %} +{% load i18n auth %} {% block title %}{% trans 'Data protection dashboard' %} · {{ block.super }}{% endblock %} @@ -11,12 +11,15 @@

{% trans 'Export requested' %}

{% include 'data_protection/__subject_list.html' with subjects=export_requested missing=export_requested_missing %} -

{% trans 'To be deleted' %}

- {% include 'data_protection/__subject_list.html' with subjects=to_be_deleted missing=to_be_deleted_missing %} + {% has_perm 'subjects.delete_subject' user as can_delete_subject %} + {% if can_delete_subject %} +

{% trans 'To be deleted' %}

+ {% include 'data_protection/__subject_list.html' with subjects=to_be_deleted missing=to_be_deleted_missing %} -

{% trans 'No legal basis' %}

- {% include 'data_protection/__subject_list.html' with subjects=no_legal_basis missing=no_legal_basis_missing %} +

{% trans 'No legal basis' %}

+ {% include 'data_protection/__subject_list.html' with subjects=no_legal_basis missing=no_legal_basis_missing %} -

{% trans 'Unreachable' %}

- {% include 'data_protection/__subject_list.html' with subjects=unreachable missing=unreachable_missing %} +

{% trans 'Unreachable' %}

+ {% include 'data_protection/__subject_list.html' with subjects=unreachable missing=unreachable_missing %} + {% endif %} {% endblock %} diff --git a/castellum/data_protection/views.py b/castellum/data_protection/views.py index 9c241e979200040a0e6befc20ac3a5b9b0618252..a364bef4977aa248123c164cc8d4248339f44aef 100644 --- a/castellum/data_protection/views.py +++ b/castellum/data_protection/views.py @@ -29,7 +29,7 @@ from . import helpers class DataProtectionView(PermissionRequiredMixin, TemplateView): template_name = 'data_protection/index.html' permission_required = [ - 'subjects.view_subject', + 'subjects.export_subject', 'castellum_auth.privacy_level_2', ] limit_by = 10 diff --git a/castellum/execution/feeds.py b/castellum/execution/feeds.py index 2bdaa9d0aac082a2db05815d5a5a165a99a93bf6..9efbec1695d8aa3014a8392e262c5a8e966cdcee 100644 --- a/castellum/execution/feeds.py +++ b/castellum/execution/feeds.py @@ -30,7 +30,7 @@ from castellum.studies.models import Study class AppointmentFeed(BaseAppointmentFeed): def get_object(self, request, *args, **kwargs): study = get_object_or_404(Study, pk=kwargs['pk'], status=Study.EXECUTION) - perms = ('recruitment.view_participation_pseudonyms', 'studies.access_study') + perms = ('recruitment.conduct_study', 'studies.access_study') if not self.request.user.has_perms(perms, obj=study): raise PermissionDenied return study diff --git a/castellum/execution/templates/execution/participation_detail.html b/castellum/execution/templates/execution/participation_detail.html index 4f8350baaee55645fc630f1002cfe7a9ee275121..6d034fe3deef9d1df8974c673cbdf7263b14112a 100644 --- a/castellum/execution/templates/execution/participation_detail.html +++ b/castellum/execution/templates/execution/participation_detail.html @@ -41,23 +41,15 @@ {% endfor %} - {% has_perm 'contacts.change_contact' user study as can_change_contact %} - {% if can_change_contact %} + {% has_perm 'subjects.change_subject' user study as can_change_subject %} + {% if can_change_subject %} {% if not subject.contact.is_complete %} {% endif %} {% trans 'Edit contact data' %} - {% endif %} - - {% has_perm 'recruitment.change_attributeset' user study as can_change_attributeset %} - {% if can_change_attributeset %} {% trans 'Edit attributes' %} - {% endif %} - - {% has_perm 'subjects.change_subject' user study as can_change_subject %} - {% if can_change_subject %} {% if subject.consent.document.is_deprecated or subject.has_consent_from_before_full_age %} diff --git a/castellum/execution/views.py b/castellum/execution/views.py index d2fbb60d6aad257650f35d8bbc81abb4fc258433..345b7e64481d9b7be2384c45adcade9550d8020a 100644 --- a/castellum/execution/views.py +++ b/castellum/execution/views.py @@ -51,7 +51,7 @@ from castellum.subjects.mixins import BaseDataProtectionUpdateView class StudyDetailView(StudyMixin, PermissionRequiredMixin, DetailView): template_name = 'execution/study_detail.html' model = Study - permission_required = 'recruitment.view_participation_pseudonyms' + permission_required = 'recruitment.conduct_study' study_status = [Study.EXECUTION] def get_object(self): @@ -76,7 +76,7 @@ class ParticipationDetailView( ): template_name = 'execution/participation_detail.html' model = Participation - permission_required = 'recruitment.view_participation_pseudonyms' + permission_required = 'recruitment.conduct_study' study_status = [Study.EXECUTION] participation_status = [Participation.INVITED] @@ -98,7 +98,7 @@ class ParticipationDetailView( class ResolveView(StudyMixin, PermissionRequiredMixin, FormView): template_name = 'execution/study_resolve.html' - permission_required = 'recruitment.view_participation_pseudonyms' + permission_required = 'recruitment.conduct_study' study_status = [Study.EXECUTION] form_class = PseudonymForm @@ -132,7 +132,7 @@ class ExecutionUpdateMixin(ParticipationMixin): return context def get_permission_required(self): - permission_required = {'recruitment.view_participation_pseudonyms'} + permission_required = {'recruitment.conduct_study'} permission_required.update(super().get_permission_required()) return permission_required @@ -178,7 +178,7 @@ class AdditionalInfoUpdateView(ExecutionUpdateMixin, BaseAdditionalInfoUpdateVie class CalendarView(StudyMixin, PermissionRequiredMixin, BaseCalendarView): model = Study - permission_required = 'recruitment.view_participation_pseudonyms' + permission_required = 'recruitment.conduct_study' study_status = [Study.EXECUTION] feed = 'execution:calendar-feed' @@ -204,7 +204,7 @@ class CalendarView(StudyMixin, PermissionRequiredMixin, BaseCalendarView): class ReceptionView(PermissionRequiredMixin, ListView): model = Appointment template_name = 'execution/reception.html' - permission_required = 'recruitment.search_execution' + permission_required = 'recruitment.view_current_appointments' def get_queryset(self): return super().get_queryset().filter( diff --git a/castellum/recruitment/feeds.py b/castellum/recruitment/feeds.py index e08edc8e758d725f4f8770f0363d228251906a9f..bd40dfb3ab422fd521b69c8a1ce259fc4a7a15e0 100644 --- a/castellum/recruitment/feeds.py +++ b/castellum/recruitment/feeds.py @@ -32,7 +32,7 @@ from .models import Participation class FollowUpFeedForStudy(BaseFollowUpFeed): def get_object(self, request, *args, **kwargs): study = get_object_or_404(Study, pk=kwargs.get('study_pk'), status=Study.EXECUTION) - perms = ('recruitment.add_participation', 'studies.access_study') + perms = ('recruitment.recruit', 'studies.access_study') if not self.request.user.has_perms(perms, obj=study): raise PermissionDenied return study @@ -48,7 +48,7 @@ class FollowUpFeedForUser(BaseFollowUpFeed): return self.request.user def items(self, user): - perms = ('recruitment.add_participation', 'studies.access_study') + perms = ('recruitment.recruit', 'studies.access_study') for study in Study.objects.filter(status=Study.EXECUTION): if not user.has_perms(perms, obj=study): continue @@ -62,7 +62,7 @@ class FollowUpFeedForUser(BaseFollowUpFeed): class AppointmentFeed(BaseAppointmentFeed): def get_object(self, request, *args, **kwargs): study = get_object_or_404(Study, pk=kwargs['pk'], status=Study.EXECUTION) - perms = ('recruitment.view_participation', 'studies.access_study') + perms = ('recruitment.recruit', 'studies.access_study') if not self.request.user.has_perms(perms, obj=study): raise PermissionDenied return study diff --git a/castellum/recruitment/migrations/0013_refactor_permissions.py b/castellum/recruitment/migrations/0013_refactor_permissions.py new file mode 100644 index 0000000000000000000000000000000000000000..c91c08fe223c5f75b312e56d45d78cd52d2d6ae3 --- /dev/null +++ b/castellum/recruitment/migrations/0013_refactor_permissions.py @@ -0,0 +1,21 @@ +# Generated by Django 3.0.8 on 2020-07-21 16:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('recruitment', '0012_attributeset_onetime_invitation_disinterest'), + ] + + operations = [ + migrations.AlterModelOptions( + name='appointment', + options={'ordering': ('start',), 'permissions': [('view_current_appointments', 'Can view current appointments')]}, + ), + migrations.AlterModelOptions( + name='participation', + options={'permissions': (('conduct_study', 'Can conduct studies'), ('search_participations', 'Can search for any participation'), ('recruit', 'Can recruit')), 'verbose_name': 'Participation', 'verbose_name_plural': 'Participations'}, + ), + ] diff --git a/castellum/recruitment/mixins.py b/castellum/recruitment/mixins.py index 6a4ff7b0ab11632be519c96616fc5e73e8bfc649..f83675348cde8ef5078f937958514257365f96b8 100644 --- a/castellum/recruitment/mixins.py +++ b/castellum/recruitment/mixins.py @@ -113,7 +113,7 @@ class ParticipationMixin(StudyMixin, SubjectMixin): class BaseAttributeSetUpdateView(PermissionRequiredMixin, UpdateView): model = AttributeSet - permission_required = 'recruitment.change_attributeset' + permission_required = 'subjects.change_subject' def get_form_class(self): return AttributeSetForm.factory(self.request.user) diff --git a/castellum/recruitment/models/appointments.py b/castellum/recruitment/models/appointments.py index 192325c8dc57074d741dcd7ed5b2c7dc7e8a7d1b..75e8e3987bbe4c0208ca76ce130575aaf1ce8268 100644 --- a/castellum/recruitment/models/appointments.py +++ b/castellum/recruitment/models/appointments.py @@ -60,6 +60,9 @@ class Appointment(models.Model): class Meta: ordering = ('start',) unique_together = ['session', 'participation'] + permissions = [ + ('view_current_appointments', _('Can view current appointments')), + ] def __str__(self): return '%s %s' % (date_format(self.start), time_format(self.start)) diff --git a/castellum/recruitment/models/recruitment.py b/castellum/recruitment/models/recruitment.py index be97e58e16721758bd6e61746b3f73008234eab1..9b181cb664b73e9ce1a7f1f9bbab8a7da7a0b51a 100644 --- a/castellum/recruitment/models/recruitment.py +++ b/castellum/recruitment/models/recruitment.py @@ -110,8 +110,9 @@ class Participation(models.Model): verbose_name_plural = _('Participations') unique_together = ('study', 'subject') permissions = ( - ('view_participation_pseudonyms', _('Can view participation pseudonyms')), - ('search_execution', _('Can search in execution')), + ('conduct_study', _('Can conduct studies')), + ('search_participations', _('Can search for any participation')), + ('recruit', _('Can recruit')), ) @property diff --git a/castellum/recruitment/templates/recruitment/__recruitment_list.html b/castellum/recruitment/templates/recruitment/__recruitment_list.html index c4829f22e0966d911d79c5912180ea93615c886b..7a38b32a46ba7d07d278d55aea70781af242d932 100644 --- a/castellum/recruitment/templates/recruitment/__recruitment_list.html +++ b/castellum/recruitment/templates/recruitment/__recruitment_list.html @@ -1,7 +1,6 @@ {% load i18n auth utils %}