mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	Invalidate registrations, fix profile creation
This commit is contained in:
		| @@ -10,7 +10,7 @@ def save_user_profile(instance, created, raw, **_kwargs): | ||||
|         # When provisionning data, do not try to autocreate | ||||
|         return | ||||
|  | ||||
|     if created: | ||||
|     if created and instance.is_active: | ||||
|         from .models import Profile | ||||
|         Profile.objects.get_or_create(user=instance) | ||||
|     instance.profile.save() | ||||
|         instance.profile.save() | ||||
|   | ||||
| @@ -102,11 +102,8 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): | ||||
|         return super().form_valid(form) | ||||
|  | ||||
|     def get_success_url(self, **kwargs): | ||||
|         if kwargs: | ||||
|             return reverse_lazy('member:user_detail', | ||||
|                                 kwargs={'pk': kwargs['id']}) | ||||
|         else: | ||||
|             return reverse_lazy('member:user_detail', args=(self.object.id,)) | ||||
|         url = 'member:user_detail' if self.object.profile.registration_valid else 'registration:future_user_detail' | ||||
|         return reverse_lazy(url, args=(self.object.id,)) | ||||
|  | ||||
|  | ||||
| class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): | ||||
| @@ -117,6 +114,12 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): | ||||
|     context_object_name = "user_object" | ||||
|     template_name = "member/profile_detail.html" | ||||
|  | ||||
|     def get_queryset(self, **kwargs): | ||||
|         """ | ||||
|         We can't display information of a not registered user. | ||||
|         """ | ||||
|         return super().get_queryset().filter(profile__registration_valid=True) | ||||
|  | ||||
|     def get_context_data(self, **kwargs): | ||||
|         context = super().get_context_data(**kwargs) | ||||
|         user = context['user_object'] | ||||
|   | ||||
| @@ -8,7 +8,9 @@ from . import views | ||||
| app_name = 'registration' | ||||
| urlpatterns = [ | ||||
|     path('signup/', views.UserCreateView.as_view(), name="signup"), | ||||
|     path('validate_email/sent', views.UserActivationEmailSentView.as_view(), name='account_activation_sent'), | ||||
|     path('validate_email/<uidb64>/<token>', views.UserActivateView.as_view(), name='account_activation'), | ||||
|     path('validate_email/sent/', views.UserActivationEmailSentView.as_view(), name='account_activation_sent'), | ||||
|     path('validate_email/<uidb64>/<token>/', views.UserActivateView.as_view(), name='account_activation'), | ||||
|     path('validate_user/', views.FutureUserListView.as_view(), name="future_user_list"), | ||||
|     path('validate_user/<int:pk>/', views.FutureUserDetailView.as_view(), name="future_user_detail"), | ||||
|     path('validate_user/<int:pk>/invalidate/', views.FutureUserInvalidateView.as_view(), name="future_user_invalidate"), | ||||
| ] | ||||
|   | ||||
| @@ -5,15 +5,18 @@ from django.conf import settings | ||||
| from django.contrib.auth.mixins import LoginRequiredMixin | ||||
| from django.contrib.auth.models import User | ||||
| from django.core.exceptions import ValidationError | ||||
| from django.shortcuts import resolve_url | ||||
| from django.shortcuts import resolve_url, redirect | ||||
| from django.urls import reverse_lazy | ||||
| from django.utils.decorators import method_decorator | ||||
| from django.utils.http import urlsafe_base64_decode | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from django.views import View | ||||
| from django.views.decorators.csrf import csrf_protect | ||||
| from django.views.generic import CreateView, TemplateView | ||||
| from django.views.generic import CreateView, TemplateView, DetailView | ||||
| from django_tables2 import SingleTableView | ||||
| from member.forms import ProfileForm | ||||
| from member.models import Profile | ||||
| from permission.backends import PermissionBackend | ||||
| from permission.views import ProtectQuerysetMixin | ||||
|  | ||||
| from .forms import SignUpForm | ||||
| @@ -42,15 +45,19 @@ class UserCreateView(CreateView): | ||||
|         If the form is valid, then the user is created with is_active set to False | ||||
|         so that the user cannot log in until the email has been validated. | ||||
|         """ | ||||
|         profile_form = ProfileForm(self.request.POST) | ||||
|         profile_form = ProfileForm(data=self.request.POST) | ||||
|         if not profile_form.is_valid(): | ||||
|             return self.form_invalid(form) | ||||
|  | ||||
|         user = form.save(commit=False) | ||||
|         user.is_active = False | ||||
|         user.profile = profile_form.save(commit=False) | ||||
|         profile_form.instance.user = user | ||||
|         profile = profile_form.save(commit=False) | ||||
|         user.profile = profile | ||||
|         user.save() | ||||
|         user.profile.save() | ||||
|         user.refresh_from_db() | ||||
|         profile.user = user | ||||
|         profile.save() | ||||
|  | ||||
|         user.profile.send_email_validation_link() | ||||
|  | ||||
| @@ -86,7 +93,6 @@ class UserActivateView(TemplateView): | ||||
|             return self.render_to_response(self.get_context_data()) | ||||
|  | ||||
|     def get_user(self, uidb64): | ||||
|         print(uidb64) | ||||
|         try: | ||||
|             # urlsafe_base64_decode() decodes to bytestring | ||||
|             uid = urlsafe_base64_decode(uidb64).decode() | ||||
| @@ -131,3 +137,32 @@ class FutureUserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi | ||||
|  | ||||
|         return context | ||||
|  | ||||
|  | ||||
| class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): | ||||
|     """ | ||||
|     Affiche les informations sur un utilisateur, sa note, ses clubs... | ||||
|     """ | ||||
|     model = User | ||||
|     context_object_name = "user_object" | ||||
|     template_name = "registration/future_profile_detail.html" | ||||
|  | ||||
|     def get_queryset(self, **kwargs): | ||||
|         """ | ||||
|         We only display information of a not registered user. | ||||
|         """ | ||||
|         return super().get_queryset().filter(profile__registration_valid=False) | ||||
|  | ||||
|  | ||||
| class FutureUserInvalidateView(ProtectQuerysetMixin, LoginRequiredMixin, View): | ||||
|     """ | ||||
|     Affiche les informations sur un utilisateur, sa note, ses clubs... | ||||
|     """ | ||||
|  | ||||
|     def dispatch(self, request, *args, **kwargs): | ||||
|         user = User.objects.filter(profile__registration_valid=False)\ | ||||
|             .filter(PermissionBackend.filter_queryset(request.user, User, "change", "is_valid"))\ | ||||
|             .get(pk=self.kwargs["pk"]) | ||||
|  | ||||
|         user.delete() | ||||
|  | ||||
|         return redirect('registration:future_user_list') | ||||
|   | ||||
| @@ -53,7 +53,7 @@ ProductFormSet = forms.inlineformset_factory( | ||||
|  | ||||
| class ProductFormSetHelper(FormHelper): | ||||
|     """ | ||||
|     Specify some template informations for the product form. | ||||
|     Specify some template information for the product form. | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, form=None): | ||||
|   | ||||
| @@ -2,7 +2,7 @@ Hi {{ user.username }}, | ||||
|  | ||||
| Welcome to {{ site_name }}. Please click on the link below to confirm your registration. | ||||
|  | ||||
| {{ protocol }}://{{ domain }}{% url 'member:account_activation' uidb64=uid token=token %} | ||||
| {{ protocol }}://{{ domain }}{% url 'registration:account_activation' uidb64=uid token=token %} | ||||
|  | ||||
| This link is only valid for a couple of days, after that you will need to contact us to validate your email. | ||||
|  | ||||
|   | ||||
							
								
								
									
										54
									
								
								templates/registration/future_profile_detail.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								templates/registration/future_profile_detail.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| {% extends "base.html" %} | ||||
| {% load static %} | ||||
| {% load i18n %} | ||||
| {% load render_table from django_tables2 %} | ||||
| {% load pretty_money %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div class="card bg-light shadow"> | ||||
|     <div class="card-header text-center" > | ||||
|         <h4> {% trans "Account #" %}  {{ object.pk }}</h4> | ||||
|     </div> | ||||
|     <div class="card-body" id="profile_infos"> | ||||
|         <dl class="row"> | ||||
|             <dt class="col-xl-6">{% trans 'name'|capfirst %}, {% trans 'first name' %}</dt> | ||||
|             <dd class="col-xl-6">{{ object.last_name }} {{ object.first_name }}</dd> | ||||
|  | ||||
|             <dt class="col-xl-6">{% trans 'username'|capfirst %}</dt> | ||||
|             <dd class="col-xl-6">{{ object.username }}</dd> | ||||
|  | ||||
|             <dt class="col-xl-6">{% trans 'email'|capfirst %}</dt> | ||||
|             <dd class="col-xl-6"><a href="mailto:{{ object.email }}">{{ object.email }}</a></dd> | ||||
|  | ||||
|             <dt class="col-xl-6">{% trans 'password'|capfirst %}</dt> | ||||
|             <dd class="col-xl-6"> | ||||
|                 <a class="small" href="{% url 'password_change' %}"> | ||||
|                     {% trans 'Change password' %} | ||||
|                 </a> | ||||
|             </dd> | ||||
|  | ||||
|             <dt class="col-xl-6">{% trans 'section'|capfirst %}</dt> | ||||
|             <dd class="col-xl-6">{{ object.profile.section }}</dd> | ||||
|  | ||||
|             <dt class="col-xl-6">{% trans 'address'|capfirst %}</dt> | ||||
|             <dd class="col-xl-6">{{ object.profile.address }}</dd> | ||||
|  | ||||
|             <dt class="col-xl-6">{% trans 'phone number'|capfirst %}</dt> | ||||
|             <dd class="col-xl-6">{{ object.profile.phone_number }}</dd> | ||||
|  | ||||
|             <dt class="col-xl-6">{% trans 'paid'|capfirst %}</dt> | ||||
|             <dd class="col-xl-6">{{ object.profile.paid|yesno }}</dd> | ||||
|         </dl> | ||||
|  | ||||
|         {% if object.pk == user.pk %} | ||||
|         <a class="small" href="{% url 'member:auth_token' %}">{% trans 'Manage auth token' %}</a> | ||||
|         {% endif %} | ||||
|     </div> | ||||
|     <div class="card-footer text-center"> | ||||
|         <a class="btn btn-primary btn-sm" href="{% url 'member:user_update_profile' object.pk %}">{% trans 'Update Profile' %}</a> | ||||
|         <a class="btn btn-danger btn-sm" href="{% url 'registration:future_user_invalidate' object.pk %}">{% trans 'Delete registration' %}</a> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -4,13 +4,19 @@ | ||||
| {% load i18n %} | ||||
|  | ||||
| {% block content %} | ||||
|     <div id="user_table"> | ||||
|         {% render_table table %} | ||||
|     </div> | ||||
|     <a href="{% url 'registration:signup' %}"><button class="btn btn-primary btn-block">{% trans "New user" %}</button></a> | ||||
|  | ||||
|     <hr> | ||||
|  | ||||
|     <a href="{% url 'registration:signup' %}"><button class="btn btn-primary btn-block">{% trans "New user" %}</button></a> | ||||
|     {% if table.data %} | ||||
|         <div id="user_table"> | ||||
|             {% render_table table %} | ||||
|         </div> | ||||
|     {% else %} | ||||
|         <div class="alert alert-warning"> | ||||
|             {% trans "There is no pending user." %} | ||||
|         </div> | ||||
|     {% endif %} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block extrajavascript %} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user