ea87918f6c5988036ffde2fc39564761442185a6
[myslice.git] / portal / actions.py
1 from django.http                import HttpResponse
2 from manifold.core.query        import Query
3 from manifoldapi.manifoldapi    import execute_query,execute_admin_query
4 from portal.models              import PendingUser, PendingSlice, PendingAuthority
5 import json
6
7 from django.contrib.auth.models  import User
8 from django.contrib.sites.models import Site
9 from django.contrib.auth        import get_user_model
10 from django.template.loader     import render_to_string
11 from django.core.mail           import EmailMultiAlternatives, send_mail
12
13 from myslice.theme              import ThemeView
14
15 theme = ThemeView()
16
17 # Thierry: moving this right into the code so 
18 # most people can use myslice without having to install sfa
19 # XXX tmp sfa dependency, should be moved to SFA gateway
20 #from sfa.util.xrn                import Xrn 
21
22
23 # Get the list of authorities
24
25 def authority_get_pis(request, authority_hrn):
26     query = Query.get('authority').filter_by('authority_hrn', '==', authority_hrn).select('pi_users')
27     results = execute_admin_query(request, query)
28     print "authority_get_pis = %s" % results
29     # NOTE: temporarily commented. Because results is giving empty list. 
30     # Needs more debugging
31     #if not results:
32     #    raise Exception, "Authority not found: %s" % authority_hrn
33     #result, = results
34     #return result['pi_users']
35     return results
36
37 def authority_get_pi_emails(request, authority_hrn):
38     pi_users = authority_get_pis(request,authority_hrn)
39     print "pi_users = %s" % pi_users
40
41     if any(pi['pi_users'] == None or not pi['pi_users']  for pi in pi_users):
42         #theme.template_name = 'email_default_recipients.txt' 
43         #default_email = render_to_string(theme.template, request)
44         #default_email = default_email.replace('\n', '')
45         #return default_email
46         # the above doesn't work
47         return ['support@myslice.info']
48     else:
49         pi_user_hrns = [ hrn for x in pi_users for hrn in x['pi_users'] ]
50         query = Query.get('user').filter_by('user_hrn', 'included', pi_user_hrns).select('user_email')
51         results = execute_admin_query(request, query)
52         return [result['user_email'] for result in results]
53
54 #clear user credentials
55 def clear_user_creds(request, user_email):
56     try:
57         user_query  = Query().get('local:user').filter_by('email', '==', user_email).select('user_id','email','password','config')
58         user_details = execute_admin_query(request, user_query)
59     
60         # getting the user_id from the session
61         for user_detail in user_details:
62             user_id = user_detail['user_id']
63             user_email = user_detail['email']
64     
65         account_query  = Query().get('local:account').filter_by('user_id', '==', user_id).select('user_id','platform_id','auth_type','config')
66         account_details = execute_admin_query(request, account_query)
67     
68         platform_query  = Query().get('local:platform').select('platform_id','platform')
69         platform_details = execute_admin_query(request, platform_query)
70     
71         for account_detail in account_details:
72             for platform_detail in platform_details:
73                 if platform_detail['platform_id'] == account_detail['platform_id']:
74                     if 'myslice' in platform_detail['platform']:
75                         account_config = json.loads(account_detail['config'])
76                         #user_cred = account_config.get('delegated_user_credential','N/A')
77                         user_cred = account_config.get('user_credential','N/A')
78                         if 'N/A' not in user_cred:
79                             user_hrn = account_config.get('user_hrn','N/A')
80                             user_pub_key = json.dumps(account_config.get('user_public_key','N/A'))
81                             user_priv_key = json.dumps(account_config.get('user_private_key','N/A'))
82                             updated_config = '{"user_public_key":'+ user_pub_key + ', "user_private_key":'+ user_priv_key + ', "user_hrn":"'+ user_hrn + '"}'
83                             user_params = { 'config': updated_config}
84                             manifold_update_account(request, user_id,user_params)
85                             return user_email
86                         else:
87                             return None
88
89     except Exception,e:
90         print "Exception in actions.py in clear_user_creds %s" % e
91         return None
92
93 def is_pi(wsgi_request, user_hrn, authority_hrn):
94     # XXX could be done in a single query !
95
96     # select pi_authorities from user where user_hrn == "ple.upmc.jordan_auge"
97     query = Query.get('user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
98     results = execute_admin_query(wsgi_request, query)
99     if not results:
100         # XXX Warning ?
101         return False
102     result = results[0]
103     user_authority_hrns = result.get('pi_authorities', [])
104     return authority_hrn in user_authority_hrns
105     
106 # SFA get record
107
108 def sfa_get_user(request, user_hrn, pub):
109     query_sfa_user = Query.get('user').filter_by('user_hrn', '==', user_hrn)
110     result_sfa_user = execute_query(request, query_sfa_user)
111     return result_sfa_user                        
112
113 def sfa_update_user(request, user_hrn, user_params):
114     # user_params: keys [public_key] 
115     if 'email' in user_params:
116         user_params['user_email'] = user_params['email']
117     query = Query.update('user').filter_by('user_hrn', '==', user_hrn).set(user_params).select('user_hrn')
118     results = execute_query(request,query)
119     return results
120
121 def sfa_add_authority(request, authority_params):
122     query = Query.create('authority').set(authority_params).select('authority_hrn')
123     results = execute_query(request, query)
124     print "sfa_add_auth results=",results
125     if not results:
126         raise Exception, "Could not create %s. Already exists ?" % authority_params['hrn']
127     return results
128
129 def sfa_add_user_to_slice(request, user_hrn, slice_params):
130 # UPDATE myslice:slice SET researcher=['ple.upmc.jordan_auge','ple.inria.thierry_parmentelat','ple.upmc.loic_baron','ple.upmc.ciro_scognamiglio','ple.upmc.mohammed-yasin_rahman','ple.upmc.azerty'] where slice_hrn=='ple.upmc.myslicedemo'
131     query_current_users = Query.get('slice').select('user').filter_by('slice_hrn','==',slice_params['hrn'])
132     results_current_users = execute_query(request, query_current_users)
133     slice_params['researcher'] = slice_params['researcher'] | results_current_users
134     query = Query.update('slice').filter_by('user_hrn', '==', user_hrn).set(slice_params).select('slice_hrn')
135     results = execute_query(request, query)
136 # Also possible but not supported yet
137 # UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
138     if not results:
139         raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
140     return results
141
142 # Propose hrn
143
144 def manifold_add_user(wsgi_request, request):
145     """Add a Manifold user corresponding to a user request.
146
147     Args:
148         wsgi_request: a WSGIRequest instance
149         request (dict): a dictionary containing the user request built from the
150             form.
151
152     Returns:
153         The user_id of the inserted user.
154
155     Raises:
156         ?
157     
158     """
159     USER_CONFIG = '{"firstname": "%(first_name)s", "lastname": "%(last_name)s", "authority": "%(authority_hrn)s"}'
160
161     user_params = {
162         'email'     : request['email'],
163         'password'  : request['password'],
164         'config'    : USER_CONFIG % request,
165         'status'    : 1,
166     }
167
168     query = Query.create('local:user').set(user_params).select('email')
169     results = execute_admin_query(request, query)
170     if not results:
171         raise Exception, "Failed creating manifold user: %s" % user_params['email']
172     result = results[0]
173     return result['email']
174
175 def manifold_update_user(request, email, user_params):
176     # user_params: password, config e.g., 
177     query = Query.update('local:user').filter_by('email', '==', email).set(user_params).select('email')
178     results = execute_admin_query(request,query)
179     # NOTE: results remains empty and goes to Exception. However, it updates the manifold DB.
180     # That's why I commented the exception part. -- Yasin 
181     #if not results:
182     #    raise Exception, "Failed updating manifold user: %s" % user_params['email']
183     #result, = results
184     return results
185
186 def manifold_add_account(request, account_params):
187     query = Query.create('local:account').set(account_params).select(['user', 'platform'])
188     results = execute_admin_query(request,query)
189     if not results:
190         raise Exception, "Failed creating manifold account on platform %s for user: %s" % (account_params['platform'], account_params['user'])
191     result, = results
192     return result['user_id']
193
194 def manifold_update_account(request,user_id,account_params):
195     # account_params: config
196     query = Query.update('local:account').filter_by('platform', '==', 'myslice').filter_by('user_id', '==', user_id).set(account_params).select('user_id')
197     results = execute_admin_query(request,query)
198     return results
199
200 #explicitly mention the platform_id
201 def manifold_delete_account(request, platform_id, user_id, account_params):
202     query = Query.delete('local:account').filter_by('platform_id', '==', platform_id).filter_by('user_id', '==', user_id).set(account_params).select('user_id')
203     results = execute_admin_query(request,query)
204     return results
205
206 def manifold_delete_user(request, user_id, user_params):
207     query = Query.delete('local:user').filter_by('user_id', '==', user_id).set(user_params).select('user_id')
208     results = execute_admin_query(request,query)
209     return results
210
211
212 #not tested
213 def manifold_add_platform(request, platform_params):
214     query = Query.create('local:platform').set(platform_params).select(['user', 'platform'])
215     results = execute_admin_query(request,query)
216     if not results:
217         raise Exception, "Failed creating manifold platform %s for user: %s" % (platform_params['platform'], platform_params['user'])
218     result, = results
219     return result['platform_id']
220
221
222 def make_request_user(user):
223     request = {}
224     request['type']          = 'user'
225     request['id']            = user.id
226     request['timestamp']     = user.created # XXX in DB ?
227     request['authority_hrn'] = user.authority_hrn
228     request['first_name']    = user.first_name
229     request['last_name']     = user.last_name
230     request['email']         = user.email
231     request['login']         = user.login
232     request['user_hrn']      = user.user_hrn
233     request['public_key']    = user.public_key
234     request['private_key']   = user.private_key
235     return request
236
237 def make_request_slice(slice):
238     request = {}
239     request['type'] = 'slice'
240     request['id'] = slice.id
241     request['user_hrn'] = slice.user_hrn
242     request['timestamp'] = slice.created
243     request['authority_hrn'] = slice.authority_hrn
244     request['slice_name'] = slice.slice_name
245     request['number_of_nodes'] = slice.number_of_nodes
246     request['type_of_nodes'] = slice.type_of_nodes
247     request['purpose'] = slice.purpose
248     return request
249
250 def make_request_authority(authority):
251     request = {}
252     request['type']                  = 'authority'
253     request['id']                    = authority.id
254     request['site_name']             = authority.site_name
255     request['site_latitude']         = authority.site_latitude
256     request['site_longitude']        = authority.site_longitude
257     request['site_url']              = authority.site_url
258     request['site_authority']        = authority.site_authority
259     request['site_abbreviated_name'] = authority.site_abbreviated_name
260     request['address_line1']         = authority.address_line1
261     request['address_line2']         = authority.address_line2
262     request['address_line3']         = authority.address_line3
263     request['address_city']          = authority.address_city
264     request['address_postalcode']    = authority.address_postalcode
265     request['address_state']         = authority.address_state
266     request['address_country']       = authority.address_country
267     request['authority_hrn']         = authority.authority_hrn
268     request['timestamp']             = authority.created
269     return request
270
271 def make_requests(pending_users, pending_slices, pending_authorities):
272     requests = []
273     for user in pending_users:
274         requests.append(make_request_user(user))
275     for slice in pending_slices:
276         requests.append(make_request_slice(slice))
277     for authority in pending_authorities:
278         requests.append(make_request_authority(authority))
279     return requests   
280
281 def get_request_by_id(ids):
282     sorted_ids = { 'user': [], 'slice': [], 'authority': [] }
283     for type__id in ids:
284         type, id = type__id.split('__')
285         sorted_ids[type].append(id)
286         
287     if not ids:
288         pending_users  = PendingUser.objects.all()
289         pending_slices = PendingSlice.objects.all()
290         pending_authorities = PendingAuthority.objects.all()
291     else:
292         pending_users  = PendingUser.objects.filter(id__in=sorted_ids['user']).all()
293         pending_slices = PendingSlice.objects.filter(id__in=sorted_ids['slice']).all()
294         pending_authorities = PendingAuthority.objects.filter(id__in=sorted_ids['authority']).all()
295
296     return make_requests(pending_users, pending_slices, pending_authorities)
297
298 def get_requests(authority_hrns=None):
299     print "get_request_by_authority auth_hrns = ", authority_hrns
300     if not authority_hrns:
301         ## get those pending users who have confirmed their emails
302         pending_users  = PendingUser.objects.filter(status__iexact = 'True')
303         pending_slices = PendingSlice.objects.all()
304         pending_authorities = PendingAuthority.objects.all()
305     else:
306         pending_users  = PendingUser.objects.filter(authority_hrn__in=authority_hrns).all()
307         pending_slices = PendingSlice.objects.filter(authority_hrn__in=authority_hrns).all()
308         pending_authorities = PendingAuthority.objects.filter(authority_hrn__in=authority_hrns).all()
309
310     return make_requests(pending_users, pending_slices, pending_authorities)
311
312 # XXX Is it in sync with the form fields ?
313
314 def portal_validate_request(wsgi_request, request_ids):
315     status = {}
316
317     if not isinstance(request_ids, list):
318         request_ids = [request_ids]
319
320     requests = get_request_by_id(request_ids)
321     for request in requests:
322         # type, id, timestamp, details, allowed -- MISSING: authority_hrn
323         # CAREFUL about details
324         # user  : first name, last name, email, password, keypair
325         # slice : number of nodes, type of nodes, purpose
326         
327         request_status = {}
328
329         if request['type'] == 'user':
330
331             try:
332                 create_user(wsgi_request, request)
333                 request_status['SFA user'] = {'status': True }
334                 PendingUser.objects.get(id=request['id']).delete()
335             except Exception, e:
336                  request_status['SFA user'] = {'status': False, 'description': str(e)}
337                        
338 #            user_params = {'status':2}
339 #            manifold_update_user(request, request['email'], user_params)
340
341             # MANIFOLD user should be added beforehand, during registration
342             #try:
343             #    manifold_user_params = { key: request[key] for key in MANIFOLD_USER_KEYS }
344             #    # XXX # manifold_add_user(manifold_user_params)
345             #    request_status['MySlice user'] = {'status': True }
346             #except Exception, e:
347             #    request_status['MySlice user'] = {'status': False, 'description': str(e)}
348
349             # XXX
350             #manifold_account_params = { key: request[key] for key in MANIFOLD_ACCOUNT_KEYS }
351             #manifold_add_account(manifold_account_params)
352             #request_status['MySlice testbed accounts'] = {'status': False }
353
354         elif request['type'] == 'slice':
355             try:
356                 create_slice(wsgi_request, request)
357                 request_status['SFA slice'] = {'status': True }
358                 PendingSlice.objects.get(id=request['id']).delete()
359
360             except Exception, e:
361                 request_status['SFA slice'] = {'status': False, 'description': str(e)}
362
363         elif request['type'] == 'authority':
364             try:
365                 #hrn = "%s.%s" % (request['authority_hrn'], request['site_authority'])
366                 hrn = request['site_authority']
367                 # XXX tmp sfa dependency
368                 from sfa.util.xrn import Xrn 
369                 urn = Xrn(hrn, request['type']).get_urn()
370                 
371                 # Only hrn is required for Manifold Query 
372                 sfa_authority_params = {
373                     'authority_hrn'        : hrn,
374                     #'authority_urn'        : urn,
375                     #'type'       : request['type'],
376                     #'pi'        : None,
377                     #'enabled'    : True
378                 }
379                 print "ADD Authority"
380                 sfa_add_authority(wsgi_request, sfa_authority_params)
381                 request_status['SFA authority'] = {'status': True }
382                 PendingAuthority.objects.get(id=request['id']).delete()
383
384             except Exception, e:
385                 request_status['SFA authority'] = {'status': False, 'description': str(e)}
386
387         # XXX Remove from Pendings in database
388
389         status['%s__%s' % (request['type'], request['id'])] = request_status
390
391     return status
392
393 def validate_action(request, **kwargs):
394     ids = filter(None, kwargs['id'].split('/'))
395     status = portal_validate_request(request, ids)
396     json_answer = json.dumps(status)
397     return HttpResponse (json_answer, mimetype="application/json")
398
399
400 def reject_action(request, **kwargs):
401     ids = filter(None, kwargs['id'].split('/'))
402     status = portal_reject_request(request, ids)
403     json_answer = json.dumps(status)
404     return HttpResponse (json_answer, mimetype="application/json")
405
406
407 def portal_reject_request(wsgi_request, request_ids):
408     status = {}
409
410     if not isinstance(request_ids, list):
411         request_ids = [request_ids]
412
413     requests = get_request_by_id(request_ids)
414     for request in requests:
415         # type, id, timestamp, details, allowed -- MISSING: authority_hrn
416         # CAREFUL about details
417         # user  : first name, last name, email, password, keypair
418         # slice : number of nodes, type of nodes, purpose
419         
420         request_status = {}
421
422         if request['type'] == 'user':
423             try:
424                 request_status['SFA user'] = {'status': True }
425                 # getting user email based on id 
426                 ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
427                 for user in PendingUser.objects.raw('SELECT id,email FROM portal_pendinguser WHERE id = %s', [request['id']]):
428                     user_email= user.email
429
430                 # get the domain url
431                 current_site = Site.objects.get_current()
432                 current_site = current_site.domain
433
434                 subject = 'User validation denied.'
435                 msg = 'You have recently registered to ' + current_site + '. We are sorry to inform you that, a manager of your institution has rejected your request. Please contact the manager of your institution for further information. For any other queries, contact us by replying to this email.'
436                 send_mail(subject, msg, 'support@onelab.eu',[user_email], fail_silently=False)
437                 # removing from Django auth_user
438                 UserModel = get_user_model()
439                 UserModel._default_manager.filter(email__iexact = user_email).delete()
440                 # removing from Django portal_pendinguser
441                 PendingUser.objects.get(id=request['id']).delete()
442                 # removing from manifold
443                 # removing manifold account
444                 user_query = Query().get('local:user') \
445                     .filter_by('email', '==', user_email)           \
446                     .select('user_id')
447                 user = execute_admin_query(wsgi_request, user_query)
448                 user_id = user[0]['user_id']
449         
450                 platform_query = Query().get('local:platform') \
451                     .filter_by('platform', '==', 'myslice')           \
452                     .select('platform_id')
453                 platform = execute_admin_query(wsgi_request, platform_query)
454                 platform_id = platform[0]['platform_id']
455                 account_params = {'user_id':user_id}
456                 manifold_delete_account(request, platform_id, user_id, account_params)           
457              
458                 # removing manifold user
459                 user_params = {'user_id':user_id}
460                 manifold_delete_user(request, user_id, user_params)
461             except Exception, e:
462                 request_status['SFA authority'] = {'status': False, 'description': str(e)}
463                       
464         elif request['type'] == 'slice':
465             request_status['SFA slice'] = {'status': True }           
466             PendingSlice.objects.get(id=request['id']).delete()
467         elif request['type'] == 'authority':
468             request_status['SFA authority'] = {'status': True }           
469             PendingAuthority.objects.get(id=request['id']).delete()
470
471         status['%s__%s' % (request['type'], request['id'])] = request_status
472
473     return status
474
475 # Django and ajax
476 # http://djangosnippets.org/snippets/942/
477
478
479
480 #-------------------------------------------------------------------------------
481 # REQUESTS - Slices
482 #-------------------------------------------------------------------------------
483
484 def create_slice(wsgi_request, request):
485     """
486     Arguments:
487         wsgi_request (~ WSGIRequest) : 
488         request (dict) : the slice request in our own dict format
489
490     Raises:
491         Exception
492     """
493     hrn = "%s.%s" % (request['authority_hrn'], request['slice_name'])
494     # XXX tmp sfa dependency
495     from sfa.util.xrn import Xrn 
496     urn = Xrn(hrn, request['type']).get_urn()
497     
498     # Add User to Slice if we have the user_hrn in pendingslice table
499     user_hrn = request.get('user_hrn', None)
500     user_hrns = list([user_hrn]) if user_hrn else list()
501     
502     user_query  = Query().get('user').select('user_hrn','user_email').filter_by('user_hrn','==',user_hrn)
503     user_details_sfa = execute_admin_query(wsgi_request, user_query)
504     if not user_details_sfa:
505         raise Exception, "User %s doesn't exist, validate user before validating slice" % user_hrn
506     for user in user_details_sfa:
507         user_email = user['user_email']
508
509     # XXX LOIC Quick fix because this is totally inconsistent
510     if not 'number_of_nodes' in request:
511         request['number_of_nodes']=""
512
513     # XXX We should create a slice with Manifold terminology
514     slice_params = {
515         'slice_hrn'        : hrn, 
516         'slice_urn'        : urn,
517         'slice_type'       : request['type'],
518         'url'              : request['number_of_nodes'],
519         'users'            : user_hrns,
520         'slice_enabled'    : True
521     }
522     # ignored in request: id, timestamp,  number_of_nodes, type_of_nodes, purpose
523
524     query = Query.create('slice').set(slice_params).select('slice_hrn')
525     results = execute_query(wsgi_request, query)
526     if not results:
527         raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
528     else:
529         clear_user_creds(wsgi_request,user_email)
530         subject = 'Slice created'
531         msg = 'A manager of your institution has validated your slice request. You can now add resources to the slice and start experimenting.'
532         send_mail(subject, msg, 'support@onelab.eu',[user_email], fail_silently=False)
533        
534     return results
535
536 def create_pending_slice(wsgi_request, request, email):
537     """
538     """
539
540     # Insert an entry in the PendingSlice table
541     s = PendingSlice(
542         slice_name      = request['slice_name'],
543         user_hrn        = request['user_hrn'],
544         authority_hrn   = request['authority_hrn'],
545         number_of_nodes = request['url'],
546         purpose         = request['purpose'],
547     )
548     s.save()
549
550     try:
551         # Send an email: the recipients are the PI of the authority
552         recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
553
554         theme.template_name = 'slice_request_email.txt' 
555         text_content = render_to_string(theme.template, request)
556     
557         theme.template_name = 'slice_request_email.html' 
558         html_content = render_to_string(theme.template, request)
559     
560         theme.template_name = 'slice_request_email_subject.txt'
561         subject = render_to_string(theme.template, request)
562         subject = subject.replace('\n', '')
563     
564         sender = email
565         msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
566         msg.attach_alternative(html_content, "text/html")
567         msg.send()
568     except Exception, e:
569         print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
570
571 #-------------------------------------------------------------------------------
572 # REQUESTS - Users
573 #-------------------------------------------------------------------------------
574
575 def manifold_add_reference_user_accounts(wsgi_request, request):
576     """When a new user is created, add reference accounts to the reference platform.
577     """
578     # XXX XXX XXX The rest of this function has to be checked XXX XXX XXX
579
580     # Retrieve user information
581     user_query  = Query().get('local:user')             \
582         .select('user_id', 'config', 'email', 'status') \
583         .filter_by('email', '==', request['email'])
584     user_details = execute_admin_query(wsgi_request, user_query)
585
586     # USER MAIN ACCOUNT != reference
587     #print 'USER MAIN ACCOUNT != reference'
588     list_accounts_query = Query().get('local:account')              \
589         .select('user_id', 'platform_id', 'auth_type', 'config')    \
590         .filter_by('user_id', '==', user_details[0]['user_id'])     \
591         .filter_by('auth_type', '!=', 'reference')
592     list_accounts = execute_admin_query(wsgi_request, list_accounts_query)
593
594     # XXX main_platform is being erased several times ???
595     for account in list_accounts:
596         main_platform_query = Query().get('local:platform')         \
597             .select('platform_id', 'platform')                      \
598             .filter_by('platform_id', '==', account['platform_id'])
599         main_platform = execute_admin_query(wsgi_request, main_platform_query)
600
601     # Add reference accounts on SFA enabled platforms
602     platforms_query = Query().get('local:platform') \
603         .filter_by('disabled', '==', '0')           \
604         .filter_by('gateway_type', '==', 'sfa')     \
605         .select('platform_id', 'gateway_type')
606     platforms = execute_admin_query(wsgi_request, platforms_query)
607     for platform in platforms:
608         #print "add reference to platform ",platform
609         manifold_account_params = {
610             'user_id'       : user_details[0]['user_id'],
611             'platform_id'   : platform['platform_id'],
612             'auth_type'     : 'reference',
613             'config'        : '{"reference_platform": "' + main_platform[0]['platform'] + '"}',
614         }
615         manifold_add_account(wsgi_request, manifold_account_params)
616
617 def sfa_create_user(wsgi_request, request, namespace = None, as_admin = False):
618     """
619     Arguments:
620         wsgi_request (~ WSGIRequest) : 
621         request (dict) : the user request in our own dict format
622
623     Raises:
624         Exception
625     """
626     from sfa.util.xrn import Xrn 
627
628     auth_pi = request.get('pi', None)
629     auth_pi = list([auth_pi]) if auth_pi else list()
630
631     # We create a user request with Manifold terminology
632     sfa_user_params = {
633         'user_hrn'          : request['user_hrn'],
634         'user_email'        : request['email'],
635         'user_urn'          : Xrn(request['user_hrn'], request['type']).get_urn(),
636         'user_type'         : request['type'],
637         'keys'              : request['public_key'],
638         'user_first_name'   : request['first_name'],
639         'user_last_name'    : request['last_name'],
640         'pi_authorities'    : auth_pi,
641         'user_enabled'      : True
642     }
643
644     if namespace is not None:
645         query = Query.create('%s:user' % namespace).set(sfa_user_params).select('user_hrn')
646     else:
647         query = Query.create('user').set(sfa_user_params).select('user_hrn')
648
649     if as_admin:
650         results = execute_admin_query(wsgi_request, query)
651     else:
652         results = execute_query(wsgi_request, query)
653
654     if not results:
655         raise Exception, "Could not create %s. Already exists ?" % sfa_user_params['user_hrn']
656     else:
657         try:
658             theme.template_name = 'user_request_validated.txt'
659             text_content = render_to_string(theme.template, request)
660             theme.template_name = 'user_request_validated.html'
661             html_content = render_to_string(theme.template, request)
662         
663             theme.template_name = 'email_default_sender.txt'
664             sender =  render_to_string(theme.template, request)
665             sender = sender.replace('\n', '')
666
667
668             subject = 'User validated'
669
670             msg = EmailMultiAlternatives(subject, text_content, sender, [request['email']])
671             msg.attach_alternative(html_content, "text/html")
672             msg.send()
673         except Exception, e:
674             print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
675
676     return results
677
678 def create_user(wsgi_request, request, namespace = None, as_admin = False):
679     # XXX This has to be stored centrally
680     USER_STATUS_ENABLED = 2
681
682     # NOTE : if we were to create a user directly (just like we create slices,
683     # we would have to perform the steps in create_pending_user too
684
685     # Add the user to the SFA registry
686     sfa_create_user(wsgi_request, request, namespace, as_admin)
687
688     # Update Manifold user status
689     manifold_update_user(wsgi_request, request['email'], {'status': USER_STATUS_ENABLED})
690
691     # Add reference accounts for platforms
692     manifold_add_reference_user_accounts(wsgi_request, request)
693
694 def create_pending_user(wsgi_request, request, user_detail):
695     """
696     """
697
698     # Insert an entry in the PendingUser table
699     b = PendingUser(
700         first_name    = request['first_name'],
701         last_name     = request['last_name'],
702         authority_hrn = request['authority_hrn'],
703         email         = request['email'],
704         password      = request['password'],
705         public_key    = request['public_key'],
706         private_key   = request['private_key'],
707         user_hrn      = request['user_hrn'],
708         pi            = request['pi'],
709         email_hash    = request['email_hash'],
710         status        = 'False',
711     )
712     b.save()
713     # sends email to user to activate the email
714     theme.template_name = 'activate_user.html'
715     html_content = render_to_string(theme.template, request)
716     theme.template_name = 'activate_user.txt'
717     text_content = render_to_string(theme.template, request)
718     theme.template_name = 'activate_user_email_subject.txt'
719     subject = render_to_string(theme.template, request)
720     subject = subject.replace('\n', '')
721     #sender = 'support@myslice.info'
722     theme.template_name = 'email_default_sender.txt'
723     sender =  render_to_string(theme.template, request)
724     sender = sender.replace('\n', '')
725     recipient = [request['email']]
726     #recipient = recipient.append(request['email'])
727
728     msg = EmailMultiAlternatives(subject, text_content, sender, recipient)
729     msg.attach_alternative(html_content, "text/html")
730     msg.send()
731    
732     # saves the user to django auth_user table [needed for password reset]
733     user = User.objects.create_user(request['email'], request['email'], request['password'])
734
735     # Creating a manifold user
736     user_id = manifold_add_user(wsgi_request, request)
737
738     # Creating a Manifold account on the MySlice platform
739     # Note the JSON representation of public and private keys already includes quotes
740     account_config = {
741         'user_hrn'          : request['user_hrn'],
742         'user_public_key'   : request['public_key'],
743     }
744     if request['private_key']:
745         account_config['user_private_key'] = request['private_key']
746
747     user_id = user_detail['user_id'] + 1 # the user_id for the newly created user in local:user
748
749     # XXX TODO: Require a myslice platform
750     # ALERT: this will disapear with ROUTERV2 of Manifold
751     # We have to consider the case where several registries can be used
752     # Removed hardcoded platform = 5
753     # This platform == 'myslice' is a TMP FIX !!
754     try:
755         reg_platform_query = Query().get('local:platform') \
756             .filter_by('platform', '==', 'myslice')           \
757             .select('platform_id')
758         reg_platform = execute_admin_query(wsgi_request, reg_platform_query)
759
760         reg_platform_id = reg_platform[0]['platform_id']
761         account_params = {
762             'platform_id'   : reg_platform_id, # XXX ALERT !!
763             'user_id'       : user_id, 
764             'auth_type'     : request['auth_type'], 
765             'config'        : json.dumps(account_config),
766         }
767         manifold_add_account(wsgi_request, account_params)
768     except Exception, e:
769         print "Failed creating manifold account on platform %s for user: %s" % ('myslice', request['email'])
770
771     try:
772         # Send an email: the recipients are the PI of the authority
773         # If No PI is defined for this Authority, send to a default email (different for each theme)
774         recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
775         
776         theme.template_name = 'user_request_email.html'
777         html_content = render_to_string(theme.template, request)
778  
779         theme.template_name = 'user_request_email.txt'
780         text_content = render_to_string(theme.template, request)
781     
782         theme.template_name = 'user_request_email_subject.txt'
783         subject = render_to_string(theme.template, request)
784         subject = subject.replace('\n', '')
785     
786         theme.template_name = 'email_default_sender.txt'
787         sender =  render_to_string(theme.template, request)
788         sender = sender.replace('\n', '')
789     
790         msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
791         msg.attach_alternative(html_content, "text/html")
792         msg.send()
793     except Exception, e:
794         print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
795         import traceback
796         traceback.print_exc()