all: invites -> invitations

This commit is contained in:
Jens Langhammer 2018-12-10 14:21:42 +01:00
parent 89c2b8d49c
commit 545795ebc6
14 changed files with 61 additions and 58 deletions

View File

@ -20,8 +20,8 @@
<li class="{% is_active 'passbook_admin:rules' 'passbook_admin:rule-create' 'passbook_admin:rule-update' 'passbook_admin:rule-delete' 'passbook_admin:rule-test' %}"> <li class="{% is_active 'passbook_admin:rules' 'passbook_admin:rule-create' 'passbook_admin:rule-update' 'passbook_admin:rule-delete' 'passbook_admin:rule-test' %}">
<a href="{% url 'passbook_admin:rules' %}">{% trans 'Rules' %}</a> <a href="{% url 'passbook_admin:rules' %}">{% trans 'Rules' %}</a>
</li> </li>
<li class="{% is_active 'passbook_admin:invites' 'passbook_admin:invite-create' 'passbook_admin:invite-update' 'passbook_admin:invite-delete' 'passbook_admin:invite-test' %}"> <li class="{% is_active 'passbook_admin:invitations' 'passbook_admin:invitation-create' 'passbook_admin:invitation-update' 'passbook_admin:invitation-delete' 'passbook_admin:invitation-test' %}">
<a href="{% url 'passbook_admin:invites' %}">{% trans 'Invites' %}</a> <a href="{% url 'passbook_admin:invitations' %}">{% trans 'Invitations' %}</a>
</li> </li>
<li> <li>
<a href="#">{% trans 'Users' %}</a> <a href="#">{% trans 'Users' %}</a>

View File

@ -9,8 +9,8 @@
{% block content %} {% block content %}
<div class="container"> <div class="container">
<h1>{% trans "Invites" %}</h1> <h1>{% trans "Invitations" %}</h1>
<a href="{% url 'passbook_admin:invite-create' %}" class="btn btn-primary"> <a href="{% url 'passbook_admin:invitation-create' %}" class="btn btn-primary">
{% trans 'Create...' %} {% trans 'Create...' %}
</a> </a>
<hr> <hr>
@ -23,13 +23,13 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for invite in object_list %} {% for invitation in object_list %}
<tr> <tr>
<td>{{ invite.name }}</td> <td>{{ invitation.name }}</td>
<td>{{ invite.provider }}</td> <td>{{ invitation.provider }}</td>
<td> <td>
<a class="btn btn-default btn-sm" href="{% url 'passbook_admin:invite-update' pk=invite.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a> <a class="btn btn-default btn-sm" href="{% url 'passbook_admin:invitation-update' pk=invitation.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>
<a class="btn btn-default btn-sm" href="{% url 'passbook_admin:invite-delete' pk=invite.uuid %}?back={{ request.get_full_path }}">{% trans 'Delete' %}</a> <a class="btn btn-default btn-sm" href="{% url 'passbook_admin:invitation-delete' pk=invitation.uuid %}?back={{ request.get_full_path }}">{% trans 'Delete' %}</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -1,8 +1,8 @@
"""passbook URL Configuration""" """passbook URL Configuration"""
from django.urls import path from django.urls import path
from passbook.admin.views import (applications, invites, overview, providers, from passbook.admin.views import (applications, invitations, overview,
rules, sources) providers, rules, sources)
urlpatterns = [ urlpatterns = [
path('', overview.AdministrationOverviewView.as_view(), name='overview'), path('', overview.AdministrationOverviewView.as_view(), name='overview'),
@ -34,10 +34,12 @@ urlpatterns = [
providers.ProviderUpdateView.as_view(), name='provider-update'), providers.ProviderUpdateView.as_view(), name='provider-update'),
path('providers/<int:pk>/delete/', path('providers/<int:pk>/delete/',
providers.ProviderDeleteView.as_view(), name='provider-delete'), providers.ProviderDeleteView.as_view(), name='provider-delete'),
# Invites # Invitations
path('invites/', invites.InviteListView.as_view(), name='invites'), path('invitations/', invitations.InviteListView.as_view(), name='invitations'),
path('invites/create/', invites.InviteCreateView.as_view(), name='invite-create'), path('invitations/create/', invitations.InviteCreateView.as_view(), name='invitation-create'),
path('invites/<uuid:pk>/update/', invites.InviteUpdateView.as_view(), name='invite-update'), path('invitations/<uuid:pk>/update/',
path('invites/<uuid:pk>/delete/', invites.InviteDeleteView.as_view(), name='invite-delete'), invitations.InviteUpdateView.as_view(), name='invitation-update'),
path('invitations/<uuid:pk>/delete/',
invitations.InviteDeleteView.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

@ -5,39 +5,39 @@ from django.utils.translation import ugettext as _
from django.views.generic import CreateView, DeleteView, ListView, UpdateView from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from passbook.admin.mixins import AdminRequiredMixin from passbook.admin.mixins import AdminRequiredMixin
from passbook.core.forms.invites import InviteForm from passbook.core.forms.invitations import InviteForm
from passbook.core.models import Invite from passbook.core.models import Invite
class InviteListView(AdminRequiredMixin, ListView): class InviteListView(AdminRequiredMixin, ListView):
"""Show list of all invites""" """Show list of all invitations"""
model = Invite model = Invite
template_name = 'administration/invite/list.html' template_name = 'administration/invitation/list.html'
class InviteCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView): class InviteCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
"""Create new Invite""" """Create new Invite"""
template_name = 'generic/create.html' template_name = 'generic/create.html'
success_url = reverse_lazy('passbook_admin:invites') success_url = reverse_lazy('passbook_admin:invitations')
success_message = _('Successfully created Invite') success_message = _('Successfully created Invite')
form_class = InviteForm form_class = InviteForm
class InviteUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView): class InviteUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView):
"""Update invite""" """Update invitation"""
model = Invite model = Invite
template_name = 'generic/update.html' template_name = 'generic/update.html'
success_url = reverse_lazy('passbook_admin:invites') success_url = reverse_lazy('passbook_admin:invitations')
success_message = _('Successfully updated Invite') success_message = _('Successfully updated Invite')
form_class = InviteForm form_class = InviteForm
class InviteDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView): class InviteDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
"""Delete invite""" """Delete invitation"""
model = Invite model = Invite
template_name = 'generic/delete.html' template_name = 'generic/delete.html'
success_url = reverse_lazy('passbook_admin:invites') success_url = reverse_lazy('passbook_admin:invitations')
success_message = _('Successfully updated Invite') success_message = _('Successfully updated Invite')

View File

@ -22,6 +22,6 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='auditentry', model_name='auditentry',
name='action', 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'), ('invite_used', 'invite_used')]), 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_used', 'invitation_used')]),
), ),
] ]

View File

@ -24,8 +24,8 @@ class AuditEntry(UUIDModel):
ACTION_SUSPICIOUS_REQUEST = 'suspicious_request' ACTION_SUSPICIOUS_REQUEST = 'suspicious_request'
ACTION_SIGN_UP = 'sign_up' ACTION_SIGN_UP = 'sign_up'
ACTION_PASSWORD_RESET = 'password_reset' ACTION_PASSWORD_RESET = 'password_reset'
ACTION_INVITE_CREATED = 'invite_created' ACTION_INVITE_CREATED = 'invitation_created'
ACTION_INVITE_USED = 'invite_used' ACTION_INVITE_USED = 'invitation_used'
ACTIONS = ( ACTIONS = (
(ACTION_LOGIN, ACTION_LOGIN), (ACTION_LOGIN, ACTION_LOGIN),
(ACTION_LOGIN_FAILED, ACTION_LOGIN_FAILED), (ACTION_LOGIN_FAILED, ACTION_LOGIN_FAILED),

View File

@ -4,7 +4,8 @@ from django.contrib.auth.signals import (user_logged_in, user_logged_out,
from django.dispatch import receiver from django.dispatch import receiver
from passbook.audit.models import AuditEntry from passbook.audit.models import AuditEntry
from passbook.core.signals import invite_created, invite_used, user_signed_up from passbook.core.signals import (invitation_created, invitation_used,
user_signed_up)
@receiver(user_logged_in) @receiver(user_logged_in)
@ -22,15 +23,15 @@ def on_user_signed_up(sender, request, user, **kwargs):
"""Log successfully signed up""" """Log successfully signed up"""
AuditEntry.create(AuditEntry.ACTION_SIGN_UP, request) AuditEntry.create(AuditEntry.ACTION_SIGN_UP, request)
@receiver(invite_created) @receiver(invitation_created)
def on_invite_created(sender, request, invite, **kwargs): def on_invitation_created(sender, request, invitation, **kwargs):
"""Log Invite creation""" """Log Invite creation"""
AuditEntry.create(AuditEntry.ACTION_INVITE_CREATED, request, invite_uuid=invite.uuid) AuditEntry.create(AuditEntry.ACTION_INVITE_CREATED, request, invitation_uuid=invitation.uuid)
@receiver(invite_used) @receiver(invitation_used)
def on_invite_used(sender, request, invite, **kwargs): def on_invitation_used(sender, request, invitation, **kwargs):
"""Log Invite usage""" """Log Invite usage"""
AuditEntry.create(AuditEntry.ACTION_INVITE_USED, request, invite_uuid=invite.uuid) AuditEntry.create(AuditEntry.ACTION_INVITE_USED, request, invitation_uuid=invitation.uuid)
@receiver(user_login_failed) @receiver(user_login_failed)
def on_user_login_failed(sender, request, user, **kwargs): def on_user_login_failed(sender, request, user, **kwargs):

View File

@ -1,4 +1,4 @@
"""passbook core invite form""" """passbook core invitation form"""
from django import forms from django import forms

View File

@ -25,7 +25,7 @@ class Migration(migrations.Migration):
], ],
options={ options={
'verbose_name': 'Invite', 'verbose_name': 'Invite',
'verbose_name_plural': 'Invites', 'verbose_name_plural': 'Invitations',
}, },
), ),
] ]

View File

@ -251,7 +251,7 @@ class DebugRule(Rule):
verbose_name_plural = _('Debug Rules') verbose_name_plural = _('Debug Rules')
class Invite(UUIDModel): class Invite(UUIDModel):
"""Single-use invite link""" """Single-use invitation link"""
created_by = models.ForeignKey('User', on_delete=models.CASCADE) created_by = models.ForeignKey('User', on_delete=models.CASCADE)
expires = models.DateTimeField(default=None, blank=True, null=True) expires = models.DateTimeField(default=None, blank=True, null=True)
@ -264,4 +264,4 @@ class Invite(UUIDModel):
class Meta: class Meta:
verbose_name = _('Invite') verbose_name = _('Invite')
verbose_name_plural = _('Invites') verbose_name_plural = _('Invitations')

View File

@ -8,5 +8,5 @@ from django.core.signals import Signal
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
invite_created = Signal(providing_args=['request', 'invite']) invitation_created = Signal(providing_args=['request', 'invitation'])
invite_used = Signal(providing_args=['request', 'invite', 'user']) invitation_used = Signal(providing_args=['request', 'invitation', 'user'])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 6.3 MiB

View File

@ -13,7 +13,7 @@ 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 Invite, User
from passbook.core.signals import invite_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
LOGGER = getLogger(__name__) LOGGER = getLogger(__name__)
@ -113,13 +113,13 @@ class LogoutView(LoginRequiredMixin, View):
class SignUpView(UserPassesTestMixin, FormView): class SignUpView(UserPassesTestMixin, FormView):
"""Sign up new user, optionally consume one-use invite link.""" """Sign up new user, optionally consume one-use invitation link."""
template_name = 'login/form.html' template_name = 'login/form.html'
form_class = SignUpForm form_class = SignUpForm
success_url = '.' success_url = '.'
# Invite insatnce, if invite link was used # Invite insatnce, if invitation link was used
_invite = None _invitation = None
# Instance of newly created user # Instance of newly created user
_user = None _user = None
@ -131,13 +131,13 @@ class SignUpView(UserPassesTestMixin, FormView):
return redirect(reverse('passbook_core:overview')) return redirect(reverse('passbook_core:overview'))
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
"""Check if sign-up is enabled or invite link given""" """Check if sign-up is enabled or invitation link given"""
allowed = False allowed = False
if 'invite' in request.GET: if 'invitation' in request.GET:
invites = Invite.objects.filter(uuid=request.GET.get('invite')) invitations = Invite.objects.filter(uuid=request.GET.get('invitation'))
allowed = invites.exists() allowed = invitations.exists()
if allowed: if allowed:
self._invite = invites.first() self._invitation = invitations.first()
if CONFIG.y('passbook.sign_up.enabled'): if CONFIG.y('passbook.sign_up.enabled'):
allowed = True allowed = True
if not allowed: if not allowed:
@ -155,21 +155,21 @@ class SignUpView(UserPassesTestMixin, FormView):
def form_valid(self, form: SignUpForm) -> HttpResponse: def form_valid(self, form: SignUpForm) -> HttpResponse:
"""Create user""" """Create user"""
self._user = SignUpView.create_user(form.cleaned_data, self.request) self._user = SignUpView.create_user(form.cleaned_data, self.request)
self.consume_invite() self.consume_invitation()
messages.success(self.request, _("Successfully signed up!")) messages.success(self.request, _("Successfully signed up!"))
LOGGER.debug("Successfully signed up %s", LOGGER.debug("Successfully signed up %s",
form.cleaned_data.get('email')) form.cleaned_data.get('email'))
return redirect(reverse('passbook_core:auth-login')) return redirect(reverse('passbook_core:auth-login'))
def consume_invite(self): def consume_invitation(self):
"""Consume invite if an invite was used""" """Consume invitation if an invitation was used"""
if self._invite: if self._invitation:
invite_used.send( invitation_used.send(
sender=self, sender=self,
request=self.request, request=self.request,
invite=self._invite, invitation=self._invitation,
user=self._user) user=self._user)
self._invite.delete() self._invitation.delete()
@staticmethod @staticmethod
def create_user(data: Dict, request: HttpRequest = None) -> User: def create_user(data: Dict, request: HttpRequest = None) -> User:

View File

@ -90,8 +90,8 @@ def login_process(request):
# # Only check if there is a connection from OAuth2 Application to product # # Only check if there is a connection from OAuth2 Application to product
# product = remote.productextensionsaml2_set.first().product_set.first() # product = remote.productextensionsaml2_set.first().product_set.first()
# relationship = UserAcquirableRelationship.objects.filter(user=request.user, model=product) # relationship = UserAcquirableRelationship.objects.filter(user=request.user, model=product)
# # Product is invite_only = True and no relation with user exists # # Product is invitation_only = True and no relation with user exists
# if product.invite_only and not relationship.exists(): # if product.invitation_only and not relationship.exists():
# access = False # access = False
# Check if we should just autosubmit # Check if we should just autosubmit
if remote.skip_authorization and access: if remote.skip_authorization and access: