portal.register: added authority_hrn (TODO: deprecate Institution)
[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
688     authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
689     #authorities_query = Query.get('authority').select('authority_hrn')
690     authorities = execute_query(request, authorities_query)
691
692     if request.method == 'POST':
693         #get_email = PendingUser.objects.get(email)
694         reg_fname = request.POST.get('firstname', '')
695         reg_lname = request.POST.get('lastname', '')
696         reg_aff = request.POST.get('affiliation','')
697         reg_auth = request.POST.get('authority_hrn', '')
698         reg_email = request.POST.get('email','').lower()
699         
700         #POST value validation  
701         if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
702             errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
703             #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
704             #return render(request, 'register_4m_f4f.html')
705         if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
706             errors.append('Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
707             #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
708             #return render(request, 'register_4m_f4f.html')
709         if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
710             errors.append('Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
711             #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
712             #return render(request, 'register_4m_f4f.html')
713         # XXX validate authority hrn !!
714         if PendingUser.objects.filter(email__iexact=reg_email):
715             errors.append('Email already registered.Please provide a new email address.')
716             #return HttpResponse("Email Already exists")
717             #return render(request, 'register_4m_f4f.html')
718         if 'generate' in request.POST['question']:
719             #import os
720             #from M2Crypto import Rand, RSA, BIO
721             
722             KEY_LENGTH = 2048
723
724             def blank_callback():
725                 "Replace the default dashes"
726                 return
727
728             # Random seed
729             Rand.rand_seed (os.urandom (KEY_LENGTH))
730             # Generate key pair
731             key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
732             # Create memory buffers
733             pri_mem = BIO.MemoryBuffer()
734             pub_mem = BIO.MemoryBuffer()
735             # Save keys to buffers
736             key.save_key_bio(pri_mem, None)
737             key.save_pub_key_bio(pub_mem)
738             # Get keys 
739             public_key = pub_mem.getvalue()
740             private_key = pri_mem.getvalue()
741             # Saving to DB
742             keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
743             keypair = re.sub("\r", "", keypair)
744             keypair = re.sub("\n", "\\n", keypair)
745             #keypair = keypair.rstrip('\r\n')
746             keypair = ''.join(keypair.split())
747             #return HttpResponse(keypair)
748         else:
749             up_file = request.FILES['user_public_key']
750             file_content =  up_file.read()
751             file_name = up_file.name
752             file_extension = os.path.splitext(file_name)[1]
753             allowed_extension =  ['.pub','.txt']
754             if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
755                 keypair = '{"user_public_key":"'+ file_content +'"}'
756                 keypair = re.sub("\r", "", keypair)
757                 keypair = re.sub("\n", "\\n",keypair)
758                 keypair = ''.join(keypair.split())
759             else:
760                 errors.append('Please upload a valid RSA public key [.txt or .pub].')
761
762         #b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff, 
763         #                email=reg_email, password=request.POST['password'], keypair=keypair)
764         #b.save()
765         if not errors:
766             b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
767                             authority_hrn=reg_auth,
768                             email=reg_email, password=request.POST['password'], keypair=keypair)
769             b.save()
770             return render(request, 'user_register_complete.html')
771
772     return render(request, 'register_4m_f4f.html',{
773         'topmenu_items': topmenu_items('Register', request),
774         'errors': errors,
775         'firstname': request.POST.get('firstname', ''),
776         'lastname': request.POST.get('lastname', ''),
777         'affiliation': request.POST.get('affiliation', ''),
778         'authority_hrn': request.POST.get('authority_hrn', ''),
779         'email': request.POST.get('email', ''),
780         'password': request.POST.get('password', ''),           
781         'authorities': authorities
782     })        
783     
784
785 # view for contact form
786 def contact(request):
787     if request.method == 'POST': # If the form has been submitted...
788         form = ContactForm(request.POST) # A form bound to the POST data
789         if form.is_valid(): # All validation rules pass
790             # Process the data in form.cleaned_data
791             first_name = form.cleaned_data['first_name']
792             last_name = form.cleaned_data['last_name']
793             affiliation = form.cleaned_data['affiliation']
794             subject = form.cleaned_data['subject']
795             message = form.cleaned_data['message']
796             email = form.cleaned_data['email'] # email of the sender
797             cc_myself = form.cleaned_data['cc_myself']
798
799             recipients = ['yasin.upmc@gmail.com']
800             if cc_myself:
801                 recipients.append(email)
802
803             from django.core.mail import send_mail
804             send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
805             return render(request,'contact_sent.html') # Redirect after POST
806     else:
807         form = ContactForm() # An unbound form
808     
809     return render(request, 'contact.html', {
810         'form': form,
811         'topmenu_items': topmenu_items('Contact Us', request),
812         'username': the_user (request)
813
814     })
815
816
817 def slice_request(request):
818     if request.method == 'POST': # If the form has been submitted...
819         form = SliceRequestForm(request.POST) # A form bound to the POST data
820         if form.is_valid(): # All validation rules pass
821             # Process the data in form.cleaned_data
822             slice_name = form.cleaned_data['slice_name']
823             number_of_nodes = form.cleaned_data['number_of_nodes']
824             type_of_nodes = form.cleaned_data['type_of_nodes']
825             purpose = form.cleaned_data['purpose']
826             email = form.cleaned_data['email'] # email of the sender
827             cc_myself = form.cleaned_data['cc_myself']
828
829             recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
830             if cc_myself:
831                 recipients.append(email)
832
833             from django.core.mail import send_mail
834             send_mail("Onelab New Slice request form submitted", [slice_name,number_of_nodes,type_of_nodes,purpose], email, recipients)
835             return render(request,'slicereq_recvd.html') # Redirect after POST
836     else:
837         form = SliceRequestForm() # An unbound form
838
839 #    template_env = {}
840 #    template_env['form'] = form
841 #    template_env['topmenu_items'] = topmenu_items('Request a slice', request) 
842 #    template_env['unfold1_main'] = render(request, 'slice_request_.html', {
843 #        'form': form,
844 #    })
845 #    from django.shortcuts                import render_to_response
846 #    from django.template                 import RequestContext
847 #    return render_to_response ('view-unfold1.html',template_env,
848 #                               context_instance=RequestContext(request))
849
850     return render(request, 'slice_request.html', {
851         'form': form,
852         'topmenu_items': topmenu_items('Request a slice', request),
853         'username': the_user (request) 
854     })
855
856
857 class PresViewView(TemplateView):
858     template_name = "view-unfold1.html"
859
860     def get_context_data(self, **kwargs):
861
862         page = Page(self.request)
863
864         pres_view = PresView(page = page)
865
866         context = super(PresViewView, self).get_context_data(**kwargs)
867
868         #context['ALL_STATIC'] = "all_static"
869         context['unfold1_main'] = pres_view.render(self.request)
870
871         # XXX This is repeated in all pages
872         # more general variables expected in the template
873         context['title'] = 'Test view that combines various plugins'
874         # the menu items on the top
875         context['topmenu_items'] = topmenu_items('PresView', self.request)
876         # so we can sho who is logged
877         context['username'] = the_user(self.request)
878
879         prelude_env = page.prelude_env()
880         context.update(prelude_env)
881
882         return context
883
884 def json_me(config_file,type):
885     json_answer = ''
886     for ligne in config_file:
887         if not ligne.startswith('#'):
888             args = ligne.split(';')
889             json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1]  + '" ,"descriptif":"' + args[2]+'"')
890             if type!="dynamic":
891                 json_answer += str(',"contraints":')
892                 if args[3]=="":
893                     json_answer += str('""')
894                 else:
895                     json_answer += str(args[3])
896             json_answer += str('},')
897     return json_answer[:-1]
898
899
900 DIR = '/var/myslice/'
901 STATIC = '%s/config_method_static' % DIR
902 DYNAMIC = '%s/config_method_dynamic' % DIR
903 ANIMATION = '%s/config_method_animation' % DIR
904
905 def pres_view_methods(request, type):
906
907     if type ==None:
908         return 0
909     elif type =="static":
910         config = open(STATIC, "r")
911         json_answer = str('{ "options": [')
912         json_answer += str(json_me(config,"static"))
913         json_answer += str('] }')
914         config.close()
915     elif type =="dynamic":
916         config = open(DYNAMIC, "r")
917         json_answer = str('{ "options": [')
918         json_answer += str(json_me(config,"dynamic"))
919         json_answer += str('] }')
920         config.close()
921     elif type =="animation":
922         config = open(ANIMATION, "r")
923         json_answer = str('{ "options": [')
924         json_answer += str(json_me(config,"animation"))
925         json_answer += str('] }')
926         config.close()
927     elif type =="all":
928         config = open(STATIC, "r")
929         json_answer = str('{ "static": [')
930         json_answer += str(json_me(config,"static"))
931         json_answer += str('],')
932         json_answer += str('"dynamic": [')
933         config.close()
934         config = open(DYNAMIC, "r")
935         json_answer += str(json_me(config,"dynamic"))
936         json_answer += str('],')
937         json_answer += str('"animation": [')
938         config.close()
939         config = open(ANIMATION, "r")
940         json_answer += str(json_me(config,"animation"))
941         json_answer += str('] }')
942         config.close()
943     else:
944         return 0
945     return HttpResponse (json_answer, mimetype="application/json")
946
947 def pres_view_animation(request, constraints, id):
948
949 # sites crees depuis 2008
950 # static.py?contraints=']date_created':1262325600&id='name_id"'
951
952     # method = request.getvalue('method') #ex : GetSites
953     #constraints = "']date_created':1262325600"
954     #id = "2"
955
956     if id == None:
957         return 0
958
959     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
960     # constraints = {}#request.getvalue('constraints') // nul = {}
961     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
962
963     config_file = open(ANIMATION, "r")
964     for ligne in config_file:
965         if not ligne.startswith('#'):
966             ligne = ligne.split('\n')
967             first = ligne[0].split(';')
968             if (str(first[1]) == str(id)):
969                 save = first
970     config_file.close()
971
972     #Les print_method, print_option sont definis par le client (js)
973     #Les animations acceptent que les connexions anonymous
974     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
975     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
976
977
978     #Creation d'un objet event
979     event = Event(args)
980     cmd = [{"params": {
981             "data": {
982                 "print_options": event.print_options,
983                 "print_method": event.print_method,
984                 "message": event.data
985             }
986         }
987     }]
988
989     json_answer = json.dumps(cmd)
990     return HttpResponse (json_answer, mimetype="application/json")
991
992 def pres_view_static(request, constraints, id):
993     #constraints = "']date_created':1262325600"
994     #id = "2"
995
996     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
997     # constraints = {}#request.getvalue('constraints') // nul = {}
998     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
999
1000     config_file = open(STATIC, "r")
1001     for ligne in config_file:
1002         if not ligne.startswith('#'):
1003             ligne = ligne.split('\n')
1004             first = ligne[0].split(';')
1005             if (str(first[1]) == str(id)):
1006                 save = first
1007     config_file.close()
1008
1009     #Les print_method, print_option sont definis par le client (js)
1010     #Les animations acceptent que les connexions anonymous
1011     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
1012     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
1013
1014
1015     #Creation d'un objet event
1016     event = Event(args)
1017     cmd = [{"params": {
1018             "data": {
1019                 "print_options": event.print_options,
1020                 "print_method": event.print_method,
1021                 "message": event.data
1022             }
1023         }
1024     }]
1025
1026     json_answer = json.dumps(cmd)
1027     return HttpResponse (json_answer, mimetype="application/json")
1028
1029 class ValidatePendingView(TemplateView):
1030     template_name = "validate_pending.html"
1031
1032     def get_context_data(self, **kwargs):
1033         # We might have slices on different registries with different user accounts 
1034         # 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
1035         # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
1036
1037         #messages.info(self.request, 'You have logged in')
1038         page = Page(self.request)
1039
1040         ctx_my_authorities = {}
1041         ctx_delegation_authorities = {}
1042
1043
1044         # The user need to be logged in
1045         if the_user(self.request):
1046             # Who can a PI validate:
1047             # His own authorities + those he has credentials for.
1048             # In MySlice we need to look at credentials also.
1049             
1050
1051             # XXX This will have to be asynchroneous. Need to implement barriers,
1052             # for now it will be sufficient to have it working statically
1053
1054             # get user_id to later on query accounts
1055             # XXX Having real query plan on local tables would simplify all this
1056             # XXX $user_email is still not available for local tables
1057             #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id')
1058             user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id')
1059             user, = execute_query(self.request, user_query)
1060             user_id = user['user_id']
1061
1062             # Query manifold to learn about available SFA platforms for more information
1063             # In general we will at least have the portal
1064             # For now we are considering all registries
1065             all_authorities = []
1066             platform_ids = []
1067             sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
1068             sfa_platforms = execute_query(self.request, sfa_platforms_query)
1069             for sfa_platform in sfa_platforms:
1070                 print "SFA PLATFORM > ", sfa_platform['platform']
1071                 if not 'auth_type' in sfa_platform:
1072                     continue
1073                 auth = sfa_platform['auth_type']
1074                 if not auth in all_authorities:
1075                     all_authorities.append(auth)
1076                 platform_ids.append(sfa_platform['platform_id'])
1077
1078             # We can check on which the user has authoritity credentials = PI rights
1079             credential_authorities = set()
1080             credential_authorities_expired = set()
1081
1082             # User account on these registries
1083             user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config')
1084             user_accounts = execute_query(self.request, user_accounts_query)
1085             #print "=" * 80
1086             #print user_accounts
1087             #print "=" * 80
1088             for user_account in user_accounts:
1089                 config = json.loads(user_account['config'])
1090                 creds = []
1091                 if 'authority_credentials' in config:
1092                     for authority_hrn, credential in config['authority_credentials'].items():
1093                         #if credential is not expired:
1094                         credential_authorities.add(authority_hrn)
1095                         #else
1096                         #    credential_authorities_expired.add(authority_hrn)
1097                 if 'delegated_authority_credentials' in config:
1098                     for authority_hrn, credential in config['delegated_authority_credentials'].items():
1099                         #if credential is not expired:
1100                         credential_authorities.add(authority_hrn)
1101                         #else
1102                         #    credential_authorities_expired.add(authority_hrn)
1103
1104             print 'credential_authorities =', credential_authorities
1105             print 'credential_authorities_expired =', credential_authorities_expired
1106
1107             # ** Where am I a PI **
1108             # For this we need to ask SFA (of all authorities) = PI function
1109             pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
1110             pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
1111             pi_authorities = set()
1112             for pa in pi_authorities_tmp:
1113                 pi_authorities |= set(pa['pi_authorities'])
1114
1115             print "pi_authorities =", pi_authorities
1116             
1117             # My authorities + I have a credential
1118             pi_credential_authorities = pi_authorities & credential_authorities
1119             pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
1120             pi_expired_credential_authorities = pi_authorities & credential_authorities_expired
1121             # Authorities I've been delegated PI rights
1122             pi_delegation_credential_authorities = credential_authorities - pi_authorities
1123             pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities
1124
1125             print "pi_credential_authorities =", pi_credential_authorities
1126             print "pi_no_credential_authorities =", pi_no_credential_authorities
1127             print "pi_expired_credential_authorities =", pi_expired_credential_authorities
1128             print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities
1129             print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities
1130
1131             # Summary intermediary
1132             pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities
1133             pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities
1134
1135             print "--"
1136             print "pi_my_authorities = ", pi_my_authorities
1137             print "pi_delegation_authorities = ", pi_delegation_authorities
1138
1139             # Summary all
1140             queried_pending_authorities = pi_my_authorities | pi_delegation_authorities
1141             print "----"
1142             print "queried_pending_authorities = ", queried_pending_authorities
1143             
1144             # Pending requests + authorities
1145             #pending_users = PendingUser.objects.filter(authority_hrn__in = queried_pending_authorities).all() 
1146             #pending_slices = PendingSlice.objects.filter(authority_hrn__in = queried_pending_authorities).all() 
1147             pending_users = PendingUser.objects.all()
1148             pending_slices = PendingSlice.objects.all()
1149
1150             # Dispatch requests and build the proper structure for the template:
1151
1152             print "pending users =", pending_users
1153             print "pending slices =", pending_slices
1154
1155             for user in pending_users:
1156                 auth_hrn = user.authority_hrn
1157
1158                 request = {}
1159                 request['type'] = 'user'
1160                 request['id'] = 'TODO' # XXX in DB ?
1161                 request['timestamp'] = 'TODO' # XXX in DB ?
1162                 request['details'] = "%s %s <%s>" % (user.first_name, user.last_name, user.email)
1163
1164                 if auth_hrn in pi_my_authorities:
1165                     dest = ctx_my_authorities
1166
1167                     # define the css class
1168                     if auth_hrn in pi_credential_authorities:
1169                         request['allowed'] = 'allowed'
1170                     elif auth_hrn in pi_expired_credential_authorities:
1171                         request['allowed'] = 'expired'
1172                     else: # pi_no_credential_authorities
1173                         request['allowed'] = 'denied'
1174
1175                 elif auth_hrn in pi_delegation_authorities:
1176                     dest = ctx_delegation_authorities
1177
1178                     if auth_hrn in pi_delegation_credential_authorities:
1179                         request['allowed'] = 'allowed'
1180                     else: # pi_delegation_expired_authorities
1181                         request['allowed'] = 'expired'
1182
1183                 else:
1184                     continue
1185                     
1186                 if not auth_hrn in dest:
1187                     dest[auth_hrn] = []
1188                 print "auth_hrn [%s] was added %r" % (auth_hrn, request)
1189                 dest[auth_hrn].append(request) 
1190
1191             for slice in pending_slices:
1192                 auth_hrn = slice.authority_hrn
1193                 if not auth_hrn:
1194                     auth_hrn = "ple.upmc" # XXX HARDCODED
1195
1196                 request = {}
1197                 request['type'] = 'slice'
1198                 request['id'] = 'TODO' # XXX in DB ?
1199                 request['timestamp'] = 'TODO' # XXX in DB ?
1200                 request['details'] = "Number of nodes: %d -- Type of nodes: %s<br/>%s" % ('TODO', 'TODO', 'TODO') # XXX 
1201                 if auth_hrn in pi_my_authorities:
1202                     dest = ctx_my_authorities
1203
1204                     # define the css class
1205                     if auth_hrn in pi_credential_authorities:
1206                         request['allowed'] = 'allowed'
1207                     elif auth_hrn in pi_expired_credential_authorities:
1208                         request['allowed'] = 'expired'
1209                     else: # pi_no_credential_authorities
1210                         request['allowed'] = 'denied'
1211
1212                 elif auth_hrn in pi_delegation_authorities:
1213                     dest = ctx_delegation_authorities
1214
1215                     if auth_hrn in pi_delegation_credential_authorities:
1216                         request['allowed'] = 'allowed'
1217                     else: # pi_delegation_expired_authorities
1218                         request['allowed'] = 'expired'
1219                     
1220                 if not auth_hrn in dest:
1221                     dest[auth_hrn] = []
1222                 dest[auth_hrn].append(request) 
1223
1224         context = super(ValidatePendingView, self).get_context_data(**kwargs)
1225         context['my_authorities']   = ctx_my_authorities
1226         context['delegation_authorities'] = ctx_delegation_authorities
1227
1228         # XXX This is repeated in all pages
1229         # more general variables expected in the template
1230         context['title'] = 'Test view that combines various plugins'
1231         # the menu items on the top
1232         context['topmenu_items'] = topmenu_items('Dashboard', self.request) 
1233         # so we can sho who is logged
1234         context['username'] = the_user(self.request) 
1235
1236         # XXX We need to prepare the page for queries
1237         #context.update(page.prelude_env())
1238
1239         return context