1 # -*- coding: utf-8 -*-
3 # portal/views.py: views for the portal application
4 # This file is part of the Manifold project.
7 # Jordan Augé <jordan.auge@lip6.fr>
8 # Mohammed Yasin Rahman <mohammed-yasin.rahman@lip6.fr>
9 # Copyright 2013, UPMC Sorbonne Universités / LIP6
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.
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
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.
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
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
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
52 from M2Crypto import Rand, RSA, BIO
55 # View for 1 platform and its details
56 class PlatformView(TemplateView):
57 template_name = "platform.html"
59 def get_context_data(self, **kwargs):
60 page = Page(self.request)
62 for key, value in kwargs.iteritems():
63 print "%s = %s" % (key, value)
64 if key == "platformname":
67 network_query = Query().get('local:platform').filter_by('platform', '==', platformname).select('platform','platform_longname','gateway_type')
68 page.enqueue_query(network_query)
70 page.expose_js_metadata()
72 networklist = Hazelnut(
76 # this is the query at the core of the slice list
77 query = network_query,
78 query_all = network_query,
80 datatables_options = {
81 # for now we turn off sorting on the checkboxes columns this way
82 # this of course should be automatic in hazelnut
83 'aoColumns' : [None, None, None, None, {'bSortable': False}],
84 'iDisplayLength' : 25,
85 'bLengthChange' : True,
89 # networklist = SimpleList(
93 # query = network_query,
96 context = super(PlatformView, self).get_context_data(**kwargs)
97 context['person'] = self.request.user
98 context['networks'] = networklist.render(self.request)
100 # XXX This is repeated in all pages
101 # more general variables expected in the template
102 context['title'] = 'Platforms connected to MySlice'
103 # the menu items on the top
104 context['topmenu_items'] = topmenu_items('Platforms', self.request)
105 # so we can sho who is logged
106 context['username'] = the_user(self.request)
108 context.update(page.prelude_env())
114 #class for my_account
115 class AccountView(TemplateView):
116 template_name = "my_account.html"
118 #This view requires login
119 @method_decorator(login_required)
120 def dispatch(self, *args, **kwargs):
121 return super(AccountView, self).dispatch(*args, **kwargs)
124 def get_context_data(self, **kwargs):
125 #page = Page(self.request)
127 user_query = Query().get('local:user').select('config','email')
128 user_details = execute_query(self.request, user_query)
130 # not always found in user_details...
132 for user_detail in user_details:
133 #email = user_detail['email']
134 if user_detail['config']:
135 config = json.loads(user_detail['config'])
137 platform_query = Query().get('local:platform').select('platform_id','platform')
138 account_query = Query().get('local:account').select('user_id','platform_id','auth_type','config')
139 platform_details = execute_query(self.request, platform_query)
140 account_details = execute_query(self.request, account_query)
142 # initial assignment needed for users having no account
147 platform_name_list = []
148 account_type_list = []
151 for account_detail in account_details:
152 for platform_detail in platform_details:
153 if platform_detail['platform_id'] == account_detail['platform_id']:
154 platform_name = platform_detail['platform']
155 account_type = account_detail['auth_type']
156 account_config = json.loads(account_detail['config'])
157 # a bit more pythonic
158 account_usr_hrn = account_config.get('user_hrn','N/A')
159 account_pub_key = account_config.get('user_public_key','N/A')
161 platform_name_list.append(platform_name)
162 account_type_list.append(account_type)
163 usr_hrn_list.append(account_usr_hrn)
164 pub_key_list.append(account_pub_key)
166 # combining 4 lists into 1 [to render in the template]
167 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)]
171 context = super(AccountView, self).get_context_data(**kwargs)
172 context['data'] = lst
173 context['person'] = self.request.user
174 context ['firstname'] = config.get('firstname',"?")
175 context ['lastname'] = config.get('lastname',"?")
176 context ['fullname'] = context['firstname'] +' '+ context['lastname']
177 context ['affiliation'] = config.get('affiliation',"Unknown Affiliation")
178 #context['users'] = userlist.render(self.request)
180 # XXX This is repeated in all pages
181 # more general variables expected in the template
182 context['title'] = 'Platforms connected to MySlice'
183 # the menu items on the top
184 context['topmenu_items'] = topmenu_items('My Account', self.request)
185 # so we can sho who is logged
186 context['username'] = the_user(self.request)
187 # context ['firstname'] = config['firstname']
188 #context.update(page.prelude_env())
197 # View for my_account form
198 #def my_account(request):
199 # return render(request, 'my_account.html', {
201 # 'topmenu_items': topmenu_items('My Account', request),
202 # 'username': the_user (request)
207 #my_acc form value processing
208 def account_process(request):
209 # getting the user_id from the session [now hardcoded]
210 get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
211 # getting user info from manifold
212 if 'submit_name' in request.POST:
213 edited_first_name = request.POST['fname']
214 edited_last_name = request.POST['lname']
215 #email = 'test_email@gmail.com'
216 #password = 'test_pp'
217 #message = 'F_Name: %s L_name: %s dummy_pp: %s' % (first_name, last_name, password)
220 # insert into DB [needed for registration page]
221 #approach borrowed from register view
222 #new_user = PendingUser.objects.create_inactive_user(edited_first_name, edited_last_name, email, password, site)
223 #conventional approach
224 #b = PendingUser(first_name=edited_first_name, last_name=edited_last_name)
227 # select and update [will be used throughout this view]
228 # select the logged in user [for the moment hard coded]
229 #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
230 # update first and last name
231 #get_user.first_name = edited_first_name
232 #get_user.last_name = edited_last_name
234 #user_params = {'config':'hello'}
235 #query = Query.update('local:user').set(user_params).select('config')
236 #results = execute_query(request,query)
238 # raise Exception, "Failed to update user: %s" % user_params['config']
240 #return result['config']
241 # create user is working fine :)
242 #user_params = ({'config':'"firstname":"HELLO"'},{'password':'hello'})
243 #user_params = { 'config':'{"firstname":"HEY"}'}
244 #user_params = {'email':'aa@aa.com','password':'demo'}
245 #manifold_add_user(request,user_params)
246 #manifold_update_user(request,user_params)
248 return HttpResponse('Sucess: First Name and Last Name Updated!')
249 elif 'submit_pass' in request.POST:
250 edited_password = request.POST['password']
251 # select the logged in user [for the moment hard coded]
252 #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
254 get_user.password = edited_password
256 return HttpResponse('Success: Password Changed!!')
257 elif 'generate' in request.POST:
258 # Generate public and private keys using SFA Library
259 from sfa.trust.certificate import Keypair
260 k = Keypair(create=True)
261 public_key = k.get_pubkey_string()
262 private_key = k.as_pem()
267 # def blank_callback():
268 # "Replace the default dashes"
272 # Rand.rand_seed (os.urandom (KEY_LENGTH))
273 # # Generate key pair
274 # key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
275 # # Create memory buffers
276 # pri_mem = BIO.MemoryBuffer()
277 # pub_mem = BIO.MemoryBuffer()
278 # # Save keys to buffers
279 # key.save_key_bio(pri_mem, None)
280 # key.save_pub_key_bio(pub_mem)
283 # public_key = pub_mem.getvalue()
284 # private_key = pri_mem.getvalue()
285 private_key = ''.join(private_key.split())
286 public_key = "ssh-rsa " + public_key
288 keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
289 # keypair = re.sub("\r", "", keypair)
290 # keypair = re.sub("\n", "\\n", keypair)
291 # #keypair = keypair.rstrip('\r\n')
292 # keypair = ''.join(keypair.split())
293 get_user.keypair = keypair
295 return HttpResponse('Success: New Keypair Generated! %s' % keypair)
297 elif 'upload_key' in request.POST:
298 up_file = request.FILES['pubkey']
299 file_content = up_file.read()
300 file_name = up_file.name
301 file_extension = os.path.splitext(file_name)[1]
302 allowed_extension = ['.pub','.txt']
303 if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
304 file_content = '{"user_public_key":"'+ file_content +'"}'
305 file_content = re.sub("\r", "", file_content)
306 file_content = re.sub("\n", "\\n",file_content)
307 file_content = ''.join(file_content.split())
308 get_user.keypair = file_content
310 return HttpResponse('Success: Publickey uploaded! Old records overwritten')
312 return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')
315 message = 'You submitted an empty form.'
316 return HttpResponse(message)
318 def register_4m_f4f(request):
321 authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
322 #authorities_query = Query.get('authority').select('authority_hrn')
323 authorities = execute_query(request, authorities_query)
325 if request.method == 'POST':
326 # We shall use a form here
328 #get_email = PendingUser.objects.get(email)
329 reg_fname = request.POST.get('firstname', '')
330 reg_lname = request.POST.get('lastname', '')
331 reg_aff = request.POST.get('affiliation','')
332 reg_auth = request.POST.get('authority_hrn', '')
333 reg_email = request.POST.get('email','').lower()
335 #POST value validation
336 if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
337 errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
338 #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
339 #return render(request, 'register_4m_f4f.html')
340 if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
341 errors.append('Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
342 #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
343 #return render(request, 'register_4m_f4f.html')
344 if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
345 errors.append('Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
346 #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
347 #return render(request, 'register_4m_f4f.html')
348 # XXX validate authority hrn !!
349 if PendingUser.objects.filter(email__iexact=reg_email):
350 errors.append('Email already registered.Please provide a new email address.')
351 #return HttpResponse("Email Already exists")
352 #return render(request, 'register_4m_f4f.html')
353 if 'generate' in request.POST['question']:
354 # Generate public and private keys using SFA Library
355 from sfa.trust.certificate import Keypair
356 k = Keypair(create=True)
357 public_key = k.get_pubkey_string()
358 private_key = k.as_pem()
362 # #from M2Crypto import Rand, RSA, BIO
366 # def blank_callback():
367 # "Replace the default dashes"
371 # Rand.rand_seed (os.urandom (KEY_LENGTH))
372 # # Generate key pair
373 # key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
374 # # Create memory buffers
375 # pri_mem = BIO.MemoryBuffer()
376 # pub_mem = BIO.MemoryBuffer()
377 # # Save keys to buffers
378 # key.save_key_bio(pri_mem, None)
379 # key.save_pub_key_bio(pub_mem)
381 # public_key = pub_mem.getvalue()
382 # private_key = pri_mem.getvalue()
384 private_key = ''.join(private_key.split())
385 public_key = "ssh-rsa " + public_key
387 keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
388 # keypair = re.sub("\r", "", keypair)
389 # keypair = re.sub("\n", "\\n", keypair)
390 # #keypair = keypair.rstrip('\r\n')
391 # keypair = ''.join(keypair.split())
393 up_file = request.FILES['user_public_key']
394 file_content = up_file.read()
395 file_name = up_file.name
396 file_extension = os.path.splitext(file_name)[1]
397 allowed_extension = ['.pub','.txt']
398 if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
399 keypair = '{"user_public_key":"'+ file_content +'"}'
400 keypair = re.sub("\r", "", keypair)
401 keypair = re.sub("\n", "\\n",keypair)
402 keypair = ''.join(keypair.split())
404 errors.append('Please upload a valid RSA public key [.txt or .pub].')
406 #b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
407 # email=reg_email, password=request.POST['password'], keypair=keypair)
411 first_name=reg_fname,
414 authority_hrn=reg_auth,
416 password=request.POST['password'],
423 first_name : reg_fname,
424 last_name : reg_lname,
425 affiliation : reg_aff,
426 authority_hrn: reg_auth,
429 cc_myself : True # form.cleaned_data['cc_myself']
432 recipients = authority_get_pi_emails(authority_hrn)
434 recipients.append(ctx['email'])
436 msg = render_to_string('user_request_email.txt', ctx)
437 send_mail("Onelab New User request submitted", msg, email, recipients)
439 return render(request, 'user_register_complete.html')
441 return render(request, 'register_4m_f4f.html',{
442 'topmenu_items': topmenu_items('Register', request),
444 'firstname': request.POST.get('firstname', ''),
445 'lastname': request.POST.get('lastname', ''),
446 'affiliation': request.POST.get('affiliation', ''),
447 'authority_hrn': request.POST.get('authority_hrn', ''),
448 'email': request.POST.get('email', ''),
449 'password': request.POST.get('password', ''),
450 'authorities': authorities
454 # view for contact form
455 def contact(request):
456 if request.method == 'POST': # If the form has been submitted...
457 form = ContactForm(request.POST) # A form bound to the POST data
458 if form.is_valid(): # All validation rules pass
459 # Process the data in form.cleaned_data
460 first_name = form.cleaned_data['first_name']
461 last_name = form.cleaned_data['last_name']
462 affiliation = form.cleaned_data['affiliation']
463 subject = form.cleaned_data['subject']
464 message = form.cleaned_data['message']
465 email = form.cleaned_data['email'] # email of the sender
466 cc_myself = form.cleaned_data['cc_myself']
468 #recipients = authority_get_pi_emails(authority_hrn)
469 recipients = ['yasin.upmc@gmail.com']
471 recipients.append(email)
473 from django.core.mail import send_mail
474 send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
475 return render(request,'contact_sent.html') # Redirect after POST
477 form = ContactForm() # An unbound form
479 return render(request, 'contact.html', {
481 'topmenu_items': topmenu_items('Contact Us', request),
482 'username': the_user (request)
487 def slice_request(request):
490 authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
491 #authorities_query = Query.get('authority').select('authority_hrn')
492 authorities = execute_query(request, authorities_query)
494 authority_hrn_tuple = []
495 for authority in authorities:
496 authority_hrn_tuple.append((authority['authority_hrn'], authority['name']))
497 authority_hrn_initial = {'authority_hrn': authority_hrn_tuple}
499 # request.POST or None ?
500 if request.method == 'POST':
501 # The form has been submitted
502 form = SliceRequestForm(request.POST, initial=authority_hrn_initial)
505 slice_name = form.cleaned_data['slice_name']
506 authority_hrn = form.cleaned_data['authority_hrn']
507 number_of_nodes = form.cleaned_data['number_of_nodes']
508 type_of_nodes = form.cleaned_data['type_of_nodes']
509 purpose = form.cleaned_data['purpose']
512 slice_name = slice_name,
513 authority_hrn = authority_hrn,
514 number_of_nodes = number_of_nodes,
515 type_of_nodes = type_of_nodes,
520 # All validation rules pass; process data in form.cleaned_data
521 # slice_name, number_of_nodes, type_of_nodes, purpose
522 email = form.cleaned_data['email'] # email of the sender
523 cc_myself = form.cleaned_data['cc_myself']
525 # The recipients are the PI of the authority
526 recipients = authority_get_pi_emails(authority_hrn)
527 #recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
529 recipients.append(email)
530 msg = render_to_string('slice_request_email.txt', form.cleaned_data)
531 send_mail("Onelab New Slice request form submitted", msg, email, recipients)
533 return render(request,'slicereq_recvd.html') # Redirect after POST
535 form = SliceRequestForm(initial=authority_hrn_initial)
538 # template_env['form'] = form
539 # template_env['topmenu_items'] = topmenu_items('Request a slice', request)
540 # template_env['unfold1_main'] = render(request, 'slice_request_.html', {
543 # from django.shortcuts import render_to_response
544 # from django.template import RequestContext
545 # return render_to_response ('view-unfold1.html',template_env,
546 # context_instance=RequestContext(request))
548 return render(request, 'slice_request.html', {
550 'topmenu_items': topmenu_items('Request a slice', request),
551 'username': the_user (request)
555 class PresViewView(TemplateView):
556 template_name = "view-unfold1.html"
558 def get_context_data(self, **kwargs):
560 page = Page(self.request)
562 pres_view = PresView(page = page)
564 context = super(PresViewView, self).get_context_data(**kwargs)
566 #context['ALL_STATIC'] = "all_static"
567 context['unfold1_main'] = pres_view.render(self.request)
569 # XXX This is repeated in all pages
570 # more general variables expected in the template
571 context['title'] = 'Test view that combines various plugins'
572 # the menu items on the top
573 context['topmenu_items'] = topmenu_items('PresView', self.request)
574 # so we can sho who is logged
575 context['username'] = the_user(self.request)
577 prelude_env = page.prelude_env()
578 context.update(prelude_env)
582 def json_me(config_file,type):
584 for ligne in config_file:
585 if not ligne.startswith('#'):
586 args = ligne.split(';')
587 json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1] + '" ,"descriptif":"' + args[2]+'"')
589 json_answer += str(',"contraints":')
591 json_answer += str('""')
593 json_answer += str(args[3])
594 json_answer += str('},')
595 return json_answer[:-1]
598 DIR = '/var/myslice/'
599 STATIC = '%s/config_method_static' % DIR
600 DYNAMIC = '%s/config_method_dynamic' % DIR
601 ANIMATION = '%s/config_method_animation' % DIR
603 def pres_view_methods(request, type):
607 elif type =="static":
608 config = open(STATIC, "r")
609 json_answer = str('{ "options": [')
610 json_answer += str(json_me(config,"static"))
611 json_answer += str('] }')
613 elif type =="dynamic":
614 config = open(DYNAMIC, "r")
615 json_answer = str('{ "options": [')
616 json_answer += str(json_me(config,"dynamic"))
617 json_answer += str('] }')
619 elif type =="animation":
620 config = open(ANIMATION, "r")
621 json_answer = str('{ "options": [')
622 json_answer += str(json_me(config,"animation"))
623 json_answer += str('] }')
626 config = open(STATIC, "r")
627 json_answer = str('{ "static": [')
628 json_answer += str(json_me(config,"static"))
629 json_answer += str('],')
630 json_answer += str('"dynamic": [')
632 config = open(DYNAMIC, "r")
633 json_answer += str(json_me(config,"dynamic"))
634 json_answer += str('],')
635 json_answer += str('"animation": [')
637 config = open(ANIMATION, "r")
638 json_answer += str(json_me(config,"animation"))
639 json_answer += str('] }')
643 return HttpResponse (json_answer, mimetype="application/json")
645 def pres_view_animation(request, constraints, id):
647 # sites crees depuis 2008
648 # static.py?contraints=']date_created':1262325600&id='name_id"'
650 # method = request.getvalue('method') #ex : GetSites
651 #constraints = "']date_created':1262325600"
657 # method = 'GetSites'#request.getvalue('method') #ex : GetSites
658 # constraints = {}#request.getvalue('constraints') // nul = {}
659 # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
661 config_file = open(ANIMATION, "r")
662 for ligne in config_file:
663 if not ligne.startswith('#'):
664 ligne = ligne.split('\n')
665 first = ligne[0].split(';')
666 if (str(first[1]) == str(id)):
670 #Les print_method, print_option sont definis par le client (js)
671 #Les animations acceptent que les connexions anonymous
672 # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
673 args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
676 #Creation d'un objet event
680 "print_options": event.print_options,
681 "print_method": event.print_method,
682 "message": event.data
687 json_answer = json.dumps(cmd)
688 return HttpResponse (json_answer, mimetype="application/json")
690 def pres_view_static(request, constraints, id):
691 #constraints = "']date_created':1262325600"
694 # method = 'GetSites'#request.getvalue('method') #ex : GetSites
695 # constraints = {}#request.getvalue('constraints') // nul = {}
696 # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
698 config_file = open(STATIC, "r")
699 for ligne in config_file:
700 if not ligne.startswith('#'):
701 ligne = ligne.split('\n')
702 first = ligne[0].split(';')
703 if (str(first[1]) == str(id)):
707 #Les print_method, print_option sont definis par le client (js)
708 #Les animations acceptent que les connexions anonymous
709 # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
710 args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
713 #Creation d'un objet event
717 "print_options": event.print_options,
718 "print_method": event.print_method,
719 "message": event.data
724 json_answer = json.dumps(cmd)
725 return HttpResponse (json_answer, mimetype="application/json")
727 class ValidatePendingView(TemplateView):
728 template_name = "validate_pending.html"
730 def get_context_data(self, **kwargs):
731 # We might have slices on different registries with different user accounts
732 # 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
733 # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
735 #messages.info(self.request, 'You have logged in')
736 page = Page(self.request)
738 ctx_my_authorities = {}
739 ctx_delegation_authorities = {}
742 # The user need to be logged in
743 if the_user(self.request):
744 # Who can a PI validate:
745 # His own authorities + those he has credentials for.
746 # In MySlice we need to look at credentials also.
749 # XXX This will have to be asynchroneous. Need to implement barriers,
750 # for now it will be sufficient to have it working statically
752 # get user_id to later on query accounts
753 # XXX Having real query plan on local tables would simplify all this
754 # XXX $user_email is still not available for local tables
755 #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id')
756 user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id')
757 user, = execute_query(self.request, user_query)
758 user_id = user['user_id']
760 # Query manifold to learn about available SFA platforms for more information
761 # In general we will at least have the portal
762 # For now we are considering all registries
765 sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
766 sfa_platforms = execute_query(self.request, sfa_platforms_query)
767 for sfa_platform in sfa_platforms:
768 print "SFA PLATFORM > ", sfa_platform['platform']
769 if not 'auth_type' in sfa_platform:
771 auth = sfa_platform['auth_type']
772 if not auth in all_authorities:
773 all_authorities.append(auth)
774 platform_ids.append(sfa_platform['platform_id'])
776 # We can check on which the user has authoritity credentials = PI rights
777 credential_authorities = set()
778 credential_authorities_expired = set()
780 # User account on these registries
781 user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config')
782 user_accounts = execute_query(self.request, user_accounts_query)
786 for user_account in user_accounts:
787 config = json.loads(user_account['config'])
789 if 'authority_credentials' in config:
790 for authority_hrn, credential in config['authority_credentials'].items():
791 #if credential is not expired:
792 credential_authorities.add(authority_hrn)
794 # credential_authorities_expired.add(authority_hrn)
795 if 'delegated_authority_credentials' in config:
796 for authority_hrn, credential in config['delegated_authority_credentials'].items():
797 #if credential is not expired:
798 credential_authorities.add(authority_hrn)
800 # credential_authorities_expired.add(authority_hrn)
802 print 'credential_authorities =', credential_authorities
803 print 'credential_authorities_expired =', credential_authorities_expired
805 # ** Where am I a PI **
806 # For this we need to ask SFA (of all authorities) = PI function
807 pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
808 pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
809 pi_authorities = set()
810 for pa in pi_authorities_tmp:
811 pi_authorities |= set(pa['pi_authorities'])
813 print "pi_authorities =", pi_authorities
815 # My authorities + I have a credential
816 pi_credential_authorities = pi_authorities & credential_authorities
817 pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
818 pi_expired_credential_authorities = pi_authorities & credential_authorities_expired
819 # Authorities I've been delegated PI rights
820 pi_delegation_credential_authorities = credential_authorities - pi_authorities
821 pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities
823 print "pi_credential_authorities =", pi_credential_authorities
824 print "pi_no_credential_authorities =", pi_no_credential_authorities
825 print "pi_expired_credential_authorities =", pi_expired_credential_authorities
826 print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities
827 print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities
829 # Summary intermediary
830 pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities
831 pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities
834 print "pi_my_authorities = ", pi_my_authorities
835 print "pi_delegation_authorities = ", pi_delegation_authorities
838 queried_pending_authorities = pi_my_authorities | pi_delegation_authorities
840 print "queried_pending_authorities = ", queried_pending_authorities
842 requests = get_request_by_authority(queried_pending_authorities)
843 for request in requests:
844 auth_hrn = request['authority_hrn']
846 if auth_hrn in pi_my_authorities:
847 dest = ctx_my_authorities
849 # define the css class
850 if auth_hrn in pi_credential_authorities:
851 request['allowed'] = 'allowed'
852 elif auth_hrn in pi_expired_credential_authorities:
853 request['allowed'] = 'expired'
854 else: # pi_no_credential_authorities
855 request['allowed'] = 'denied'
857 elif auth_hrn in pi_delegation_authorities:
858 dest = ctx_delegation_authorities
860 if auth_hrn in pi_delegation_credential_authorities:
861 request['allowed'] = 'allowed'
862 else: # pi_delegation_expired_authorities
863 request['allowed'] = 'expired'
868 if not auth_hrn in dest:
870 dest[auth_hrn].append(request)
872 context = super(ValidatePendingView, self).get_context_data(**kwargs)
873 context['my_authorities'] = ctx_my_authorities
874 context['delegation_authorities'] = ctx_delegation_authorities
876 # XXX This is repeated in all pages
877 # more general variables expected in the template
878 context['title'] = 'Test view that combines various plugins'
879 # the menu items on the top
880 context['topmenu_items'] = topmenu_items('Dashboard', self.request)
881 # so we can sho who is logged
882 context['username'] = the_user(self.request)
884 # XXX We need to prepare the page for queries
885 #context.update(page.prelude_env())