Merge branch 'jordan' of ssh://git.onelab.eu/git/myslice into jordan
[myslice.git] / portal / views.py
1 # -*- coding: utf-8 -*-
2 #
3 # portal/views.py: views for the portal application
4 # This file is part of the Manifold project.
5 #
6 # Authors:
7 #   Jordan AugĂ© <jordan.auge@lip6.fr>
8 #   Mohammed Yasin Rahman <mohammed-yasin.rahman@lip6.fr>
9 # Copyright 2013, UPMC Sorbonne UniversitĂ©s / LIP6
10 #
11 # This program is free software; you can redistribute it and/or modify it under
12 # the terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 3, or (at your option) any later version.
14
15 # This program is distributed in the hope that it will be useful, but WITHOUT
16 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18 # details.
19
20 # You should have received a copy of the GNU General Public License along with
21 # this program; see the file COPYING.  If not, write to the Free Software
22 # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 import os.path, re
25 import json
26
27 #from django.views.generic        import View
28 from django.views.generic.base   import TemplateView
29 from django.shortcuts            import render
30 from django.template.loader      import render_to_string
31 from django.core.mail            import send_mail
32 from django.utils.decorators     import method_decorator
33 from django.contrib.auth.decorators import login_required
34
35 from plugins.lists.simplelist    import SimpleList
36 from plugins.hazelnut            import Hazelnut
37 from plugins.pres_view           import PresView
38 from portal.event import Event
39
40 from portal                      import signals
41 from portal.forms                import SliceRequestForm, ContactForm
42 from portal.util                 import RegistrationView, ActivationView
43 from portal.models               import PendingUser, PendingSlice
44 from portal.actions              import authority_get_pi_emails, get_request_by_authority, manifold_add_user, manifold_update_user
45 from manifold.manifoldapi        import execute_query
46 from manifold.core.query         import Query
47 from unfold.page                 import Page
48 from myslice.viewutils           import topmenu_items, the_user
49 from django.http                 import HttpResponseRedirect, HttpResponse
50
51 #class for my_account
52 class AccountView(TemplateView):
53     template_name = "my_account.html"
54     
55     #This view requires login 
56     @method_decorator(login_required)
57     def dispatch(self, *args, **kwargs):
58         return super(AccountView, self).dispatch(*args, **kwargs)
59
60
61     def get_context_data(self, **kwargs):
62         #page = Page(self.request)
63
64         user_query  = Query().get('local:user').select('config','email')
65         user_details = execute_query(self.request, user_query)
66         
67         # not always found in user_details...
68         config={}
69         for user_detail in user_details:
70             #email = user_detail['email']
71             if user_detail['config']:
72                 config = json.loads(user_detail['config'])
73
74         platform_query  = Query().get('local:platform').select('platform_id','platform')
75         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
76         platform_details = execute_query(self.request, platform_query)
77         account_details = execute_query(self.request, account_query)
78        
79         # initial assignment needed for users having no account  
80         platform_name = ''
81         account_type = ''
82         account_usr_hrn = ''
83         account_pub_key = ''
84         platform_name_list = []
85         account_type_list = []
86         usr_hrn_list = []
87         pub_key_list = []          
88         for account_detail in account_details:
89             for platform_detail in platform_details:
90                 if platform_detail['platform_id'] == account_detail['platform_id']:
91                     platform_name = platform_detail['platform']
92                     account_type = account_detail['auth_type']
93                     account_config = json.loads(account_detail['config'])
94                     # a bit more pythonic
95                     account_usr_hrn = account_config.get('user_hrn','N/A')
96                     account_pub_key = account_config.get('user_public_key','N/A')
97                     
98                     platform_name_list.append(platform_name)
99                     account_type_list.append(account_type)
100                     usr_hrn_list.append(account_usr_hrn)
101                     pub_key_list.append(account_pub_key)
102         
103         # combining 4 lists into 1 [to render in the template] 
104         lst = [{'platform_name': t[0], 'account_type': t[1], 'usr_hrn':t[2], 'usr_pubkey':t[3]} for t in zip(platform_name_list, account_type_list, usr_hrn_list, pub_key_list)]    
105         #print "test"
106         #print lst
107
108         context = super(AccountView, self).get_context_data(**kwargs)
109         context['data'] = lst
110         context['person']   = self.request.user
111         context ['firstname'] = config.get('firstname',"?")
112         context ['lastname'] = config.get('lastname',"?")
113         context ['fullname'] = context['firstname'] +' '+ context['lastname']
114         context ['authority'] = config.get('authority',"Unknown Authority")
115         #context['users'] = userlist.render(self.request)
116         
117         # XXX This is repeated in all pages
118         # more general variables expected in the template
119         context['title'] = 'Platforms connected to MySlice'
120         # the menu items on the top
121         context['topmenu_items'] = topmenu_items('My Account', self.request)
122         # so we can sho who is logged
123         context['username'] = the_user(self.request)
124 #        context ['firstname'] = config['firstname']
125         #context.update(page.prelude_env())
126         return context
127
128 @login_required
129 #my_acc form value processing
130 def account_process(request):
131     user_query  = Query().get('local:user').select('password','config')
132     user_details = execute_query(request, user_query)
133
134     if 'submit_name' in request.POST:
135         edited_first_name =  request.POST['fname']
136         edited_last_name =  request.POST['lname']
137         
138         config={}
139         for user_config in user_details:
140         #email = user_detail['email']
141             if user_config['config']:
142                 config = json.loads(user_config['config'])
143                 config['firstname'] = edited_first_name
144                 config['lastname'] = edited_last_name
145                 config['authority'] = config.get('authority','Unknown Authority')
146                 updated_config = json.dumps(config)
147         
148         # updating config local:user in manifold       
149         user_params = { 'config': updated_config}
150         manifold_update_user(request,user_params)
151         # this will be depricated, we will show the success msg in same page
152         return HttpResponse('Sucess: First Name and Last Name Updated!')       
153     elif 'submit_pass' in request.POST:
154         edited_password = request.POST['password']
155         
156         for user_pass in user_details:
157             user_pass['password'] = edited_password
158         #updating password in local:user
159         user_params = { 'password': user_pass['password']}
160         manifold_update_user(request,user_params)
161
162         return HttpResponse('Success: Password Changed!!')
163     elif 'generate' in request.POST:
164         # Generate public and private keys using SFA Library
165         from sfa.trust.certificate  import Keypair
166         k = Keypair(create=True)
167         public_key = k.get_pubkey_string()
168         private_key = k.as_pem()
169         private_key = ''.join(private_key.split())
170         public_key = "ssh-rsa " + public_key
171         # Saving to DB
172         keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
173 #        keypair = re.sub("\r", "", keypair)
174 #        keypair = re.sub("\n", "\\n", keypair)
175 #        #keypair = keypair.rstrip('\r\n')
176 #        keypair = ''.join(keypair.split())
177         get_user.keypair = keypair
178         get_user.save()
179         return HttpResponse('Success: New Keypair Generated! %s' % keypair)
180
181     elif 'upload_key' in request.POST:
182         up_file = request.FILES['pubkey']
183         file_content =  up_file.read()
184         file_name = up_file.name
185         file_extension = os.path.splitext(file_name)[1] 
186         allowed_extension =  ['.pub','.txt']
187         if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
188             file_content = '{"user_public_key":"'+ file_content +'"}'
189             file_content = re.sub("\r", "", file_content)
190             file_content = re.sub("\n", "\\n",file_content)
191             file_content = ''.join(file_content.split())
192             get_user.keypair = file_content
193             get_user.save()
194             return HttpResponse('Success: Publickey uploaded! Old records overwritten')
195         else:
196             return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')    
197         
198     else:
199         message = 'You submitted an empty form.'
200         return HttpResponse(message)
201
202 def register_4m_f4f(request):
203     errors = []
204
205     authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
206     #authorities_query = Query.get('authority').select('authority_hrn')
207     authorities = execute_query(request, authorities_query)
208
209     if request.method == 'POST':
210         # We shall use a form here
211
212         #get_email = PendingUser.objects.get(email)
213         reg_fname = request.POST.get('firstname', '')
214         reg_lname = request.POST.get('lastname', '')
215         #reg_aff = request.POST.get('affiliation','')
216         reg_auth = request.POST.get('authority_hrn', '')
217         reg_email = request.POST.get('email','').lower()
218         
219         #POST value validation  
220         if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
221             errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
222             #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
223             #return render(request, 'register_4m_f4f.html')
224         if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
225             errors.append('Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
226             #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
227             #return render(request, 'register_4m_f4f.html')
228 #        if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
229 #            errors.append('Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
230             #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
231             #return render(request, 'register_4m_f4f.html')
232         # XXX validate authority hrn !!
233         if PendingUser.objects.filter(email__iexact=reg_email):
234             errors.append('Email already registered.Please provide a new email address.')
235             #return HttpResponse("Email Already exists")
236             #return render(request, 'register_4m_f4f.html')
237         if 'generate' in request.POST['question']:
238             # Generate public and private keys using SFA Library
239             from sfa.trust.certificate  import Keypair
240             k = Keypair(create=True)
241             public_key = k.get_pubkey_string()
242             private_key = k.as_pem()
243             private_key = ''.join(private_key.split())
244             public_key = "ssh-rsa " + public_key
245             # Saving to DB
246             keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
247 #            keypair = re.sub("\r", "", keypair)
248 #            keypair = re.sub("\n", "\\n", keypair)
249 #            #keypair = keypair.rstrip('\r\n')
250 #            keypair = ''.join(keypair.split())
251         else:
252             up_file = request.FILES['user_public_key']
253             file_content =  up_file.read()
254             file_name = up_file.name
255             file_extension = os.path.splitext(file_name)[1]
256             allowed_extension =  ['.pub','.txt']
257             if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
258                 keypair = '{"user_public_key":"'+ file_content +'"}'
259                 keypair = re.sub("\r", "", keypair)
260                 keypair = re.sub("\n", "\\n",keypair)
261                 keypair = ''.join(keypair.split())
262             else:
263                 errors.append('Please upload a valid RSA public key [.txt or .pub].')
264
265         #b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff, 
266         #                email=reg_email, password=request.POST['password'], keypair=keypair)
267         #b.save()
268         if not errors:
269             b = PendingUser(
270                 first_name=reg_fname, 
271                 last_name=reg_lname, 
272                 #affiliation=reg_aff,
273                 authority_hrn=reg_auth,
274                 email=reg_email, 
275                 password=request.POST['password'],
276                 keypair=keypair
277             )
278             b.save()
279
280             # Send email
281             ctx = {
282                 first_name   : reg_fname, 
283                 last_name    : reg_lname, 
284                 #affiliation  : reg_aff,
285                 authority_hrn: reg_auth,
286                 email        : reg_email, 
287                 keypair      : keypair,
288                 cc_myself    : True # form.cleaned_data['cc_myself']
289             }
290
291             recipients = authority_get_pi_emails(authority_hrn)
292             if ctx['cc_myself']:
293                 recipients.append(ctx['email'])
294
295             msg = render_to_string('user_request_email.txt', ctx)
296             send_mail("Onelab New User request submitted", msg, email, recipients)
297
298             return render(request, 'user_register_complete.html')
299
300     return render(request, 'register_4m_f4f.html',{
301         'topmenu_items': topmenu_items('Register', request),
302         'errors': errors,
303         'firstname': request.POST.get('firstname', ''),
304         'lastname': request.POST.get('lastname', ''),
305         #'affiliation': request.POST.get('affiliation', ''),
306         'authority_hrn': request.POST.get('authority_hrn', ''),
307         'email': request.POST.get('email', ''),
308         'password': request.POST.get('password', ''),           
309         'authorities': authorities
310     })        
311     
312
313 # view for contact form
314 def contact(request):
315     if request.method == 'POST': # If the form has been submitted...
316         form = ContactForm(request.POST) # A form bound to the POST data
317         if form.is_valid(): # All validation rules pass
318             # Process the data in form.cleaned_data
319             first_name = form.cleaned_data['first_name']
320             last_name = form.cleaned_data['last_name']
321             affiliation = form.cleaned_data['affiliation']
322             subject = form.cleaned_data['subject']
323             message = form.cleaned_data['message']
324             email = form.cleaned_data['email'] # email of the sender
325             cc_myself = form.cleaned_data['cc_myself']
326
327             #recipients = authority_get_pi_emails(authority_hrn)
328             recipients = ['yasin.upmc@gmail.com']
329             if cc_myself:
330                 recipients.append(email)
331
332             from django.core.mail import send_mail
333             send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
334             return render(request,'contact_sent.html') # Redirect after POST
335     else:
336         form = ContactForm() # An unbound form
337     
338     return render(request, 'contact.html', {
339         'form': form,
340         'topmenu_items': topmenu_items('Contact Us', request),
341         'username': the_user (request)
342
343     })
344
345 @login_required
346 def slice_request(request):
347     errors = []
348
349     authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
350     #authorities_query = Query.get('authority').select('authority_hrn')
351     authorities = execute_query(request, authorities_query)
352
353     authority_hrn_tuple = []
354     for authority in authorities:
355         authority_hrn_tuple.append((authority['authority_hrn'], authority['name']))
356     authority_hrn_initial = {'authority_hrn': authority_hrn_tuple}
357         
358     # request.POST or None ?
359     if request.method == 'POST':
360         # The form has been submitted
361         form = SliceRequestForm(request.POST, initial=authority_hrn_initial) 
362
363         if form.is_valid():
364             slice_name      = form.cleaned_data['slice_name']
365             authority_hrn   = form.cleaned_data['authority_hrn']
366             number_of_nodes = form.cleaned_data['number_of_nodes']
367             type_of_nodes   = form.cleaned_data['type_of_nodes']
368             purpose         = form.cleaned_data['purpose']
369             
370             s = PendingSlice(
371                 slice_name      = slice_name,
372                 authority_hrn   = authority_hrn,
373                 number_of_nodes = number_of_nodes,
374                 type_of_nodes   = type_of_nodes,
375                 purpose         = purpose
376             )
377             s.save()
378
379             # All validation rules pass; process data in form.cleaned_data
380             # slice_name, number_of_nodes, type_of_nodes, purpose
381             email = form.cleaned_data['email'] # email of the sender
382             cc_myself = form.cleaned_data['cc_myself']
383
384             # The recipients are the PI of the authority
385             recipients = authority_get_pi_emails(authority_hrn)
386             #recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
387             if cc_myself:
388                 recipients.append(email)
389             msg = render_to_string('slice_request_email.txt', form.cleaned_data)
390             send_mail("Onelab New Slice request form submitted", msg, email, recipients)
391
392             return render(request,'slicereq_recvd.html') # Redirect after POST
393     else:
394         form = SliceRequestForm(initial=authority_hrn_initial)
395
396 #    template_env = {}
397 #    template_env['form'] = form
398 #    template_env['topmenu_items'] = topmenu_items('Request a slice', request) 
399 #    template_env['unfold1_main'] = render(request, 'slice_request_.html', {
400 #        'form': form,
401 #    })
402 #    from django.shortcuts                import render_to_response
403 #    from django.template                 import RequestContext
404 #    return render_to_response ('view-unfold1.html',template_env,
405 #                               context_instance=RequestContext(request))
406
407     return render(request, 'slice_request.html', {
408         'form': form,
409         'topmenu_items': topmenu_items('Request a slice', request),
410         'username': the_user (request) 
411     })
412
413
414 class PresViewView(TemplateView):
415     template_name = "view-unfold1.html"
416
417     def get_context_data(self, **kwargs):
418
419         page = Page(self.request)
420
421         pres_view = PresView(page = page)
422
423         context = super(PresViewView, self).get_context_data(**kwargs)
424
425         #context['ALL_STATIC'] = "all_static"
426         context['unfold1_main'] = pres_view.render(self.request)
427
428         # XXX This is repeated in all pages
429         # more general variables expected in the template
430         context['title'] = 'Test view that combines various plugins'
431         # the menu items on the top
432         context['topmenu_items'] = topmenu_items('PresView', self.request)
433         # so we can sho who is logged
434         context['username'] = the_user(self.request)
435
436         prelude_env = page.prelude_env()
437         context.update(prelude_env)
438
439         return context
440
441 def json_me(config_file,type):
442     json_answer = ''
443     for ligne in config_file:
444         if not ligne.startswith('#'):
445             args = ligne.split(';')
446             json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1]  + '" ,"descriptif":"' + args[2]+'"')
447             if type!="dynamic":
448                 json_answer += str(',"contraints":')
449                 if args[3]=="":
450                     json_answer += str('""')
451                 else:
452                     json_answer += str(args[3])
453             json_answer += str('},')
454     return json_answer[:-1]
455
456
457 DIR = '/var/myslice/'
458 STATIC = '%s/config_method_static' % DIR
459 DYNAMIC = '%s/config_method_dynamic' % DIR
460 ANIMATION = '%s/config_method_animation' % DIR
461
462 def pres_view_methods(request, type):
463
464     if type ==None:
465         return 0
466     elif type =="static":
467         config = open(STATIC, "r")
468         json_answer = str('{ "options": [')
469         json_answer += str(json_me(config,"static"))
470         json_answer += str('] }')
471         config.close()
472     elif type =="dynamic":
473         config = open(DYNAMIC, "r")
474         json_answer = str('{ "options": [')
475         json_answer += str(json_me(config,"dynamic"))
476         json_answer += str('] }')
477         config.close()
478     elif type =="animation":
479         config = open(ANIMATION, "r")
480         json_answer = str('{ "options": [')
481         json_answer += str(json_me(config,"animation"))
482         json_answer += str('] }')
483         config.close()
484     elif type =="all":
485         config = open(STATIC, "r")
486         json_answer = str('{ "static": [')
487         json_answer += str(json_me(config,"static"))
488         json_answer += str('],')
489         json_answer += str('"dynamic": [')
490         config.close()
491         config = open(DYNAMIC, "r")
492         json_answer += str(json_me(config,"dynamic"))
493         json_answer += str('],')
494         json_answer += str('"animation": [')
495         config.close()
496         config = open(ANIMATION, "r")
497         json_answer += str(json_me(config,"animation"))
498         json_answer += str('] }')
499         config.close()
500     else:
501         return 0
502     return HttpResponse (json_answer, mimetype="application/json")
503
504 def pres_view_animation(request, constraints, id):
505
506 # sites crees depuis 2008
507 # static.py?contraints=']date_created':1262325600&id='name_id"'
508
509     # method = request.getvalue('method') #ex : GetSites
510     #constraints = "']date_created':1262325600"
511     #id = "2"
512
513     if id == None:
514         return 0
515
516     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
517     # constraints = {}#request.getvalue('constraints') // nul = {}
518     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
519
520     config_file = open(ANIMATION, "r")
521     for ligne in config_file:
522         if not ligne.startswith('#'):
523             ligne = ligne.split('\n')
524             first = ligne[0].split(';')
525             if (str(first[1]) == str(id)):
526                 save = first
527     config_file.close()
528
529     #Les print_method, print_option sont definis par le client (js)
530     #Les animations acceptent que les connexions anonymous
531     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
532     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
533
534
535     #Creation d'un objet event
536     event = Event(args)
537     cmd = [{"params": {
538             "data": {
539                 "print_options": event.print_options,
540                 "print_method": event.print_method,
541                 "message": event.data
542             }
543         }
544     }]
545
546     json_answer = json.dumps(cmd)
547     return HttpResponse (json_answer, mimetype="application/json")
548
549 def pres_view_static(request, constraints, id):
550     #constraints = "']date_created':1262325600"
551     #id = "2"
552
553     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
554     # constraints = {}#request.getvalue('constraints') // nul = {}
555     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
556
557     config_file = open(STATIC, "r")
558     for ligne in config_file:
559         if not ligne.startswith('#'):
560             ligne = ligne.split('\n')
561             first = ligne[0].split(';')
562             if (str(first[1]) == str(id)):
563                 save = first
564     config_file.close()
565
566     #Les print_method, print_option sont definis par le client (js)
567     #Les animations acceptent que les connexions anonymous
568     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
569     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
570
571
572     #Creation d'un objet event
573     event = Event(args)
574     cmd = [{"params": {
575             "data": {
576                 "print_options": event.print_options,
577                 "print_method": event.print_method,
578                 "message": event.data
579             }
580         }
581     }]
582
583     json_answer = json.dumps(cmd)
584     return HttpResponse (json_answer, mimetype="application/json")
585
586 class ValidatePendingView(TemplateView):
587     template_name = "validate_pending.html"
588
589     def get_context_data(self, **kwargs):
590         # We might have slices on different registries with different user accounts 
591         # 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
592         # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
593
594         #messages.info(self.request, 'You have logged in')
595         page = Page(self.request)
596
597         ctx_my_authorities = {}
598         ctx_delegation_authorities = {}
599
600
601         # The user need to be logged in
602         if the_user(self.request):
603             # Who can a PI validate:
604             # His own authorities + those he has credentials for.
605             # In MySlice we need to look at credentials also.
606             
607
608             # XXX This will have to be asynchroneous. Need to implement barriers,
609             # for now it will be sufficient to have it working statically
610
611             # get user_id to later on query accounts
612             # XXX Having real query plan on local tables would simplify all this
613             # XXX $user_email is still not available for local tables
614             #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id')
615             user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id')
616             user, = execute_query(self.request, user_query)
617             user_id = user['user_id']
618
619             # Query manifold to learn about available SFA platforms for more information
620             # In general we will at least have the portal
621             # For now we are considering all registries
622             all_authorities = []
623             platform_ids = []
624             sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
625             sfa_platforms = execute_query(self.request, sfa_platforms_query)
626             for sfa_platform in sfa_platforms:
627                 print "SFA PLATFORM > ", sfa_platform['platform']
628                 if not 'auth_type' in sfa_platform:
629                     continue
630                 auth = sfa_platform['auth_type']
631                 if not auth in all_authorities:
632                     all_authorities.append(auth)
633                 platform_ids.append(sfa_platform['platform_id'])
634
635             # We can check on which the user has authoritity credentials = PI rights
636             credential_authorities = set()
637             credential_authorities_expired = set()
638
639             # User account on these registries
640             user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config')
641             user_accounts = execute_query(self.request, user_accounts_query)
642             #print "=" * 80
643             #print user_accounts
644             #print "=" * 80
645             for user_account in user_accounts:
646                 config = json.loads(user_account['config'])
647                 creds = []
648                 if 'authority_credentials' in config:
649                     for authority_hrn, credential in config['authority_credentials'].items():
650                         #if credential is not expired:
651                         credential_authorities.add(authority_hrn)
652                         #else
653                         #    credential_authorities_expired.add(authority_hrn)
654                 if 'delegated_authority_credentials' in config:
655                     for authority_hrn, credential in config['delegated_authority_credentials'].items():
656                         #if credential is not expired:
657                         credential_authorities.add(authority_hrn)
658                         #else
659                         #    credential_authorities_expired.add(authority_hrn)
660
661             print 'credential_authorities =', credential_authorities
662             print 'credential_authorities_expired =', credential_authorities_expired
663
664             # ** Where am I a PI **
665             # For this we need to ask SFA (of all authorities) = PI function
666             pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
667             pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
668             pi_authorities = set()
669             for pa in pi_authorities_tmp:
670                 pi_authorities |= set(pa['pi_authorities'])
671
672             print "pi_authorities =", pi_authorities
673             
674             # My authorities + I have a credential
675             pi_credential_authorities = pi_authorities & credential_authorities
676             pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
677             pi_expired_credential_authorities = pi_authorities & credential_authorities_expired
678             # Authorities I've been delegated PI rights
679             pi_delegation_credential_authorities = credential_authorities - pi_authorities
680             pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities
681
682             print "pi_credential_authorities =", pi_credential_authorities
683             print "pi_no_credential_authorities =", pi_no_credential_authorities
684             print "pi_expired_credential_authorities =", pi_expired_credential_authorities
685             print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities
686             print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities
687
688             # Summary intermediary
689             pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities
690             pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities
691
692             print "--"
693             print "pi_my_authorities = ", pi_my_authorities
694             print "pi_delegation_authorities = ", pi_delegation_authorities
695
696             # Summary all
697             queried_pending_authorities = pi_my_authorities | pi_delegation_authorities
698             print "----"
699             print "queried_pending_authorities = ", queried_pending_authorities
700
701             requests = get_request_by_authority(queried_pending_authorities)
702             for request in requests:
703                 auth_hrn = request['authority_hrn']
704
705                 if auth_hrn in pi_my_authorities:
706                     dest = ctx_my_authorities
707
708                     # define the css class
709                     if auth_hrn in pi_credential_authorities:
710                         request['allowed'] = 'allowed'
711                     elif auth_hrn in pi_expired_credential_authorities:
712                         request['allowed'] = 'expired'
713                     else: # pi_no_credential_authorities
714                         request['allowed'] = 'denied'
715
716                 elif auth_hrn in pi_delegation_authorities:
717                     dest = ctx_delegation_authorities
718
719                     if auth_hrn in pi_delegation_credential_authorities:
720                         request['allowed'] = 'allowed'
721                     else: # pi_delegation_expired_authorities
722                         request['allowed'] = 'expired'
723
724                 else:
725                     continue
726
727                 if not auth_hrn in dest:
728                     dest[auth_hrn] = []
729                 dest[auth_hrn].append(request) 
730         
731         context = super(ValidatePendingView, self).get_context_data(**kwargs)
732         context['my_authorities']   = ctx_my_authorities
733         context['delegation_authorities'] = ctx_delegation_authorities
734
735         # XXX This is repeated in all pages
736         # more general variables expected in the template
737         context['title'] = 'Test view that combines various plugins'
738         # the menu items on the top
739         context['topmenu_items'] = topmenu_items('Dashboard', self.request) 
740         # so we can sho who is logged
741         context['username'] = the_user(self.request) 
742
743         # XXX We need to prepare the page for queries
744         #context.update(page.prelude_env())
745
746         return context