We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Mot de passe perdu
Cette fonctionnalité de fonctionne pas sur mon ordinateur mais fonctionne sur l'ordinateur de Gabin Schieffer <br/> Proposé par julie.geffraye@eleves.ec-nantes.fr

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `server/apps/account/urls.py`
Content:
```
1 from django.conf.urls import url
2 from django.urls import path
3 
4 from .views import *
5 
6 app_name = 'account'
7 
8 urlpatterns = [
9     path('login', AuthView.as_view(), name='login'),
10     path('logout', LogoutView.as_view(), name='logout'),
11     path('registration', RegistrationView.as_view(), name='registration'),
12     path('registration/temporary/<int:id>/approve', ApproveTemporaryRegistrationView.as_view(),
13          name='temp-req-approve'),
14     path('registration/temporary/<int:id>/deny', DenyTemporaryRegistrationView.as_view(),
15          name='temp-req-deny'),
16     path('registration/temporary', TemporaryRegistrationView.as_view(),
17          name='temporary-registration'),
18     path('activate/<slug:uidb64>/<slug:token>/',
19          ConfirmUser.as_view(), name='confirm'),
20     path('activate/<slug:uidb64>/<slug:token>/temporary',
21          ConfirmUserTemporary.as_view(), name='confirm-temporary'),
22     path('permanent', PermanentAccountUpgradeView.as_view(),
23          name='upgrade-permanent'),
24     path('forgotten', ForgottenPassView.as_view(), name='forgotten_pass'),
25     path('reset_pass/<slug:uidb64>/<slug:token>',
26          PasswordResetConfirmCustomView.as_view(), name='reset_pass'),
27     path('<slug:user_id>/student', redirect_to_student, name='redirect-student'),
28 ]
29
```

Path: `server/apps/account/views.py`
Content:
```
1 from datetime import date
2 from typing import Any, Dict, Union
3 from django.conf import settings
4 from django.contrib.auth import login, logout
5 from django.contrib.sites.shortcuts import get_current_site
6 from django.http.response import HttpResponse
7 from django.views.generic.edit import FormView
8 from django.shortcuts import get_object_or_404
9 
10 from apps.utils.accessMixins import UserIsSuperAdmin
11 from .forms import SignUpForm, LoginForm, ForgottenPassForm, TemporaryRequestSignUpForm, UpgradePermanentAccountForm
12 from .tokens import account_activation_token
13 from django.contrib import messages
14 from django.shortcuts import render, redirect
15 from django.template.loader import render_to_string
16 from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
17 from django.utils.encoding import force_bytes, force_text
18 from django.urls import reverse, reverse_lazy
19 
20 from django.contrib.auth.views import PasswordResetConfirmView
21 from django.views import View
22 
23 from django.contrib.auth.forms import SetPasswordForm
24 from django.contrib.auth.mixins import LoginRequiredMixin
25 
26 from django.contrib.auth.models import User
27 from apps.student.models import Student
28 
29 from .emailAuthBackend import EmailBackend
30 from .models import TemporaryAccessRequest
31 from .utils import user_creation, send_email_confirmation
32 
33 
34 class RegistrationView(FormView):
35     template_name = 'account/registration.html'
36     form_class = SignUpForm
37 
38     def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
39         context = super().get_context_data(**kwargs)
40         context['temporary_registration'] = settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today()
41         return context
42 
43     def form_valid(self, form):
44         user_creation(form, self.request)
45         return redirect(reverse('home:home'))
46 
47 
48 class TemporaryRegistrationView(FormView):
49     form_class = TemporaryRequestSignUpForm
50     template_name = 'account/temporary_registration.html'
51 
52     def dispatch(self, request, *args: Any, **kwargs: Any):
53         """Do not allow to use this view outside of allowed temporary accounts windows."""
54         if not settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today():
55             return redirect(reverse('account:registration'))
56         return super().dispatch(request, *args, **kwargs)
57 
58     def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
59         context = super().get_context_data(**kwargs)
60         context['DEADLINE_TEMPORARY_REGISTRATION'] = settings.TEMPORARY_ACCOUNTS_DATE_LIMIT
61         return context
62 
63     def form_valid(self, form) -> HttpResponse:
64         user_creation(form, self.request)
65         return redirect(reverse('home:home'))
66 
67 
68 class ConfirmUser(View):
69     def get(self, request, uidb64, token):
70         tempAccessReq: Union[TemporaryAccessRequest, None] = None
71         try:
72             uid = force_text(urlsafe_base64_decode(uidb64))
73             user = User.objects.get(pk=uid)
74         except (TypeError, ValueError, OverflowError, User.DoesNotExist):
75             return render(self.request, 'account/activation_invalid.html')
76         # checking if the user is not a temporary one
77         try:
78             tempAccessReq: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(
79                 user=user.pk)
80             if not tempAccessReq.approved:
81                 return render(self.request, 'account/activation_invalid.html')
82         except TemporaryAccessRequest.DoesNotExist:
83             tempAccessReq = None
84         # checking if the token is valid.
85         if account_activation_token.check_token(user, token):
86             # if valid set active true
87             user.is_active = True
88             if tempAccessReq is not None:
89                 user.email = tempAccessReq.final_email
90                 tempAccessReq.delete()
91                 messages.warning(
92                     request, f'Dorénavant vous devez utiliser {user.email} pour vous connecter.')
93             user.save()
94             login(self.request, user,
95                   backend='apps.account.emailAuthBackend.EmailBackend')
96             messages.success(request, 'Votre compte est desormais actif !')
97             return redirect(reverse('home:home'))
98         else:
99             return render(self.request, 'account/activation_invalid.html')
100 
101 
102 class AuthView(FormView):
103     template_name = 'account/login.html'
104     form_class = LoginForm
105 
106     def get(self, request):
107         if request.user.is_authenticated:
108             user = request.user
109             message = f'Vous etes déjà connecté en tant que {user.first_name.title()}.'
110             messages.warning(request, message)
111             return redirect(reverse('home:home'))
112         else:
113             return super(AuthView, AuthView).get(self, request)
114 
115     def form_invalid(self, form):
116         message = f'Veuillez vous connecter avec votre adresse mail ECN.'
117         messages.warning(self.request, message)
118         return redirect(reverse('account:login'))
119 
120     def form_valid(self, form):
121         username = form.cleaned_data['email']
122         password = form.cleaned_data['password']
123         user = EmailBackend.authenticate(username=username, password=password)
124         if user is not None:
125             if user.is_active:
126                 message = f'Bonjour {user.first_name.title()} !'
127                 messages.success(self.request, message)
128             else:
129                 if settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today():
130                     # During certain periods allow temporary accounts.
131                     try:
132                         temporaryAccessRequest: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(
133                             user=user
134                         )
135                         if not temporaryAccessRequest.mail_valid:
136                             message = 'Votre compte n\'est pas encore actif.\
137                             Veuillez cliquer sur le lien envoyé par mail pour l\'\
138                                 activer.'
139                             messages.error(self.request, message)
140                             return redirect(reverse('account:login'))
141                         if temporaryAccessRequest.approved_until <= date.today():
142                             message = 'Votre compte n\'a pas encore été approuvé.\
143                                 On vous prévient par mail dès que c\'est le cas.'
144                             messages.error(self.request, message)
145                             return redirect(reverse('account:login'))
146                         message = f'Votre compte n\'est pas encore définitif.\
147                             Veuillez le valider <a href="{reverse("account:upgrade-permanent")}">ici</a>.\
148                             Attention après le {temporaryAccessRequest.approved_until}\
149                             vous ne pourrez plus vous connecter si vous n\'avez pas renseigné votre adresse Centrale.'
150                         messages.warning(self.request, message)
151                     except TemporaryAccessRequest.DoesNotExist:
152                         messages.error(
153                             self.request, 'Identifiant inconnu ou mot de passe invalide.')
154                         return redirect(reverse('account:login'))
155                 else:
156                     messages.warning(
157                         self.request, 'Votre compte n\'est pas encore actif. Veuillez cliquer sur le lien dans \'email.')
158             login(self.request, user,
159                   backend='apps.account.emailAuthBackend.EmailBackend')
160             return redirect(reverse('home:home'))
161         else:
162             messages.error(
163                 self.request, 'Identifiant inconnu ou mot de passe invalide.')
164             return redirect(reverse('account:login'))
165 
166 
167 class LogoutView(View):
168     def get(self, request):
169         logout(request)
170         messages.success(request, 'Vous avez été déconnecté.')
171         return redirect(reverse('account:login'))
172 
173 
174 class ForgottenPassView(FormView):
175     form_class = ForgottenPassForm
176     template_name = 'account/forgotten_pass.html'
177 
178     def form_valid(self, form):
179         user = User.objects.get(email=form.cleaned_data['email'])
180         if user is not None:
181             subject = '[Nantral Platform] Reinitialisation de votre mot de passe'
182             current_site = get_current_site(self.request)
183             message = render_to_string('account/mail/password_request.html', {
184                 'user': user,
185                 'domain': current_site.domain,
186                 'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),
187                 # method will generate a hash value with user related data
188                 'token': account_activation_token.make_token(user),
189             })
190             user.email_user(
191                 subject, message, 'accounts@nantral-platform.fr', html_message=message)
192         messages.success(
193             self.request, 'Un email de récuperation a été envoyé si cette adresse existe.')
194         return redirect(reverse('account:login'))
195 
196 
197 class PasswordResetConfirmCustomView(PasswordResetConfirmView):
198     template_name = 'account/reset_password.html'
199     post_reset_login = True
200     post_reset_login_backend = 'apps.account.emailAuthBackend.EmailBackend'
201     form_class = SetPasswordForm
202     token_generator = account_activation_token
203     success_url = reverse_lazy('home:home')
204 
205 
206 def redirect_to_student(request, user_id):
207     user = User.objects.get(id=user_id)
208     student = Student.objects.get(user=user)
209     return redirect('student:update', student.pk)
210 
211 
212 class ABCApprovalTemporaryResgistrationView(UserIsSuperAdmin, View):
213     def get(self, request, id):
214         self.temp_req: TemporaryAccessRequest = get_object_or_404(
215             TemporaryAccessRequest, id=id)
216 
217         if self.temp_req.approved:
218             messages.warning(request, f'Cette requête a déjà été approuvée.')
219             return redirect(reverse('home:home'))
220 
221 
222 class ApproveTemporaryRegistrationView(ABCApprovalTemporaryResgistrationView):
223     def get(self, request, id):
224         super().get(request, id)
225         self.temp_req.approve()
226         messages.success(
227             request, f'Vous avez accepté la demande de {self.temp_req.user.first_name} {self.temp_req.user.last_name}')
228         return redirect(reverse('home:home'))
229 
230 
231 class DenyTemporaryRegistrationView(ABCApprovalTemporaryResgistrationView):
232     def get(self, request, id):
233         super().get(request, id)
234         messages.success(
235             request, f'Vous avez refusé la demande de {self.temp_req.user.first_name} {self.temp_req.user.last_name}')
236         self.temp_req.deny()
237         return redirect(reverse('home:home'))
238 
239 
240 class ConfirmUserTemporary(View):
241     def get(self, request, uidb64, token):
242         try:
243             uid = force_text(urlsafe_base64_decode(uidb64))
244             user = User.objects.get(pk=uid)
245         except (TypeError, ValueError, OverflowError, User.DoesNotExist):
246             user = None
247         # checking if the user exists, if the token is valid.
248         if user is not None and account_activation_token.check_token(user, token):
249             try:
250                 temp_req: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(
251                     user=user)
252                 temp_req.mail_valid = True
253                 temp_req.save()
254             except TemporaryAccessRequest.DoesNotExist:
255                 return render(self.request, 'account/activation_invalid.html')
256             messages.success(request, 'Votre addresse mail est confirmé! \n\
257             Comme vous n\'avez pas utilisé votre adresse Centrale, vous devez encore attendre qu\'un administrateur vérifie votre inscription.\n\
258             On vous prévient par mail dès que c\'est bon!. ')
259             return redirect(reverse('home:home'))
260         else:
261             return render(self.request, 'account/activation_invalid.html')
262 
263 
264 class PermanentAccountUpgradeView(LoginRequiredMixin, FormView):
265     form_class = UpgradePermanentAccountForm
266     template_name = 'account/permanent_account_upgrade.html'
267     success_url = reverse_lazy('home:home')
268 
269     def get(self, request):
270         get_object_or_404(
271             TemporaryAccessRequest,
272             user=self.request.user
273         )
274         return super().get(request)
275 
276     def form_valid(self, form: UpgradePermanentAccountForm) -> HttpResponse:
277         temp_request = get_object_or_404(
278             TemporaryAccessRequest,
279             user=self.request.user
280         )
281         temp_request.final_email = form.cleaned_data['email']
282         temp_request.save()
283         send_email_confirmation(
284             self.request.user, self.request, send_to=form.cleaned_data['email'])
285         return super().form_valid(form)
286
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/server/apps/account/urls.py b/server/apps/account/urls.py
--- a/server/apps/account/urls.py
+++ b/server/apps/account/urls.py
@@ -22,7 +22,7 @@
     path('permanent', PermanentAccountUpgradeView.as_view(),
          name='upgrade-permanent'),
     path('forgotten', ForgottenPassView.as_view(), name='forgotten_pass'),
-    path('reset_pass/<slug:uidb64>/<slug:token>',
+    path('reset_pass/<slug:uidb64>/<slug:token>/',
          PasswordResetConfirmCustomView.as_view(), name='reset_pass'),
     path('<slug:user_id>/student', redirect_to_student, name='redirect-student'),
 ]
diff --git a/server/apps/account/views.py b/server/apps/account/views.py
--- a/server/apps/account/views.py
+++ b/server/apps/account/views.py
@@ -176,19 +176,22 @@
     template_name = 'account/forgotten_pass.html'
 
     def form_valid(self, form):
-        user = User.objects.get(email=form.cleaned_data['email'])
-        if user is not None:
-            subject = '[Nantral Platform] Reinitialisation de votre mot de passe'
-            current_site = get_current_site(self.request)
-            message = render_to_string('account/mail/password_request.html', {
-                'user': user,
-                'domain': current_site.domain,
-                'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),
-                # method will generate a hash value with user related data
-                'token': account_activation_token.make_token(user),
-            })
-            user.email_user(
-                subject, message, 'accounts@nantral-platform.fr', html_message=message)
+        try:
+            user = User.objects.get(email=form.cleaned_data['email'])
+            if user is not None:
+                subject = '[Nantral Platform] Reinitialisation de votre mot de passe'
+                current_site = get_current_site(self.request)
+                message = render_to_string('account/mail/password_request.html', {
+                    'user': user,
+                    'domain': current_site.domain,
+                    'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),
+                    # method will generate a hash value with user related data
+                    'token': account_activation_token.make_token(user),
+                })
+                user.email_user(
+                    subject, message, 'accounts@nantral-platform.fr', html_message=message)
+        except User.DoesNotExist:
+            pass
         messages.success(
             self.request, 'Un email de récuperation a été envoyé si cette adresse existe.')
         return redirect(reverse('account:login'))

{"golden_diff": "diff --git a/server/apps/account/urls.py b/server/apps/account/urls.py\n--- a/server/apps/account/urls.py\n+++ b/server/apps/account/urls.py\n@@ -22,7 +22,7 @@\n     path('permanent', PermanentAccountUpgradeView.as_view(),\n          name='upgrade-permanent'),\n     path('forgotten', ForgottenPassView.as_view(), name='forgotten_pass'),\n-    path('reset_pass/<slug:uidb64>/<slug:token>',\n+    path('reset_pass/<slug:uidb64>/<slug:token>/',\n          PasswordResetConfirmCustomView.as_view(), name='reset_pass'),\n     path('<slug:user_id>/student', redirect_to_student, name='redirect-student'),\n ]\ndiff --git a/server/apps/account/views.py b/server/apps/account/views.py\n--- a/server/apps/account/views.py\n+++ b/server/apps/account/views.py\n@@ -176,19 +176,22 @@\n     template_name = 'account/forgotten_pass.html'\n \n     def form_valid(self, form):\n-        user = User.objects.get(email=form.cleaned_data['email'])\n-        if user is not None:\n-            subject = '[Nantral Platform] Reinitialisation de votre mot de passe'\n-            current_site = get_current_site(self.request)\n-            message = render_to_string('account/mail/password_request.html', {\n-                'user': user,\n-                'domain': current_site.domain,\n-                'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),\n-                # method will generate a hash value with user related data\n-                'token': account_activation_token.make_token(user),\n-            })\n-            user.email_user(\n-                subject, message, 'accounts@nantral-platform.fr', html_message=message)\n+        try:\n+            user = User.objects.get(email=form.cleaned_data['email'])\n+            if user is not None:\n+                subject = '[Nantral Platform] Reinitialisation de votre mot de passe'\n+                current_site = get_current_site(self.request)\n+                message = render_to_string('account/mail/password_request.html', {\n+                    'user': user,\n+                    'domain': current_site.domain,\n+                    'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),\n+                    # method will generate a hash value with user related data\n+                    'token': account_activation_token.make_token(user),\n+                })\n+                user.email_user(\n+                    subject, message, 'accounts@nantral-platform.fr', html_message=message)\n+        except User.DoesNotExist:\n+            pass\n         messages.success(\n             self.request, 'Un email de r\u00e9cuperation a \u00e9t\u00e9 envoy\u00e9 si cette adresse existe.')\n         return redirect(reverse('account:login'))\n", "issue": "Mot de passe perdu\nCette fonctionnalit\u00e9 de fonctionne pas sur mon ordinateur mais fonctionne sur l'ordinateur de Gabin Schieffer <br/> Propos\u00e9 par julie.geffraye@eleves.ec-nantes.fr\n", "before_files": [{"content": "from django.conf.urls import url\nfrom django.urls import path\n\nfrom .views import *\n\napp_name = 'account'\n\nurlpatterns = [\n    path('login', AuthView.as_view(), name='login'),\n    path('logout', LogoutView.as_view(), name='logout'),\n    path('registration', RegistrationView.as_view(), name='registration'),\n    path('registration/temporary/<int:id>/approve', ApproveTemporaryRegistrationView.as_view(),\n         name='temp-req-approve'),\n    path('registration/temporary/<int:id>/deny', DenyTemporaryRegistrationView.as_view(),\n         name='temp-req-deny'),\n    path('registration/temporary', TemporaryRegistrationView.as_view(),\n         name='temporary-registration'),\n    path('activate/<slug:uidb64>/<slug:token>/',\n         ConfirmUser.as_view(), name='confirm'),\n    path('activate/<slug:uidb64>/<slug:token>/temporary',\n         ConfirmUserTemporary.as_view(), name='confirm-temporary'),\n    path('permanent', PermanentAccountUpgradeView.as_view(),\n         name='upgrade-permanent'),\n    path('forgotten', ForgottenPassView.as_view(), name='forgotten_pass'),\n    path('reset_pass/<slug:uidb64>/<slug:token>',\n         PasswordResetConfirmCustomView.as_view(), name='reset_pass'),\n    path('<slug:user_id>/student', redirect_to_student, name='redirect-student'),\n]\n", "path": "server/apps/account/urls.py"}, {"content": "from datetime import date\nfrom typing import Any, Dict, Union\nfrom django.conf import settings\nfrom django.contrib.auth import login, logout\nfrom django.contrib.sites.shortcuts import get_current_site\nfrom django.http.response import HttpResponse\nfrom django.views.generic.edit import FormView\nfrom django.shortcuts import get_object_or_404\n\nfrom apps.utils.accessMixins import UserIsSuperAdmin\nfrom .forms import SignUpForm, LoginForm, ForgottenPassForm, TemporaryRequestSignUpForm, UpgradePermanentAccountForm\nfrom .tokens import account_activation_token\nfrom django.contrib import messages\nfrom django.shortcuts import render, redirect\nfrom django.template.loader import render_to_string\nfrom django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode\nfrom django.utils.encoding import force_bytes, force_text\nfrom django.urls import reverse, reverse_lazy\n\nfrom django.contrib.auth.views import PasswordResetConfirmView\nfrom django.views import View\n\nfrom django.contrib.auth.forms import SetPasswordForm\nfrom django.contrib.auth.mixins import LoginRequiredMixin\n\nfrom django.contrib.auth.models import User\nfrom apps.student.models import Student\n\nfrom .emailAuthBackend import EmailBackend\nfrom .models import TemporaryAccessRequest\nfrom .utils import user_creation, send_email_confirmation\n\n\nclass RegistrationView(FormView):\n    template_name = 'account/registration.html'\n    form_class = SignUpForm\n\n    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:\n        context = super().get_context_data(**kwargs)\n        context['temporary_registration'] = settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today()\n        return context\n\n    def form_valid(self, form):\n        user_creation(form, self.request)\n        return redirect(reverse('home:home'))\n\n\nclass TemporaryRegistrationView(FormView):\n    form_class = TemporaryRequestSignUpForm\n    template_name = 'account/temporary_registration.html'\n\n    def dispatch(self, request, *args: Any, **kwargs: Any):\n        \"\"\"Do not allow to use this view outside of allowed temporary accounts windows.\"\"\"\n        if not settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today():\n            return redirect(reverse('account:registration'))\n        return super().dispatch(request, *args, **kwargs)\n\n    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:\n        context = super().get_context_data(**kwargs)\n        context['DEADLINE_TEMPORARY_REGISTRATION'] = settings.TEMPORARY_ACCOUNTS_DATE_LIMIT\n        return context\n\n    def form_valid(self, form) -> HttpResponse:\n        user_creation(form, self.request)\n        return redirect(reverse('home:home'))\n\n\nclass ConfirmUser(View):\n    def get(self, request, uidb64, token):\n        tempAccessReq: Union[TemporaryAccessRequest, None] = None\n        try:\n            uid = force_text(urlsafe_base64_decode(uidb64))\n            user = User.objects.get(pk=uid)\n        except (TypeError, ValueError, OverflowError, User.DoesNotExist):\n            return render(self.request, 'account/activation_invalid.html')\n        # checking if the user is not a temporary one\n        try:\n            tempAccessReq: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(\n                user=user.pk)\n            if not tempAccessReq.approved:\n                return render(self.request, 'account/activation_invalid.html')\n        except TemporaryAccessRequest.DoesNotExist:\n            tempAccessReq = None\n        # checking if the token is valid.\n        if account_activation_token.check_token(user, token):\n            # if valid set active true\n            user.is_active = True\n            if tempAccessReq is not None:\n                user.email = tempAccessReq.final_email\n                tempAccessReq.delete()\n                messages.warning(\n                    request, f'Dor\u00e9navant vous devez utiliser {user.email} pour vous connecter.')\n            user.save()\n            login(self.request, user,\n                  backend='apps.account.emailAuthBackend.EmailBackend')\n            messages.success(request, 'Votre compte est desormais actif !')\n            return redirect(reverse('home:home'))\n        else:\n            return render(self.request, 'account/activation_invalid.html')\n\n\nclass AuthView(FormView):\n    template_name = 'account/login.html'\n    form_class = LoginForm\n\n    def get(self, request):\n        if request.user.is_authenticated:\n            user = request.user\n            message = f'Vous etes d\u00e9j\u00e0 connect\u00e9 en tant que {user.first_name.title()}.'\n            messages.warning(request, message)\n            return redirect(reverse('home:home'))\n        else:\n            return super(AuthView, AuthView).get(self, request)\n\n    def form_invalid(self, form):\n        message = f'Veuillez vous connecter avec votre adresse mail ECN.'\n        messages.warning(self.request, message)\n        return redirect(reverse('account:login'))\n\n    def form_valid(self, form):\n        username = form.cleaned_data['email']\n        password = form.cleaned_data['password']\n        user = EmailBackend.authenticate(username=username, password=password)\n        if user is not None:\n            if user.is_active:\n                message = f'Bonjour {user.first_name.title()} !'\n                messages.success(self.request, message)\n            else:\n                if settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today():\n                    # During certain periods allow temporary accounts.\n                    try:\n                        temporaryAccessRequest: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(\n                            user=user\n                        )\n                        if not temporaryAccessRequest.mail_valid:\n                            message = 'Votre compte n\\'est pas encore actif.\\\n                            Veuillez cliquer sur le lien envoy\u00e9 par mail pour l\\'\\\n                                activer.'\n                            messages.error(self.request, message)\n                            return redirect(reverse('account:login'))\n                        if temporaryAccessRequest.approved_until <= date.today():\n                            message = 'Votre compte n\\'a pas encore \u00e9t\u00e9 approuv\u00e9.\\\n                                On vous pr\u00e9vient par mail d\u00e8s que c\\'est le cas.'\n                            messages.error(self.request, message)\n                            return redirect(reverse('account:login'))\n                        message = f'Votre compte n\\'est pas encore d\u00e9finitif.\\\n                            Veuillez le valider <a href=\"{reverse(\"account:upgrade-permanent\")}\">ici</a>.\\\n                            Attention apr\u00e8s le {temporaryAccessRequest.approved_until}\\\n                            vous ne pourrez plus vous connecter si vous n\\'avez pas renseign\u00e9 votre adresse Centrale.'\n                        messages.warning(self.request, message)\n                    except TemporaryAccessRequest.DoesNotExist:\n                        messages.error(\n                            self.request, 'Identifiant inconnu ou mot de passe invalide.')\n                        return redirect(reverse('account:login'))\n                else:\n                    messages.warning(\n                        self.request, 'Votre compte n\\'est pas encore actif. Veuillez cliquer sur le lien dans \\'email.')\n            login(self.request, user,\n                  backend='apps.account.emailAuthBackend.EmailBackend')\n            return redirect(reverse('home:home'))\n        else:\n            messages.error(\n                self.request, 'Identifiant inconnu ou mot de passe invalide.')\n            return redirect(reverse('account:login'))\n\n\nclass LogoutView(View):\n    def get(self, request):\n        logout(request)\n        messages.success(request, 'Vous avez \u00e9t\u00e9 d\u00e9connect\u00e9.')\n        return redirect(reverse('account:login'))\n\n\nclass ForgottenPassView(FormView):\n    form_class = ForgottenPassForm\n    template_name = 'account/forgotten_pass.html'\n\n    def form_valid(self, form):\n        user = User.objects.get(email=form.cleaned_data['email'])\n        if user is not None:\n            subject = '[Nantral Platform] Reinitialisation de votre mot de passe'\n            current_site = get_current_site(self.request)\n            message = render_to_string('account/mail/password_request.html', {\n                'user': user,\n                'domain': current_site.domain,\n                'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),\n                # method will generate a hash value with user related data\n                'token': account_activation_token.make_token(user),\n            })\n            user.email_user(\n                subject, message, 'accounts@nantral-platform.fr', html_message=message)\n        messages.success(\n            self.request, 'Un email de r\u00e9cuperation a \u00e9t\u00e9 envoy\u00e9 si cette adresse existe.')\n        return redirect(reverse('account:login'))\n\n\nclass PasswordResetConfirmCustomView(PasswordResetConfirmView):\n    template_name = 'account/reset_password.html'\n    post_reset_login = True\n    post_reset_login_backend = 'apps.account.emailAuthBackend.EmailBackend'\n    form_class = SetPasswordForm\n    token_generator = account_activation_token\n    success_url = reverse_lazy('home:home')\n\n\ndef redirect_to_student(request, user_id):\n    user = User.objects.get(id=user_id)\n    student = Student.objects.get(user=user)\n    return redirect('student:update', student.pk)\n\n\nclass ABCApprovalTemporaryResgistrationView(UserIsSuperAdmin, View):\n    def get(self, request, id):\n        self.temp_req: TemporaryAccessRequest = get_object_or_404(\n            TemporaryAccessRequest, id=id)\n\n        if self.temp_req.approved:\n            messages.warning(request, f'Cette requ\u00eate a d\u00e9j\u00e0 \u00e9t\u00e9 approuv\u00e9e.')\n            return redirect(reverse('home:home'))\n\n\nclass ApproveTemporaryRegistrationView(ABCApprovalTemporaryResgistrationView):\n    def get(self, request, id):\n        super().get(request, id)\n        self.temp_req.approve()\n        messages.success(\n            request, f'Vous avez accept\u00e9 la demande de {self.temp_req.user.first_name} {self.temp_req.user.last_name}')\n        return redirect(reverse('home:home'))\n\n\nclass DenyTemporaryRegistrationView(ABCApprovalTemporaryResgistrationView):\n    def get(self, request, id):\n        super().get(request, id)\n        messages.success(\n            request, f'Vous avez refus\u00e9 la demande de {self.temp_req.user.first_name} {self.temp_req.user.last_name}')\n        self.temp_req.deny()\n        return redirect(reverse('home:home'))\n\n\nclass ConfirmUserTemporary(View):\n    def get(self, request, uidb64, token):\n        try:\n            uid = force_text(urlsafe_base64_decode(uidb64))\n            user = User.objects.get(pk=uid)\n        except (TypeError, ValueError, OverflowError, User.DoesNotExist):\n            user = None\n        # checking if the user exists, if the token is valid.\n        if user is not None and account_activation_token.check_token(user, token):\n            try:\n                temp_req: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(\n                    user=user)\n                temp_req.mail_valid = True\n                temp_req.save()\n            except TemporaryAccessRequest.DoesNotExist:\n                return render(self.request, 'account/activation_invalid.html')\n            messages.success(request, 'Votre addresse mail est confirm\u00e9! \\n\\\n            Comme vous n\\'avez pas utilis\u00e9 votre adresse Centrale, vous devez encore attendre qu\\'un administrateur v\u00e9rifie votre inscription.\\n\\\n            On vous pr\u00e9vient par mail d\u00e8s que c\\'est bon!. ')\n            return redirect(reverse('home:home'))\n        else:\n            return render(self.request, 'account/activation_invalid.html')\n\n\nclass PermanentAccountUpgradeView(LoginRequiredMixin, FormView):\n    form_class = UpgradePermanentAccountForm\n    template_name = 'account/permanent_account_upgrade.html'\n    success_url = reverse_lazy('home:home')\n\n    def get(self, request):\n        get_object_or_404(\n            TemporaryAccessRequest,\n            user=self.request.user\n        )\n        return super().get(request)\n\n    def form_valid(self, form: UpgradePermanentAccountForm) -> HttpResponse:\n        temp_request = get_object_or_404(\n            TemporaryAccessRequest,\n            user=self.request.user\n        )\n        temp_request.final_email = form.cleaned_data['email']\n        temp_request.save()\n        send_email_confirmation(\n            self.request.user, self.request, send_to=form.cleaned_data['email'])\n        return super().form_valid(form)\n", "path": "server/apps/account/views.py"}], "after_files": [{"content": "from django.conf.urls import url\nfrom django.urls import path\n\nfrom .views import *\n\napp_name = 'account'\n\nurlpatterns = [\n    path('login', AuthView.as_view(), name='login'),\n    path('logout', LogoutView.as_view(), name='logout'),\n    path('registration', RegistrationView.as_view(), name='registration'),\n    path('registration/temporary/<int:id>/approve', ApproveTemporaryRegistrationView.as_view(),\n         name='temp-req-approve'),\n    path('registration/temporary/<int:id>/deny', DenyTemporaryRegistrationView.as_view(),\n         name='temp-req-deny'),\n    path('registration/temporary', TemporaryRegistrationView.as_view(),\n         name='temporary-registration'),\n    path('activate/<slug:uidb64>/<slug:token>/',\n         ConfirmUser.as_view(), name='confirm'),\n    path('activate/<slug:uidb64>/<slug:token>/temporary',\n         ConfirmUserTemporary.as_view(), name='confirm-temporary'),\n    path('permanent', PermanentAccountUpgradeView.as_view(),\n         name='upgrade-permanent'),\n    path('forgotten', ForgottenPassView.as_view(), name='forgotten_pass'),\n    path('reset_pass/<slug:uidb64>/<slug:token>/',\n         PasswordResetConfirmCustomView.as_view(), name='reset_pass'),\n    path('<slug:user_id>/student', redirect_to_student, name='redirect-student'),\n]\n", "path": "server/apps/account/urls.py"}, {"content": "from datetime import date\nfrom typing import Any, Dict, Union\nfrom django.conf import settings\nfrom django.contrib.auth import login, logout\nfrom django.contrib.sites.shortcuts import get_current_site\nfrom django.http.response import HttpResponse\nfrom django.views.generic.edit import FormView\nfrom django.shortcuts import get_object_or_404\n\nfrom apps.utils.accessMixins import UserIsSuperAdmin\nfrom .forms import SignUpForm, LoginForm, ForgottenPassForm, TemporaryRequestSignUpForm, UpgradePermanentAccountForm\nfrom .tokens import account_activation_token\nfrom django.contrib import messages\nfrom django.shortcuts import render, redirect\nfrom django.template.loader import render_to_string\nfrom django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode\nfrom django.utils.encoding import force_bytes, force_text\nfrom django.urls import reverse, reverse_lazy\n\nfrom django.contrib.auth.views import PasswordResetConfirmView\nfrom django.views import View\n\nfrom django.contrib.auth.forms import SetPasswordForm\nfrom django.contrib.auth.mixins import LoginRequiredMixin\n\nfrom django.contrib.auth.models import User\nfrom apps.student.models import Student\n\nfrom .emailAuthBackend import EmailBackend\nfrom .models import TemporaryAccessRequest\nfrom .utils import user_creation, send_email_confirmation\n\n\nclass RegistrationView(FormView):\n    template_name = 'account/registration.html'\n    form_class = SignUpForm\n\n    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:\n        context = super().get_context_data(**kwargs)\n        context['temporary_registration'] = settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today()\n        return context\n\n    def form_valid(self, form):\n        user_creation(form, self.request)\n        return redirect(reverse('home:home'))\n\n\nclass TemporaryRegistrationView(FormView):\n    form_class = TemporaryRequestSignUpForm\n    template_name = 'account/temporary_registration.html'\n\n    def dispatch(self, request, *args: Any, **kwargs: Any):\n        \"\"\"Do not allow to use this view outside of allowed temporary accounts windows.\"\"\"\n        if not settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today():\n            return redirect(reverse('account:registration'))\n        return super().dispatch(request, *args, **kwargs)\n\n    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:\n        context = super().get_context_data(**kwargs)\n        context['DEADLINE_TEMPORARY_REGISTRATION'] = settings.TEMPORARY_ACCOUNTS_DATE_LIMIT\n        return context\n\n    def form_valid(self, form) -> HttpResponse:\n        user_creation(form, self.request)\n        return redirect(reverse('home:home'))\n\n\nclass ConfirmUser(View):\n    def get(self, request, uidb64, token):\n        tempAccessReq: Union[TemporaryAccessRequest, None] = None\n        try:\n            uid = force_text(urlsafe_base64_decode(uidb64))\n            user = User.objects.get(pk=uid)\n        except (TypeError, ValueError, OverflowError, User.DoesNotExist):\n            return render(self.request, 'account/activation_invalid.html')\n        # checking if the user is not a temporary one\n        try:\n            tempAccessReq: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(\n                user=user.pk)\n            if not tempAccessReq.approved:\n                return render(self.request, 'account/activation_invalid.html')\n        except TemporaryAccessRequest.DoesNotExist:\n            tempAccessReq = None\n        # checking if the token is valid.\n        if account_activation_token.check_token(user, token):\n            # if valid set active true\n            user.is_active = True\n            if tempAccessReq is not None:\n                user.email = tempAccessReq.final_email\n                tempAccessReq.delete()\n                messages.warning(\n                    request, f'Dor\u00e9navant vous devez utiliser {user.email} pour vous connecter.')\n            user.save()\n            login(self.request, user,\n                  backend='apps.account.emailAuthBackend.EmailBackend')\n            messages.success(request, 'Votre compte est desormais actif !')\n            return redirect(reverse('home:home'))\n        else:\n            return render(self.request, 'account/activation_invalid.html')\n\n\nclass AuthView(FormView):\n    template_name = 'account/login.html'\n    form_class = LoginForm\n\n    def get(self, request):\n        if request.user.is_authenticated:\n            user = request.user\n            message = f'Vous etes d\u00e9j\u00e0 connect\u00e9 en tant que {user.first_name.title()}.'\n            messages.warning(request, message)\n            return redirect(reverse('home:home'))\n        else:\n            return super(AuthView, AuthView).get(self, request)\n\n    def form_invalid(self, form):\n        message = f'Veuillez vous connecter avec votre adresse mail ECN.'\n        messages.warning(self.request, message)\n        return redirect(reverse('account:login'))\n\n    def form_valid(self, form):\n        username = form.cleaned_data['email']\n        password = form.cleaned_data['password']\n        user = EmailBackend.authenticate(username=username, password=password)\n        if user is not None:\n            if user.is_active:\n                message = f'Bonjour {user.first_name.title()} !'\n                messages.success(self.request, message)\n            else:\n                if settings.TEMPORARY_ACCOUNTS_DATE_LIMIT >= date.today():\n                    # During certain periods allow temporary accounts.\n                    try:\n                        temporaryAccessRequest: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(\n                            user=user\n                        )\n                        if not temporaryAccessRequest.mail_valid:\n                            message = 'Votre compte n\\'est pas encore actif.\\\n                            Veuillez cliquer sur le lien envoy\u00e9 par mail pour l\\'\\\n                                activer.'\n                            messages.error(self.request, message)\n                            return redirect(reverse('account:login'))\n                        if temporaryAccessRequest.approved_until <= date.today():\n                            message = 'Votre compte n\\'a pas encore \u00e9t\u00e9 approuv\u00e9.\\\n                                On vous pr\u00e9vient par mail d\u00e8s que c\\'est le cas.'\n                            messages.error(self.request, message)\n                            return redirect(reverse('account:login'))\n                        message = f'Votre compte n\\'est pas encore d\u00e9finitif.\\\n                            Veuillez le valider <a href=\"{reverse(\"account:upgrade-permanent\")}\">ici</a>.\\\n                            Attention apr\u00e8s le {temporaryAccessRequest.approved_until}\\\n                            vous ne pourrez plus vous connecter si vous n\\'avez pas renseign\u00e9 votre adresse Centrale.'\n                        messages.warning(self.request, message)\n                    except TemporaryAccessRequest.DoesNotExist:\n                        messages.error(\n                            self.request, 'Identifiant inconnu ou mot de passe invalide.')\n                        return redirect(reverse('account:login'))\n                else:\n                    messages.warning(\n                        self.request, 'Votre compte n\\'est pas encore actif. Veuillez cliquer sur le lien dans \\'email.')\n            login(self.request, user,\n                  backend='apps.account.emailAuthBackend.EmailBackend')\n            return redirect(reverse('home:home'))\n        else:\n            messages.error(\n                self.request, 'Identifiant inconnu ou mot de passe invalide.')\n            return redirect(reverse('account:login'))\n\n\nclass LogoutView(View):\n    def get(self, request):\n        logout(request)\n        messages.success(request, 'Vous avez \u00e9t\u00e9 d\u00e9connect\u00e9.')\n        return redirect(reverse('account:login'))\n\n\nclass ForgottenPassView(FormView):\n    form_class = ForgottenPassForm\n    template_name = 'account/forgotten_pass.html'\n\n    def form_valid(self, form):\n        try:\n            user = User.objects.get(email=form.cleaned_data['email'])\n            if user is not None:\n                subject = '[Nantral Platform] Reinitialisation de votre mot de passe'\n                current_site = get_current_site(self.request)\n                message = render_to_string('account/mail/password_request.html', {\n                    'user': user,\n                    'domain': current_site.domain,\n                    'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),\n                    # method will generate a hash value with user related data\n                    'token': account_activation_token.make_token(user),\n                })\n                user.email_user(\n                    subject, message, 'accounts@nantral-platform.fr', html_message=message)\n        except User.DoesNotExist:\n            pass\n        messages.success(\n            self.request, 'Un email de r\u00e9cuperation a \u00e9t\u00e9 envoy\u00e9 si cette adresse existe.')\n        return redirect(reverse('account:login'))\n\n\nclass PasswordResetConfirmCustomView(PasswordResetConfirmView):\n    template_name = 'account/reset_password.html'\n    post_reset_login = True\n    post_reset_login_backend = 'apps.account.emailAuthBackend.EmailBackend'\n    form_class = SetPasswordForm\n    token_generator = account_activation_token\n    success_url = reverse_lazy('home:home')\n\n\ndef redirect_to_student(request, user_id):\n    user = User.objects.get(id=user_id)\n    student = Student.objects.get(user=user)\n    return redirect('student:update', student.pk)\n\n\nclass ABCApprovalTemporaryResgistrationView(UserIsSuperAdmin, View):\n    def get(self, request, id):\n        self.temp_req: TemporaryAccessRequest = get_object_or_404(\n            TemporaryAccessRequest, id=id)\n\n        if self.temp_req.approved:\n            messages.warning(request, f'Cette requ\u00eate a d\u00e9j\u00e0 \u00e9t\u00e9 approuv\u00e9e.')\n            return redirect(reverse('home:home'))\n\n\nclass ApproveTemporaryRegistrationView(ABCApprovalTemporaryResgistrationView):\n    def get(self, request, id):\n        super().get(request, id)\n        self.temp_req.approve()\n        messages.success(\n            request, f'Vous avez accept\u00e9 la demande de {self.temp_req.user.first_name} {self.temp_req.user.last_name}')\n        return redirect(reverse('home:home'))\n\n\nclass DenyTemporaryRegistrationView(ABCApprovalTemporaryResgistrationView):\n    def get(self, request, id):\n        super().get(request, id)\n        messages.success(\n            request, f'Vous avez refus\u00e9 la demande de {self.temp_req.user.first_name} {self.temp_req.user.last_name}')\n        self.temp_req.deny()\n        return redirect(reverse('home:home'))\n\n\nclass ConfirmUserTemporary(View):\n    def get(self, request, uidb64, token):\n        try:\n            uid = force_text(urlsafe_base64_decode(uidb64))\n            user = User.objects.get(pk=uid)\n        except (TypeError, ValueError, OverflowError, User.DoesNotExist):\n            user = None\n        # checking if the user exists, if the token is valid.\n        if user is not None and account_activation_token.check_token(user, token):\n            try:\n                temp_req: TemporaryAccessRequest = TemporaryAccessRequest.objects.get(\n                    user=user)\n                temp_req.mail_valid = True\n                temp_req.save()\n            except TemporaryAccessRequest.DoesNotExist:\n                return render(self.request, 'account/activation_invalid.html')\n            messages.success(request, 'Votre addresse mail est confirm\u00e9! \\n\\\n            Comme vous n\\'avez pas utilis\u00e9 votre adresse Centrale, vous devez encore attendre qu\\'un administrateur v\u00e9rifie votre inscription.\\n\\\n            On vous pr\u00e9vient par mail d\u00e8s que c\\'est bon!. ')\n            return redirect(reverse('home:home'))\n        else:\n            return render(self.request, 'account/activation_invalid.html')\n\n\nclass PermanentAccountUpgradeView(LoginRequiredMixin, FormView):\n    form_class = UpgradePermanentAccountForm\n    template_name = 'account/permanent_account_upgrade.html'\n    success_url = reverse_lazy('home:home')\n\n    def get(self, request):\n        get_object_or_404(\n            TemporaryAccessRequest,\n            user=self.request.user\n        )\n        return super().get(request)\n\n    def form_valid(self, form: UpgradePermanentAccountForm) -> HttpResponse:\n        temp_request = get_object_or_404(\n            TemporaryAccessRequest,\n            user=self.request.user\n        )\n        temp_request.final_email = form.cleaned_data['email']\n        temp_request.save()\n        send_email_confirmation(\n            self.request.user, self.request, send_to=form.cleaned_data['email'])\n        return super().form_valid(form)\n", "path": "server/apps/account/views.py"}]}