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