Skip to content

Commit

Permalink
paperless approval without any other auth but the PI's inbox
Browse files Browse the repository at this point in the history
  • Loading branch information
adRn-s committed Nov 30, 2023
1 parent 1ef156b commit 63b3d1f
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 45 deletions.
2 changes: 1 addition & 1 deletion backend/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def paperless_approval(self):
and self.email.split("@")[1] == settings.SERVER_EMAIL.split("@")[1]
):
result_user = True
return False # result_user and result_pi # and not self.is_pi
return result_user and result_pi # and not self.is_pi

def __str__(self):
this_user_email = self.email
Expand Down
8 changes: 4 additions & 4 deletions backend/request/templates/approval.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
</style>
<p>Dear {{ pi_name }},</p>
<p>
{{ full_name }} requested your approval on this experiment. <b>Please treat the link within this email message as a one-time password, scoped for the authorization of this sequencing request.</b> To approve it, click <a href={{ token_url }}>this link</a> yourself (assuming you have access to Parkour at the moment, e.g. using VPN while traveling).
&emsp; {{ full_name }} requested your approval on this experiment. <b>Please treat <a href={{ token_url }}>this link</a> as a one-time password, scoped for the authorization of this particular sequencing request.</b> Click on it to approve.
<br />
Else, just forward -or Reply "OK"- to this email. Then {{ full_name }}, would be authenticated (log-in) within Parkour LIMS, be able click the special link themselves.
&emsp; If you are unable to reach Parkour2 now (e.g. using mobile phone on a train without VPN access), consider forwarding this email to anyone else within the Institute's network, they can click on it (even without an account).
<br />
Afterward, processing will be started right away at the facility. <b>If you don't want to approve the sequencing request, ignore this email. Ask for any changes, and the re-sending of a new e-mail just like this one (with a new link).</b>
&emsp; <b>If you don't want to approve the sequencing request, ignore this email.</b> Ask {{ full_name }} for any changes, and the re-sending of a new e-mail just like this one (there's going to be a new link, invalidating the current one).
</p>
<hr />
<p>{{ full_name }} wrote:</p>
<p>{{ message }}</p>
<p>&emsp; {{ message }}</p>
<br />
{% if records %}
<hr />
Expand Down
2 changes: 1 addition & 1 deletion backend/request/templates/approved.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% load i18n %}
{% autoescape off %}
<p>Dear {{ full_name }},</p>
<p>{{ pi_name }} approved this experiment. Sequencing will start as soon as possible, please be patient.</p>
<p>&emsp; {{ pi_name }} approved this experiment. Sequencing will start as soon as possible, please be patient.</p>
<p>
--
<br />
Expand Down
83 changes: 45 additions & 38 deletions backend/request/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from rest_framework import filters, status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound
from rest_framework.permissions import IsAdminUser
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.response import Response

from .models import FileRequest, Request
Expand Down Expand Up @@ -659,53 +659,18 @@ def solicite_approval(self, request, pk=None): # pragma: no cover
"full_name": instance.user.full_name,
"pi_name": instance.user.pi.name,
"message": message,
"token_url": f"{url_scheme}://{url_domain}/api/requests/{instance.id}/approve?{url_query}",
"token_url": f"{url_scheme}://{url_domain}/api/approve/this/?pk={instance.id}&{url_query}",
"records": records,
},
),
from_email=settings.SERVER_EMAIL,
recipient_list=[instance.user.pi.email],
)
except Exception as e:
error = str(e)
logger.exception(e)
return JsonResponse({"success": not error, "error": error})

@action(methods=["get"], detail=True)
def approve(self, request, *args, **kwargs): # pragma: no cover
"""Process token sent to PI."""
error = ""
instance = self.get_object()
try:
# if request.user.id != instance.user.id:
# raise ValueError(
# f"Sorry {instance.user}, the link is only valid for {request.user}!"
# )
token = request.query_params.get("token")
if token == instance.token:
instance.libraries.all().update(status=1)
instance.samples.all().update(status=1)
instance.token = None
instance.save(update_fields=["token"])
else:
raise ValueError(f"Token mismatch.")
except Exception as e:
error = str(e)
logger.exception(e)
return JsonResponse({"success": not error, "error": error})
send_mail(
subject=f"[ Parkour2 | seq. request was approved ] ",
message="",
html_message=render_to_string(
"approved.html",
{
"full_name": instance.user.full_name,
"pi_name": instance.user.pi.name,
},
),
recipient_list=[instance.user.email],
)
return HttpResponseRedirect("/")

@action(methods=["post"], detail=True, permission_classes=[IsAdminUser])
def send_email(self, request, pk=None): # pragma: no cover
"""Send an email to the user."""
Expand Down Expand Up @@ -1060,3 +1025,45 @@ def _get_post_data(self, request):
else:
post_data = json.loads(request.data.get("data", "{}"))
return post_data


class ApproveViewSet(viewsets.ModelViewSet):
permission_classes = [AllowAny]
serializer_class = RequestSerializer
queryset = Request.objects.all().filter(id=0)

@action(methods=["get"], detail=False)
def this(self, request, *args, **kwargs): # pragma: no cover
"""Process token sent to PI."""
error = ""
try:
token = request.query_params.get("token")
pk = request.query_params.get("pk")
instance = list(Request.objects.filter(id=pk))[0]
if not all(s == 0 for s in instance.statuses):
raise ValueError(f"Not all statuses are zero: {instance.statuses}")
if token == instance.token:
instance.libraries.all().update(status=1)
instance.samples.all().update(status=1)
instance.token = None
instance.save(update_fields=["token"])
else:
raise ValueError(f"Token mismatch.")
except Exception as e:
error = str(e)
logger.exception(e)
return JsonResponse({"success": not error, "error": error})
send_mail(
subject=f"[ Parkour2 | seq. request was approved ] {instance.name}",
message="",
html_message=render_to_string(
"approved.html",
{
"full_name": instance.user.full_name,
"pi_name": instance.user.pi.name,
},
),
from_email=settings.SERVER_EMAIL,
recipient_list=[instance.user.email, instance.user.pi.email],
)
return HttpResponseRedirect("/")
3 changes: 2 additions & 1 deletion backend/wui/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
)
from metadata_exporter.views import MetadataExporterViewSet
from pooling.views import PoolingViewSet
from request.views import RequestViewSet
from request.views import ApproveViewSet, RequestViewSet
from rest_framework import routers
from sample.views import NucleicAcidTypeViewSet, SampleViewSet
from stats.views import RunStatisticsViewSet, SequencesStatisticsViewSet
Expand All @@ -41,6 +41,7 @@

router.register(r"duties", DutyViewSet, basename="duties")
router.register(r"requests", RequestViewSet, basename="request")
router.register(r"approve", ApproveViewSet, basename="approve")
router.register(r"cost_units", CostUnitsViewSet, basename="cost-units")
router.register(r"organisms", OrganismViewSet, basename="organism")
router.register(r"read_lengths", ReadLengthViewSet, basename="read-length")
Expand Down

0 comments on commit 63b3d1f

Please sign in to comment.