added link based signup

This commit is contained in:
vabene1111 2020-09-01 21:35:37 +02:00
parent 392ee73719
commit 7f68bbd25d
10 changed files with 102 additions and 7 deletions

View File

@ -125,6 +125,13 @@ class ViewLogAdmin(admin.ModelAdmin):
admin.site.register(ViewLog, ViewLogAdmin) admin.site.register(ViewLog, ViewLogAdmin)
class InviteLinkAdmin(admin.ModelAdmin):
list_display = ('username', 'group', 'valid_until', 'created_by', 'created_at', 'used_by')
admin.site.register(InviteLink, InviteLinkAdmin)
class CookLogAdmin(admin.ModelAdmin): class CookLogAdmin(admin.ModelAdmin):
list_display = ('recipe', 'created_by', 'created_at', 'rating', 'servings') list_display = ('recipe', 'created_by', 'created_at', 'rating', 'servings')

View File

@ -280,7 +280,7 @@ class InviteLinkForm(forms.ModelForm):
} }
class SuperUserForm(forms.Form): class UserCreateForm(forms.Form):
name = forms.CharField() name = forms.CharField()
password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'})) password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}))
password_confirm = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'})) password_confirm = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}))

View File

@ -307,6 +307,9 @@ class InviteLink(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.uuid}'
class CookLog(models.Model): class CookLog(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)

View File

@ -118,10 +118,13 @@ class ShoppingListTable(tables.Table):
class InviteLinkTable(tables.Table): class InviteLinkTable(tables.Table):
link = tables.TemplateColumn("<a href='{% url 'view_signup' record.uuid %}' >" + _('Link') + "</a>")
delete = tables.TemplateColumn("<a href='{% url 'delete_invite_link' record.id %}' >" + _('Delete') + "</a>")
class Meta: class Meta:
model = InviteLink model = InviteLink
template_name = 'generic/table_template.html' template_name = 'generic/table_template.html'
fields = ('id', 'username', 'group', 'valid_until', 'created_by', 'created_at', 'used_by') fields = ('username', 'group', 'valid_until', 'created_by', 'created_at')
class ViewLogTable(tables.Table): class ViewLogTable(tables.Table):

View File

@ -1,6 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n %}
{% block title %}{% trans 'Login' %}{% endblock %}
{% block content %} {% block content %}
{% if form.errors %} {% if form.errors %}

View File

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% load crispy_forms_filters %}
{% load i18n %}
{% block title %}{% trans 'Register' %}{% endblock %}
{% block content %}
<h3>{% trans 'Create your Account' %}</h3>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-success" type="submit"><i class="fas fa-save"></i> {% trans 'Create User' %}
</button>
</form>
{% endblock %}

View File

@ -29,6 +29,7 @@ router.register(r'view-log', api.ViewLogViewSet)
urlpatterns = [ urlpatterns = [
path('', views.index, name='index'), path('', views.index, name='index'),
path('setup/', views.setup, name='view_setup'), path('setup/', views.setup, name='view_setup'),
path('signup/<slug:token>', views.signup, name='view_signup'),
path('system/', views.system, name='view_system'), path('system/', views.system, name='view_system'),
path('search/', views.search, name='view_search'), path('search/', views.search, name='view_search'),
path('books/', views.books, name='view_books'), path('books/', views.books, name='view_books'),

View File

@ -9,7 +9,7 @@ from django.views.generic import DeleteView
from cookbook.helper.permission_helper import group_required, GroupRequiredMixin, OwnerRequiredMixin from cookbook.helper.permission_helper import group_required, GroupRequiredMixin, OwnerRequiredMixin
from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeBook, \ from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeBook, \
RecipeBookEntry, MealPlan, Food RecipeBookEntry, MealPlan, Food, InviteLink
from cookbook.provider.dropbox import Dropbox from cookbook.provider.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud from cookbook.provider.nextcloud import Nextcloud
@ -148,3 +148,14 @@ class MealPlanDelete(OwnerRequiredMixin, DeleteView):
context = super(MealPlanDelete, self).get_context_data(**kwargs) context = super(MealPlanDelete, self).get_context_data(**kwargs)
context['title'] = _("Meal-Plan") context['title'] = _("Meal-Plan")
return context return context
class InviteLinkDelete(OwnerRequiredMixin, DeleteView):
template_name = "generic/delete_template.html"
model = InviteLink
success_url = reverse_lazy('list_invite_link')
def get_context_data(self, **kwargs):
context = super(InviteLinkDelete, self).get_context_data(**kwargs)
context['title'] = _("Invite Link")
return context

View File

@ -1,3 +1,5 @@
from datetime import datetime
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db.models.functions import Lower from django.db.models.functions import Lower
from django.shortcuts import render from django.shortcuts import render
@ -63,7 +65,7 @@ def storage(request):
@group_required('admin') @group_required('admin')
def invite_link(request): def invite_link(request):
table = InviteLinkTable(InviteLink.objects.all()) table = InviteLinkTable(InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None).all())
RequestConfig(request, paginate={'per_page': 25}).configure(table) RequestConfig(request, paginate={'per_page': 25}).configure(table)
return render(request, 'generic/list_template.html', {'title': _("Invite Links"), 'table': table, 'create_url': 'new_invite_link'}) return render(request, 'generic/list_template.html', {'title': _("Invite Links"), 'table': table, 'create_url': 'new_invite_link'})

View File

@ -1,7 +1,7 @@
import copy import copy
import os import os
from datetime import datetime, timedelta from datetime import datetime, timedelta
from uuid import UUID
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import update_session_auth_hash, authenticate from django.contrib.auth import update_session_auth_hash, authenticate
from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.forms import PasswordChangeForm
@ -240,7 +240,7 @@ def setup(request):
return HttpResponseRedirect(reverse('login')) return HttpResponseRedirect(reverse('login'))
if request.method == 'POST': if request.method == 'POST':
form = SuperUserForm(request.POST) form = UserCreateForm(request.POST)
if form.is_valid(): if form.is_valid():
if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: if form.cleaned_data['password'] != form.cleaned_data['password_confirm']:
form.add_error('password', _('Passwords dont match!')) form.add_error('password', _('Passwords dont match!'))
@ -260,11 +260,59 @@ def setup(request):
for m in e: for m in e:
form.add_error('password', m) form.add_error('password', m)
else: else:
form = SuperUserForm() form = UserCreateForm()
return render(request, 'setup.html', {'form': form}) return render(request, 'setup.html', {'form': form})
def signup(request, token):
try:
token = UUID(token, version=4)
except ValueError:
messages.add_message(request, messages.ERROR, _('Malformed Invite Link supplied!'))
return HttpResponseRedirect(reverse('index'))
if link := InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, uuid=token).first():
if request.method == 'POST':
form = UserCreateForm(request.POST)
if link.username != '':
data = dict(form.data)
data['name'] = link.username
form.data = data
if form.is_valid():
if form.cleaned_data['password'] != form.cleaned_data['password_confirm']:
form.add_error('password', _('Passwords dont match!'))
else:
user = User(
username=form.cleaned_data['name'],
)
try:
validate_password(form.cleaned_data['password'], user=user)
user.set_password(form.cleaned_data['password'])
user.save()
messages.add_message(request, messages.SUCCESS, _('User has been created, please login!'))
link.used_by = user
link.save()
user.groups.add(link.group)
return HttpResponseRedirect(reverse('login'))
except ValidationError as e:
for m in e:
form.add_error('password', m)
else:
form = UserCreateForm()
if link.username != '':
form.fields['name'].initial = link.username
form.fields['name'].disabled = True
return render(request, 'registration/signup.html', {'form': form, 'link': link})
messages.add_message(request, messages.ERROR, _('Invite Link not valid or already used!'))
return HttpResponseRedirect(reverse('index'))
def markdown_info(request): def markdown_info(request):
return render(request, 'markdown_info.html', {}) return render(request, 'markdown_info.html', {})