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/',
providers.ProviderDeleteView.as_view(), name='provider-delete'),
# Invitations
path('invitations/', invitations.InviteListView.as_view(), name='invitations'),
path('invitations/create/', invitations.InviteCreateView.as_view(), name='invitation-create'),
path('invitations/', invitations.InvitationListView.as_view(), name='invitations'),
path('invitations/create/',
invitations.InvitationCreateView.as_view(), name='invitation-create'),
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'))
]

View File

@ -1,38 +1,40 @@
"""passbook Invite administration"""
"""passbook Invitation administration"""
from django.contrib.messages.views import SuccessMessageMixin
from django.http import HttpResponseRedirect
from django.urls import reverse_lazy
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.core.forms.invitations import InviteForm
from passbook.core.models import Invite
from passbook.core.forms.invitations import InvitationForm
from passbook.core.models import Invitation
class InviteListView(AdminRequiredMixin, ListView):
class InvitationListView(AdminRequiredMixin, ListView):
"""Show list of all invitations"""
model = Invite
model = Invitation
template_name = 'administration/invitation/list.html'
class InviteCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
"""Create new Invite"""
class InvitationCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
"""Create new Invitation"""
template_name = 'generic/create.html'
success_url = reverse_lazy('passbook_admin:invitations')
success_message = _('Successfully created Invite')
form_class = InviteForm
success_message = _('Successfully created Invitation')
form_class = InvitationForm
def get_initial(self):
return {
'created_by': self.request.user
}
def form_valid(self, form):
obj = form.save(commit=False)
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"""
model = Invite
model = Invitation
template_name = 'generic/delete.html'
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)
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)
@receiver(invitation_used)
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)
@receiver(user_login_failed)

View File

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

View File

@ -15,7 +15,7 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name='Invite',
name='Invitation',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('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)),
],
options={
'verbose_name': 'Invite',
'verbose_name': 'Invitation',
'verbose_name_plural': 'Invitations',
},
),

View File

@ -8,6 +8,7 @@ from uuid import uuid4
import reversion
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from model_utils.managers import InheritanceManager
@ -250,7 +251,7 @@ class DebugRule(Rule):
verbose_name = _('Debug Rule')
verbose_name_plural = _('Debug Rules')
class Invite(UUIDModel):
class Invitation(UUIDModel):
"""Single-use invitation link"""
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_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):
return "Invite %s created by %s" % (self.uuid, self.created_by)
return "Invitation %s created by %s" % (self.uuid, self.created_by)
class Meta:
verbose_name = _('Invite')
verbose_name = _('Invitation')
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.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'])
# 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 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.lib.config import CONFIG
@ -118,7 +118,7 @@ class SignUpView(UserPassesTestMixin, FormView):
template_name = 'login/form.html'
form_class = SignUpForm
success_url = '.'
# Invite insatnce, if invitation link was used
# Invitation insatnce, if invitation link was used
_invitation = None
# Instance of newly created user
_user = None
@ -134,7 +134,7 @@ class SignUpView(UserPassesTestMixin, FormView):
"""Check if sign-up is enabled or invitation link given"""
allowed = False
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()
if allowed:
self._invitation = invitations.first()
@ -145,6 +145,16 @@ class SignUpView(UserPassesTestMixin, FormView):
return redirect(reverse('passbook_core:auth-login'))
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):
kwargs['config'] = CONFIG.get('passbook')
kwargs['is_login'] = True