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