added a view for each platform, to be improved using different plugins... example...
[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
31 from plugins.lists.simplelist    import SimpleList
32 from plugins.hazelnut            import Hazelnut
33 from plugins.pres_view           import PresView
34 from portal.event import Event
35 import json
36
37 from portal                      import signals
38 from portal.forms                import SliceRequestForm, ContactForm
39 from portal.util                 import RegistrationView, ActivationView
40 from portal.models               import PendingUser, PendingSlice
41 from manifold.core.query         import Query
42 from unfold.page                 import Page
43 from myslice.viewutils           import topmenu_items, the_user
44 from django.http                 import HttpResponseRedirect, HttpResponse
45
46 from M2Crypto                    import Rand, RSA, BIO
47 import os, re
48
49 class DashboardView(TemplateView):
50     template_name = "dashboard.html"
51
52     def get_context_data(self, **kwargs):
53         # We might have slices on different registries with different user accounts 
54         # We note that this portal could be specific to a given registry, to which we register users, but i'm not sure that simplifies things
55         # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
56
57         #messages.info(self.request, 'You have logged in')
58         page = Page(self.request)
59
60         # Slow...
61         #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
62         slice_query = Query().get('user').filter_by('user_hrn', '==', '$user_hrn').select('user_hrn', 'slice.slice_hrn')
63         auth_query  = Query().get('network').select('network_hrn')
64         page.enqueue_query(slice_query)
65         page.enqueue_query(auth_query)
66
67         page.expose_js_metadata()
68         page.expose_queries()
69
70         slicelist = SimpleList(
71             title = None,
72             page  = page,
73             key   = 'slice.slice_hrn',
74             query = slice_query,
75         )
76          
77         authlist = SimpleList(
78             title = None,
79             page  = page,
80             key   = 'network_hrn',
81             query = auth_query,
82         )
83
84         context = super(DashboardView, self).get_context_data(**kwargs)
85         context['person']   = self.request.user
86         context['networks'] = authlist.render(self.request) 
87         context['slices']   = slicelist.render(self.request)
88
89         # XXX This is repeated in all pages
90         # more general variables expected in the template
91         context['title'] = 'Test view that combines various plugins'
92         # the menu items on the top
93         context['topmenu_items'] = topmenu_items('Dashboard', self.request) 
94         # so we can sho who is logged
95         context['username'] = the_user(self.request) 
96
97         context.update(page.prelude_env())
98
99         return context
100
101 # DEPRECATED #class UserRegisterView(RegistrationView):
102 # DEPRECATED #    """
103 # DEPRECATED #    A registration backend which follows a simple workflow:
104 # DEPRECATED #
105 # DEPRECATED #    1. User signs up, inactive account is created.
106 # DEPRECATED #
107 # DEPRECATED #    2. Email is sent to user with activation link.
108 # DEPRECATED #
109 # DEPRECATED #    3. User clicks activation link, account is now active.
110 # DEPRECATED #
111 # DEPRECATED #    Using this backend requires that
112 # DEPRECATED #
113 # DEPRECATED #    * ``registration`` be listed in the ``INSTALLED_APPS`` setting
114 # DEPRECATED #      (since this backend makes use of models defined in this
115 # DEPRECATED #      application).
116 # DEPRECATED #
117 # DEPRECATED #    * The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying
118 # DEPRECATED #      (as an integer) the number of days from registration during
119 # DEPRECATED #      which a user may activate their account (after that period
120 # DEPRECATED #      expires, activation will be disallowed).
121 # DEPRECATED #
122 # DEPRECATED #    * The creation of the templates
123 # DEPRECATED #      ``registration/activation_email_subject.txt`` and
124 # DEPRECATED #      ``registration/activation_email.txt``, which will be used for
125 # DEPRECATED #      the activation email. See the notes for this backends
126 # DEPRECATED #      ``register`` method for details regarding these templates.
127 # DEPRECATED #
128 # DEPRECATED #    Additionally, registration can be temporarily closed by adding the
129 # DEPRECATED #    setting ``REGISTRATION_OPEN`` and setting it to
130 # DEPRECATED #    ``False``. Omitting this setting, or setting it to ``True``, will
131 # DEPRECATED #    be interpreted as meaning that registration is currently open and
132 # DEPRECATED #    permitt ed.
133 # DEPRECATED #
134 # DEPRECATED #    Internally, this is accomplished via storing an activation key in
135 # DEPRECATED #    an instance of ``registration.models.RegistrationProfile``. See
136 # DEPRECATED #    that model and its custom manager for full documentation of its
137 # DEPRECATED #    fields and supported operations.
138 # DEPRECATED #    
139 # DEPRECATED #    """
140 # DEPRECATED ## DEPRECATED #    form_class = UserRegisterForm
141 # DEPRECATED #    
142 # DEPRECATED #    def register(self, request, **cleaned_data):
143 # DEPRECATED #        """
144 # DEPRECATED #        Given a username, email address and password, register a new
145 # DEPRECATED #        user account, which will initially be inactive.
146 # DEPRECATED #
147 # DEPRECATED #        Along with the new ``User`` object, a new
148 # DEPRECATED #        ``registration.models.RegistrationProfile`` will be created,
149 # DEPRECATED #        tied to that ``User``, containing the activation key which
150 # DEPRECATED #        will be used for this account.
151 # DEPRECATED #
152 # DEPRECATED #        An email will be sent to the supplied email address; this
153 # DEPRECATED #        email should contain an activation link. The email will be
154 # DEPRECATED #        rendered using two templates. See the documentation for
155 # DEPRECATED #        ``RegistrationProfile.send_activation_email()`` for
156 # DEPRECATED #        information about these templates and the contexts provided to
157 # DEPRECATED #        them.
158 # DEPRECATED #
159 # DEPRECATED #        After the ``User`` and ``RegistrationProfile`` are created and
160 # DEPRECATED #        the activation email is sent, the signal
161 # DEPRECATED #        ``registration.signals.user_registered`` will be sent, with
162 # DEPRECATED #        the new ``User`` as the keyword argument ``user`` and the
163 # DEPRECATED #        class of this backend as the sender.
164 # DEPRECATED #
165 # DEPRECATED #        """
166 # DEPRECATED #        first_name = cleaned_data['first_name']
167 # DEPRECATED #        last_name  = cleaned_data['last_name']
168 # DEPRECATED #        affiliation= cleaned_data['affiliation']
169 # DEPRECATED #        email      = cleaned_data['email']
170 # DEPRECATED #        password   = cleaned_data['password1']
171 # DEPRECATED #        
172 # DEPRECATED #        #password2  = cleaned_data['password2']
173 # DEPRECATED #        keypair    = cleaned_data['keypair']
174 # DEPRECATED #
175 # DEPRECATED #        #if Site._meta.installed:
176 # DEPRECATED #        #    site = Site.objects.get_current()
177 # DEPRECATED #        #else:
178 # DEPRECATED #        #    site = RequestSite(request) 
179 # DEPRECATED #        site = None
180 # DEPRECATED #
181 # DEPRECATED #        new_user = PendingUser.objects.create_inactive_user(first_name, last_name, email, password, site)
182 # DEPRECATED #        signals.user_registered.send(sender=self.__class__,
183 # DEPRECATED #                                     user=new_user,
184 # DEPRECATED #                                     request=request)
185 # DEPRECATED #        return new_user
186 # DEPRECATED #
187 # DEPRECATED #    def get_context_data(self, **kwargs):
188 # DEPRECATED #        context = super(UserRegisterView, self).get_context_data(**kwargs)
189 # DEPRECATED #        context['topmenu_items'] = topmenu_items('Register', self.request)
190 # DEPRECATED #        context['username'] = the_user (self.request)
191 # DEPRECATED #        return context
192 # DEPRECATED #
193 # DEPRECATED #    def registration_allowed(self, request):
194 # DEPRECATED #        """
195 # DEPRECATED #        Indicate whether account registration is currently permitted,
196 # DEPRECATED #        based on the value of the setting ``REGISTRATION_OPEN``. This
197 # DEPRECATED #        is determined as follows:
198 # DEPRECATED #
199 # DEPRECATED #        * If ``REGISTRATION_OPEN`` is not specified in settings, or is
200 # DEPRECATED #          set to ``True``, registration is permitted.
201 # DEPRECATED #
202 # DEPRECATED #        * If ``REGISTRATION_OPEN`` is both specified and set to
203 # DEPRECATED #          ``False``, registration is not permitted.
204 # DEPRECATED #        
205 # DEPRECATED #        """
206 # DEPRECATED #        return getattr(settings, 'REGISTRATION_OPEN', True)
207 # DEPRECATED #
208 # DEPRECATED #    def get_success_url(self, request, user):
209 # DEPRECATED #        """
210 # DEPRECATED #        Return the name of the URL to redirect to after successful
211 # DEPRECATED #        user registration.
212 # DEPRECATED #        
213 # DEPRECATED #        """
214 # DEPRECATED #        return ('user_register_complete', (), {})
215 # DEPRECATED #
216 # DEPRECATED #
217 # DEPRECATED #class UserValidateView(ActivationView):
218 # DEPRECATED #    def activate(self, request, activation_key):
219 # DEPRECATED #        """
220 # DEPRECATED #        Given an an activation key, look up and activate the user
221 # DEPRECATED #        account corresponding to that key (if possible).
222 # DEPRECATED #
223 # DEPRECATED #        After successful activation, the signal
224 # DEPRECATED #        ``registration.signals.user_activated`` will be sent, with the
225 # DEPRECATED #        newly activated ``User`` as the keyword argument ``user`` and
226 # DEPRECATED #        the class of this backend as the sender.
227 # DEPRECATED #        
228 # DEPRECATED #        """
229 # DEPRECATED #        activated_user = RegistrationProfile.objects.activate_user(activation_key)
230 # DEPRECATED #        if activated_user:
231 # DEPRECATED #            signals.user_activated.send(sender=self.__class__,
232 # DEPRECATED #                                        user=activated_user,
233 # DEPRECATED #                                        request=request)
234 # DEPRECATED #        return activated_user
235 # DEPRECATED #
236 # DEPRECATED #    def get_success_url(self, request, user):
237 # DEPRECATED #        return ('registration_activation_complete', (), {})
238 # DEPRECATED #
239 # DEPRECATED #
240 # DEPRECATED #from portal.portalpage  import PortalPage
241 # DEPRECATED #from plugins.wizard     import Wizard
242 # DEPRECATED #from plugins.form       import CreateForm
243 # DEPRECATED #from plugins.raw.raw    import Raw          # XXX
244 # DEPRECATED #
245 # DEPRECATED #from myslice.viewutils  import the_user
246 # DEPRECATED #
247 # DEPRECATED #from django.template.loader import render_to_string
248 # DEPRECATED #from django.template import RequestContext
249 # DEPRECATED #from django.views import generic
250 # DEPRECATED #
251 # DEPRECATED #from django.contrib.formtools.wizard.views import NamedUrlSessionWizardView
252 # DEPRECATED ##from django.core.files.storage import FileSystemStorage
253 # DEPRECATED #from django.core.files.storage import default_storage
254 # DEPRECATED #
255 # DEPRECATED ##class MerlinWizard(NamedUrlSessionWizardView):
256 # DEPRECATED ##
257 # DEPRECATED ##    ...
258 # DEPRECATED ##    ...
259 # DEPRECATED ##
260 # DEPRECATED ##    @classonlymethod
261 # DEPRECATED ##    def as_view(cls, *args, **kwargs):
262 # DEPRECATED ##        kwargs.update({
263 # DEPRECATED ##            'form_list': [
264 # DEPRECATED ##                NameForm,
265 # DEPRECATED ##                QuestForm,
266 # DEPRECATED ##                ColorForm,
267 # DEPRECATED ##            ],
268 # DEPRECATED ##            'url_name': 'merlin_wizard'
269 # DEPRECATED ##        })
270 # DEPRECATED ##        return super(MerlinWizard, cls).as_view(*args, **kwargs)
271 # DEPRECATED #
272 # DEPRECATED #class UserRegisterWizardView(NamedUrlSessionWizardView):
273 # DEPRECATED ##class UserRegisterWizardView(LoginRequiredMixin, NamedUrlSessionWizardView):
274 # DEPRECATED #    # Notice that I specify a file storage instance. If you don't specify this,
275 # DEPRECATED #    # and you need to support FileField or ImageField in your forms, you'll get
276 # DEPRECATED #    # errors from Django. This is something else I think could be handled by
277 # DEPRECATED #    # the views better. Seems to me that it should just use whatever the
278 # DEPRECATED #    # default/specified storage is for the rest of your project/application.
279 # DEPRECATED #    file_storage = default_storage # FileSystemStorage()
280 # DEPRECATED #    template_name = "register_user_wizard.html"
281 # DEPRECATED #
282 # DEPRECATED #    def done(self, form_list, **kwargs):
283 # DEPRECATED #        step1_form = form_list[0]
284 # DEPRECATED #        step2_form = form_list[1]
285 # DEPRECATED #
286 # DEPRECATED #        productext = self.create_product(product_form)
287 # DEPRECATED #        shippings = self.create_shippings(productext, shipping_forms)
288 # DEPRECATED #        images = self.create_images(productext, image_forms)
289 # DEPRECATED #
290 # DEPRECATED #        if all([productext, shippings, images]):
291 # DEPRECATED #            del self.request.session["wizard_product_wizard_view"]
292 # DEPRECATED #
293 # DEPRECATED #            messages.success(self.request,
294 # DEPRECATED #                _("Your product has been created."))
295 # DEPRECATED #            return HttpResponseRedirect(self.get_success_url(productext))
296 # DEPRECATED #
297 # DEPRECATED #        messages.error(self.request, _("Something went wrong creating your "
298 # DEPRECATED #            "product. Please try again or contact support."))
299 # DEPRECATED #        return HttpResponseRedirect(reverse("register_wizard"))
300 # DEPRECATED #
301 # DEPRECATED #    #def get_form_kwargs(self, step):
302 # DEPRECATED #    #    if step == "product":
303 # DEPRECATED #    #        return {"user": self.request.user}
304 # DEPRECATED #    #    return {}
305 # DEPRECATED #
306 # DEPRECATED ## The portal should hook the slice and user creation pages
307 # DEPRECATED #
308 # DEPRECATED #def register_user(request):
309 # DEPRECATED #    
310 # DEPRECATED #    if request.method == 'POST':
311 # DEPRECATED #        form = UserRegisterForm(request.POST) # Nous reprenons les donnĂ©es
312 # DEPRECATED #        if form.is_valid():
313 # DEPRECATED #            first_name = form.cleaned_data['first_name']
314 # DEPRECATED #            last_name  = form.cleaned_data['last_name']
315 # DEPRECATED #            email      = form.cleaned_data['email']
316 # DEPRECATED #            password   = form.cleaned_data['password']
317 # DEPRECATED #            password2  = form.cleaned_data['password2']
318 # DEPRECATED #            keypair    = form.cleaned_data['keypair']
319 # DEPRECATED #            ## Ici nous pouvons traiter les donnĂ©es du formulaire
320 # DEPRECATED #            #sujet = form.cleaned_data['sujet']
321 # DEPRECATED #            #message = form.cleaned_data['message']
322 # DEPRECATED #            #envoyeur = form.cleaned_data['envoyeur']
323 # DEPRECATED #            #renvoi = form.cleaned_data['renvoi']
324 # DEPRECATED #            ## Nous pourrions ici envoyer l'e-mail grâce aux donnĂ©es que nous venons de rĂ©cupĂ©rer
325 # DEPRECATED #            #envoi = True
326 # DEPRECATED #    else:
327 # DEPRECATED #        form = UserRegisterForm()
328 # DEPRECATED #    return render(request, 'register_user.html', locals())
329 # DEPRECATED #
330 # DEPRECATED #def index(request):
331 # DEPRECATED #
332 # DEPRECATED #    WIZARD_TITLE = 'User registration'
333 # DEPRECATED #    STEP1_TITLE  = 'Enter your details'
334 # DEPRECATED #    STEP2_TITLE  = 'Select your institution'
335 # DEPRECATED #    STEP3_TITLE  = 'Authentication'
336 # DEPRECATED #    STEP4_TITLE  = 'Request a slice (optional)'
337 # DEPRECATED #    STEP5_TITLE  = 'Waiting for validation'
338 # DEPRECATED #    STEP6_TITLE  = 'Account validated'
339 # DEPRECATED #
340 # DEPRECATED #    STEP0 = render_to_string('account_validated.html', context_instance=RequestContext(request))
341 # DEPRECATED #    STEP2_HTML   = """
342 # DEPRECATED #    coucou
343 # DEPRECATED #    """
344 # DEPRECATED #    STEP4 = """
345 # DEPRECATED #    mede
346 # DEPRECATED #    """
347 # DEPRECATED #    STEP5 = render_to_string('account_validated.html', context_instance=RequestContext(request))
348 # DEPRECATED #
349 # DEPRECATED #    p = PortalPage(request)
350 # DEPRECATED #
351 # DEPRECATED #    # This is redundant with the Wizard title
352 # DEPRECATED #    p << "<h3>User registration</h3>"
353 # DEPRECATED #
354 # DEPRECATED #    sons = []
355 # DEPRECATED #    start_step = 1
356 # DEPRECATED #
357 # DEPRECATED #    # STEP 1
358 # DEPRECATED #    # If the user already exists (is logged), let's display a summary of his account details
359 # DEPRECATED #    # Otherwise propose a form to fill in
360 # DEPRECATED #    if the_user(request):
361 # DEPRECATED #        # Fill a disabled form with user info
362 # DEPRECATED #        # Please logout to register another user
363 # DEPRECATED #        sons.append(Raw(page=p, title=STEP1_TITLE, togglable=False, html=STEP0))
364 # DEPRECATED #        start_step += 1
365 # DEPRECATED #    else:
366 # DEPRECATED #        # We could pass a list of fields also, instead of retrieving them from metadata
367 # DEPRECATED #        # Otherwise we need some heuristics to display nice forms
368 # DEPRECATED #        # XXX Could we log the user in after the form is validated ?
369 # DEPRECATED #        # XXX Explain the password is for XXX
370 # DEPRECATED #        field_list = [{
371 # DEPRECATED #            'name'        : 'First name',
372 # DEPRECATED #            'field'       : 'firstname',
373 # DEPRECATED #            'type'        : 'text',
374 # DEPRECATED #            'validate_rx' : '^[a-zA-Z -]+$',
375 # DEPRECATED #            'validate_err': 'Your first name must be comprised of letters only',
376 # DEPRECATED #            'description' : 'Enter your first name',
377 # DEPRECATED #        }, {
378 # DEPRECATED #            'name'        : 'Last name',
379 # DEPRECATED #            'field'       : 'lastname',
380 # DEPRECATED #            'type'        : 'text',
381 # DEPRECATED #            'validate_rx' : '^[a-zA-Z -]+$',
382 # DEPRECATED #            'validate_err': 'Your last name must be comprised of letters only',
383 # DEPRECATED #            'description' : 'Enter your last name',
384 # DEPRECATED #        }, { 
385 # DEPRECATED #            'name'        : 'Email',
386 # DEPRECATED #            'field'       : 'email',
387 # DEPRECATED #            'type'        : 'text',
388 # DEPRECATED #            'description' : 'Enter your email address',
389 # DEPRECATED #        }, {
390 # DEPRECATED #            'name'        : 'Password',
391 # DEPRECATED #            'field'       : 'password',
392 # DEPRECATED #            'type'        : 'password',
393 # DEPRECATED #            'description' : 'Enter your password',
394 # DEPRECATED #        }, {
395 # DEPRECATED #            'name'        : 'Confirm password',
396 # DEPRECATED #            'field'       : 'password2',
397 # DEPRECATED #            'type'        : 'password',
398 # DEPRECATED #            'description' : 'Enter your password again',
399 # DEPRECATED #        }]
400 # DEPRECATED #        sons.append(CreateForm(page = p, title = STEP1_TITLE, togglable = False, object = 'local:user', fields = field_list))
401 # DEPRECATED #
402 # DEPRECATED #    # STEP 2
403 # DEPRECATED #    # If the user already exists (is logged), let's display a summary of its institution
404 # DEPRECATED #    # Otherwise propose a form to fill in (we should base our selection on the email)
405 # DEPRECATED #    if the_user(request):
406 # DEPRECATED #        # Fill a disabled form with institution
407 # DEPRECATED #        # Please logout to register another user
408 # DEPRECATED #        sons.append(Raw(page=p, title=STEP2_TITLE, togglable=False, html="User created"))
409 # DEPRECATED #        start_step += 1
410 # DEPRECATED #    else:
411 # DEPRECATED #        sons.append(CreateForm(page = p, title = STEP2_TITLE, togglable = False, object = 'slice')) #institution'))
412 # DEPRECATED #
413 # DEPRECATED #    # STEP3
414 # DEPRECATED #    # Please should your prefered authentication method
415 # DEPRECATED #    # This step should allow the user to either choose the user or managed mode in MySlice
416 # DEPRECATED #    sons.append(Raw(page = p, title = STEP3_TITLE, togglable = False, html = STEP2_HTML))
417 # DEPRECATED #
418 # DEPRECATED #    # Step 4: Request a slice (optional)
419 # DEPRECATED #    sons.append(CreateForm(page = p, title = STEP4_TITLE, togglable = False, object = 'slice'))
420 # DEPRECATED #
421 # DEPRECATED #    # Step 5: Your request is waiting for validation
422 # DEPRECATED #    # Periodic refresh
423 # DEPRECATED #    sons.append(Raw(page = p, title = STEP5_TITLE, togglable = False, html = STEP4))
424 # DEPRECATED #
425 # DEPRECATED #    # Step 6: Account validation  = welcome for newly validated users
426 # DEPRECATED #    # . delegation
427 # DEPRECATED #    # . platforms
428 # DEPRECATED #    # . slice
429 # DEPRECATED #    # . pointers
430 # DEPRECATED #    sons.append(Raw(page = p, title = STEP6_TITLE, togglable = False, html = STEP5))
431 # DEPRECATED #
432 # DEPRECATED #    wizard = Wizard(
433 # DEPRECATED #        page       = p,
434 # DEPRECATED #        title      = WIZARD_TITLE,
435 # DEPRECATED #        togglable  = False,
436 # DEPRECATED #        sons       = sons,
437 # DEPRECATED #        start_step = start_step,
438 # DEPRECATED #    )
439 # DEPRECATED #
440 # DEPRECATED #    p << wizard.render(request) # in portal page if possible
441 # DEPRECATED #
442 # DEPRECATED #    return p.render()
443
444
445 # DEPRECATED ## view for my_account
446 # DEPRECATED # class MyAccountView(TemplateView):
447 # DEPRECATED #    template_name = "my_account.html"
448 # DEPRECATED #    
449 # DEPRECATED #    def from_process(self, request, **cleaned_data): 
450 # DEPRECATED #        #if request.method == 'POST':
451 # DEPRECATED #         #       if request.POST['submit_name']:
452 # DEPRECATED #        if 'fname' in request.POST:            
453 # DEPRECATED #                messsag= "Got Name"
454 # DEPRECATED #                #return render(request, 'portal/my_account.html')
455 # DEPRECATED #                #response = HttpResponse("Here's the text of the Web page.")    
456 # DEPRECATED #                return HttpResponse(message)
457 # DEPRECATED #            
458 # DEPRECATED #    def get_context_data(self, **kwargs):
459 # DEPRECATED #        page = Page(self.request)
460 # DEPRECATED #        context = super(MyAccountView, self).get_context_data(**kwargs)
461 # DEPRECATED #        context['person']   = self.request.user
462 # DEPRECATED #        # XXX This is repeated in all pages
463 # DEPRECATED #        # more general variables expected in the template
464 # DEPRECATED #        context['title'] = 'User Profile Page'
465 # DEPRECATED #        # the menu items on the top
466 # DEPRECATED #        context['topmenu_items'] = topmenu_items('my_account', self.request)
467 # DEPRECATED #        # so we can sho who is logged
468 # DEPRECATED #        context['username'] = the_user(self.request)
469 # DEPRECATED #        context.update(page.prelude_env())
470 # DEPRECATED #        return context
471
472
473
474 # View for my_account form
475 def my_account(request):
476     return render(request, 'my_account.html', {
477         #'form': form,
478         'topmenu_items': topmenu_items('My Account', request),
479         'username': the_user (request)
480     })
481
482 # View for platforms
483 class PlatformsView(TemplateView):
484     template_name = "platforms.html"
485
486     def get_context_data(self, **kwargs):
487         page = Page(self.request)
488
489         network_query  = Query().get('local:platform').filter_by('disabled', '==', '0').select('platform','platform_longname','gateway_type')
490         page.enqueue_query(network_query)
491
492         page.expose_js_metadata()
493         page.expose_queries()
494         networklist = Hazelnut(
495             page  = page,
496             title = 'List',
497             domid = 'checkboxes',
498             # this is the query at the core of the slice list
499             query = network_query,
500             query_all = network_query,
501             checkboxes = False,
502             datatables_options = {
503             # for now we turn off sorting on the checkboxes columns this way
504             # this of course should be automatic in hazelnut
505             'aoColumns'      : [None, None, None, None, {'bSortable': False}],
506             'iDisplayLength' : 25,
507             'bLengthChange'  : True,
508             },
509         )
510 #
511 #        networklist = SimpleList(
512 #            title = None,
513 #            page  = page,
514 #            key   = 'platform',
515 #            query = network_query,
516 #        )
517
518         context = super(PlatformsView, self).get_context_data(**kwargs)
519         context['person']   = self.request.user
520         context['networks'] = networklist.render(self.request)
521
522         # XXX This is repeated in all pages
523         # more general variables expected in the template
524         context['title'] = 'Platforms connected to MySlice'
525         # the menu items on the top
526         context['topmenu_items'] = topmenu_items('Platforms', self.request)
527         # so we can sho who is logged
528         context['username'] = the_user(self.request)
529
530         context.update(page.prelude_env())
531
532         return context
533
534 # View for 1 platform and its details
535 class PlatformView(TemplateView):
536     template_name = "platform.html"
537
538     def get_context_data(self, **kwargs):
539         page = Page(self.request)
540
541         for key, value in kwargs.iteritems():
542             print "%s = %s" % (key, value)       
543             if key == "platformname":
544                 platformname=value
545                 
546         network_query  = Query().get('local:platform').filter_by('platform', '==', platformname).select('platform','platform_longname','gateway_type')
547         page.enqueue_query(network_query)
548
549         page.expose_js_metadata()
550         page.expose_queries()
551         networklist = Hazelnut(
552             page  = page,
553             title = 'List',
554             domid = 'checkboxes',
555             # this is the query at the core of the slice list
556             query = network_query,
557             query_all = network_query,
558             checkboxes = False,
559             datatables_options = {
560             # for now we turn off sorting on the checkboxes columns this way
561             # this of course should be automatic in hazelnut
562             'aoColumns'      : [None, None, None, None, {'bSortable': False}],
563             'iDisplayLength' : 25,
564             'bLengthChange'  : True,
565             },
566         )
567 #
568 #        networklist = SimpleList(
569 #            title = None,
570 #            page  = page,
571 #            key   = 'platform',
572 #            query = network_query,
573 #        )
574
575         context = super(PlatformView, self).get_context_data(**kwargs)
576         context['person']   = self.request.user
577         context['networks'] = networklist.render(self.request)
578
579         # XXX This is repeated in all pages
580         # more general variables expected in the template
581         context['title'] = 'Platforms connected to MySlice'
582         # the menu items on the top
583         # context['topmenu_items'] = topmenu_items('Platforms', self.request)
584         # so we can sho who is logged
585         context['username'] = the_user(self.request)
586
587         context.update(page.prelude_env())
588
589         return context
590
591 #my_acc form value processing
592 def acc_process(request):
593     # getting the user_id from the session [now hardcoded]
594     get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
595     if 'submit_name' in request.POST:
596         edited_first_name =  request.POST['fname']
597         edited_last_name =  request.POST['lname']
598         #email = 'test_email@gmail.com'
599         #password = 'test_pp'
600         #message = 'F_Name: %s L_name: %s dummy_pp: %s' % (first_name, last_name, password)
601         #site = None
602         
603         # insert into DB [needed for registration page]
604         #approach borrowed from register view     
605         #new_user = PendingUser.objects.create_inactive_user(edited_first_name, edited_last_name, email,  password, site) 
606         #conventional approach
607         #b = PendingUser(first_name=edited_first_name, last_name=edited_last_name)
608         #b.save()
609         
610         # select and update [will be used throughout this view]
611         # select the logged in user [for the moment hard coded]
612         #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
613         # update first and last name
614         get_user.first_name = edited_first_name
615         get_user.last_name = edited_last_name
616         get_user.save() 
617
618         return HttpResponse('Success: Name Updated!!')       
619     elif 'submit_pass' in request.POST:
620         edited_password = request.POST['password']
621         # select the logged in user [for the moment hard coded]
622         #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
623         # update password
624         get_user.password = edited_password
625         get_user.save()
626         return HttpResponse('Success: Password Changed!!')
627     elif 'generate' in request.POST:
628         #import os
629         #from M2Crypto import Rand, RSA, BIO
630
631         KEY_LENGTH = 2048
632
633         def blank_callback():
634             "Replace the default dashes"
635             return
636
637         # Random seed
638         Rand.rand_seed (os.urandom (KEY_LENGTH))
639         # Generate key pair
640         key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
641         # Create memory buffers
642         pri_mem = BIO.MemoryBuffer()
643         pub_mem = BIO.MemoryBuffer()
644         # Save keys to buffers
645         key.save_key_bio(pri_mem, None)
646         key.save_pub_key_bio(pub_mem)
647
648         # Get keys 
649         public_key = pub_mem.getvalue()
650         private_key = pri_mem.getvalue()
651         # Saving to DB
652         keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
653         keypair = re.sub("\r", "", keypair)
654         keypair = re.sub("\n", "\\n", keypair)
655         #keypair = keypair.rstrip('\r\n')
656         keypair = ''.join(keypair.split())
657         get_user.keypair = keypair
658         get_user.save()
659         return HttpResponse('Success: New Keypair Generated! %s' % keypair)
660
661     elif 'upload_key' in request.POST:
662         up_file = request.FILES['pubkey']
663         file_content =  up_file.read()
664         file_name = up_file.name
665         file_extension = os.path.splitext(file_name)[1] 
666         allowed_extension =  ['.pub','.txt']
667         if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
668             file_content = '{"user_public_key":"'+ file_content +'"}'
669             file_content = re.sub("\r", "", file_content)
670             file_content = re.sub("\n", "\\n",file_content)
671             file_content = ''.join(file_content.split())
672             get_user.keypair = file_content
673             get_user.save()
674             return HttpResponse('Success: Publickey uploaded! Old records overwritten')
675         else:
676             return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')    
677         
678     else:
679         message = 'You submitted an empty form.'
680         return HttpResponse(message)
681
682 def register_4m_f4f(request):
683     errors = []
684     if request.method == 'POST':
685         #get_email = PendingUser.objects.get(email)
686         reg_fname = request.POST.get('firstname', '')
687         reg_lname = request.POST.get('lastname', '')
688         reg_aff = request.POST.get('affiliation','')
689         reg_email = request.POST.get('email','').lower()
690         
691         #POST value validation  
692         if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
693             errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
694             #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
695             #return render(request, 'register_4m_f4f.html')
696         if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
697             errors.append('Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
698             #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
699             #return render(request, 'register_4m_f4f.html')
700         if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
701             errors.append('Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
702             #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
703             #return render(request, 'register_4m_f4f.html')
704         if PendingUser.objects.filter(email__iexact=reg_email):
705             errors.append('Email already registered.Please provide a new email address.')
706             #return HttpResponse("Email Already exists")
707             #return render(request, 'register_4m_f4f.html')
708         if 'generate' in request.POST['question']:
709             #import os
710             #from M2Crypto import Rand, RSA, BIO
711             
712             KEY_LENGTH = 2048
713
714             def blank_callback():
715                 "Replace the default dashes"
716                 return
717
718             # Random seed
719             Rand.rand_seed (os.urandom (KEY_LENGTH))
720             # Generate key pair
721             key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
722             # Create memory buffers
723             pri_mem = BIO.MemoryBuffer()
724             pub_mem = BIO.MemoryBuffer()
725             # Save keys to buffers
726             key.save_key_bio(pri_mem, None)
727             key.save_pub_key_bio(pub_mem)
728             # Get keys 
729             public_key = pub_mem.getvalue()
730             private_key = pri_mem.getvalue()
731             # Saving to DB
732             keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
733             keypair = re.sub("\r", "", keypair)
734             keypair = re.sub("\n", "\\n", keypair)
735             #keypair = keypair.rstrip('\r\n')
736             keypair = ''.join(keypair.split())
737             #return HttpResponse(keypair)
738         else:
739             up_file = request.FILES['user_public_key']
740             file_content =  up_file.read()
741             file_name = up_file.name
742             file_extension = os.path.splitext(file_name)[1]
743             allowed_extension =  ['.pub','.txt']
744             if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
745                 keypair = '{"user_public_key":"'+ file_content +'"}'
746                 keypair = re.sub("\r", "", keypair)
747                 keypair = re.sub("\n", "\\n",keypair)
748                 keypair = ''.join(keypair.split())
749             else:
750                 errors.append('Please upload a valid RSA public key [.txt or .pub].')
751
752         #b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff, 
753         #                email=reg_email, password=request.POST['password'], keypair=keypair)
754         #b.save()
755         if not errors:
756             b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
757                             email=reg_email, password=request.POST['password'], keypair=keypair)
758             b.save()
759             return render(request, 'user_register_complete.html')
760
761     return render(request, 'register_4m_f4f.html',{
762         'topmenu_items': topmenu_items('Register', request),
763         'errors': errors,
764         'firstname': request.POST.get('firstname', ''),
765         'lastname': request.POST.get('lastname', ''),
766         'affiliation': request.POST.get('affiliation', ''),
767         'email': request.POST.get('email', ''),
768         'password': request.POST.get('password', ''),           
769     })        
770     
771
772 # view for contact form
773 def contact(request):
774     if request.method == 'POST': # If the form has been submitted...
775         form = ContactForm(request.POST) # A form bound to the POST data
776         if form.is_valid(): # All validation rules pass
777             # Process the data in form.cleaned_data
778             first_name = form.cleaned_data['first_name']
779             last_name = form.cleaned_data['last_name']
780             affiliation = form.cleaned_data['affiliation']
781             subject = form.cleaned_data['subject']
782             message = form.cleaned_data['message']
783             email = form.cleaned_data['email'] # email of the sender
784             cc_myself = form.cleaned_data['cc_myself']
785
786             recipients = ['yasin.upmc@gmail.com']
787             if cc_myself:
788                 recipients.append(email)
789
790             from django.core.mail import send_mail
791             send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
792             return render(request,'contact_sent.html') # Redirect after POST
793     else:
794         form = ContactForm() # An unbound form
795     
796     return render(request, 'contact.html', {
797         'form': form,
798         'topmenu_items': topmenu_items('Contact Us', request),
799         'username': the_user (request)
800
801     })
802
803
804 def slice_request(request):
805     if request.method == 'POST': # If the form has been submitted...
806         form = SliceRequestForm(request.POST) # A form bound to the POST data
807         if form.is_valid(): # All validation rules pass
808             # Process the data in form.cleaned_data
809             slice_name = form.cleaned_data['slice_name']
810             number_of_nodes = form.cleaned_data['number_of_nodes']
811             type_of_nodes = form.cleaned_data['type_of_nodes']
812             purpose = form.cleaned_data['purpose']
813             email = form.cleaned_data['email'] # email of the sender
814             cc_myself = form.cleaned_data['cc_myself']
815
816             recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
817             if cc_myself:
818                 recipients.append(email)
819
820             from django.core.mail import send_mail
821             send_mail("Onelab New Slice request form submitted", [slice_name,number_of_nodes,type_of_nodes,purpose], email, recipients)
822             return render(request,'slicereq_recvd.html') # Redirect after POST
823     else:
824         form = SliceRequestForm() # An unbound form
825
826 #    template_env = {}
827 #    template_env['form'] = form
828 #    template_env['topmenu_items'] = topmenu_items('Request a slice', request) 
829 #    template_env['unfold1_main'] = render(request, 'slice_request_.html', {
830 #        'form': form,
831 #    })
832 #    from django.shortcuts                import render_to_response
833 #    from django.template                 import RequestContext
834 #    return render_to_response ('view-unfold1.html',template_env,
835 #                               context_instance=RequestContext(request))
836
837     return render(request, 'slice_request.html', {
838         'form': form,
839         'topmenu_items': topmenu_items('Request a slice', request),
840         'username': the_user (request) 
841     })
842
843
844 class PresViewView(TemplateView):
845     template_name = "view-unfold1.html"
846
847     def get_context_data(self, **kwargs):
848
849         page = Page(self.request)
850
851         pres_view = PresView(page = page)
852
853         context = super(PresViewView, self).get_context_data(**kwargs)
854
855         #context['ALL_STATIC'] = "all_static"
856         context['unfold1_main'] = pres_view.render(self.request)
857
858         # XXX This is repeated in all pages
859         # more general variables expected in the template
860         context['title'] = 'Test view that combines various plugins'
861         # the menu items on the top
862         context['topmenu_items'] = topmenu_items('PresView', self.request)
863         # so we can sho who is logged
864         context['username'] = the_user(self.request)
865
866         prelude_env = page.prelude_env()
867         context.update(prelude_env)
868
869         return context
870
871 def json_me(config_file,type):
872     json_answer = ''
873     for ligne in config_file:
874         if not ligne.startswith('#'):
875             args = ligne.split(';')
876             json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1]  + '" ,"descriptif":"' + args[2]+'"')
877             if type!="dynamic":
878                 json_answer += str(',"contraints":')
879                 if args[3]=="":
880                     json_answer += str('""')
881                 else:
882                     json_answer += str(args[3])
883             json_answer += str('},')
884     return json_answer[:-1]
885
886
887 DIR = '/var/myslice/'
888 STATIC = '%s/config_method_static' % DIR
889 DYNAMIC = '%s/config_method_dynamic' % DIR
890 ANIMATION = '%s/config_method_animation' % DIR
891
892 def pres_view_methods(request, type):
893
894     if type ==None:
895         return 0
896     elif type =="static":
897         config = open(STATIC, "r")
898         json_answer = str('{ "options": [')
899         json_answer += str(json_me(config,"static"))
900         json_answer += str('] }')
901         config.close()
902     elif type =="dynamic":
903         config = open(DYNAMIC, "r")
904         json_answer = str('{ "options": [')
905         json_answer += str(json_me(config,"dynamic"))
906         json_answer += str('] }')
907         config.close()
908     elif type =="animation":
909         config = open(ANIMATION, "r")
910         json_answer = str('{ "options": [')
911         json_answer += str(json_me(config,"animation"))
912         json_answer += str('] }')
913         config.close()
914     elif type =="all":
915         config = open(STATIC, "r")
916         json_answer = str('{ "static": [')
917         json_answer += str(json_me(config,"static"))
918         json_answer += str('],')
919         json_answer += str('"dynamic": [')
920         config.close()
921         config = open(DYNAMIC, "r")
922         json_answer += str(json_me(config,"dynamic"))
923         json_answer += str('],')
924         json_answer += str('"animation": [')
925         config.close()
926         config = open(ANIMATION, "r")
927         json_answer += str(json_me(config,"animation"))
928         json_answer += str('] }')
929         config.close()
930     else:
931         return 0
932     return HttpResponse (json_answer, mimetype="application/json")
933
934 def pres_view_animation(request, constraints, id):
935
936 # sites crees depuis 2008
937 # static.py?contraints=']date_created':1262325600&id='name_id"'
938
939     # method = request.getvalue('method') #ex : GetSites
940     #constraints = "']date_created':1262325600"
941     #id = "2"
942
943     if id == None:
944         return 0
945
946     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
947     # constraints = {}#request.getvalue('constraints') // nul = {}
948     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
949
950     config_file = open(ANIMATION, "r")
951     for ligne in config_file:
952         if not ligne.startswith('#'):
953             ligne = ligne.split('\n')
954             first = ligne[0].split(';')
955             if (str(first[1]) == str(id)):
956                 save = first
957     config_file.close()
958
959     #Les print_method, print_option sont definis par le client (js)
960     #Les animations acceptent que les connexions anonymous
961     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
962     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
963
964
965     #Creation d'un objet event
966     event = Event(args)
967     cmd = [{"params": {
968             "data": {
969                 "print_options": event.print_options,
970                 "print_method": event.print_method,
971                 "message": event.data
972             }
973         }
974     }]
975
976     json_answer = json.dumps(cmd)
977     return HttpResponse (json_answer, mimetype="application/json")
978
979 def pres_view_static(request, constraints, id):
980     #constraints = "']date_created':1262325600"
981     #id = "2"
982
983     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
984     # constraints = {}#request.getvalue('constraints') // nul = {}
985     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
986
987     config_file = open(STATIC, "r")
988     for ligne in config_file:
989         if not ligne.startswith('#'):
990             ligne = ligne.split('\n')
991             first = ligne[0].split(';')
992             if (str(first[1]) == str(id)):
993                 save = first
994     config_file.close()
995
996     #Les print_method, print_option sont definis par le client (js)
997     #Les animations acceptent que les connexions anonymous
998     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
999     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
1000
1001
1002     #Creation d'un objet event
1003     event = Event(args)
1004     cmd = [{"params": {
1005             "data": {
1006                 "print_options": event.print_options,
1007                 "print_method": event.print_method,
1008                 "message": event.data
1009             }
1010         }
1011     }]
1012
1013     json_answer = json.dumps(cmd)
1014     return HttpResponse (json_answer, mimetype="application/json")