SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit c24029ca authored by Jean-Sébastien Caux's avatar Jean-Sébastien Caux
Browse files

Add organizations.Contact: activate account

parent 76e2c958
No related branches found
No related tags found
No related merge requests found
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.db import transaction
from .constants import ROLE_KINDS
from .models import Contact
class ContactActivationForm(forms.ModelForm):
class Meta:
model = User
fields = []
password_new = forms.CharField(label='* Password', widget=forms.PasswordInput())
password_verif = forms.CharField(label='* Verify password', widget=forms.PasswordInput(),
help_text='Your password must contain at least 8 characters')
def clean(self, *args, **kwargs):
try:
self.instance.org_contact
except Contact.DoesNotExist:
self.add_error(None, 'Your account is invalid, please contact the administrator.')
return super().clean(*args, **kwargs)
def clean_password(self):
password = self.cleaned_data.get('password_new', '')
try:
validate_password(password, self.instance)
except ValidationError as error_message:
self.add_error('password_new', error_message)
return password
def clean_password_verif(self):
if self.cleaned_data.get('password_new', '') != self.cleaned_data.get('password_verif', ''):
self.add_error('password_verif', 'Your password entries must match')
return self.cleaned_data.get('password_verif', '')
@transaction.atomic
def activate_user(self):
if self.errors:
return forms.ValidationError
# Activate account
self.instance.is_active = True
self.instance.set_password(self.cleaned_data['password_new'])
self.instance.save()
return self.instance
{% extends 'scipost/base.html' %}
{% load bootstrap %}
{% block pagetitle %}{{block.super}} Activate Account{% endblock pagetitle %}
{% block content %}
<h1 class="highlight">Activate Account</h1>
<div class="row justify-content-center">
<div class="col-md-8">
<h2>{{ contact.get_title_display }} {{ contact.user.first_name }} {{ contact.user.last_name }}</h2>
<h3>{{ contact.user.email }}</h3>
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-8 mb-5">
<form method="post">
{% csrf_token %}
{{ form|bootstrap }}
<input class="btn btn-primary" type="submit" value="Activate"/>
</form>
</div>
</div>
{% endblock content %}
...@@ -32,6 +32,11 @@ urlpatterns = [ ...@@ -32,6 +32,11 @@ urlpatterns = [
views.OrganizationDetailView.as_view(), views.OrganizationDetailView.as_view(),
name='organization_details' name='organization_details'
), ),
url(
r'^activate/(?P<activation_key>.+)$',
views.activate_account,
name='activate_account'
),
url( url(
r'^dashboard/$', r'^dashboard/$',
views.dashboard, views.dashboard,
......
...@@ -2,9 +2,11 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" ...@@ -2,9 +2,11 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3" __license__ = "AGPL v3"
from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
from django.shortcuts import render from django.shortcuts import get_object_or_404, render, reverse, redirect
from django.utils import timezone from django.utils import timezone
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.views.generic.edit import CreateView, UpdateView, DeleteView
...@@ -13,9 +15,11 @@ from django.views.generic.list import ListView ...@@ -13,9 +15,11 @@ from django.views.generic.list import ListView
from guardian.decorators import permission_required from guardian.decorators import permission_required
from .constants import ORGTYPE_PRIVATE_BENEFACTOR from .constants import ORGTYPE_PRIVATE_BENEFACTOR
from .models import Organization from .forms import ContactActivationForm
from .models import Organization, Contact
from funders.models import Funder from funders.models import Funder
from organizations.decorators import has_contact
from partners.models import ProspectivePartner, Partner from partners.models import ProspectivePartner, Partner
from scipost.mixins import PermissionsMixin from scipost.mixins import PermissionsMixin
...@@ -98,6 +102,25 @@ class OrganizationDetailView(DetailView): ...@@ -98,6 +102,25 @@ class OrganizationDetailView(DetailView):
return queryset return queryset
def activate_account(request, activation_key):
contact = get_object_or_404(Contact, user__is_active=False,
activation_key=activation_key,
user__email__icontains=request.GET.get('email', None))
# TODO: Key Expires fallback
form = ContactActivationForm(request.POST or None, instance=contact.user)
if form.is_valid():
form.activate_user()
messages.success(request, '<h3>Thank you for activating your account</h3>')
return redirect(reverse('organizations:dashboard'))
context = {
'contact': contact,
'form': form
}
return render(request, 'organizations/activate_account.html', context)
@login_required @login_required
def dashboard(request): def dashboard(request):
""" """
...@@ -106,9 +129,12 @@ def dashboard(request): ...@@ -106,9 +129,12 @@ def dashboard(request):
This page is meant as a personal page for Contacts, where they will for example be able This page is meant as a personal page for Contacts, where they will for example be able
to read their personal data and agreements. to read their personal data and agreements.
""" """
context = {} if not (request.user.has_perm('scipost.can_manage_organizations') or
try: has_contact(request.user)):
context['roles'] = request.user.org_contact.roles.all() raise PermissionDenied
except:
pass context = {
'roles': request.user.org_contact.roles.all()
}
return render(request, 'organizations/dashboard.html', context) return render(request, 'organizations/dashboard.html', context)
...@@ -41,11 +41,13 @@ class Command(BaseCommand): ...@@ -41,11 +41,13 @@ class Command(BaseCommand):
# Create Permissions # Create Permissions
content_type = ContentType.objects.get_for_model(Contributor) content_type = ContentType.objects.get_for_model(Contributor)
# Supporting Partners # Organizations
can_manage_organizations, created = Permission.objects.get_or_create( can_manage_organizations, created = Permission.objects.get_or_create(
codename='can_manage_organizations', codename='can_manage_organizations',
name='Can manage Organizations', name='Can manage Organizations',
content_type=content_type) content_type=content_type)
# Supporting Partners
can_manage_SPB, created = Permission.objects.get_or_create( can_manage_SPB, created = Permission.objects.get_or_create(
codename='can_manage_SPB', codename='can_manage_SPB',
name='Can manage Supporting Partners Board', name='Can manage Supporting Partners Board',
......
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