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