add SignUp Confirmation (required by default, can be disabled in invitations) closes #6
This commit is contained in:
		| @ -27,7 +27,7 @@ class InvitationForm(forms.ModelForm): | |||||||
|     class Meta: |     class Meta: | ||||||
|  |  | ||||||
|         model = Invitation |         model = Invitation | ||||||
|         fields = ['expires', 'fixed_username', 'fixed_email'] |         fields = ['expires', 'fixed_username', 'fixed_email', 'needs_confirmation'] | ||||||
|         labels = { |         labels = { | ||||||
|             'fixed_username': "Force user's username (optional)", |             'fixed_username': "Force user's username (optional)", | ||||||
|             'fixed_email': "Force user's email (optional)", |             'fixed_email': "Force user's email (optional)", | ||||||
|  | |||||||
| @ -0,0 +1,18 @@ | |||||||
|  | # Generated by Django 2.1.7 on 2019-02-25 19:57 | ||||||
|  |  | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('passbook_core', '0012_nonce'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='invitation', | ||||||
|  |             name='needs_confirmation', | ||||||
|  |             field=models.BooleanField(default=True), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @ -392,6 +392,7 @@ class Invitation(UUIDModel): | |||||||
|     expires = models.DateTimeField(default=None, blank=True, null=True) |     expires = models.DateTimeField(default=None, blank=True, null=True) | ||||||
|     fixed_username = models.TextField(blank=True, default=None) |     fixed_username = models.TextField(blank=True, default=None) | ||||||
|     fixed_email = models.TextField(blank=True, default=None) |     fixed_email = models.TextField(blank=True, default=None) | ||||||
|  |     needs_confirmation = models.BooleanField(default=True) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def link(self): |     def link(self): | ||||||
|  | |||||||
| @ -19,7 +19,8 @@ core_urls = [ | |||||||
|     path('auth/login/', authentication.LoginView.as_view(), name='auth-login'), |     path('auth/login/', authentication.LoginView.as_view(), name='auth-login'), | ||||||
|     path('auth/logout/', authentication.LogoutView.as_view(), name='auth-logout'), |     path('auth/logout/', authentication.LogoutView.as_view(), name='auth-logout'), | ||||||
|     path('auth/sign_up/', authentication.SignUpView.as_view(), name='auth-sign-up'), |     path('auth/sign_up/', authentication.SignUpView.as_view(), name='auth-sign-up'), | ||||||
|     # path('auth/sign_up/<uuid:nonce>/confirm/', , name='auth-sign-up-confirm'), |     path('auth/sign_up/<uuid:nonce>/confirm/', authentication.SignUpConfirmView.as_view(), | ||||||
|  |          name='auth-sign-up-confirm'), | ||||||
|     path('auth/process/denied/', view.FactorPermissionDeniedView.as_view(), name='auth-denied'), |     path('auth/process/denied/', view.FactorPermissionDeniedView.as_view(), name='auth-denied'), | ||||||
|     path('auth/password/reset/<uuid:nonce>/', authentication.PasswordResetView.as_view(), |     path('auth/password/reset/<uuid:nonce>/', authentication.PasswordResetView.as_view(), | ||||||
|          name='auth-password-reset'), |          name='auth-password-reset'), | ||||||
|  | |||||||
| @ -139,6 +139,15 @@ 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) | ||||||
|  |         needs_confirmation = True | ||||||
|  |         if self._invitation and not self._invitation.needs_confirmation: | ||||||
|  |             needs_confirmation = False | ||||||
|  |         if needs_confirmation: | ||||||
|  |             nonce = Nonce.objects.create(user=self._user) | ||||||
|  |             LOGGER.debug(str(nonce.uuid)) | ||||||
|  |             # TODO: Send E-Mail to user | ||||||
|  |             self._user.is_active = False | ||||||
|  |             self._user.save() | ||||||
|         self.consume_invitation() |         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", | ||||||
| @ -185,12 +194,24 @@ class SignUpView(UserPassesTestMixin, FormView): | |||||||
|             sender=SignUpView, |             sender=SignUpView, | ||||||
|             user=new_user, |             user=new_user, | ||||||
|             request=request) |             request=request) | ||||||
|         # TODO: Implement Verification, via email or others |  | ||||||
|         # if needs_confirmation: |  | ||||||
|         #     Create Account Confirmation UUID |  | ||||||
|         #     AccountConfirmation.objects.create(user=new_user) |  | ||||||
|         return new_user |         return new_user | ||||||
|  |  | ||||||
|  | class SignUpConfirmView(View): | ||||||
|  |     """Confirm registration from Nonce""" | ||||||
|  |  | ||||||
|  |     def get(self, request, nonce): | ||||||
|  |         """Verify UUID and activate user""" | ||||||
|  |         nonce = get_object_or_404(Nonce, uuid=nonce) | ||||||
|  |         nonce.user.is_active = True | ||||||
|  |         nonce.user.save() | ||||||
|  |         # Workaround: hardcoded reference to ModelBackend, needs testing | ||||||
|  |         nonce.user.backend = 'django.contrib.auth.backends.ModelBackend' | ||||||
|  |         login(request, nonce.user) | ||||||
|  |         nonce.delete() | ||||||
|  |         messages.success(request, _('Successfully confirmed registration.')) | ||||||
|  |         return redirect('passbook_core:overview') | ||||||
|  |  | ||||||
|  |  | ||||||
| class PasswordResetView(View): | class PasswordResetView(View): | ||||||
|     """Temporarily authenticate User and allow them to reset their password""" |     """Temporarily authenticate User and allow them to reset their password""" | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer