all: invites -> invitations
This commit is contained in:
parent
89c2b8d49c
commit
545795ebc6
|
@ -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' %}">
|
||||
<a href="{% url 'passbook_admin:rules' %}">{% trans 'Rules' %}</a>
|
||||
</li>
|
||||
<li class="{% is_active 'passbook_admin:invites' 'passbook_admin:invite-create' 'passbook_admin:invite-update' 'passbook_admin:invite-delete' 'passbook_admin:invite-test' %}">
|
||||
<a href="{% url 'passbook_admin:invites' %}">{% trans 'Invites' %}</a>
|
||||
<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:invitations' %}">{% trans 'Invitations' %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">{% trans 'Users' %}</a>
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>{% trans "Invites" %}</h1>
|
||||
<a href="{% url 'passbook_admin:invite-create' %}" class="btn btn-primary">
|
||||
<h1>{% trans "Invitations" %}</h1>
|
||||
<a href="{% url 'passbook_admin:invitation-create' %}" class="btn btn-primary">
|
||||
{% trans 'Create...' %}
|
||||
</a>
|
||||
<hr>
|
||||
|
@ -23,13 +23,13 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for invite in object_list %}
|
||||
{% for invitation in object_list %}
|
||||
<tr>
|
||||
<td>{{ invite.name }}</td>
|
||||
<td>{{ invite.provider }}</td>
|
||||
<td>{{ invitation.name }}</td>
|
||||
<td>{{ invitation.provider }}</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: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-update' pk=invitation.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</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>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
"""passbook URL Configuration"""
|
||||
from django.urls import path
|
||||
|
||||
from passbook.admin.views import (applications, invites, overview, providers,
|
||||
rules, sources)
|
||||
from passbook.admin.views import (applications, invitations, overview,
|
||||
providers, rules, sources)
|
||||
|
||||
urlpatterns = [
|
||||
path('', overview.AdministrationOverviewView.as_view(), name='overview'),
|
||||
|
@ -34,10 +34,12 @@ urlpatterns = [
|
|||
providers.ProviderUpdateView.as_view(), name='provider-update'),
|
||||
path('providers/<int:pk>/delete/',
|
||||
providers.ProviderDeleteView.as_view(), name='provider-delete'),
|
||||
# Invites
|
||||
path('invites/', invites.InviteListView.as_view(), name='invites'),
|
||||
path('invites/create/', invites.InviteCreateView.as_view(), name='invite-create'),
|
||||
path('invites/<uuid:pk>/update/', invites.InviteUpdateView.as_view(), name='invite-update'),
|
||||
path('invites/<uuid:pk>/delete/', invites.InviteDeleteView.as_view(), name='invite-delete'),
|
||||
# Invitations
|
||||
path('invitations/', invitations.InviteListView.as_view(), name='invitations'),
|
||||
path('invitations/create/', invitations.InviteCreateView.as_view(), name='invitation-create'),
|
||||
path('invitations/<uuid:pk>/update/',
|
||||
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'))
|
||||
]
|
||||
|
|
|
@ -5,39 +5,39 @@ from django.utils.translation import ugettext as _
|
|||
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
|
||||
|
||||
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
|
||||
|
||||
|
||||
class InviteListView(AdminRequiredMixin, ListView):
|
||||
"""Show list of all invites"""
|
||||
"""Show list of all invitations"""
|
||||
|
||||
model = Invite
|
||||
template_name = 'administration/invite/list.html'
|
||||
template_name = 'administration/invitation/list.html'
|
||||
|
||||
|
||||
class InviteCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
|
||||
"""Create new Invite"""
|
||||
|
||||
template_name = 'generic/create.html'
|
||||
success_url = reverse_lazy('passbook_admin:invites')
|
||||
success_url = reverse_lazy('passbook_admin:invitations')
|
||||
success_message = _('Successfully created Invite')
|
||||
form_class = InviteForm
|
||||
|
||||
|
||||
class InviteUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView):
|
||||
"""Update invite"""
|
||||
"""Update invitation"""
|
||||
|
||||
model = Invite
|
||||
template_name = 'generic/update.html'
|
||||
success_url = reverse_lazy('passbook_admin:invites')
|
||||
success_url = reverse_lazy('passbook_admin:invitations')
|
||||
success_message = _('Successfully updated Invite')
|
||||
form_class = InviteForm
|
||||
|
||||
class InviteDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
|
||||
"""Delete invite"""
|
||||
"""Delete invitation"""
|
||||
|
||||
model = Invite
|
||||
template_name = 'generic/delete.html'
|
||||
success_url = reverse_lazy('passbook_admin:invites')
|
||||
success_url = reverse_lazy('passbook_admin:invitations')
|
||||
success_message = _('Successfully updated Invite')
|
|
@ -22,6 +22,6 @@ class Migration(migrations.Migration):
|
|||
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'), ('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')]),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -24,8 +24,8 @@ class AuditEntry(UUIDModel):
|
|||
ACTION_SUSPICIOUS_REQUEST = 'suspicious_request'
|
||||
ACTION_SIGN_UP = 'sign_up'
|
||||
ACTION_PASSWORD_RESET = 'password_reset'
|
||||
ACTION_INVITE_CREATED = 'invite_created'
|
||||
ACTION_INVITE_USED = 'invite_used'
|
||||
ACTION_INVITE_CREATED = 'invitation_created'
|
||||
ACTION_INVITE_USED = 'invitation_used'
|
||||
ACTIONS = (
|
||||
(ACTION_LOGIN, ACTION_LOGIN),
|
||||
(ACTION_LOGIN_FAILED, ACTION_LOGIN_FAILED),
|
||||
|
|
|
@ -4,7 +4,8 @@ from django.contrib.auth.signals import (user_logged_in, user_logged_out,
|
|||
from django.dispatch import receiver
|
||||
|
||||
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)
|
||||
|
@ -22,15 +23,15 @@ def on_user_signed_up(sender, request, user, **kwargs):
|
|||
"""Log successfully signed up"""
|
||||
AuditEntry.create(AuditEntry.ACTION_SIGN_UP, request)
|
||||
|
||||
@receiver(invite_created)
|
||||
def on_invite_created(sender, request, invite, **kwargs):
|
||||
@receiver(invitation_created)
|
||||
def on_invitation_created(sender, request, invitation, **kwargs):
|
||||
"""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)
|
||||
def on_invite_used(sender, request, invite, **kwargs):
|
||||
@receiver(invitation_used)
|
||||
def on_invitation_used(sender, request, invitation, **kwargs):
|
||||
"""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)
|
||||
def on_user_login_failed(sender, request, user, **kwargs):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""passbook core invite form"""
|
||||
"""passbook core invitation form"""
|
||||
|
||||
from django import forms
|
||||
|
|
@ -25,7 +25,7 @@ class Migration(migrations.Migration):
|
|||
],
|
||||
options={
|
||||
'verbose_name': 'Invite',
|
||||
'verbose_name_plural': 'Invites',
|
||||
'verbose_name_plural': 'Invitations',
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -251,7 +251,7 @@ class DebugRule(Rule):
|
|||
verbose_name_plural = _('Debug Rules')
|
||||
|
||||
class Invite(UUIDModel):
|
||||
"""Single-use invite link"""
|
||||
"""Single-use invitation link"""
|
||||
|
||||
created_by = models.ForeignKey('User', on_delete=models.CASCADE)
|
||||
expires = models.DateTimeField(default=None, blank=True, null=True)
|
||||
|
@ -264,4 +264,4 @@ class Invite(UUIDModel):
|
|||
class Meta:
|
||||
|
||||
verbose_name = _('Invite')
|
||||
verbose_name_plural = _('Invites')
|
||||
verbose_name_plural = _('Invitations')
|
||||
|
|
|
@ -8,5 +8,5 @@ from django.core.signals import Signal
|
|||
|
||||
user_signed_up = Signal(providing_args=['request', 'user'])
|
||||
# TODO: Send this signal in admin interface
|
||||
invite_created = Signal(providing_args=['request', 'invite'])
|
||||
invite_used = Signal(providing_args=['request', 'invite', 'user'])
|
||||
invitation_created = Signal(providing_args=['request', 'invitation'])
|
||||
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 |
|
@ -13,7 +13,7 @@ from django.views.generic import FormView
|
|||
|
||||
from passbook.core.forms.authentication import LoginForm, SignUpForm
|
||||
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
|
||||
|
||||
LOGGER = getLogger(__name__)
|
||||
|
@ -113,13 +113,13 @@ class LogoutView(LoginRequiredMixin, View):
|
|||
|
||||
|
||||
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'
|
||||
form_class = SignUpForm
|
||||
success_url = '.'
|
||||
# Invite insatnce, if invite link was used
|
||||
_invite = None
|
||||
# Invite insatnce, if invitation link was used
|
||||
_invitation = None
|
||||
# Instance of newly created user
|
||||
_user = None
|
||||
|
||||
|
@ -131,13 +131,13 @@ class SignUpView(UserPassesTestMixin, FormView):
|
|||
return redirect(reverse('passbook_core:overview'))
|
||||
|
||||
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
|
||||
if 'invite' in request.GET:
|
||||
invites = Invite.objects.filter(uuid=request.GET.get('invite'))
|
||||
allowed = invites.exists()
|
||||
if 'invitation' in request.GET:
|
||||
invitations = Invite.objects.filter(uuid=request.GET.get('invitation'))
|
||||
allowed = invitations.exists()
|
||||
if allowed:
|
||||
self._invite = invites.first()
|
||||
self._invitation = invitations.first()
|
||||
if CONFIG.y('passbook.sign_up.enabled'):
|
||||
allowed = True
|
||||
if not allowed:
|
||||
|
@ -155,21 +155,21 @@ class SignUpView(UserPassesTestMixin, FormView):
|
|||
def form_valid(self, form: SignUpForm) -> HttpResponse:
|
||||
"""Create user"""
|
||||
self._user = SignUpView.create_user(form.cleaned_data, self.request)
|
||||
self.consume_invite()
|
||||
self.consume_invitation()
|
||||
messages.success(self.request, _("Successfully signed up!"))
|
||||
LOGGER.debug("Successfully signed up %s",
|
||||
form.cleaned_data.get('email'))
|
||||
return redirect(reverse('passbook_core:auth-login'))
|
||||
|
||||
def consume_invite(self):
|
||||
"""Consume invite if an invite was used"""
|
||||
if self._invite:
|
||||
invite_used.send(
|
||||
def consume_invitation(self):
|
||||
"""Consume invitation if an invitation was used"""
|
||||
if self._invitation:
|
||||
invitation_used.send(
|
||||
sender=self,
|
||||
request=self.request,
|
||||
invite=self._invite,
|
||||
invitation=self._invitation,
|
||||
user=self._user)
|
||||
self._invite.delete()
|
||||
self._invitation.delete()
|
||||
|
||||
@staticmethod
|
||||
def create_user(data: Dict, request: HttpRequest = None) -> User:
|
||||
|
|
|
@ -90,8 +90,8 @@ def login_process(request):
|
|||
# # Only check if there is a connection from OAuth2 Application to product
|
||||
# product = remote.productextensionsaml2_set.first().product_set.first()
|
||||
# relationship = UserAcquirableRelationship.objects.filter(user=request.user, model=product)
|
||||
# # Product is invite_only = True and no relation with user exists
|
||||
# if product.invite_only and not relationship.exists():
|
||||
# # Product is invitation_only = True and no relation with user exists
|
||||
# if product.invitation_only and not relationship.exists():
|
||||
# access = False
|
||||
# Check if we should just autosubmit
|
||||
if remote.skip_authorization and access:
|
||||
|
|
Reference in a new issue