updates for onelab portal demo
[myslice.git] / portal / views.py
1 # -*- coding: utf-8 -*-
2 #
3 # portal/views.py: views for the portal application
4 # This file is part of the Manifold project.
5 #
6 # Authors:
7 #   Jordan Augé <jordan.auge@lip6.fr>
8 # Copyright 2013, UPMC Sorbonne Universités / LIP6
9 #
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.
13
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
17 # details.
18
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.
22
23 from django.conf                 import settings
24 from django.contrib.sites.models import Site, RequestSite
25 from django.contrib              import messages
26 from django.views.generic        import View
27 from django.views.generic.base   import TemplateView
28 from django.shortcuts            import render
29 from plugins.lists.simplelist    import SimpleList
30 from portal                      import signals
31 from portal.forms                import UserRegisterForm, SliceRequestForm
32 from portal.util                 import RegistrationView, ActivationView
33 from portal.models               import PendingUser, PendingSlice
34 from manifold.core.query         import Query
35 from unfold.page                 import Page
36 from myslice.viewutils           import topmenu_items, the_user
37
38 class DashboardView(TemplateView):
39     template_name = "dashboard.html"
40
41     def get_context_data(self, **kwargs):
42         user_hrn = 'ple.upmc.jordan_auge'
43
44         #messages.info(self.request, 'You have logged in')
45         page = Page(self.request)
46
47         # Slow...
48         #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
49         slice_query = Query().get('user').filter_by('user_hrn', '==', user_hrn).select('user_hrn', 'slice.slice_hrn')
50         auth_query  = Query().get('network').select('network_hrn')
51         page.enqueue_query(slice_query)
52         page.enqueue_query(auth_query)
53
54         page.expose_queries()
55
56         slicelist = SimpleList(
57             title = None,
58             page  = page,
59             key   = 'slice.slice_hrn',
60             query = slice_query,
61         )
62          
63         authlist = SimpleList(
64             title = None,
65             page  = page,
66             key   = 'network_hrn',
67             query = auth_query,
68         )
69
70         context = super(DashboardView, self).get_context_data(**kwargs)
71         context['person']   = self.request.user
72         context['networks'] = authlist.render(self.request) 
73         context['slices']   = slicelist.render(self.request)
74
75         # XXX This is repeated in all pages
76         # more general variables expected in the template
77         context['title'] = 'Test view that combines various plugins'
78         # the menu items on the top
79         context['topmenu_items'] = topmenu_items('Dashboard', self.request) 
80         # so we can sho who is logged
81         context['username'] = the_user(self.request) 
82
83         context.update(page.prelude_env())
84
85         return context
86
87 class UserRegisterView(RegistrationView):
88     """
89     A registration backend which follows a simple workflow:
90
91     1. User signs up, inactive account is created.
92
93     2. Email is sent to user with activation link.
94
95     3. User clicks activation link, account is now active.
96
97     Using this backend requires that
98
99     * ``registration`` be listed in the ``INSTALLED_APPS`` setting
100       (since this backend makes use of models defined in this
101       application).
102
103     * The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying
104       (as an integer) the number of days from registration during
105       which a user may activate their account (after that period
106       expires, activation will be disallowed).
107
108     * The creation of the templates
109       ``registration/activation_email_subject.txt`` and
110       ``registration/activation_email.txt``, which will be used for
111       the activation email. See the notes for this backends
112       ``register`` method for details regarding these templates.
113
114     Additionally, registration can be temporarily closed by adding the
115     setting ``REGISTRATION_OPEN`` and setting it to
116     ``False``. Omitting this setting, or setting it to ``True``, will
117     be interpreted as meaning that registration is currently open and
118     permitted.
119
120     Internally, this is accomplished via storing an activation key in
121     an instance of ``registration.models.RegistrationProfile``. See
122     that model and its custom manager for full documentation of its
123     fields and supported operations.
124     
125     """
126     form_class = UserRegisterForm
127     
128     def register(self, request, **cleaned_data):
129         """
130         Given a username, email address and password, register a new
131         user account, which will initially be inactive.
132
133         Along with the new ``User`` object, a new
134         ``registration.models.RegistrationProfile`` will be created,
135         tied to that ``User``, containing the activation key which
136         will be used for this account.
137
138         An email will be sent to the supplied email address; this
139         email should contain an activation link. The email will be
140         rendered using two templates. See the documentation for
141         ``RegistrationProfile.send_activation_email()`` for
142         information about these templates and the contexts provided to
143         them.
144
145         After the ``User`` and ``RegistrationProfile`` are created and
146         the activation email is sent, the signal
147         ``registration.signals.user_registered`` will be sent, with
148         the new ``User`` as the keyword argument ``user`` and the
149         class of this backend as the sender.
150
151         """
152         first_name = cleaned_data['first_name']
153         last_name  = cleaned_data['last_name']
154         email      = cleaned_data['email']
155         password   = cleaned_data['password1']
156         #password2  = cleaned_data['password2']
157         keypair    = cleaned_data['keypair']
158
159         #if Site._meta.installed:
160         #    site = Site.objects.get_current()
161         #else:
162         #    site = RequestSite(request) 
163         site = None
164
165         new_user = PendingUser.objects.create_inactive_user(first_name, last_name, email, password, site)
166         signals.user_registered.send(sender=self.__class__,
167                                      user=new_user,
168                                      request=request)
169         return new_user
170
171     def registration_allowed(self, request):
172         """
173         Indicate whether account registration is currently permitted,
174         based on the value of the setting ``REGISTRATION_OPEN``. This
175         is determined as follows:
176
177         * If ``REGISTRATION_OPEN`` is not specified in settings, or is
178           set to ``True``, registration is permitted.
179
180         * If ``REGISTRATION_OPEN`` is both specified and set to
181           ``False``, registration is not permitted.
182         
183         """
184         return getattr(settings, 'REGISTRATION_OPEN', True)
185
186     def get_success_url(self, request, user):
187         """
188         Return the name of the URL to redirect to after successful
189         user registration.
190         
191         """
192         return ('user_register_complete', (), {})
193
194
195 class UserValidateView(ActivationView):
196     def activate(self, request, activation_key):
197         """
198         Given an an activation key, look up and activate the user
199         account corresponding to that key (if possible).
200
201         After successful activation, the signal
202         ``registration.signals.user_activated`` will be sent, with the
203         newly activated ``User`` as the keyword argument ``user`` and
204         the class of this backend as the sender.
205         
206         """
207         activated_user = RegistrationProfile.objects.activate_user(activation_key)
208         if activated_user:
209             signals.user_activated.send(sender=self.__class__,
210                                         user=activated_user,
211                                         request=request)
212         return activated_user
213
214     def get_success_url(self, request, user):
215         return ('registration_activation_complete', (), {})
216
217
218 # DEPRECATED #from portal.portalpage  import PortalPage
219 # DEPRECATED #from plugins.wizard     import Wizard
220 # DEPRECATED #from plugins.form       import CreateForm
221 # DEPRECATED #from plugins.raw.raw    import Raw          # XXX
222 # DEPRECATED #
223 # DEPRECATED #from myslice.viewutils  import the_user
224 # DEPRECATED #
225 # DEPRECATED #from django.template.loader import render_to_string
226 # DEPRECATED #from django.template import RequestContext
227 # DEPRECATED #from django.views import generic
228 # DEPRECATED #
229 # DEPRECATED #from django.contrib.formtools.wizard.views import NamedUrlSessionWizardView
230 # DEPRECATED ##from django.core.files.storage import FileSystemStorage
231 # DEPRECATED #from django.core.files.storage import default_storage
232 # DEPRECATED #
233 # DEPRECATED ##class MerlinWizard(NamedUrlSessionWizardView):
234 # DEPRECATED ##
235 # DEPRECATED ##    ...
236 # DEPRECATED ##    ...
237 # DEPRECATED ##
238 # DEPRECATED ##    @classonlymethod
239 # DEPRECATED ##    def as_view(cls, *args, **kwargs):
240 # DEPRECATED ##        kwargs.update({
241 # DEPRECATED ##            'form_list': [
242 # DEPRECATED ##                NameForm,
243 # DEPRECATED ##                QuestForm,
244 # DEPRECATED ##                ColorForm,
245 # DEPRECATED ##            ],
246 # DEPRECATED ##            'url_name': 'merlin_wizard'
247 # DEPRECATED ##        })
248 # DEPRECATED ##        return super(MerlinWizard, cls).as_view(*args, **kwargs)
249 # DEPRECATED #
250 # DEPRECATED #class UserRegisterWizardView(NamedUrlSessionWizardView):
251 # DEPRECATED ##class UserRegisterWizardView(LoginRequiredMixin, NamedUrlSessionWizardView):
252 # DEPRECATED #    # Notice that I specify a file storage instance. If you don't specify this,
253 # DEPRECATED #    # and you need to support FileField or ImageField in your forms, you'll get
254 # DEPRECATED #    # errors from Django. This is something else I think could be handled by
255 # DEPRECATED #    # the views better. Seems to me that it should just use whatever the
256 # DEPRECATED #    # default/specified storage is for the rest of your project/application.
257 # DEPRECATED #    file_storage = default_storage # FileSystemStorage()
258 # DEPRECATED #    template_name = "register_user_wizard.html"
259 # DEPRECATED #
260 # DEPRECATED #    def done(self, form_list, **kwargs):
261 # DEPRECATED #        step1_form = form_list[0]
262 # DEPRECATED #        step2_form = form_list[1]
263 # DEPRECATED #
264 # DEPRECATED #        productext = self.create_product(product_form)
265 # DEPRECATED #        shippings = self.create_shippings(productext, shipping_forms)
266 # DEPRECATED #        images = self.create_images(productext, image_forms)
267 # DEPRECATED #
268 # DEPRECATED #        if all([productext, shippings, images]):
269 # DEPRECATED #            del self.request.session["wizard_product_wizard_view"]
270 # DEPRECATED #
271 # DEPRECATED #            messages.success(self.request,
272 # DEPRECATED #                _("Your product has been created."))
273 # DEPRECATED #            return HttpResponseRedirect(self.get_success_url(productext))
274 # DEPRECATED #
275 # DEPRECATED #        messages.error(self.request, _("Something went wrong creating your "
276 # DEPRECATED #            "product. Please try again or contact support."))
277 # DEPRECATED #        return HttpResponseRedirect(reverse("register_wizard"))
278 # DEPRECATED #
279 # DEPRECATED #    #def get_form_kwargs(self, step):
280 # DEPRECATED #    #    if step == "product":
281 # DEPRECATED #    #        return {"user": self.request.user}
282 # DEPRECATED #    #    return {}
283 # DEPRECATED #
284 # DEPRECATED ## The portal should hook the slice and user creation pages
285 # DEPRECATED #
286 # DEPRECATED #def register_user(request):
287 # DEPRECATED #    
288 # DEPRECATED #    if request.method == 'POST':
289 # DEPRECATED #        form = UserRegisterForm(request.POST) # Nous reprenons les données
290 # DEPRECATED #        if form.is_valid():
291 # DEPRECATED #            first_name = form.cleaned_data['first_name']
292 # DEPRECATED #            last_name  = form.cleaned_data['last_name']
293 # DEPRECATED #            email      = form.cleaned_data['email']
294 # DEPRECATED #            password   = form.cleaned_data['password']
295 # DEPRECATED #            password2  = form.cleaned_data['password2']
296 # DEPRECATED #            keypair    = form.cleaned_data['keypair']
297 # DEPRECATED #            ## Ici nous pouvons traiter les données du formulaire
298 # DEPRECATED #            #sujet = form.cleaned_data['sujet']
299 # DEPRECATED #            #message = form.cleaned_data['message']
300 # DEPRECATED #            #envoyeur = form.cleaned_data['envoyeur']
301 # DEPRECATED #            #renvoi = form.cleaned_data['renvoi']
302 # DEPRECATED #            ## Nous pourrions ici envoyer l'e-mail grâce aux données que nous venons de récupérer
303 # DEPRECATED #            #envoi = True
304 # DEPRECATED #    else:
305 # DEPRECATED #        form = UserRegisterForm()
306 # DEPRECATED #    return render(request, 'register_user.html', locals())
307 # DEPRECATED #
308 # DEPRECATED #def index(request):
309 # DEPRECATED #
310 # DEPRECATED #    WIZARD_TITLE = 'User registration'
311 # DEPRECATED #    STEP1_TITLE  = 'Enter your details'
312 # DEPRECATED #    STEP2_TITLE  = 'Select your institution'
313 # DEPRECATED #    STEP3_TITLE  = 'Authentication'
314 # DEPRECATED #    STEP4_TITLE  = 'Request a slice (optional)'
315 # DEPRECATED #    STEP5_TITLE  = 'Waiting for validation'
316 # DEPRECATED #    STEP6_TITLE  = 'Account validated'
317 # DEPRECATED #
318 # DEPRECATED #    STEP0 = render_to_string('account_validated.html', context_instance=RequestContext(request))
319 # DEPRECATED #    STEP2_HTML   = """
320 # DEPRECATED #    coucou
321 # DEPRECATED #    """
322 # DEPRECATED #    STEP4 = """
323 # DEPRECATED #    mede
324 # DEPRECATED #    """
325 # DEPRECATED #    STEP5 = render_to_string('account_validated.html', context_instance=RequestContext(request))
326 # DEPRECATED #
327 # DEPRECATED #    p = PortalPage(request)
328 # DEPRECATED #
329 # DEPRECATED #    # This is redundant with the Wizard title
330 # DEPRECATED #    p << "<h3>User registration</h3>"
331 # DEPRECATED #
332 # DEPRECATED #    sons = []
333 # DEPRECATED #    start_step = 1
334 # DEPRECATED #
335 # DEPRECATED #    # STEP 1
336 # DEPRECATED #    # If the user already exists (is logged), let's display a summary of his account details
337 # DEPRECATED #    # Otherwise propose a form to fill in
338 # DEPRECATED #    if the_user(request):
339 # DEPRECATED #        # Fill a disabled form with user info
340 # DEPRECATED #        # Please logout to register another user
341 # DEPRECATED #        sons.append(Raw(page=p, title=STEP1_TITLE, togglable=False, html=STEP0))
342 # DEPRECATED #        start_step += 1
343 # DEPRECATED #    else:
344 # DEPRECATED #        # We could pass a list of fields also, instead of retrieving them from metadata
345 # DEPRECATED #        # Otherwise we need some heuristics to display nice forms
346 # DEPRECATED #        # XXX Could we log the user in after the form is validated ?
347 # DEPRECATED #        # XXX Explain the password is for XXX
348 # DEPRECATED #        field_list = [{
349 # DEPRECATED #            'name'        : 'First name',
350 # DEPRECATED #            'field'       : 'firstname',
351 # DEPRECATED #            'type'        : 'text',
352 # DEPRECATED #            'validate_rx' : '^[a-zA-Z -]+$',
353 # DEPRECATED #            'validate_err': 'Your first name must be comprised of letters only',
354 # DEPRECATED #            'description' : 'Enter your first name',
355 # DEPRECATED #        }, {
356 # DEPRECATED #            'name'        : 'Last name',
357 # DEPRECATED #            'field'       : 'lastname',
358 # DEPRECATED #            'type'        : 'text',
359 # DEPRECATED #            'validate_rx' : '^[a-zA-Z -]+$',
360 # DEPRECATED #            'validate_err': 'Your last name must be comprised of letters only',
361 # DEPRECATED #            'description' : 'Enter your last name',
362 # DEPRECATED #        }, { 
363 # DEPRECATED #            'name'        : 'Email',
364 # DEPRECATED #            'field'       : 'email',
365 # DEPRECATED #            'type'        : 'text',
366 # DEPRECATED #            'description' : 'Enter your email address',
367 # DEPRECATED #        }, {
368 # DEPRECATED #            'name'        : 'Password',
369 # DEPRECATED #            'field'       : 'password',
370 # DEPRECATED #            'type'        : 'password',
371 # DEPRECATED #            'description' : 'Enter your password',
372 # DEPRECATED #        }, {
373 # DEPRECATED #            'name'        : 'Confirm password',
374 # DEPRECATED #            'field'       : 'password2',
375 # DEPRECATED #            'type'        : 'password',
376 # DEPRECATED #            'description' : 'Enter your password again',
377 # DEPRECATED #        }]
378 # DEPRECATED #        sons.append(CreateForm(page = p, title = STEP1_TITLE, togglable = False, object = 'local:user', fields = field_list))
379 # DEPRECATED #
380 # DEPRECATED #    # STEP 2
381 # DEPRECATED #    # If the user already exists (is logged), let's display a summary of its institution
382 # DEPRECATED #    # Otherwise propose a form to fill in (we should base our selection on the email)
383 # DEPRECATED #    if the_user(request):
384 # DEPRECATED #        # Fill a disabled form with institution
385 # DEPRECATED #        # Please logout to register another user
386 # DEPRECATED #        sons.append(Raw(page=p, title=STEP2_TITLE, togglable=False, html="User created"))
387 # DEPRECATED #        start_step += 1
388 # DEPRECATED #    else:
389 # DEPRECATED #        sons.append(CreateForm(page = p, title = STEP2_TITLE, togglable = False, object = 'slice')) #institution'))
390 # DEPRECATED #
391 # DEPRECATED #    # STEP3
392 # DEPRECATED #    # Please should your prefered authentication method
393 # DEPRECATED #    # This step should allow the user to either choose the user or managed mode in MySlice
394 # DEPRECATED #    sons.append(Raw(page = p, title = STEP3_TITLE, togglable = False, html = STEP2_HTML))
395 # DEPRECATED #
396 # DEPRECATED #    # Step 4: Request a slice (optional)
397 # DEPRECATED #    sons.append(CreateForm(page = p, title = STEP4_TITLE, togglable = False, object = 'slice'))
398 # DEPRECATED #
399 # DEPRECATED #    # Step 5: Your request is waiting for validation
400 # DEPRECATED #    # Periodic refresh
401 # DEPRECATED #    sons.append(Raw(page = p, title = STEP5_TITLE, togglable = False, html = STEP4))
402 # DEPRECATED #
403 # DEPRECATED #    # Step 6: Account validation  = welcome for newly validated users
404 # DEPRECATED #    # . delegation
405 # DEPRECATED #    # . platforms
406 # DEPRECATED #    # . slice
407 # DEPRECATED #    # . pointers
408 # DEPRECATED #    sons.append(Raw(page = p, title = STEP6_TITLE, togglable = False, html = STEP5))
409 # DEPRECATED #
410 # DEPRECATED #    wizard = Wizard(
411 # DEPRECATED #        page       = p,
412 # DEPRECATED #        title      = WIZARD_TITLE,
413 # DEPRECATED #        togglable  = False,
414 # DEPRECATED #        sons       = sons,
415 # DEPRECATED #        start_step = start_step,
416 # DEPRECATED #    )
417 # DEPRECATED #
418 # DEPRECATED #    p << wizard.render(request) # in portal page if possible
419 # DEPRECATED #
420 # DEPRECATED #    return p.render()