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