1 # -*- coding: utf-8 -*-
3 # portal/views.py: views for the portal application
4 # This file is part of the Manifold project.
7 # Jordan Augé <jordan.auge@lip6.fr>
8 # Copyright 2013, UPMC Sorbonne Universités / LIP6
10 # This program is free software; you can redistribute it and/or modify it under
11 # the terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 3, or (at your option) any later version.
14 # This program is distributed in the hope that it will be useful, but WITHOUT
15 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 # You should have received a copy of the GNU General Public License along with
20 # this program; see the file COPYING. If not, write to the Free Software
21 # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 from django.conf import settings
24 from django.contrib.sites.models import RequestSite
25 from django.contrib.sites.models import Site
27 from django.shortcuts import render
28 from portal.forms import UserRegisterForm, SliceRequestForm
29 from portal.util import RegistrationView, ActivationView
30 from portal.models import PendingUser, PendingSlice
31 from portal import signals
33 class UserRegisterView(RegistrationView):
35 A registration backend which follows a simple workflow:
37 1. User signs up, inactive account is created.
39 2. Email is sent to user with activation link.
41 3. User clicks activation link, account is now active.
43 Using this backend requires that
45 * ``registration`` be listed in the ``INSTALLED_APPS`` setting
46 (since this backend makes use of models defined in this
49 * The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying
50 (as an integer) the number of days from registration during
51 which a user may activate their account (after that period
52 expires, activation will be disallowed).
54 * The creation of the templates
55 ``registration/activation_email_subject.txt`` and
56 ``registration/activation_email.txt``, which will be used for
57 the activation email. See the notes for this backends
58 ``register`` method for details regarding these templates.
60 Additionally, registration can be temporarily closed by adding the
61 setting ``REGISTRATION_OPEN`` and setting it to
62 ``False``. Omitting this setting, or setting it to ``True``, will
63 be interpreted as meaning that registration is currently open and
66 Internally, this is accomplished via storing an activation key in
67 an instance of ``registration.models.RegistrationProfile``. See
68 that model and its custom manager for full documentation of its
69 fields and supported operations.
72 form_class = UserRegisterForm
74 def register(self, request, **cleaned_data):
76 Given a username, email address and password, register a new
77 user account, which will initially be inactive.
79 Along with the new ``User`` object, a new
80 ``registration.models.RegistrationProfile`` will be created,
81 tied to that ``User``, containing the activation key which
82 will be used for this account.
84 An email will be sent to the supplied email address; this
85 email should contain an activation link. The email will be
86 rendered using two templates. See the documentation for
87 ``RegistrationProfile.send_activation_email()`` for
88 information about these templates and the contexts provided to
91 After the ``User`` and ``RegistrationProfile`` are created and
92 the activation email is sent, the signal
93 ``registration.signals.user_registered`` will be sent, with
94 the new ``User`` as the keyword argument ``user`` and the
95 class of this backend as the sender.
98 first_name = cleaned_data['first_name']
99 last_name = cleaned_data['last_name']
100 email = cleaned_data['email']
101 password = cleaned_data['password1']
102 #password2 = cleaned_data['password2']
103 keypair = cleaned_data['keypair']
105 #if Site._meta.installed:
106 # site = Site.objects.get_current()
108 # site = RequestSite(request)
111 new_user = PendingUser.objects.create_inactive_user(first_name, last_name, email, password, site)
112 signals.user_registered.send(sender=self.__class__,
117 def registration_allowed(self, request):
119 Indicate whether account registration is currently permitted,
120 based on the value of the setting ``REGISTRATION_OPEN``. This
121 is determined as follows:
123 * If ``REGISTRATION_OPEN`` is not specified in settings, or is
124 set to ``True``, registration is permitted.
126 * If ``REGISTRATION_OPEN`` is both specified and set to
127 ``False``, registration is not permitted.
130 return getattr(settings, 'REGISTRATION_OPEN', True)
132 def get_success_url(self, request, user):
134 Return the name of the URL to redirect to after successful
138 return ('user_register_complete', (), {})
141 class UserValidateView(ActivationView):
142 def activate(self, request, activation_key):
144 Given an an activation key, look up and activate the user
145 account corresponding to that key (if possible).
147 After successful activation, the signal
148 ``registration.signals.user_activated`` will be sent, with the
149 newly activated ``User`` as the keyword argument ``user`` and
150 the class of this backend as the sender.
153 activated_user = RegistrationProfile.objects.activate_user(activation_key)
155 signals.user_activated.send(sender=self.__class__,
158 return activated_user
160 def get_success_url(self, request, user):
161 return ('registration_activation_complete', (), {})
164 # DEPRECATED #from portal.portalpage import PortalPage
165 # DEPRECATED #from plugins.wizard import Wizard
166 # DEPRECATED #from plugins.form import CreateForm
167 # DEPRECATED #from plugins.raw.raw import Raw # XXX
169 # DEPRECATED #from myslice.viewutils import the_user
171 # DEPRECATED #from django.template.loader import render_to_string
172 # DEPRECATED #from django.template import RequestContext
173 # DEPRECATED #from django.views import generic
175 # DEPRECATED #from django.contrib.formtools.wizard.views import NamedUrlSessionWizardView
176 # DEPRECATED ##from django.core.files.storage import FileSystemStorage
177 # DEPRECATED #from django.core.files.storage import default_storage
179 # DEPRECATED ##class MerlinWizard(NamedUrlSessionWizardView):
184 # DEPRECATED ## @classonlymethod
185 # DEPRECATED ## def as_view(cls, *args, **kwargs):
186 # DEPRECATED ## kwargs.update({
187 # DEPRECATED ## 'form_list': [
188 # DEPRECATED ## NameForm,
189 # DEPRECATED ## QuestForm,
190 # DEPRECATED ## ColorForm,
192 # DEPRECATED ## 'url_name': 'merlin_wizard'
194 # DEPRECATED ## return super(MerlinWizard, cls).as_view(*args, **kwargs)
196 # DEPRECATED #class UserRegisterWizardView(NamedUrlSessionWizardView):
197 # DEPRECATED ##class UserRegisterWizardView(LoginRequiredMixin, NamedUrlSessionWizardView):
198 # DEPRECATED # # Notice that I specify a file storage instance. If you don't specify this,
199 # DEPRECATED # # and you need to support FileField or ImageField in your forms, you'll get
200 # DEPRECATED # # errors from Django. This is something else I think could be handled by
201 # DEPRECATED # # the views better. Seems to me that it should just use whatever the
202 # DEPRECATED # # default/specified storage is for the rest of your project/application.
203 # DEPRECATED # file_storage = default_storage # FileSystemStorage()
204 # DEPRECATED # template_name = "register_user_wizard.html"
206 # DEPRECATED # def done(self, form_list, **kwargs):
207 # DEPRECATED # step1_form = form_list[0]
208 # DEPRECATED # step2_form = form_list[1]
210 # DEPRECATED # productext = self.create_product(product_form)
211 # DEPRECATED # shippings = self.create_shippings(productext, shipping_forms)
212 # DEPRECATED # images = self.create_images(productext, image_forms)
214 # DEPRECATED # if all([productext, shippings, images]):
215 # DEPRECATED # del self.request.session["wizard_product_wizard_view"]
217 # DEPRECATED # messages.success(self.request,
218 # DEPRECATED # _("Your product has been created."))
219 # DEPRECATED # return HttpResponseRedirect(self.get_success_url(productext))
221 # DEPRECATED # messages.error(self.request, _("Something went wrong creating your "
222 # DEPRECATED # "product. Please try again or contact support."))
223 # DEPRECATED # return HttpResponseRedirect(reverse("register_wizard"))
225 # DEPRECATED # #def get_form_kwargs(self, step):
226 # DEPRECATED # # if step == "product":
227 # DEPRECATED # # return {"user": self.request.user}
228 # DEPRECATED # # return {}
230 # DEPRECATED ## The portal should hook the slice and user creation pages
232 # DEPRECATED #def register_user(request):
234 # DEPRECATED # if request.method == 'POST':
235 # DEPRECATED # form = UserRegisterForm(request.POST) # Nous reprenons les données
236 # DEPRECATED # if form.is_valid():
237 # DEPRECATED # first_name = form.cleaned_data['first_name']
238 # DEPRECATED # last_name = form.cleaned_data['last_name']
239 # DEPRECATED # email = form.cleaned_data['email']
240 # DEPRECATED # password = form.cleaned_data['password']
241 # DEPRECATED # password2 = form.cleaned_data['password2']
242 # DEPRECATED # keypair = form.cleaned_data['keypair']
243 # DEPRECATED # ## Ici nous pouvons traiter les données du formulaire
244 # DEPRECATED # #sujet = form.cleaned_data['sujet']
245 # DEPRECATED # #message = form.cleaned_data['message']
246 # DEPRECATED # #envoyeur = form.cleaned_data['envoyeur']
247 # DEPRECATED # #renvoi = form.cleaned_data['renvoi']
248 # DEPRECATED # ## Nous pourrions ici envoyer l'e-mail grâce aux données que nous venons de récupérer
249 # DEPRECATED # #envoi = True
251 # DEPRECATED # form = UserRegisterForm()
252 # DEPRECATED # return render(request, 'register_user.html', locals())
254 # DEPRECATED #def index(request):
256 # DEPRECATED # WIZARD_TITLE = 'User registration'
257 # DEPRECATED # STEP1_TITLE = 'Enter your details'
258 # DEPRECATED # STEP2_TITLE = 'Select your institution'
259 # DEPRECATED # STEP3_TITLE = 'Authentication'
260 # DEPRECATED # STEP4_TITLE = 'Request a slice (optional)'
261 # DEPRECATED # STEP5_TITLE = 'Waiting for validation'
262 # DEPRECATED # STEP6_TITLE = 'Account validated'
264 # DEPRECATED # STEP0 = render_to_string('account_validated.html', context_instance=RequestContext(request))
265 # DEPRECATED # STEP2_HTML = """
266 # DEPRECATED # coucou
268 # DEPRECATED # STEP4 = """
271 # DEPRECATED # STEP5 = render_to_string('account_validated.html', context_instance=RequestContext(request))
273 # DEPRECATED # p = PortalPage(request)
275 # DEPRECATED # # This is redundant with the Wizard title
276 # DEPRECATED # p << "<h3>User registration</h3>"
278 # DEPRECATED # sons = []
279 # DEPRECATED # start_step = 1
281 # DEPRECATED # # STEP 1
282 # DEPRECATED # # If the user already exists (is logged), let's display a summary of his account details
283 # DEPRECATED # # Otherwise propose a form to fill in
284 # DEPRECATED # if the_user(request):
285 # DEPRECATED # # Fill a disabled form with user info
286 # DEPRECATED # # Please logout to register another user
287 # DEPRECATED # sons.append(Raw(page=p, title=STEP1_TITLE, togglable=False, html=STEP0))
288 # DEPRECATED # start_step += 1
290 # DEPRECATED # # We could pass a list of fields also, instead of retrieving them from metadata
291 # DEPRECATED # # Otherwise we need some heuristics to display nice forms
292 # DEPRECATED # # XXX Could we log the user in after the form is validated ?
293 # DEPRECATED # # XXX Explain the password is for XXX
294 # DEPRECATED # field_list = [{
295 # DEPRECATED # 'name' : 'First name',
296 # DEPRECATED # 'field' : 'firstname',
297 # DEPRECATED # 'type' : 'text',
298 # DEPRECATED # 'validate_rx' : '^[a-zA-Z -]+$',
299 # DEPRECATED # 'validate_err': 'Your first name must be comprised of letters only',
300 # DEPRECATED # 'description' : 'Enter your first name',
302 # DEPRECATED # 'name' : 'Last name',
303 # DEPRECATED # 'field' : 'lastname',
304 # DEPRECATED # 'type' : 'text',
305 # DEPRECATED # 'validate_rx' : '^[a-zA-Z -]+$',
306 # DEPRECATED # 'validate_err': 'Your last name must be comprised of letters only',
307 # DEPRECATED # 'description' : 'Enter your last name',
309 # DEPRECATED # 'name' : 'Email',
310 # DEPRECATED # 'field' : 'email',
311 # DEPRECATED # 'type' : 'text',
312 # DEPRECATED # 'description' : 'Enter your email address',
314 # DEPRECATED # 'name' : 'Password',
315 # DEPRECATED # 'field' : 'password',
316 # DEPRECATED # 'type' : 'password',
317 # DEPRECATED # 'description' : 'Enter your password',
319 # DEPRECATED # 'name' : 'Confirm password',
320 # DEPRECATED # 'field' : 'password2',
321 # DEPRECATED # 'type' : 'password',
322 # DEPRECATED # 'description' : 'Enter your password again',
324 # DEPRECATED # sons.append(CreateForm(page = p, title = STEP1_TITLE, togglable = False, object = 'local:user', fields = field_list))
326 # DEPRECATED # # STEP 2
327 # DEPRECATED # # If the user already exists (is logged), let's display a summary of its institution
328 # DEPRECATED # # Otherwise propose a form to fill in (we should base our selection on the email)
329 # DEPRECATED # if the_user(request):
330 # DEPRECATED # # Fill a disabled form with institution
331 # DEPRECATED # # Please logout to register another user
332 # DEPRECATED # sons.append(Raw(page=p, title=STEP2_TITLE, togglable=False, html="User created"))
333 # DEPRECATED # start_step += 1
335 # DEPRECATED # sons.append(CreateForm(page = p, title = STEP2_TITLE, togglable = False, object = 'slice')) #institution'))
337 # DEPRECATED # # STEP3
338 # DEPRECATED # # Please should your prefered authentication method
339 # DEPRECATED # # This step should allow the user to either choose the user or managed mode in MySlice
340 # DEPRECATED # sons.append(Raw(page = p, title = STEP3_TITLE, togglable = False, html = STEP2_HTML))
342 # DEPRECATED # # Step 4: Request a slice (optional)
343 # DEPRECATED # sons.append(CreateForm(page = p, title = STEP4_TITLE, togglable = False, object = 'slice'))
345 # DEPRECATED # # Step 5: Your request is waiting for validation
346 # DEPRECATED # # Periodic refresh
347 # DEPRECATED # sons.append(Raw(page = p, title = STEP5_TITLE, togglable = False, html = STEP4))
349 # DEPRECATED # # Step 6: Account validation = welcome for newly validated users
350 # DEPRECATED # # . delegation
351 # DEPRECATED # # . platforms
352 # DEPRECATED # # . slice
353 # DEPRECATED # # . pointers
354 # DEPRECATED # sons.append(Raw(page = p, title = STEP6_TITLE, togglable = False, html = STEP5))
356 # DEPRECATED # wizard = Wizard(
357 # DEPRECATED # page = p,
358 # DEPRECATED # title = WIZARD_TITLE,
359 # DEPRECATED # togglable = False,
360 # DEPRECATED # sons = sons,
361 # DEPRECATED # start_step = start_step,
364 # DEPRECATED # p << wizard.render(request) # in portal page if possible
366 # DEPRECATED # return p.render()