d8c5501f714decb7a58fa2d0d6703f7de86f38cd
[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.core.query         import Query
47 from manifold.manifoldapi        import execute_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 # View for platforms
56 class PlatformsView(TemplateView):
57     template_name = "platforms.html"
58
59     def get_context_data(self, **kwargs):
60         page = Page(self.request)
61
62         #network_query  = Query().get('local:platform').filter_by('disabled', '==', '0').select('platform','platform_longname','gateway_type')
63         network_query  = Query().get('local:platform').select('platform','platform_longname','gateway_type')
64         page.enqueue_query(network_query)
65
66         page.expose_js_metadata()
67         page.expose_queries()
68         networklist = Hazelnut(
69             page  = page,
70             title = 'List',
71             domid = 'checkboxes',
72             # this is the query at the core of the slice list
73             query = network_query,
74             query_all = network_query,
75             checkboxes = False,
76             datatables_options = {
77             # for now we turn off sorting on the checkboxes columns this way
78             # this of course should be automatic in hazelnut
79             'aoColumns'      : [None, None, None, None, {'bSortable': False}],
80             'iDisplayLength' : 25,
81             'bLengthChange'  : True,
82             },
83         )
84 #
85 #        networklist = SimpleList(
86 #            title = None,
87 #            page  = page,
88 #            key   = 'platform',
89 #            query = network_query,
90 #        )
91
92         context = super(PlatformsView, self).get_context_data(**kwargs)
93         context['person']   = self.request.user
94         context['networks'] = networklist.render(self.request)
95
96         # XXX This is repeated in all pages
97         # more general variables expected in the template
98         context['title'] = 'Platforms connected to MySlice'
99         # the menu items on the top
100         context['topmenu_items'] = topmenu_items('Platforms', self.request)
101         # so we can sho who is logged
102         context['username'] = the_user(self.request)
103
104         context.update(page.prelude_env())
105
106         return context
107
108
109
110 # View for 1 platform and its details
111 class PlatformView(TemplateView):
112     template_name = "platform.html"
113
114     def get_context_data(self, **kwargs):
115         page = Page(self.request)
116
117         for key, value in kwargs.iteritems():
118             print "%s = %s" % (key, value)       
119             if key == "platformname":
120                 platformname=value
121                 
122         network_query  = Query().get('local:platform').filter_by('platform', '==', platformname).select('platform','platform_longname','gateway_type')
123         page.enqueue_query(network_query)
124
125         page.expose_js_metadata()
126         page.expose_queries()
127         networklist = Hazelnut(
128             page  = page,
129             title = 'List',
130             domid = 'checkboxes',
131             # this is the query at the core of the slice list
132             query = network_query,
133             query_all = network_query,
134             checkboxes = False,
135             datatables_options = {
136             # for now we turn off sorting on the checkboxes columns this way
137             # this of course should be automatic in hazelnut
138             'aoColumns'      : [None, None, None, None, {'bSortable': False}],
139             'iDisplayLength' : 25,
140             'bLengthChange'  : True,
141             },
142         )
143 #
144 #        networklist = SimpleList(
145 #            title = None,
146 #            page  = page,
147 #            key   = 'platform',
148 #            query = network_query,
149 #        )
150
151         context = super(PlatformView, self).get_context_data(**kwargs)
152         context['person']   = self.request.user
153         context['networks'] = networklist.render(self.request)
154
155         # XXX This is repeated in all pages
156         # more general variables expected in the template
157         context['title'] = 'Platforms connected to MySlice'
158         # the menu items on the top
159         context['topmenu_items'] = topmenu_items('Platforms', self.request)
160         # so we can sho who is logged
161         context['username'] = the_user(self.request)
162
163         context.update(page.prelude_env())
164
165         return context
166
167
168
169 #class for my_account
170 class AccountView(TemplateView):
171     template_name = "my_account.html"
172     
173     #This view requires login 
174     @method_decorator(login_required)
175     def dispatch(self, *args, **kwargs):
176         return super(AccountView, self).dispatch(*args, **kwargs)
177
178
179     def get_context_data(self, **kwargs):
180         #page = Page(self.request)
181
182         user_query  = Query().get('local:user').select('config','email')
183         user_details = execute_query(self.request, user_query)
184         
185         # not always found in user_details...
186         config={}
187         for user_detail in user_details:
188             #email = user_detail['email']
189             if user_detail['config']:
190                 config = json.loads(user_detail['config'])
191
192         platform_query  = Query().get('local:platform').select('platform_id','platform')
193         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
194         platform_details = execute_query(self.request, platform_query)
195         account_details = execute_query(self.request, account_query)
196        
197         # initial assignment needed for users having no account  
198         platform_name = ''
199         account_type = ''
200         account_usr_hrn = ''
201         account_pub_key = ''
202         platform_name_list = []
203         account_type_list = []
204         usr_hrn_list = []
205         pub_key_list = []          
206         for account_detail in account_details:
207             for platform_detail in platform_details:
208                 if platform_detail['platform_id'] == account_detail['platform_id']:
209                     platform_name = platform_detail['platform']
210                     account_type = account_detail['auth_type']
211                     account_config = json.loads(account_detail['config'])
212                     # a bit more pythonic
213                     account_usr_hrn = account_config.get('user_hrn','N/A')
214                     account_pub_key = account_config.get('user_public_key','N/A')
215                     
216                     platform_name_list.append(platform_name)
217                     account_type_list.append(account_type)
218                     usr_hrn_list.append(account_usr_hrn)
219                     pub_key_list.append(account_pub_key)
220         
221         # combining 4 lists into 1 [to render in the template] 
222         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)]    
223         #print "test"
224         #print lst
225
226         context = super(AccountView, self).get_context_data(**kwargs)
227         context['data'] = lst
228         context['person']   = self.request.user
229         context ['firstname'] = config.get('firstname',"?")
230         context ['lastname'] = config.get('lastname',"?")
231         context ['fullname'] = context['firstname'] +' '+ context['lastname']
232         context ['affiliation'] = config.get('affiliation',"Unknown Affiliation")
233         #context['users'] = userlist.render(self.request)
234         
235         # XXX This is repeated in all pages
236         # more general variables expected in the template
237         context['title'] = 'Platforms connected to MySlice'
238         # the menu items on the top
239         context['topmenu_items'] = topmenu_items('My Account', self.request)
240         # so we can sho who is logged
241         context['username'] = the_user(self.request)
242 #        context ['firstname'] = config['firstname']
243         #context.update(page.prelude_env())
244         return context
245
246
247
248
249
250
251 @login_required
252 # View for my_account form
253 #def my_account(request):
254 #    return render(request, 'my_account.html', {
255 #        #'form': form,
256 #        'topmenu_items': topmenu_items('My Account', request),
257 #        'username': the_user (request)
258 #    })
259
260
261 @login_required
262 #my_acc form value processing
263 def account_process(request):
264     # getting the user_id from the session [now hardcoded]
265     get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
266     # getting user info from manifold
267     if 'submit_name' in request.POST:
268         edited_first_name =  request.POST['fname']
269         edited_last_name =  request.POST['lname']
270         #email = 'test_email@gmail.com'
271         #password = 'test_pp'
272         #message = 'F_Name: %s L_name: %s dummy_pp: %s' % (first_name, last_name, password)
273         #site = None
274         
275         # insert into DB [needed for registration page]
276         #approach borrowed from register view     
277         #new_user = PendingUser.objects.create_inactive_user(edited_first_name, edited_last_name, email,  password, site) 
278         #conventional approach
279         #b = PendingUser(first_name=edited_first_name, last_name=edited_last_name)
280         #b.save()
281         
282         # select and update [will be used throughout this view]
283         # select the logged in user [for the moment hard coded]
284         #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
285         # update first and last name
286         #get_user.first_name = edited_first_name
287         #get_user.last_name = edited_last_name
288         #get_user.save()
289         #user_params = {'config':'hello'}
290         #query = Query.update('local:user').set(user_params).select('config')
291         #results = execute_query(request,query)
292         #if not results:
293         #    raise Exception, "Failed to update user: %s" % user_params['config']
294         #result, = results
295         #return result['config']
296         # create user is working fine :)
297         #user_params = ({'config':'"firstname":"HELLO"'},{'password':'hello'})
298         #user_params = { 'config':'{"firstname":"HEY"}'}
299         #user_params = {'email':'aa@aa.com','password':'demo'}
300         #manifold_add_user(request,user_params)        
301         #manifold_update_user(request,user_params)
302
303         return HttpResponse('Sucess: First Name and Last Name Updated!')       
304     elif 'submit_pass' in request.POST:
305         edited_password = request.POST['password']
306         # select the logged in user [for the moment hard coded]
307         #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
308         # update password
309         get_user.password = edited_password
310         get_user.save()
311         return HttpResponse('Success: Password Changed!!')
312     elif 'generate' in request.POST:
313         # Generate public and private keys using SFA Library
314         from sfa.trust.certificate  import Keypair
315         k = Keypair(create=True)
316         public_key = k.get_pubkey_string()
317         private_key = k.as_pem()
318        
319 # DEPRECATED
320 #        KEY_LENGTH = 2048
321 #
322 #        def blank_callback():
323 #            "Replace the default dashes"
324 #            return
325 #
326 #        # Random seed
327 #        Rand.rand_seed (os.urandom (KEY_LENGTH))
328 #        # Generate key pair
329 #        key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
330 #        # Create memory buffers
331 #        pri_mem = BIO.MemoryBuffer()
332 #        pub_mem = BIO.MemoryBuffer()
333 #        # Save keys to buffers
334 #        key.save_key_bio(pri_mem, None)
335 #        key.save_pub_key_bio(pub_mem)
336 #
337 #        # Get keys 
338 #        public_key = pub_mem.getvalue()
339 #        private_key = pri_mem.getvalue()
340         private_key = ''.join(private_key.split())
341         public_key = "ssh-rsa " + public_key
342         # Saving to DB
343         keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
344 #        keypair = re.sub("\r", "", keypair)
345 #        keypair = re.sub("\n", "\\n", keypair)
346 #        #keypair = keypair.rstrip('\r\n')
347 #        keypair = ''.join(keypair.split())
348         get_user.keypair = keypair
349         get_user.save()
350         return HttpResponse('Success: New Keypair Generated! %s' % keypair)
351
352     elif 'upload_key' in request.POST:
353         up_file = request.FILES['pubkey']
354         file_content =  up_file.read()
355         file_name = up_file.name
356         file_extension = os.path.splitext(file_name)[1] 
357         allowed_extension =  ['.pub','.txt']
358         if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
359             file_content = '{"user_public_key":"'+ file_content +'"}'
360             file_content = re.sub("\r", "", file_content)
361             file_content = re.sub("\n", "\\n",file_content)
362             file_content = ''.join(file_content.split())
363             get_user.keypair = file_content
364             get_user.save()
365             return HttpResponse('Success: Publickey uploaded! Old records overwritten')
366         else:
367             return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')    
368         
369     else:
370         message = 'You submitted an empty form.'
371         return HttpResponse(message)
372
373 def register_4m_f4f(request):
374     errors = []
375
376     authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
377     #authorities_query = Query.get('authority').select('authority_hrn')
378     authorities = execute_query(request, authorities_query)
379
380     if request.method == 'POST':
381         # We shall use a form here
382
383         #get_email = PendingUser.objects.get(email)
384         reg_fname = request.POST.get('firstname', '')
385         reg_lname = request.POST.get('lastname', '')
386         reg_aff = request.POST.get('affiliation','')
387         reg_auth = request.POST.get('authority_hrn', '')
388         reg_email = request.POST.get('email','').lower()
389         
390         #POST value validation  
391         if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
392             errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
393             #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
394             #return render(request, 'register_4m_f4f.html')
395         if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
396             errors.append('Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
397             #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
398             #return render(request, 'register_4m_f4f.html')
399         if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
400             errors.append('Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
401             #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
402             #return render(request, 'register_4m_f4f.html')
403         # XXX validate authority hrn !!
404         if PendingUser.objects.filter(email__iexact=reg_email):
405             errors.append('Email already registered.Please provide a new email address.')
406             #return HttpResponse("Email Already exists")
407             #return render(request, 'register_4m_f4f.html')
408         if 'generate' in request.POST['question']:
409             # Generate public and private keys using SFA Library
410             from sfa.trust.certificate  import Keypair
411             k = Keypair(create=True)
412             public_key = k.get_pubkey_string()
413             private_key = k.as_pem()
414
415 # DEPRECATED
416 #            #import os
417 #            #from M2Crypto import Rand, RSA, BIO
418 #            
419 #            KEY_LENGTH = 2048
420 #
421 #            def blank_callback():
422 #                "Replace the default dashes"
423 #                return
424 #
425 #            # Random seed
426 #            Rand.rand_seed (os.urandom (KEY_LENGTH))
427 #            # Generate key pair
428 #            key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
429 #            # Create memory buffers
430 #            pri_mem = BIO.MemoryBuffer()
431 #            pub_mem = BIO.MemoryBuffer()
432 #            # Save keys to buffers
433 #            key.save_key_bio(pri_mem, None)
434 #            key.save_pub_key_bio(pub_mem)
435 #            # Get keys 
436 #            public_key = pub_mem.getvalue()
437 #            private_key = pri_mem.getvalue()
438
439             private_key = ''.join(private_key.split())
440             public_key = "ssh-rsa " + public_key
441             # Saving to DB
442             keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
443 #            keypair = re.sub("\r", "", keypair)
444 #            keypair = re.sub("\n", "\\n", keypair)
445 #            #keypair = keypair.rstrip('\r\n')
446 #            keypair = ''.join(keypair.split())
447         else:
448             up_file = request.FILES['user_public_key']
449             file_content =  up_file.read()
450             file_name = up_file.name
451             file_extension = os.path.splitext(file_name)[1]
452             allowed_extension =  ['.pub','.txt']
453             if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
454                 keypair = '{"user_public_key":"'+ file_content +'"}'
455                 keypair = re.sub("\r", "", keypair)
456                 keypair = re.sub("\n", "\\n",keypair)
457                 keypair = ''.join(keypair.split())
458             else:
459                 errors.append('Please upload a valid RSA public key [.txt or .pub].')
460
461         #b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff, 
462         #                email=reg_email, password=request.POST['password'], keypair=keypair)
463         #b.save()
464         if not errors:
465             b = PendingUser(
466                 first_name=reg_fname, 
467                 last_name=reg_lname, 
468                 affiliation=reg_aff,
469                 authority_hrn=reg_auth,
470                 email=reg_email, 
471                 password=request.POST['password'],
472                 keypair=keypair
473             )
474             b.save()
475
476             # Send email
477             ctx = {
478                 first_name   : reg_fname, 
479                 last_name    : reg_lname, 
480                 affiliation  : reg_aff,
481                 authority_hrn: reg_auth,
482                 email        : reg_email, 
483                 keypair      : keypair,
484                 cc_myself    : True # form.cleaned_data['cc_myself']
485             }
486
487             recipients = authority_get_pi_emails(authority_hrn)
488             if ctx['cc_myself']:
489                 recipients.append(ctx['email'])
490
491             msg = render_to_string('user_request_email.txt', ctx)
492             send_mail("Onelab New User request submitted", msg, email, recipients)
493
494             return render(request, 'user_register_complete.html')
495
496     return render(request, 'register_4m_f4f.html',{
497         'topmenu_items': topmenu_items('Register', request),
498         'errors': errors,
499         'firstname': request.POST.get('firstname', ''),
500         'lastname': request.POST.get('lastname', ''),
501         'affiliation': request.POST.get('affiliation', ''),
502         'authority_hrn': request.POST.get('authority_hrn', ''),
503         'email': request.POST.get('email', ''),
504         'password': request.POST.get('password', ''),           
505         'authorities': authorities
506     })        
507     
508
509 # view for contact form
510 def contact(request):
511     if request.method == 'POST': # If the form has been submitted...
512         form = ContactForm(request.POST) # A form bound to the POST data
513         if form.is_valid(): # All validation rules pass
514             # Process the data in form.cleaned_data
515             first_name = form.cleaned_data['first_name']
516             last_name = form.cleaned_data['last_name']
517             affiliation = form.cleaned_data['affiliation']
518             subject = form.cleaned_data['subject']
519             message = form.cleaned_data['message']
520             email = form.cleaned_data['email'] # email of the sender
521             cc_myself = form.cleaned_data['cc_myself']
522
523             #recipients = authority_get_pi_emails(authority_hrn)
524             recipients = ['yasin.upmc@gmail.com']
525             if cc_myself:
526                 recipients.append(email)
527
528             from django.core.mail import send_mail
529             send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
530             return render(request,'contact_sent.html') # Redirect after POST
531     else:
532         form = ContactForm() # An unbound form
533     
534     return render(request, 'contact.html', {
535         'form': form,
536         'topmenu_items': topmenu_items('Contact Us', request),
537         'username': the_user (request)
538
539     })
540
541 @login_required
542 def slice_request(request):
543     errors = []
544
545     authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
546     #authorities_query = Query.get('authority').select('authority_hrn')
547     authorities = execute_query(request, authorities_query)
548
549     authority_hrn_tuple = []
550     for authority in authorities:
551         authority_hrn_tuple.append((authority['authority_hrn'], authority['name']))
552     authority_hrn_initial = {'authority_hrn': authority_hrn_tuple}
553         
554     # request.POST or None ?
555     if request.method == 'POST':
556         # The form has been submitted
557         form = SliceRequestForm(request.POST, initial=authority_hrn_initial) 
558
559         if form.is_valid():
560             slice_name      = form.cleaned_data['slice_name']
561             authority_hrn   = form.cleaned_data['authority_hrn']
562             number_of_nodes = form.cleaned_data['number_of_nodes']
563             type_of_nodes   = form.cleaned_data['type_of_nodes']
564             purpose         = form.cleaned_data['purpose']
565             
566             s = PendingSlice(
567                 slice_name      = slice_name,
568                 authority_hrn   = authority_hrn,
569                 number_of_nodes = number_of_nodes,
570                 type_of_nodes   = type_of_nodes,
571                 purpose         = purpose
572             )
573             s.save()
574
575             # All validation rules pass; process data in form.cleaned_data
576             # slice_name, number_of_nodes, type_of_nodes, purpose
577             email = form.cleaned_data['email'] # email of the sender
578             cc_myself = form.cleaned_data['cc_myself']
579
580             # The recipients are the PI of the authority
581             recipients = authority_get_pi_emails(authority_hrn)
582             #recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
583             if cc_myself:
584                 recipients.append(email)
585             msg = render_to_string('slice_request_email.txt', form.cleaned_data)
586             send_mail("Onelab New Slice request form submitted", msg, email, recipients)
587
588             return render(request,'slicereq_recvd.html') # Redirect after POST
589     else:
590         form = SliceRequestForm(initial=authority_hrn_initial)
591
592 #    template_env = {}
593 #    template_env['form'] = form
594 #    template_env['topmenu_items'] = topmenu_items('Request a slice', request) 
595 #    template_env['unfold1_main'] = render(request, 'slice_request_.html', {
596 #        'form': form,
597 #    })
598 #    from django.shortcuts                import render_to_response
599 #    from django.template                 import RequestContext
600 #    return render_to_response ('view-unfold1.html',template_env,
601 #                               context_instance=RequestContext(request))
602
603     return render(request, 'slice_request.html', {
604         'form': form,
605         'topmenu_items': topmenu_items('Request a slice', request),
606         'username': the_user (request) 
607     })
608
609
610 class PresViewView(TemplateView):
611     template_name = "view-unfold1.html"
612
613     def get_context_data(self, **kwargs):
614
615         page = Page(self.request)
616
617         pres_view = PresView(page = page)
618
619         context = super(PresViewView, self).get_context_data(**kwargs)
620
621         #context['ALL_STATIC'] = "all_static"
622         context['unfold1_main'] = pres_view.render(self.request)
623
624         # XXX This is repeated in all pages
625         # more general variables expected in the template
626         context['title'] = 'Test view that combines various plugins'
627         # the menu items on the top
628         context['topmenu_items'] = topmenu_items('PresView', self.request)
629         # so we can sho who is logged
630         context['username'] = the_user(self.request)
631
632         prelude_env = page.prelude_env()
633         context.update(prelude_env)
634
635         return context
636
637 def json_me(config_file,type):
638     json_answer = ''
639     for ligne in config_file:
640         if not ligne.startswith('#'):
641             args = ligne.split(';')
642             json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1]  + '" ,"descriptif":"' + args[2]+'"')
643             if type!="dynamic":
644                 json_answer += str(',"contraints":')
645                 if args[3]=="":
646                     json_answer += str('""')
647                 else:
648                     json_answer += str(args[3])
649             json_answer += str('},')
650     return json_answer[:-1]
651
652
653 DIR = '/var/myslice/'
654 STATIC = '%s/config_method_static' % DIR
655 DYNAMIC = '%s/config_method_dynamic' % DIR
656 ANIMATION = '%s/config_method_animation' % DIR
657
658 def pres_view_methods(request, type):
659
660     if type ==None:
661         return 0
662     elif type =="static":
663         config = open(STATIC, "r")
664         json_answer = str('{ "options": [')
665         json_answer += str(json_me(config,"static"))
666         json_answer += str('] }')
667         config.close()
668     elif type =="dynamic":
669         config = open(DYNAMIC, "r")
670         json_answer = str('{ "options": [')
671         json_answer += str(json_me(config,"dynamic"))
672         json_answer += str('] }')
673         config.close()
674     elif type =="animation":
675         config = open(ANIMATION, "r")
676         json_answer = str('{ "options": [')
677         json_answer += str(json_me(config,"animation"))
678         json_answer += str('] }')
679         config.close()
680     elif type =="all":
681         config = open(STATIC, "r")
682         json_answer = str('{ "static": [')
683         json_answer += str(json_me(config,"static"))
684         json_answer += str('],')
685         json_answer += str('"dynamic": [')
686         config.close()
687         config = open(DYNAMIC, "r")
688         json_answer += str(json_me(config,"dynamic"))
689         json_answer += str('],')
690         json_answer += str('"animation": [')
691         config.close()
692         config = open(ANIMATION, "r")
693         json_answer += str(json_me(config,"animation"))
694         json_answer += str('] }')
695         config.close()
696     else:
697         return 0
698     return HttpResponse (json_answer, mimetype="application/json")
699
700 def pres_view_animation(request, constraints, id):
701
702 # sites crees depuis 2008
703 # static.py?contraints=']date_created':1262325600&id='name_id"'
704
705     # method = request.getvalue('method') #ex : GetSites
706     #constraints = "']date_created':1262325600"
707     #id = "2"
708
709     if id == None:
710         return 0
711
712     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
713     # constraints = {}#request.getvalue('constraints') // nul = {}
714     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
715
716     config_file = open(ANIMATION, "r")
717     for ligne in config_file:
718         if not ligne.startswith('#'):
719             ligne = ligne.split('\n')
720             first = ligne[0].split(';')
721             if (str(first[1]) == str(id)):
722                 save = first
723     config_file.close()
724
725     #Les print_method, print_option sont definis par le client (js)
726     #Les animations acceptent que les connexions anonymous
727     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
728     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
729
730
731     #Creation d'un objet event
732     event = Event(args)
733     cmd = [{"params": {
734             "data": {
735                 "print_options": event.print_options,
736                 "print_method": event.print_method,
737                 "message": event.data
738             }
739         }
740     }]
741
742     json_answer = json.dumps(cmd)
743     return HttpResponse (json_answer, mimetype="application/json")
744
745 def pres_view_static(request, constraints, id):
746     #constraints = "']date_created':1262325600"
747     #id = "2"
748
749     # method = 'GetSites'#request.getvalue('method') #ex : GetSites
750     # constraints = {}#request.getvalue('constraints') // nul = {}
751     # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
752
753     config_file = open(STATIC, "r")
754     for ligne in config_file:
755         if not ligne.startswith('#'):
756             ligne = ligne.split('\n')
757             first = ligne[0].split(';')
758             if (str(first[1]) == str(id)):
759                 save = first
760     config_file.close()
761
762     #Les print_method, print_option sont definis par le client (js)
763     #Les animations acceptent que les connexions anonymous
764     # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
765     args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
766
767
768     #Creation d'un objet event
769     event = Event(args)
770     cmd = [{"params": {
771             "data": {
772                 "print_options": event.print_options,
773                 "print_method": event.print_method,
774                 "message": event.data
775             }
776         }
777     }]
778
779     json_answer = json.dumps(cmd)
780     return HttpResponse (json_answer, mimetype="application/json")
781
782 class ValidatePendingView(TemplateView):
783     template_name = "validate_pending.html"
784
785     def get_context_data(self, **kwargs):
786         # We might have slices on different registries with different user accounts 
787         # 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
788         # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
789
790         #messages.info(self.request, 'You have logged in')
791         page = Page(self.request)
792
793         ctx_my_authorities = {}
794         ctx_delegation_authorities = {}
795
796
797         # The user need to be logged in
798         if the_user(self.request):
799             # Who can a PI validate:
800             # His own authorities + those he has credentials for.
801             # In MySlice we need to look at credentials also.
802             
803
804             # XXX This will have to be asynchroneous. Need to implement barriers,
805             # for now it will be sufficient to have it working statically
806
807             # get user_id to later on query accounts
808             # XXX Having real query plan on local tables would simplify all this
809             # XXX $user_email is still not available for local tables
810             #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id')
811             user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id')
812             user, = execute_query(self.request, user_query)
813             user_id = user['user_id']
814
815             # Query manifold to learn about available SFA platforms for more information
816             # In general we will at least have the portal
817             # For now we are considering all registries
818             all_authorities = []
819             platform_ids = []
820             sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
821             sfa_platforms = execute_query(self.request, sfa_platforms_query)
822             for sfa_platform in sfa_platforms:
823                 print "SFA PLATFORM > ", sfa_platform['platform']
824                 if not 'auth_type' in sfa_platform:
825                     continue
826                 auth = sfa_platform['auth_type']
827                 if not auth in all_authorities:
828                     all_authorities.append(auth)
829                 platform_ids.append(sfa_platform['platform_id'])
830
831             # We can check on which the user has authoritity credentials = PI rights
832             credential_authorities = set()
833             credential_authorities_expired = set()
834
835             # User account on these registries
836             user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config')
837             user_accounts = execute_query(self.request, user_accounts_query)
838             #print "=" * 80
839             #print user_accounts
840             #print "=" * 80
841             for user_account in user_accounts:
842                 config = json.loads(user_account['config'])
843                 creds = []
844                 if 'authority_credentials' in config:
845                     for authority_hrn, credential in config['authority_credentials'].items():
846                         #if credential is not expired:
847                         credential_authorities.add(authority_hrn)
848                         #else
849                         #    credential_authorities_expired.add(authority_hrn)
850                 if 'delegated_authority_credentials' in config:
851                     for authority_hrn, credential in config['delegated_authority_credentials'].items():
852                         #if credential is not expired:
853                         credential_authorities.add(authority_hrn)
854                         #else
855                         #    credential_authorities_expired.add(authority_hrn)
856
857             print 'credential_authorities =', credential_authorities
858             print 'credential_authorities_expired =', credential_authorities_expired
859
860             # ** Where am I a PI **
861             # For this we need to ask SFA (of all authorities) = PI function
862             pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
863             pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
864             pi_authorities = set()
865             for pa in pi_authorities_tmp:
866                 pi_authorities |= set(pa['pi_authorities'])
867
868             print "pi_authorities =", pi_authorities
869             
870             # My authorities + I have a credential
871             pi_credential_authorities = pi_authorities & credential_authorities
872             pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
873             pi_expired_credential_authorities = pi_authorities & credential_authorities_expired
874             # Authorities I've been delegated PI rights
875             pi_delegation_credential_authorities = credential_authorities - pi_authorities
876             pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities
877
878             print "pi_credential_authorities =", pi_credential_authorities
879             print "pi_no_credential_authorities =", pi_no_credential_authorities
880             print "pi_expired_credential_authorities =", pi_expired_credential_authorities
881             print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities
882             print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities
883
884             # Summary intermediary
885             pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities
886             pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities
887
888             print "--"
889             print "pi_my_authorities = ", pi_my_authorities
890             print "pi_delegation_authorities = ", pi_delegation_authorities
891
892             # Summary all
893             queried_pending_authorities = pi_my_authorities | pi_delegation_authorities
894             print "----"
895             print "queried_pending_authorities = ", queried_pending_authorities
896
897             requests = get_request_by_authority(queried_pending_authorities)
898             for request in requests:
899                 auth_hrn = request['authority_hrn']
900
901                 if auth_hrn in pi_my_authorities:
902                     dest = ctx_my_authorities
903
904                     # define the css class
905                     if auth_hrn in pi_credential_authorities:
906                         request['allowed'] = 'allowed'
907                     elif auth_hrn in pi_expired_credential_authorities:
908                         request['allowed'] = 'expired'
909                     else: # pi_no_credential_authorities
910                         request['allowed'] = 'denied'
911
912                 elif auth_hrn in pi_delegation_authorities:
913                     dest = ctx_delegation_authorities
914
915                     if auth_hrn in pi_delegation_credential_authorities:
916                         request['allowed'] = 'allowed'
917                     else: # pi_delegation_expired_authorities
918                         request['allowed'] = 'expired'
919
920                 else:
921                     continue
922
923                 if not auth_hrn in dest:
924                     dest[auth_hrn] = []
925                 dest[auth_hrn].append(request) 
926         
927         context = super(ValidatePendingView, self).get_context_data(**kwargs)
928         context['my_authorities']   = ctx_my_authorities
929         context['delegation_authorities'] = ctx_delegation_authorities
930
931         # XXX This is repeated in all pages
932         # more general variables expected in the template
933         context['title'] = 'Test view that combines various plugins'
934         # the menu items on the top
935         context['topmenu_items'] = topmenu_items('Dashboard', self.request) 
936         # so we can sho who is logged
937         context['username'] = the_user(self.request) 
938
939         # XXX We need to prepare the page for queries
940         #context.update(page.prelude_env())
941
942         return context