all: fully switch to Invitation

This commit is contained in:
Jens Langhammer 2018-12-10 14:49:15 +01:00
parent 57f285ae54
commit d0099edac4
9 changed files with 73 additions and 37 deletions

View file

@ -35,9 +35,10 @@ urlpatterns = [
path('providers/<int:pk>/delete/', path('providers/<int:pk>/delete/',
providers.ProviderDeleteView.as_view(), name='provider-delete'), providers.ProviderDeleteView.as_view(), name='provider-delete'),
# Invitations # Invitations
path('invitations/', invitations.InviteListView.as_view(), name='invitations'), path('invitations/', invitations.InvitationListView.as_view(), name='invitations'),
path('invitations/create/', invitations.InviteCreateView.as_view(), name='invitation-create'), path('invitations/create/',
invitations.InvitationCreateView.as_view(), name='invitation-create'),
path('invitations/<uuid:pk>/delete/', path('invitations/<uuid:pk>/delete/',
invitations.InviteDeleteView.as_view(), name='invitation-delete'), invitations.InvitationDeleteView.as_view(), name='invitation-delete'),
# path('api/v1/', include('passbook.admin.api.v1.urls')) # path('api/v1/', include('passbook.admin.api.v1.urls'))
] ]

View file

@ -1,38 +1,40 @@
"""passbook Invite administration""" """passbook Invitation administration"""
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.http import HttpResponseRedirect
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic import CreateView, DeleteView, ListView, UpdateView from django.views.generic import CreateView, DeleteView, ListView
from passbook.admin.mixins import AdminRequiredMixin from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.forms.invitations import InviteForm from passbook.core.forms.invitations import InvitationForm
from passbook.core.models import Invite from passbook.core.models import Invitation
class InviteListView(AdminRequiredMixin, ListView): class InvitationListView(AdminRequiredMixin, ListView):
"""Show list of all invitations""" """Show list of all invitations"""
model = Invite model = Invitation
template_name = 'administration/invitation/list.html' template_name = 'administration/invitation/list.html'
class InviteCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView): class InvitationCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
"""Create new Invite""" """Create new Invitation"""
template_name = 'generic/create.html' template_name = 'generic/create.html'
success_url = reverse_lazy('passbook_admin:invitations') success_url = reverse_lazy('passbook_admin:invitations')
success_message = _('Successfully created Invite') success_message = _('Successfully created Invitation')
form_class = InviteForm form_class = InvitationForm
def get_initial(self): def form_valid(self, form):
return { obj = form.save(commit=False)
'created_by': self.request.user obj.created_by = self.request.user
} obj.save()
return HttpResponseRedirect(self.success_url)
class InviteDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView): class InvitationDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
"""Delete invitation""" """Delete invitation"""
model = Invite model = Invitation
template_name = 'generic/delete.html' template_name = 'generic/delete.html'
success_url = reverse_lazy('passbook_admin:invitations') success_url = reverse_lazy('passbook_admin:invitations')
success_message = _('Successfully updated Invite') success_message = _('Successfully updated Invitation')

View file

@ -0,0 +1,18 @@
# Generated by Django 2.1.4 on 2018-12-10 13:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('passbook_audit', '0003_auto_20181210_1213'),
]
operations = [
migrations.AlterField(
model_name='auditentry',
name='action',
field=models.TextField(choices=[('login', 'login'), ('login_failed', 'login_failed'), ('logout', 'logout'), ('authorize_application', 'authorize_application'), ('suspicious_request', 'suspicious_request'), ('sign_up', 'sign_up'), ('password_reset', 'password_reset'), ('invitation_created', 'invitation_created'), ('invitation_used', 'invitation_used')]),
),
]

View file

@ -25,12 +25,12 @@ def on_user_signed_up(sender, request, user, **kwargs):
@receiver(invitation_created) @receiver(invitation_created)
def on_invitation_created(sender, request, invitation, **kwargs): def on_invitation_created(sender, request, invitation, **kwargs):
"""Log Invite creation""" """Log Invitation creation"""
AuditEntry.create(AuditEntry.ACTION_INVITE_CREATED, request, invitation_uuid=invitation.uuid) AuditEntry.create(AuditEntry.ACTION_INVITE_CREATED, request, invitation_uuid=invitation.uuid)
@receiver(invitation_used) @receiver(invitation_used)
def on_invitation_used(sender, request, invitation, **kwargs): def on_invitation_used(sender, request, invitation, **kwargs):
"""Log Invite usage""" """Log Invitation usage"""
AuditEntry.create(AuditEntry.ACTION_INVITE_USED, request, invitation_uuid=invitation.uuid) AuditEntry.create(AuditEntry.ACTION_INVITE_USED, request, invitation_uuid=invitation.uuid)
@receiver(user_login_failed) @receiver(user_login_failed)

View file

@ -2,22 +2,21 @@
from django import forms from django import forms
from passbook.core.models import Invite from passbook.core.models import Invitation
class InviteForm(forms.ModelForm): class InvitationForm(forms.ModelForm):
"""InviteForm""" """InvitationForm"""
class Meta: class Meta:
model = Invite model = Invitation
fields = ['created_by', 'expires', 'fixed_username', 'fixed_email'] fields = ['expires', 'fixed_username', 'fixed_email']
labels = { labels = {
'fixed_username': "Force user's username (optional)", 'fixed_username': "Force user's username (optional)",
'fixed_email': "Force user's email (optional)", 'fixed_email': "Force user's email (optional)",
} }
widgets = { widgets = {
'created_by': forms.Select(attrs={'disabled': 'disabled'}),
'fixed_username': forms.TextInput(), 'fixed_username': forms.TextInput(),
'fixed_email': forms.TextInput(), 'fixed_email': forms.TextInput(),
} }

View file

@ -15,7 +15,7 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Invite', name='Invitation',
fields=[ fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('expires', models.DateTimeField(blank=True, default=None, null=True)), ('expires', models.DateTimeField(blank=True, default=None, null=True)),
@ -24,7 +24,7 @@ class Migration(migrations.Migration):
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
'verbose_name': 'Invite', 'verbose_name': 'Invitation',
'verbose_name_plural': 'Invitations', 'verbose_name_plural': 'Invitations',
}, },
), ),

View file

@ -8,6 +8,7 @@ from uuid import uuid4
import reversion import reversion
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from django.urls import reverse_lazy
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from model_utils.managers import InheritanceManager from model_utils.managers import InheritanceManager
@ -250,7 +251,7 @@ class DebugRule(Rule):
verbose_name = _('Debug Rule') verbose_name = _('Debug Rule')
verbose_name_plural = _('Debug Rules') verbose_name_plural = _('Debug Rules')
class Invite(UUIDModel): class Invitation(UUIDModel):
"""Single-use invitation link""" """Single-use invitation link"""
created_by = models.ForeignKey('User', on_delete=models.CASCADE) created_by = models.ForeignKey('User', on_delete=models.CASCADE)
@ -258,10 +259,15 @@ class Invite(UUIDModel):
fixed_username = models.TextField(blank=True, default=None) fixed_username = models.TextField(blank=True, default=None)
fixed_email = models.TextField(blank=True, default=None) fixed_email = models.TextField(blank=True, default=None)
@property
def link(self):
"""Get link to use invitation"""
return reverse_lazy('passbook_core:auth-sign-up') + '?invitation=%s' % self.uuid
def __str__(self): def __str__(self):
return "Invite %s created by %s" % (self.uuid, self.created_by) return "Invitation %s created by %s" % (self.uuid, self.created_by)
class Meta: class Meta:
verbose_name = _('Invite') verbose_name = _('Invitation')
verbose_name_plural = _('Invitations') verbose_name_plural = _('Invitations')

View file

@ -4,7 +4,7 @@ from django.core.signals import Signal
# from django.db.models.signals import post_save, pre_delete # from django.db.models.signals import post_save, pre_delete
# from django.dispatch import receiver # from django.dispatch import receiver
# from passbook.core.models import Invite, User # from passbook.core.models import Invitation, User
user_signed_up = Signal(providing_args=['request', 'user']) user_signed_up = Signal(providing_args=['request', 'user'])
# TODO: Send this signal in admin interface # TODO: Send this signal in admin interface

View file

@ -12,7 +12,7 @@ from django.views import View
from django.views.generic import FormView from django.views.generic import FormView
from passbook.core.forms.authentication import LoginForm, SignUpForm from passbook.core.forms.authentication import LoginForm, SignUpForm
from passbook.core.models import Invite, User from passbook.core.models import Invitation, User
from passbook.core.signals import invitation_used, user_signed_up from passbook.core.signals import invitation_used, user_signed_up
from passbook.lib.config import CONFIG from passbook.lib.config import CONFIG
@ -118,7 +118,7 @@ class SignUpView(UserPassesTestMixin, FormView):
template_name = 'login/form.html' template_name = 'login/form.html'
form_class = SignUpForm form_class = SignUpForm
success_url = '.' success_url = '.'
# Invite insatnce, if invitation link was used # Invitation insatnce, if invitation link was used
_invitation = None _invitation = None
# Instance of newly created user # Instance of newly created user
_user = None _user = None
@ -134,7 +134,7 @@ class SignUpView(UserPassesTestMixin, FormView):
"""Check if sign-up is enabled or invitation link given""" """Check if sign-up is enabled or invitation link given"""
allowed = False allowed = False
if 'invitation' in request.GET: if 'invitation' in request.GET:
invitations = Invite.objects.filter(uuid=request.GET.get('invitation')) invitations = Invitation.objects.filter(uuid=request.GET.get('invitation'))
allowed = invitations.exists() allowed = invitations.exists()
if allowed: if allowed:
self._invitation = invitations.first() self._invitation = invitations.first()
@ -145,6 +145,16 @@ class SignUpView(UserPassesTestMixin, FormView):
return redirect(reverse('passbook_core:auth-login')) return redirect(reverse('passbook_core:auth-login'))
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_initial(self):
if self._invitation:
initial = {}
if self._invitation.fixed_username:
initial['username'] = self._invitation.fixed_username
if self._invitation.fixed_email:
initial['e-mail'] = self._invitation.fixed_email
return initial
return super().get_initial()
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs['config'] = CONFIG.get('passbook') kwargs['config'] = CONFIG.get('passbook')
kwargs['is_login'] = True kwargs['is_login'] = True