Skip to content

Commit

Permalink
Adds permission requests for archives and reader studies (#1272)
Browse files Browse the repository at this point in the history
* Adds ReaderStudyPermissionRequest and ArchivePermissionRequest

* Adds Archive and ReaderStudy Forms

* Adds public reader study option

* Create ArchivePermissionRequestUpdate and ReaderStudyPermissionRequestUpdate views

* Adds signal handling

* Adds ReaderStudyPermissionRequestCreate and ArchivePermissionRequestCreate

* Adds ReaderStudyPermissionRequestList and ArchivePermissionRequestList

* Hook up Create/List/Update views

* Correct mock location

* Updates list views

* Adds permission request forms

* Adds permission request list links

* Fix test warnings

Closes #1168

* Fix permission tests

* Recreate migration

* Adds permission requests test

* Update permissions on update view

* Add missing kwargs
  • Loading branch information
jmsmkn committed Apr 7, 2020
1 parent 8b2e74b commit a8cd8e0
Show file tree
Hide file tree
Showing 46 changed files with 1,577 additions and 288 deletions.
2 changes: 2 additions & 0 deletions app/grandchallenge/algorithms/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from grandchallenge.algorithms.models import (
Algorithm,
AlgorithmImage,
AlgorithmPermissionRequest,
Job,
Result,
)
Expand Down Expand Up @@ -44,3 +45,4 @@ def error_message(self, obj):
admin.site.register(AlgorithmImage)
admin.site.register(Job, JobAdmin)
admin.site.register(Result)
admin.site.register(AlgorithmPermissionRequest)
77 changes: 0 additions & 77 deletions app/grandchallenge/algorithms/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,86 +2,9 @@
from django.contrib.sites.models import Site
from django.core.mail import send_mail

from grandchallenge.core.utils.email import send_templated_email
from grandchallenge.evaluation.templatetags.evaluation_extras import user_error


def send_permission_request_email(obj):
"""
Emails the editors that someone has requested to view an algorithm.
Parameters
----------
obj:
AlgorithmPermissionRequest object containing info on which
user requested access to which algorithm.
"""
title = f"[{obj.algorithm.title}] New access request"
kwargs = {
"user": obj.user,
"site": Site.objects.get_current(),
"algorithm": obj.algorithm,
}
for editor in obj.algorithm.editors_group.user_set.all():
kwargs["editor"] = editor
send_templated_email(
title,
"algorithms/emails/access_request.html",
kwargs,
[editor.email],
)


def send_permission_granted_email(obj):
"""
Emails the requester that their request has been approved.
Parameters
----------
obj:
AlgorithmPermissionRequest object containing info on which
user requested access to which algorithm.
"""
title = f"[{obj.algorithm.title}] Access granted"
kwargs = {
"user": obj.user,
"site": Site.objects.get_current(),
"algorithm": obj.algorithm,
}
send_templated_email(
title,
"algorithms/emails/access_granted.html",
kwargs,
[obj.user.email],
)


def send_permission_denied_email(obj):
"""
Emails the requester that their request has been approved.
Parameters
----------
obj:
AlgorithmPermissionRequest object containing info on which
user requested access to which algorithm and optionally the
reason for rejection.
"""
title = f"[{obj.algorithm.title}] Access denied"
kwargs = {
"user": obj.user,
"site": Site.objects.get_current(),
"algorithm": obj.algorithm,
"permission_request": obj,
}
send_templated_email(
title,
"algorithms/emails/access_denied.html",
kwargs,
[obj.user.email],
)


def send_failed_job_email(job):
algorithm = job.algorithm_image.algorithm
message = (
Expand Down
20 changes: 8 additions & 12 deletions app/grandchallenge/algorithms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Result,
)
from grandchallenge.core.forms import (
PermissionRequestUpdateForm,
SaveFormInitMixin,
WorkstationUserFilterMixin,
)
Expand Down Expand Up @@ -124,19 +125,23 @@ class EditorsForm(UserGroupForm):
class UsersForm(UserGroupForm):
role = "user"

def add_or_remove_user(self, *args, algorithm):
def add_or_remove_user(self, *, algorithm):
super().add_or_remove_user(algorithm=algorithm)

user = self.cleaned_data["user"]

try:
permission_request = AlgorithmPermissionRequest.objects.get(
user=user, algorithm=algorithm
)
except ObjectDoesNotExist:
return

if self.cleaned_data["action"] == self.REMOVE:
permission_request.status = AlgorithmPermissionRequest.REJECTED
else:
permission_request.status = AlgorithmPermissionRequest.ACCEPTED

permission_request.save()


Expand All @@ -146,15 +151,6 @@ class Meta:
fields = ("comment", "public")


class PermissionRequestUpdateForm(SaveFormInitMixin, ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["status"].choices = (
c
for c in AlgorithmPermissionRequest.REGISTRATION_CHOICES
if c[0] != AlgorithmPermissionRequest.PENDING
)

class Meta:
class AlgorithmPermissionRequestUpdateForm(PermissionRequestUpdateForm):
class Meta(PermissionRequestUpdateForm.Meta):
model = AlgorithmPermissionRequest
fields = ("status", "rejection_text")
25 changes: 22 additions & 3 deletions app/grandchallenge/algorithms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,12 +518,31 @@ class AlgorithmPermissionRequest(RequestBase):
),
)

@property
def base_object(self):
return self.algorithm

@property
def object_name(self):
return self.algorithm.title
return self.base_object.title

@property
def add_method(self):
return self.base_object.add_user

@property
def remove_method(self):
return self.base_object.remove_user

@property
def permission_list_url(self):
return reverse(
f"algorithms:permission-request-list",
kwargs={"slug": self.base_object.slug},
)

def __str__(self):
return f"{self.algorithm.title} registration request by user {self.user.username}"
return f"{self.object_name} registration request by user {self.user.username}"

class Meta:
class Meta(RequestBase.Meta):
unique_together = (("algorithm", "user"),)
24 changes: 2 additions & 22 deletions app/grandchallenge/algorithms/signals.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
from django.db.models.signals import m2m_changed, pre_save
from django.db.models.signals import m2m_changed
from django.dispatch import receiver
from guardian.shortcuts import assign_perm, remove_perm

from grandchallenge.algorithms.emails import (
send_permission_denied_email,
send_permission_granted_email,
send_permission_request_email,
)
from grandchallenge.algorithms.models import AlgorithmPermissionRequest, Result
from grandchallenge.algorithms.models import Result
from grandchallenge.cases.models import Image


Expand Down Expand Up @@ -60,18 +55,3 @@ def update_image_permissions(instance, action, reverse, model, pk_set, **_):
exclude_results = []

image.update_public_group_permissions(exclude_results=exclude_results)


@receiver(pre_save, sender=AlgorithmPermissionRequest)
def process_algorithm_permission_request(sender, instance, *_, **__):
old_values = sender.objects.filter(pk=instance.pk).first()
old_status = old_values.status if old_values else None
if instance.status != old_status:
if instance.status == AlgorithmPermissionRequest.PENDING:
send_permission_request_email(instance)
elif instance.status == AlgorithmPermissionRequest.ACCEPTED:
instance.algorithm.add_user(instance.user)
send_permission_granted_email(instance)
else:
instance.algorithm.remove_user(instance.user)
send_permission_denied_email(instance)
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ <h2>Request access</h2>
{% if not permission_request %}
<p>
You currently do not have permission to use this algorithm.
If you would like to use the algortihm, you can request permission here.
If you would like to use the algorithm, you can request permission here.
</p>
<p>
An email will be sent to the algorithm's editors.
Expand All @@ -62,13 +62,13 @@ <h2>Request access</h2>
</form>
{% else %}
<p>
You currently {% if permission_request.status != 'ACPT' %}do not {% endif%}have permission to view this algorithm.
You currently {% if permission_request.status != permission_request.ACCEPTED %}do not {% endif%}have permission to view this algorithm.
</p>
<p>
You have already sent a permission request.
The status of your request is <span class="font-weight-bold">{{ permission_request.get_status_display|lower }}</span>.
</p>
{% if permission_request.status == 'RJCT' %}
{% if permission_request.status == permission_request.REJECTED %}
{% if permission_request.rejection_text %}
<p>
The algorithm's editors have left the following reason for the rejection:
Expand All @@ -77,15 +77,6 @@ <h2>Request access</h2>
{{ permission_request.rejection_text }}
</p>
{% endif %}
<form action="{% url 'algorithms:permission-request-update' slug=algorithm.slug pk=permission_request.pk %}" method="post">
{% csrf_token %}
<input type="hidden"
name="status"
value="PEND"/>
<input type="submit"
value="Request access again"
class="btn btn-primary"/>
</form>
{% endif %}
{% endif %}
{% endif %}
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit a8cd8e0

Please sign in to comment.