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