added link based signup
This commit is contained in:
parent
392ee73719
commit
7f68bbd25d
@ -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')
|
||||||
|
|
||||||
|
@ -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'}))
|
||||||
|
@ -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)
|
||||||
|
@ -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):
|
||||||
|
@ -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 %}
|
||||||
|
18
cookbook/templates/registration/signup.html
Normal file
18
cookbook/templates/registration/signup.html
Normal 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 %}
|
@ -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'),
|
||||||
|
@ -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
|
||||||
|
@ -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'})
|
||||||
|
@ -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', {})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user