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