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