SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 696c1e14 authored by Jorran de Wit's avatar Jorran de Wit
Browse files

Improve registration vetting

Editorial Administrators are able to reset and resend the verification key
to a person who requested a key. All registrations are shown, so also
old ones. Should this view be extended to have some kind of cleanup function
to periodically remove (specific) old registrations?
parent 612f3f62
No related branches found
No related tags found
No related merge requests found
......@@ -124,6 +124,7 @@ subject_areas_dict = {}
for k in subject_areas_raw_dict.keys():
subject_areas_dict.update(dict(subject_areas_raw_dict[k]))
CONTRIBUTOR_NEWLY_REGISTERED = 0
CONTRIBUTOR_NORMAL = 1
CONTRIBUTOR_STATUS = (
# status determine the type of Contributor:
......@@ -135,7 +136,7 @@ CONTRIBUTOR_STATUS = (
# -2: other account already exists for this person
# -3: barred from SciPost (abusive behaviour)
# -4: disabled account (deceased)
(0, 'newly registered'),
(CONTRIBUTOR_NEWLY_REGISTERED, 'newly registered'),
(CONTRIBUTOR_NORMAL, 'normal user'),
(-1, 'not a professional scientist'),
(-2, 'other account already exists'),
......
......@@ -61,6 +61,10 @@ class Command(BaseCommand):
codename='can_invite_Fellows',
name='Can invite Fellows',
content_type=content_type)
can_resend_registration_requests, created = Permission.objects.get_or_create(
codename='can_resend_registration_requests',
name='Can resend registration activation emails',
content_type=content_type)
# Communications
can_email_group_members, created = Permission.objects.get_or_create(
......@@ -215,6 +219,7 @@ class Command(BaseCommand):
can_view_production,
can_publish_accepted_submission,
can_attend_VGMs,
can_resend_registration_requests,
])
EditorialCollege.permissions.set([
can_view_pool,
......
......@@ -3,7 +3,7 @@ import datetime
from django.db import models
from django.db.models import Q
from .constants import CONTRIBUTOR_NORMAL
from .constants import CONTRIBUTOR_NORMAL, CONTRIBUTOR_NEWLY_REGISTERED
class FellowManager(models.Manager):
......@@ -20,3 +20,6 @@ class FellowManager(models.Manager):
class ContributorManager(models.Manager):
def active(self):
return self.filter(user__is_active=True, status=CONTRIBUTOR_NORMAL)
def awaiting_validation(self):
return self.filter(user__is_active=False, status=CONTRIBUTOR_NEWLY_REGISTERED)
......@@ -103,7 +103,6 @@ class Contributor(models.Model):
salt = self.user.username.encode('utf8')
self.activation_key = hashlib.sha1(salt+salt).hexdigest()
self.key_expires = datetime.datetime.now() + datetime.timedelta(days=2)
self.save()
def discipline_as_string(self):
# Redundant, to be removed in future
......
......@@ -205,7 +205,13 @@
<ul>
{% if perms.scipost.can_vet_registration_requests %}
<li><a href="{% url 'scipost:vet_registration_requests' %}">Vet Registration requests</a> ({{ nr_reg_to_vet }})</li>
<li>Awaiting validation ({{ nr_reg_awaiting_validation }}) (no action necessary)</li>
<li>
{% if perms.scipost.can_resend_registration_requests %}
<a href="{% url 'scipost:registration_requests' %}">Awaiting validation</a> ({{ nr_reg_awaiting_validation }})
{% else %}
Awaiting validation ({{ nr_reg_awaiting_validation }})
{% endif %}
</li>
{% endif %}
{% if perms.scipost.can_draft_registration_invitations %}
<li><a href="{% url 'scipost:draft_registration_invitation' %}">Draft a Registration Invitation</a></li>
......
{% extends 'scipost/_personal_page_base.html' %}
{% block pagetitle %}: registration awaiting validation{% endblock pagetitle %}
{% load bootstrap %}
{% block breadcrumb_items %}
{{block.super}}
<span class="breadcrumb-item">Registration awaiting validation</span>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-12">
<h1 class="highlight">Registration awaiting validation</h1>
<p>
These Contributors did not yet activate their account. Sometimes, this link is never clicked on (email is either lost to spam, or not received).<br>
As per this page, you are able to send a reminder email to the as-yet-unconfirmed contributor.
</p>
</div>
</div>
<div class="row">
<div class="col-12">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Date requested</th>
<th>Key expires</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for contributor in unactive_contributors %}
<tr>
<td>{{contributor.user.first_name}} {{contributor.user.last_name}}</td>
<td>{{contributor.user.email}}</td>
<td>{{contributor.user.date_joined|timesince}} ago</td>
<td>
{% if contributor.key_expires < now %}
<span class="text-danger">Expired {{contributor.key_expires|timesince}} ago</span>
{% else %}
Expires in {{contributor.key_expires|timeuntil}}
{% endif %}
</td>
<td>
<form action="{% url 'scipost:registration_requests_reset' contributor.id %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-warning" value="Reset and resend" />
</form>
</td>
</tr>
{% empty %}
<tr>
<td colspan="5">All registrations have been activated.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock content %}
......@@ -84,6 +84,9 @@ urlpatterns = [
views.vet_registration_requests, name='vet_registration_requests'),
url(r'^vet_registration_request_ack/(?P<contributor_id>[0-9]+)$',
views.vet_registration_request_ack, name='vet_registration_request_ack'),
url(r'^registration_requests$', views.registration_requests, name="registration_requests"),
url(r'^registration_requests/(?P<contributor_id>[0-9]+)/reset$',
views.registration_requests_reset, name="registration_requests_reset"),
url(r'^registration_invitations/(?P<draft_id>[0-9]+)$',
views.registration_invitations, name="registration_invitations_from_draft"),
url(r'^registration_invitations$',
......
......@@ -278,6 +278,7 @@ def request_new_activation_link(request, contributor_id, key):
if request.GET.get('confirm', False):
# Generate a new email activation key and link
contributor.generate_key()
contributor.save()
Utils.load({'contributor': contributor}, request)
Utils.send_new_activation_link_email()
......@@ -385,6 +386,36 @@ def vet_registration_request_ack(request, contributor_id):
return redirect(reverse('scipost:vet_registration_requests'))
@permission_required('scipost.can_resend_registration_requests', return_403=True)
def registration_requests(request):
'''
List all inactive users. These are users that have filled the registration form,
but did not yet activate their account using the validation email.
'''
unactive_contributors = (Contributor.objects.awaiting_validation()
.prefetch_related('user')
.order_by('-key_expires'))
context = {
'unactive_contributors': unactive_contributors,
'now': timezone.now()
}
return render(request, 'scipost/registration_requests.html', context)
@require_POST
@permission_required('scipost.can_resend_registration_requests', return_403=True)
def registration_requests_reset(request, contributor_id):
'''
Reset specific activation_key for Contributor and resend activation mail.
'''
contributor = get_object_or_404(Contributor.objects.awaiting_validation(), id=contributor_id)
contributor.generate_key()
contributor.save()
Utils.load({'contributor': contributor}, request)
Utils.send_new_activation_link_email()
return redirect(reverse('scipost:registration_requests'))
@permission_required('scipost.can_draft_registration_invitations', return_403=True)
def draft_registration_invitation(request):
"""
......@@ -758,9 +789,9 @@ def personal_page(request):
# count the number of pending registration requests
nr_reg_to_vet = Contributor.objects.filter(user__is_active=True, status=0).count()
nr_reg_awaiting_validation = Contributor.objects.filter(
user__is_active=False, key_expires__gte=now,
key_expires__lte=intwodays, status=0).count()
nr_reg_awaiting_validation = (Contributor.objects.awaiting_validation()
# .filter(key_expires__gte=now, key_expires__lte=intwodays)
.count())
nr_submissions_to_assign = Submission.objects.filter(status__in=['unassigned']).count()
nr_recommendations_to_prepare_for_voting = EICRecommendation.objects.filter(
submission__status__in=['voting_in_preparation']).count()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment