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