added a page to list the platforms plugged into MySlice, need to be improved...
[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
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 UserRegisterForm, 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 class UserRegisterView(RegistrationView):
102     """
103     A registration backend which follows a simple workflow:
104
105     1. User signs up, inactive account is created.
106
107     2. Email is sent to user with activation link.
108
109     3. User clicks activation link, account is now active.
110
111     Using this backend requires that
112
113     * ``registration`` be listed in the ``INSTALLED_APPS`` setting
114       (since this backend makes use of models defined in this
115       application).
116
117     * The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying
118       (as an integer) the number of days from registration during
119       which a user may activate their account (after that period
120       expires, activation will be disallowed).
121
122     * The creation of the templates
123       ``registration/activation_email_subject.txt`` and
124       ``registration/activation_email.txt``, which will be used for
125       the activation email. See the notes for this backends
126       ``register`` method for details regarding these templates.
127
128     Additionally, registration can be temporarily closed by adding the
129     setting ``REGISTRATION_OPEN`` and setting it to
130     ``False``. Omitting this setting, or setting it to ``True``, will
131     be interpreted as meaning that registration is currently open and
132     permitt ed.
133
134     Internally, this is accomplished via storing an activation key in
135     an instance of ``registration.models.RegistrationProfile``. See
136     that model and its custom manager for full documentation of its
137     fields and supported operations.
138     
139     """
140     form_class = UserRegisterForm
141     
142     def register(self, request, **cleaned_data):
143         """
144         Given a username, email address and password, register a new
145         user account, which will initially be inactive.
146
147         Along with the new ``User`` object, a new
148         ``registration.models.RegistrationProfile`` will be created,
149         tied to that ``User``, containing the activation key which
150         will be used for this account.
151
152         An email will be sent to the supplied email address; this
153         email should contain an activation link. The email will be
154         rendered using two templates. See the documentation for
155         ``RegistrationProfile.send_activation_email()`` for
156         information about these templates and the contexts provided to
157         them.
158
159         After the ``User`` and ``RegistrationProfile`` are created and
160         the activation email is sent, the signal
161         ``registration.signals.user_registered`` will be sent, with
162         the new ``User`` as the keyword argument ``user`` and the
163         class of this backend as the sender.
164
165         """
166         first_name = cleaned_data['first_name']
167         last_name  = cleaned_data['last_name']
168         affiliation= cleaned_data['affiliation']
169         email      = cleaned_data['email']
170         password   = cleaned_data['password1']
171         
172         #password2  = cleaned_data['password2']
173         keypair    = cleaned_data['keypair']
174
175         #if Site._meta.installed:
176         #    site = Site.objects.get_current()
177         #else:
178         #    site = RequestSite(request) 
179         site = None
180
181         new_user = PendingUser.objects.create_inactive_user(first_name, last_name, email, password, site)
182         signals.user_registered.send(sender=self.__class__,
183                                      user=new_user,
184                                      request=request)
185         return new_user
186
187     def get_context_data(self, **kwargs):
188         context = super(UserRegisterView, self).get_context_data(**kwargs)
189         context['topmenu_items'] = topmenu_items('Register', self.request)
190         context['username'] = the_user (self.request)
191         return context
192
193     def registration_allowed(self, request):
194         """
195         Indicate whether account registration is currently permitted,
196         based on the value of the setting ``REGISTRATION_OPEN``. This
197         is determined as follows:
198
199         * If ``REGISTRATION_OPEN`` is not specified in settings, or is
200           set to ``True``, registration is permitted.
201
202         * If ``REGISTRATION_OPEN`` is both specified and set to
203           ``False``, registration is not permitted.
204         
205         """
206         return getattr(settings, 'REGISTRATION_OPEN', True)
207
208     def get_success_url(self, request, user):
209         """
210         Return the name of the URL to redirect to after successful
211         user registration.
212         
213         """
214         return ('user_register_complete', (), {})
215
216
217 class UserValidateView(ActivationView):
218     def activate(self, request, activation_key):
219         """
220         Given an an activation key, look up and activate the user
221         account corresponding to that key (if possible).
222
223         After successful activation, the signal
224         ``registration.signals.user_activated`` will be sent, with the
225         newly activated ``User`` as the keyword argument ``user`` and
226         the class of this backend as the sender.
227         
228         """
229         activated_user = RegistrationProfile.objects.activate_user(activation_key)
230         if activated_user:
231             signals.user_activated.send(sender=self.__class__,
232                                         user=activated_user,
233                                         request=request)
234         return activated_user
235
236     def get_success_url(self, request, user):
237         return ('registration_activation_complete', (), {})
238
239
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').select('platform')
490         page.enqueue_query(network_query)
491
492         page.expose_js_metadata()
493         page.expose_queries()
494
495         networklist = SimpleList(
496             title = None,
497             page  = page,
498             key   = 'platform',
499             query = network_query,
500         )
501
502         context = super(PlatformsView, self).get_context_data(**kwargs)
503         context['person']   = self.request.user
504         context['networks'] = networklist.render(self.request)
505
506         # XXX This is repeated in all pages
507         # more general variables expected in the template
508         context['title'] = 'Platforms connected to MySlice'
509         # the menu items on the top
510         context['topmenu_items'] = topmenu_items('Platforms', self.request)
511         # so we can sho who is logged
512         context['username'] = the_user(self.request)
513
514         context.update(page.prelude_env())
515
516         return context
517
518 #my_acc form value processing
519 def acc_process(request):
520     # getting the user_id from the session [now hardcoded]
521     get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
522     if 'submit_name' in request.POST:
523         edited_first_name =  request.POST['fname']
524         edited_last_name =  request.POST['lname']
525         #email = 'test_email@gmail.com'
526         #password = 'test_pp'
527         #message = 'F_Name: %s L_name: %s dummy_pp: %s' % (first_name, last_name, password)
528         #site = None
529         
530         # insert into DB [needed for registration page]
531         #approach borrowed from register view     
532         #new_user = PendingUser.objects.create_inactive_user(edited_first_name, edited_last_name, email,  password, site) 
533         #conventional approach
534         #b = PendingUser(first_name=edited_first_name, last_name=edited_last_name)
535         #b.save()
536         
537         # select and update [will be used throughout this view]
538         # select the logged in user [for the moment hard coded]
539         #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
540         # update first and last name
541         get_user.first_name = edited_first_name
542         get_user.last_name = edited_last_name
543         get_user.save() 
544
545         return HttpResponse('Success: Name Updated!!')       
546     elif 'submit_pass' in request.POST:
547         edited_password = request.POST['password']
548         # select the logged in user [for the moment hard coded]
549         #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
550         # update password
551         get_user.password = edited_password
552         get_user.save()
553         return HttpResponse('Success: Password Changed!!')
554     elif 'generate' in request.POST:
555         #import os
556         #from M2Crypto import Rand, RSA, BIO
557
558         KEY_LENGTH = 2048
559
560         def blank_callback():
561             "Replace the default dashes"
562             return
563
564         # Random seed
565         Rand.rand_seed (os.urandom (KEY_LENGTH))
566         # Generate key pair
567         key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
568         # Create memory buffers
569         pri_mem = BIO.MemoryBuffer()
570         pub_mem = BIO.MemoryBuffer()
571         # Save keys to buffers
572         key.save_key_bio(pri_mem, None)
573         key.save_pub_key_bio(pub_mem)
574
575         # Get keys 
576         public_key = pub_mem.getvalue()
577         private_key = pri_mem.getvalue()
578         # Saving to DB
579         keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
580         keypair = re.sub("\r", "", keypair)
581         keypair = re.sub("\n", "\\n", keypair)
582         #keypair = keypair.rstrip('\r\n')
583         keypair = ''.join(keypair.split())
584         get_user.keypair = keypair
585         get_user.save()
586         return HttpResponse('Success: New Keypair Generated! %s' % keypair)
587
588     elif 'upload_key' in request.POST:
589         up_file = request.FILES['pubkey']
590         file_content =  up_file.read()
591         file_name = up_file.name
592         file_extension = os.path.splitext(file_name)[1] 
593         allowed_extension =  ['.pub','.txt']
594         if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
595             file_content = '{"user_public_key":"'+ file_content +'"}'
596             file_content = re.sub("\r", "", file_content)
597             file_content = re.sub("\n", "\\n",file_content)
598             file_content = ''.join(file_content.split())
599             get_user.keypair = file_content
600             get_user.save()
601             return HttpResponse('Success: Publickey uploaded! Old records overwritten')
602         else:
603             return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')    
604         
605     else:
606         message = 'You submitted an empty form.'
607         return HttpResponse(message)
608
609 def register_4m_f4f(request):
610     #return render(request, 'register_4m_f4f.html')
611
612 #def reg_4m_f4f_process(request):
613     if 'submit' in request.POST:
614         #get_email = PendingUser.objects.get(email)
615         reg_fname = request.POST['firstname']
616         reg_lname = request.POST['lastname']
617         reg_aff = request.POST['affiliation']
618         reg_email = request.POST['email'].lower()
619         
620         #POST value validation  
621         if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
622             messages.error(request, 'First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
623             #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
624             return render(request, 'register_4m_f4f.html')
625         if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
626             messages.error(request, 'Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
627             #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
628             return render(request, 'register_4m_f4f.html')
629         if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
630             messages.error(request, 'Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
631             #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
632             return render(request, 'register_4m_f4f.html')
633         if PendingUser.objects.filter(email__iexact=reg_email):
634             messages.error(request, 'Email already registered.Please provide a new email address.')
635             #return HttpResponse("Email Already exists")
636             return render(request, 'register_4m_f4f.html')
637         if 'generate' in request.POST['question']:
638             #import os
639             #from M2Crypto import Rand, RSA, BIO
640             
641             KEY_LENGTH = 2048
642
643             def blank_callback():
644                 "Replace the default dashes"
645                 return
646
647             # Random seed
648             Rand.rand_seed (os.urandom (KEY_LENGTH))
649             # Generate key pair
650             key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
651             # Create memory buffers
652             pri_mem = BIO.MemoryBuffer()
653             pub_mem = BIO.MemoryBuffer()
654             # Save keys to buffers
655             key.save_key_bio(pri_mem, None)
656             key.save_pub_key_bio(pub_mem)
657             # Get keys 
658             public_key = pub_mem.getvalue()
659             private_key = pri_mem.getvalue()
660             # Saving to DB
661             keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
662             keypair = re.sub("\r", "", keypair)
663             keypair = re.sub("\n", "\\n", keypair)
664             #keypair = keypair.rstrip('\r\n')
665             keypair = ''.join(keypair.split())
666             #return HttpResponse(keypair)
667         else:
668             up_file = request.FILES['user_public_key']
669             file_content =  up_file.read()
670             file_name = up_file.name
671             file_extension = os.path.splitext(file_name)[1]
672             allowed_extension =  ['.pub','.txt']
673             if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
674                 keypair = '{"user_public_key":"'+ file_content +'"}'
675                 keypair = re.sub("\r", "", keypair)
676                 keypair = re.sub("\n", "\\n",keypair)
677                 keypair = ''.join(keypair.split())
678             else:
679                 return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')
680
681         b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff, 
682                         email=reg_email, password=request.POST['password'], keypair=keypair)
683         b.save()
684
685         return render(request, 'user_register_complete.html')
686     return render(request, 'register_4m_f4f.html')        
687     
688
689 # view for contact form
690 def contact(request):
691     if request.method == 'POST': # If the form has been submitted...
692         form = ContactForm(request.POST) # A form bound to the POST data
693         if form.is_valid(): # All validation rules pass
694             # Process the data in form.cleaned_data
695             first_name = form.cleaned_data['first_name']
696             last_name = form.cleaned_data['last_name']
697             affiliation = form.cleaned_data['affiliation']
698             subject = form.cleaned_data['subject']
699             message = form.cleaned_data['message']
700             email = form.cleaned_data['email'] # email of the sender
701             cc_myself = form.cleaned_data['cc_myself']
702
703             recipients = ['yasin.upmc@gmail.com']
704             if cc_myself:
705                 recipients.append(email)
706
707             from django.core.mail import send_mail
708             send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
709             return render(request,'contact_sent.html') # Redirect after POST
710     else:
711         form = ContactForm() # An unbound form
712     
713     return render(request, 'contact.html', {
714         'form': form,
715         'topmenu_items': topmenu_items('Contact Us', request),
716         'username': the_user (request)
717
718     })
719
720
721 def slice_request(request):
722     if request.method == 'POST': # If the form has been submitted...
723         form = SliceRequestForm(request.POST) # A form bound to the POST data
724         if form.is_valid(): # All validation rules pass
725             # Process the data in form.cleaned_data
726             slice_name = form.cleaned_data['slice_name']
727             number_of_nodes = form.cleaned_data['number_of_nodes']
728             type_of_nodes = form.cleaned_data['type_of_nodes']
729             purpose = form.cleaned_data['purpose']
730             email = form.cleaned_data['email'] # email of the sender
731             cc_myself = form.cleaned_data['cc_myself']
732
733             recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
734             if cc_myself:
735                 recipients.append(email)
736
737             from django.core.mail import send_mail
738             send_mail("Onelab New Slice request form submitted", [slice_name,number_of_nodes,type_of_nodes,purpose], email, recipients)
739             return render(request,'slicereq_recvd.html') # Redirect after POST
740     else:
741         form = SliceRequestForm() # An unbound form
742
743 #    template_env = {}
744 #    template_env['form'] = form
745 #    template_env['topmenu_items'] = topmenu_items('Request a slice', request) 
746 #    template_env['unfold1_main'] = render(request, 'slice_request_.html', {
747 #        'form': form,
748 #    })
749 #    from django.shortcuts                import render_to_response
750 #    from django.template                 import RequestContext
751 #    return render_to_response ('view-unfold1.html',template_env,
752 #                               context_instance=RequestContext(request))
753
754     return render(request, 'slice_request.html', {
755         'form': form,
756         'topmenu_items': topmenu_items('Request a slice', request),
757         'username': the_user (request) 
758     })
759
760
761 class PresViewView(TemplateView):
762     template_name = "view-unfold1.html"
763
764     def get_context_data(self, **kwargs):
765
766         page = Page(self.request)
767
768         pres_view = PresView(page = page)
769
770         context = super(PresViewView, self).get_context_data(**kwargs)
771
772         #context['ALL_STATIC'] = "all_static"
773         context['unfold1_main'] = pres_view.render(self.request)
774
775         # XXX This is repeated in all pages
776         # more general variables expected in the template
777         context['title'] = 'Test view that combines various plugins'
778         # the menu items on the top
779         context['topmenu_items'] = topmenu_items('PresView', self.request)
780         # so we can sho who is logged
781         context['username'] = the_user(self.request)
782
783         prelude_env = page.prelude_env()
784         context.update(prelude_env)
785
786         return context
787
788 def json_me(config_file,type):
789     json_answer = ''
790     for ligne in config_file:
791         if not ligne.startswith('#'):
792             args = ligne.split(';')
793             json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1]  + '" ,"descriptif":"' + args[2]+'"')
794             if type!="dynamic":
795                 json_answer += str(',"contraints":')
796                 if args[3]=="":
797                     json_answer += str('""')
798                 else:
799                     json_answer += str(args[3])
800             json_answer += str('},')
801     return json_answer[:-1]
802
803
804 DIR = '/var/myslice/'
805 STATIC = '%s/config_method_static' % DIR
806 DYNAMIC = '%s/config_method_dynamic' % DIR
807 ANIMATION = '%s/config_method_animation' % DIR
808
809 def pres_view_methods(request, type):
810
811     if type ==None:
812         return 0
813     elif type =="static":
814         config = open(STATIC, "r")
815         json_answer = str('{ "options": [')
816         json_answer += str(json_me(config,"static"))
817         json_answer += str('] }')
818         config.close()
819     elif type =="dynamic":
820         config = open(DYNAMIC, "r")
821         json_answer = str('{ "options": [')
822         json_answer += str(json_me(config,"dynamic"))
823         json_answer += str('] }')
824         config.close()
825     elif type =="animation":
826         config = open(ANIMATION, "r")
827         json_answer = str('{ "options": [')
828         json_answer += str(json_me(config,"animation"))
829         json_answer += str('] }')
830         config.close()
831     elif type =="all":
832         config = open(STATIC, "r")
833         json_answer = str('{ "static": [')
834         json_answer += str(json_me(config,"static"))
835         json_answer += str('],')
836         json_answer += str('"dynamic": [')
837         config.close()
838         config = open(DYNAMIC, "r")
839         json_answer += str(json_me(config,"dynamic"))
840         json_answer += str('],')
841         json_answer += str('"animation": [')
842         config.close()
843         config = open(ANIMATION, "r")
844         json_answer += str(json_me(config,"animation"))
845         json_answer += str('] }')
846         config.close()
847     else:
848         return 0
849     return HttpResponse (json_answer, mimetype="application/json")
850
851 def pres_view_animation(request, constraints, id):
852
853 # sites crees depuis 2008
854 # static.py?contraints=']date_created':1262325600&id='name_id"'
855
856     # method = request.getvalue('method') #ex : GetSites
857     #constraints = "']date_created':1262325600"
858     #id = "2"
859
860     if id == None:
861         return 0
862
863     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
864     # constraints = {}#request.getvalue('constraints') // nul = {}
865     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
866
867     config_file = open(ANIMATION, "r")
868     for ligne in config_file:
869         if not ligne.startswith('#'):
870             ligne = ligne.split('\n')
871             first = ligne[0].split(';')
872             if (str(first[1]) == str(id)):
873                 save = first
874     config_file.close()
875
876     #Les print_method, print_option sont definis par le client (js)
877     #Les animations acceptent que les connexions anonymous
878     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
879     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
880
881
882     #Creation d'un objet event
883     event = Event(args)
884     cmd = [{"params": {
885             "data": {
886                 "print_options": event.print_options,
887                 "print_method": event.print_method,
888                 "message": event.data
889             }
890         }
891     }]
892
893     json_answer = json.dumps(cmd)
894     return HttpResponse (json_answer, mimetype="application/json")
895
896 def pres_view_static(request, constraints, id):
897     #constraints = "']date_created':1262325600"
898     #id = "2"
899
900     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
901     # constraints = {}#request.getvalue('constraints') // nul = {}
902     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
903
904     config_file = open(STATIC, "r")
905     for ligne in config_file:
906         if not ligne.startswith('#'):
907             ligne = ligne.split('\n')
908             first = ligne[0].split(';')
909             if (str(first[1]) == str(id)):
910                 save = first
911     config_file.close()
912
913     #Les print_method, print_option sont definis par le client (js)
914     #Les animations acceptent que les connexions anonymous
915     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
916     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
917
918
919     #Creation d'un objet event
920     event = Event(args)
921     cmd = [{"params": {
922             "data": {
923                 "print_options": event.print_options,
924                 "print_method": event.print_method,
925                 "message": event.data
926             }
927         }
928     }]
929
930     json_answer = json.dumps(cmd)
931     return HttpResponse (json_answer, mimetype="application/json")