From 846c660811a06088bb2e260ad93b8a41044bff72 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sun, 21 Feb 2021 15:08:43 +0100 Subject: [PATCH] usr signup and more --- cookbook/admin.py | 18 ++- cookbook/forms.py | 12 +- cookbook/helper/permission_helper.py | 20 ++- cookbook/helper/scope_middleware.py | 17 ++- cookbook/integration/integration.py | 3 +- .../migrations/0109_auto_20210221_1204.py | 63 +++++++++ .../migrations/0110_auto_20210221_1406.py | 19 +++ cookbook/migrations/0111_space_created_by.py | 32 +++++ cookbook/models.py | 31 ++++- cookbook/serializer.py | 23 +--- cookbook/templates/no_groups_info.html | 2 +- cookbook/templates/no_space_info.html | 20 +++ cookbook/urls.py | 2 +- cookbook/views/new.py | 5 + cookbook/views/views.py | 126 ++++++++---------- 15 files changed, 287 insertions(+), 106 deletions(-) create mode 100644 cookbook/migrations/0109_auto_20210221_1204.py create mode 100644 cookbook/migrations/0110_auto_20210221_1406.py create mode 100644 cookbook/migrations/0111_space_created_by.py create mode 100644 cookbook/templates/no_space_info.html diff --git a/cookbook/admin.py b/cookbook/admin.py index 76af757a6..8893a7a09 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -1,4 +1,6 @@ from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from django.contrib.auth.models import User, Group from .models import (Comment, CookLog, Food, Ingredient, InviteLink, Keyword, MealPlan, MealType, NutritionInformation, Recipe, @@ -8,6 +10,17 @@ from .models import (Comment, CookLog, Food, Ingredient, InviteLink, Keyword, ViewLog, Supermarket, SupermarketCategory, SupermarketCategoryRelation) +class CustomUserAdmin(UserAdmin): + def has_add_permission(self, request, obj=None): + return False + + +admin.site.unregister(User) +admin.site.register(User, CustomUserAdmin) + +admin.site.unregister(Group) + + class SpaceAdmin(admin.ModelAdmin): list_display = ('name', 'message') @@ -16,10 +29,7 @@ admin.site.register(Space, SpaceAdmin) class UserPreferenceAdmin(admin.ModelAdmin): - list_display = ( - 'name', 'theme', 'nav_color', - 'default_page', 'search_style', 'comments' - ) + list_display = ('name', 'space', 'theme', 'nav_color', 'default_page', 'search_style',) @staticmethod def name(obj): diff --git a/cookbook/forms.py b/cookbook/forms.py index 1e68f42c6..73a80417a 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -6,7 +6,7 @@ from emoji_picker.widgets import EmojiPickerTextInput from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe, RecipeBook, RecipeBookEntry, Storage, Sync, Unit, User, - UserPreference, SupermarketCategory, MealType) + UserPreference, SupermarketCategory, MealType, Space) class SelectWidget(widgets.Select): @@ -371,12 +371,20 @@ class MealPlanForm(forms.ModelForm): class InviteLinkForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + user = kwargs.pop('user') + super().__init__(*args, **kwargs) + self.fields['space'].queryset = Space.objects.filter(created_by=user).all() + class Meta: model = InviteLink - fields = ('username', 'group', 'valid_until') + fields = ('username', 'group', 'valid_until', 'space') help_texts = { 'username': _('A username is not required, if left blank the new user can choose one.') # noqa: E501 } + field_classes = { + 'space': SafeModelChoiceField, + } class UserCreateForm(forms.Form): diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index fa9e12009..ebd7d0828 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -123,9 +123,13 @@ class GroupRequiredMixin(object): messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse_lazy('index')) - if self.get_object().get_space() != request.space: - messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) - return HttpResponseRedirect(reverse_lazy('index')) + try: + obj = self.get_object() + if obj.get_space() != request.space: + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse_lazy('index')) + except AttributeError: + pass return super(GroupRequiredMixin, self).dispatch(request, *args, **kwargs) @@ -141,9 +145,13 @@ class OwnerRequiredMixin(object): messages.add_message(request, messages.ERROR, _('You cannot interact with this object as it is not owned by you!')) return HttpResponseRedirect(reverse('index')) - if self.get_object().get_space() != request.space: - messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) - return HttpResponseRedirect(reverse_lazy('index')) + try: + obj = self.get_object() + if obj.get_space() != request.space: + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse_lazy('index')) + except AttributeError: + pass return super(OwnerRequiredMixin, self).dispatch(request, *args, **kwargs) diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index 2ec472f49..9726d5263 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -1,3 +1,5 @@ +from django.shortcuts import redirect +from django.urls import reverse from django_scopes import scope, scopes_disabled @@ -7,10 +9,21 @@ class ScopeMiddleware: def __call__(self, request): if request.user.is_authenticated: - request.space = request.user.userpreference.space + + if request.user.groups.count() == 0: + return redirect('view_no_group') with scopes_disabled(): - #with scope(space=request.space): + if request.user.userpreference.space is None and not reverse('view_no_space') in request.path and not reverse('account_logout') in request.path: + return redirect(reverse('view_no_space')) + + if request.path.startswith('/admin/'): + with scopes_disabled(): + return self.get_response(request) + + request.space = request.user.userpreference.space + # with scopes_disabled(): + with scope(space=request.space): return self.get_response(request) else: return self.get_response(request) diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index 49329e41f..49200d546 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -27,7 +27,8 @@ class Integration: self.keyword = Keyword.objects.create( name=f'Import {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}.{datetime.datetime.now().strftime("%S")}', description=f'Imported by {request.user.get_user_name()} at {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}', - icon='📥' + icon='📥', + space=request.space ) def do_export(self, recipes): diff --git a/cookbook/migrations/0109_auto_20210221_1204.py b/cookbook/migrations/0109_auto_20210221_1204.py new file mode 100644 index 000000000..37308fa76 --- /dev/null +++ b/cookbook/migrations/0109_auto_20210221_1204.py @@ -0,0 +1,63 @@ +# Generated by Django 3.1.6 on 2021-02-21 11:04 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0108_auto_20210219_1410'), + ] + + operations = [ + migrations.RemoveField( + model_name='recipebookentry', + name='space', + ), + migrations.AlterField( + model_name='food', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterField( + model_name='keyword', + name='name', + field=models.CharField(max_length=64), + ), + migrations.AlterField( + model_name='supermarket', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterField( + model_name='supermarketcategory', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterField( + model_name='unit', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterUniqueTogether( + name='food', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='keyword', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='supermarket', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='supermarketcategory', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='unit', + unique_together={('space', 'name')}, + ), + ] diff --git a/cookbook/migrations/0110_auto_20210221_1406.py b/cookbook/migrations/0110_auto_20210221_1406.py new file mode 100644 index 000000000..47e002ff8 --- /dev/null +++ b/cookbook/migrations/0110_auto_20210221_1406.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.6 on 2021-02-21 13:06 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0109_auto_20210221_1204'), + ] + + operations = [ + migrations.AlterField( + model_name='userpreference', + name='space', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + ] diff --git a/cookbook/migrations/0111_space_created_by.py b/cookbook/migrations/0111_space_created_by.py new file mode 100644 index 000000000..7f42a74e5 --- /dev/null +++ b/cookbook/migrations/0111_space_created_by.py @@ -0,0 +1,32 @@ +# Generated by Django 3.1.6 on 2021-02-21 13:19 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +from django_scopes import scopes_disabled + + +def set_default_owner(apps, schema_editor): + Space = apps.get_model('cookbook', 'Space') + User = apps.get_model('auth', 'user') + + with scopes_disabled(): + for x in Space.objects.all(): + x.created_by = User.objects.filter(is_superuser=True).first() + x.save() + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('cookbook', '0110_auto_20210221_1406'), + ] + + operations = [ + migrations.AddField( + model_name='space', + name='created_by', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL), + ), + migrations.RunPython(set_default_owner), + ] diff --git a/cookbook/models.py b/cookbook/models.py index dd3b10985..e89e7745a 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -45,8 +45,12 @@ class PermissionModelMixin: class Space(models.Model): name = models.CharField(max_length=128, default='Default') + created_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True) message = models.CharField(max_length=512, default='', blank=True) + def __str__(self): + return self.name + class UserPreference(models.Model, PermissionModelMixin): # Themes @@ -121,7 +125,7 @@ class UserPreference(models.Model, PermissionModelMixin): shopping_auto_sync = models.IntegerField(default=5) sticky_navbar = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT) - space = models.ForeignKey(Space, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE, null=True) objects = ScopedManager(space='space') def __str__(self): @@ -168,7 +172,7 @@ class Sync(models.Model, PermissionModelMixin): class SupermarketCategory(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) space = models.ForeignKey(Space, on_delete=models.CASCADE) @@ -177,9 +181,12 @@ class SupermarketCategory(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class Supermarket(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) categories = models.ManyToManyField(SupermarketCategory, through='SupermarketCategoryRelation') @@ -189,6 +196,9 @@ class Supermarket(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class SupermarketCategoryRelation(models.Model, PermissionModelMixin): supermarket = models.ForeignKey(Supermarket, on_delete=models.CASCADE, related_name='category_to_supermarket') @@ -218,7 +228,7 @@ class SyncLog(models.Model, PermissionModelMixin): class Keyword(models.Model, PermissionModelMixin): - name = models.CharField(max_length=64, unique=True) + name = models.CharField(max_length=64) icon = models.CharField(max_length=16, blank=True, null=True) description = models.TextField(default="", blank=True) created_at = models.DateTimeField(auto_now_add=True) @@ -233,9 +243,12 @@ class Keyword(models.Model, PermissionModelMixin): else: return f"{self.name}" + class Meta: + unique_together = (('space', 'name'),) + class Unit(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) space = models.ForeignKey(Space, on_delete=models.CASCADE) @@ -244,9 +257,12 @@ class Unit(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class Food(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL) supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL) ignore_shopping = models.BooleanField(default=False) @@ -258,6 +274,9 @@ class Food(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class Ingredient(models.Model, PermissionModelMixin): food = models.ForeignKey(Food, on_delete=models.PROTECT, null=True, blank=True) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index f52c2c926..436f849df 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -111,17 +111,12 @@ class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer): return str(obj) def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = Keyword.objects.get_or_create(name=validated_data['name']) + obj, created = Keyword.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj class Meta: model = Keyword - fields = ( - 'id', 'name', 'icon', 'label', 'description', - 'created_at', 'updated_at' - ) + fields = ('id', 'name', 'icon', 'label', 'description', 'created_at', 'updated_at') read_only_fields = ('id',) @@ -129,9 +124,7 @@ class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer): class UnitSerializer(UniqueFieldsMixin, serializers.ModelSerializer): def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = Unit.objects.get_or_create(name=validated_data['name']) + obj, created = Unit.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj class Meta: @@ -143,9 +136,7 @@ class UnitSerializer(UniqueFieldsMixin, serializers.ModelSerializer): class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerializer): def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = SupermarketCategory.objects.get_or_create(name=validated_data['name']) + obj, created = SupermarketCategory.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj def update(self, instance, validated_data): @@ -176,9 +167,7 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer): supermarket_category = SupermarketCategorySerializer(allow_null=True, required=False) def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = Food.objects.get_or_create(name=validated_data['name']) + obj, created = Food.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj def update(self, instance, validated_data): @@ -256,6 +245,7 @@ class RecipeSerializer(WritableNestedModelSerializer): def create(self, validated_data): validated_data['created_by'] = self.context['request'].user + validated_data['space'] = self.context['request'].space return super().create(validated_data) @@ -455,4 +445,5 @@ class RecipeExportSerializer(WritableNestedModelSerializer): def create(self, validated_data): validated_data['created_by'] = self.context['request'].user + validated_data['space'] = self.context['request'].space return super().create(validated_data) diff --git a/cookbook/templates/no_groups_info.html b/cookbook/templates/no_groups_info.html index 53b5f04c2..eac51be12 100644 --- a/cookbook/templates/no_groups_info.html +++ b/cookbook/templates/no_groups_info.html @@ -2,7 +2,7 @@ {% load static %} {% load i18n %} -{% block title %}{% trans "Offline" %}{% endblock %} +{% block title %}{% trans "No Permissions" %}{% endblock %} {% block content %} diff --git a/cookbook/templates/no_space_info.html b/cookbook/templates/no_space_info.html new file mode 100644 index 000000000..f8ad26e84 --- /dev/null +++ b/cookbook/templates/no_space_info.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load static %} +{% load i18n %} + +{% block title %}{% trans "No Space" %}{% endblock %} + + +{% block content %} + +
+ +

{% trans 'No Space' %}

+
+ + {% trans 'You are not a member of any space. Please contact your administrator.' %}
+ +
+ +{% endblock %} + diff --git a/cookbook/urls.py b/cookbook/urls.py index 08b3a834f..c446a1b6a 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -40,6 +40,7 @@ urlpatterns = [ path('', views.index, name='index'), path('setup/', views.setup, name='view_setup'), path('no-group', views.no_groups, name='view_no_group'), + path('no-space', views.no_space, name='view_no_space'), path('signup/', views.signup, name='view_signup'), path('system/', views.system, name='view_system'), path('search/', views.search, name='view_search'), @@ -105,7 +106,6 @@ urlpatterns = [ path('offline/', views.offline, name='view_offline'), - path('service-worker.js', (TemplateView.as_view(template_name="sw.js", content_type='application/javascript', )), name='service_worker'), path('manifest.json', (TemplateView.as_view(template_name="manifest.json", content_type='application/json', )), name='web_manifest'), ] diff --git a/cookbook/views/new.py b/cookbook/views/new.py index 16acb9921..927c873c4 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -212,3 +212,8 @@ class InviteLinkCreate(GroupRequiredMixin, CreateView): context = super(InviteLinkCreate, self).get_context_data(**kwargs) context['title'] = _("Invite Link") return context + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs.update({'user': self.request.user}) + return kwargs diff --git a/cookbook/views/views.py b/cookbook/views/views.py index d08e9a19c..f781a7662 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -26,7 +26,7 @@ from cookbook.forms import (CommentForm, Recipe, RecipeBookEntryForm, User, UserPreferenceForm) from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission from cookbook.models import (Comment, CookLog, InviteLink, MealPlan, - RecipeBook, RecipeBookEntry, ViewLog, ShoppingList) + RecipeBook, RecipeBookEntry, ViewLog, ShoppingList, Space) from cookbook.tables import (CookLogTable, RecipeTable, RecipeTableSmall, ViewLogTable) from recipes.settings import DEMO @@ -92,6 +92,10 @@ def no_groups(request): return render(request, 'no_groups_info.html') +def no_space(request): + return render(request, 'no_space_info.html') + + def recipe_view(request, pk, share=None): with scopes_disabled(): recipe = get_object_or_404(Recipe, pk=pk) @@ -331,11 +335,8 @@ def system(request): def setup(request): - if (User.objects.count() > 0 - or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS): # noqa: E501 - messages.add_message(request, messages.ERROR, - _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.') # noqa: E501 - ) + if User.objects.count() > 0 or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS: + messages.add_message(request, messages.ERROR, _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.')) return HttpResponseRedirect(reverse('account_login')) if request.method == 'POST': @@ -344,20 +345,19 @@ def setup(request): if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: # noqa: E501 form.add_error('password', _('Passwords dont match!')) else: - user = User( - username=form.cleaned_data['name'], - is_superuser=True, - is_staff=True - ) + user = User(username=form.cleaned_data['name'], is_superuser=True, is_staff=True) 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!') - ) + user.userpreference.space = Space.objects.first() + user.userpreference.save() + + with scopes_disabled(): + for x in Space.objects.all(): + x.created_by = user + x.save() + messages.add_message(request, messages.SUCCESS, _('User has been created, please login!')) return HttpResponseRedirect(reverse('account_login')) except ValidationError as e: for m in e: @@ -369,60 +369,52 @@ def setup(request): 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')) + with scopes_disabled(): + 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': + updated_request = request.POST.copy() + if link.username != '': + updated_request.update({'name': link.username}) + + form = UserCreateForm(updated_request) + + if form.is_valid(): + if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: # noqa: E501 + 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) + + user.userpreference.space = link.space + user.userpreference.save() + return HttpResponseRedirect(reverse('account_login')) + except ValidationError as e: + for m in e: + form.add_error('password', m) + else: + form = UserCreateForm() - if link := InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, uuid=token).first(): - if request.method == 'POST': - updated_request = request.POST.copy() if link.username != '': - updated_request.update({'name': link.username}) + form.fields['name'].initial = link.username + form.fields['name'].disabled = True + return render(request, 'account/signup.html', {'form': form, 'link': link}) - form = UserCreateForm(updated_request) - - if form.is_valid(): - if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: # noqa: E501 - 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('account_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, 'account/signup.html', {'form': form, 'link': link} - ) - - messages.add_message( - request, messages.ERROR, _('Invite Link not valid or already used!') - ) - return HttpResponseRedirect(reverse('index')) + messages.add_message(request, messages.ERROR, _('Invite Link not valid or already used!')) + return HttpResponseRedirect(reverse('index')) def markdown_info(request):