typo in actions
[myslice.git] / portal / actions.py
index 90f7db9..a0509dc 100644 (file)
@@ -1,13 +1,13 @@
 from django.http                    import HttpResponse
 from manifold.core.query            import Query
 from manifoldapi.manifoldapi        import execute_query,execute_admin_query
 from django.http                    import HttpResponse
 from manifold.core.query            import Query
 from manifoldapi.manifoldapi        import execute_query,execute_admin_query
-from portal.models                  import PendingUser, PendingSlice, PendingAuthority
+from portal.models                  import PendingUser, PendingSlice, PendingAuthority, PendingProject, PendingJoin
 from unfold.page                    import Page
 
 from unfold.page                    import Page
 
+import hashlib
 import json
 
 from django.contrib.auth.models     import User
 import json
 
 from django.contrib.auth.models     import User
-from django.contrib.sites.models    import Site
 from django.contrib.auth            import get_user_model
 from django.template.loader         import render_to_string
 from django.core.mail               import EmailMultiAlternatives, send_mail
 from django.contrib.auth            import get_user_model
 from django.template.loader         import render_to_string
 from django.core.mail               import EmailMultiAlternatives, send_mail
@@ -15,6 +15,9 @@ from django.core.mail               import EmailMultiAlternatives, send_mail
 from myslice.theme                  import ThemeView
 from myslice.configengine           import ConfigEngine
 
 from myslice.theme                  import ThemeView
 from myslice.configengine           import ConfigEngine
 
+from myslice.settings import logger
+
+from rest.sfa_api import sfa_client
 
 theme = ThemeView()
 
 
 theme = ThemeView()
 
@@ -25,14 +28,87 @@ import activity.slice
 # XXX tmp sfa dependency, should be moved to SFA gateway
 #from sfa.util.xrn                import Xrn 
 
 # XXX tmp sfa dependency, should be moved to SFA gateway
 #from sfa.util.xrn                import Xrn 
 
+def get_myslice_platform(request):
+    platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled','config').filter_by('platform','==','myslice')
+    platform_details = execute_query(request, platform_query)
+    if isinstance(platform_details,list):
+        for platform_detail in platform_details:
+            return platform_detail
+    else:
+        return None
+
+def get_myslice_account(request):
+    try:
+        platform_myslice = get_myslice_platform(request)
+        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config').filter_by('platform_id','==',platform_myslice['platform_id'])
+        account_details = execute_query(request, account_query)
+        for account_detail in account_details:
+            return account_detail
+    except Exception as e:
+        print e
+        return None
+
+def get_registry_url(request):
+    try:
+        platform_detail = get_myslice_platform(request)
+        platform_config = json.loads(platform_detail['config'])
+        import socket
+        hostname = socket.gethostbyaddr(socket.gethostname())[0]
+        registry = platform_config.get('registry','N/A')
+        if 'localhost' in registry:
+            port = registry.split(':')[-1:][0]
+            registry = "http://" + hostname +':'+ port
+        return registry
+    except Exception as e:
+        print e
+        return None
+
+def get_jfed_identity(request):
+    try:
+        account_detail = get_myslice_account(request)
+        account_config = json.loads(account_detail['config'])
+        if 'user_private_key' in account_config:
+            private_key = account_config['user_private_key']
+            user_hrn = account_config.get('user_hrn','N/A')
+            platform_detail = get_myslice_platform(request)
+            registry = get_registry_url(request)
+            #registry = 'http://sfa-fed4fire.pl.sophia.inria.fr:12345/'
+            jfed_identity = user_hrn + '\n' + registry + '\n' + private_key 
+            return jfed_identity
+        else:
+            return None
+    except Exception as e:
+        print e
+        return None
+
+def getAuthorities(request, admin = False):
+    # XXX theme has to be the same as the root authority 
+    result = sfa_client(request,'List',hrn=theme.theme,object_type='authority',platforms=['myslice'],admin=admin)
+    authorities = list()
+    try:
+        for item in result['myslice']:
+            t_hrn = item['hrn'].split('.')
+            if 'name' in item:
+                authorities.append({'authority_hrn':item['hrn'], 'name':item['name'], 'shortname':t_hrn[-1].upper()})    
+            else:
+                authorities.append({'authority_hrn':item['hrn']})    
+    except:
+        logger.error(result)
+    return sorted(authorities)
+
 
 # Get the list of pis in a given authority
 def authority_get_pis(request, authority_hrn):
 
 # Get the list of pis in a given authority
 def authority_get_pis(request, authority_hrn):
+    # CACHE PB with fields
+    page = Page(request)
+    metadata = page.get_metadata()
+    auth_md = metadata.details_by_object('authority')
+    auth_fields = [column['name'] for column in auth_md['column']]
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query = Query.get('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).select('pi_users')
+    query = Query.get('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).select(auth_fields)
     results = execute_admin_query(request, query)
     results = execute_admin_query(request, query)
-    print "authority_get_pis = %s" % results
+    #print "authority_get_pis = %s" % results
     # NOTE: temporarily commented. Because results is giving empty list. 
     # Needs more debugging
     #if not results:
     # NOTE: temporarily commented. Because results is giving empty list. 
     # Needs more debugging
     #if not results:
@@ -76,48 +152,75 @@ def authority_check_pis(request, user_email):
             pi_status = True
         return pi_status
 
             pi_status = True
         return pi_status
 
-    except Exception,e:
-        print "Exception in actions.py in authority_check_pis %s" % e
+    except Exception as e:
+        logger.error("Exception in actions.py in authority_check_pis {}".format(e))
         return None
 
 
         return None
 
 
-def authority_add_pis(request, authority_hrn,user_hrn):
+def authority_add_pis(request, authority_hrn, user_hrn):
     try:
     try:
+        pi_list = []
         # getting pis of the authority of the user
         pis = authority_get_pis (request, authority_hrn)
         for pi in pis:
             pi_list = pi['pi_users']
    
         updated_pi_list = pi_list.append(user_hrn) 
         # getting pis of the authority of the user
         pis = authority_get_pis (request, authority_hrn)
         for pi in pis:
             pi_list = pi['pi_users']
    
         updated_pi_list = pi_list.append(user_hrn) 
-        query = Query.update('authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
+        query = Query.update('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
         results = execute_query(request,query)
         newpis = authority_get_pis (request, authority_hrn)
         results = execute_query(request,query)
         newpis = authority_get_pis (request, authority_hrn)
-        return newpis
-    except Exception,e: 
-        print "Exception in actions.py in authority_add_pis %s" % e
-        return None
+       
+        # Add the user to the slices of the project he/she joined
+        if len(authority_hrn.split('.')) > 2:
+            # this authority_hrn is a project
+            query_slices = Query.get('myslice:slice').filter_by('parent_authority', '==', authority_hrn).select('slice_hrn')
+            results_slices = execute_query(request,query_slices)
+            for s in results_slices:
+                sfa_add_user_to_slice(request, user_hrn, s['slice_hrn'])
+        # Clear Credentials of the user 
+        user_email = get_user_email(request, user_hrn)
+        clear_user_creds(request, user_email)
 
 
+        return newpis
+    except Exception as e: 
+        logger.error("Exception in actions.py in authority_add_pis {}".format(e))
+        raise Exception, "Exception in actions.py in authority_add_pis {}".format(e)
 
 
-def authority_remove_pis(request, authority_hrn,user_hrn):
+def authority_remove_pis(request, authority_hrn, user_hrn):
     try:
     try:
+        pi_list = []
         # getting pis of the authority of the user
         pis = authority_get_pis (request, authority_hrn)
         for pi in pis:
             pi_list = pi['pi_users']
  
         updated_pi_list = pi_list.remove(user_hrn) 
         # getting pis of the authority of the user
         pis = authority_get_pis (request, authority_hrn)
         for pi in pis:
             pi_list = pi['pi_users']
  
         updated_pi_list = pi_list.remove(user_hrn) 
-        query = Query.update('authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
+        query = Query.update('myslice:authority').filter_by('authority_hrn', '==', authority_hrn).set({'pi_users':pi_list})
         results = execute_query(request,query)
         newpis = authority_get_pis (request, authority_hrn)
         results = execute_query(request,query)
         newpis = authority_get_pis (request, authority_hrn)
+
+        # Remove the user from the slices of the project he/she left
+        if len(authority_hrn.split('.')) > 2:
+            # this authority_hrn is a project
+            query_slices = Query.get('myslice:slice').filter_by('parent_authority', '==', authority_hrn).select('slice_hrn')
+            results_slices = execute_query(request,query_slices)
+            for s in results_slices:
+                print 'remove from slice %s' % s
+                sfa_remove_user_from_slice(request, user_hrn, s['slice_hrn'])
+
+        # Clear Credentials of the user 
+        user_email = get_user_email(request, user_hrn)
+        clear_user_creds(request, user_email)
+
         return newpis
         return newpis
-    except Exception,e: 
-        print "Exception in actions.py in authority_remove_pis %s" % e
-        return None
+    except Exception as e: 
+        logger.error("Exception in actions.py in authority_remove_pis {}".format(e))
+        raise Exception, "Exception in actions.py in authority_remove_pis {}".format(e)
 
 
 def authority_get_pi_emails(request, authority_hrn):
     pi_users = authority_get_pis(request,authority_hrn)
 
 
 def authority_get_pi_emails(request, authority_hrn):
     pi_users = authority_get_pis(request,authority_hrn)
-    print "pi_users = %s" % pi_users
+    logger.info("pi_users = %s" % pi_users)
 
     if any(pi['pi_users'] == None or not pi['pi_users']  for pi in pi_users):
         #theme.template_name = 'email_default_recipients.txt' 
 
     if any(pi['pi_users'] == None or not pi['pi_users']  for pi in pi_users):
         #theme.template_name = 'email_default_recipients.txt' 
@@ -134,6 +237,11 @@ def authority_get_pi_emails(request, authority_hrn):
         results = execute_admin_query(request, query)
         return [result['user_email'] for result in results]
 
         results = execute_admin_query(request, query)
         return [result['user_email'] for result in results]
 
+def get_user_email(request, user_hrn):
+    query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('user_email')
+    results = execute_admin_query(request, query)
+    return results[0]['user_email'] 
+
 #clear user credentials
 def clear_user_creds(request, user_email):
     try:
 #clear user credentials
 def clear_user_creds(request, user_email):
     try:
@@ -169,13 +277,13 @@ def clear_user_creds(request, user_email):
                         else:
                             return None
 
                         else:
                             return None
 
-    except Exception,e:
-        print "Exception in actions.py in clear_user_creds %s" % e
+    except Exception as e:
+        logger.error("Exception in actions.py in clear_user_creds {}".format(e))
         return None
 
 def is_pi(wsgi_request, user_hrn, authority_hrn):
     # authorities from user where user_hrn == "ple.upmc.jordan_auge"
         return None
 
 def is_pi(wsgi_request, user_hrn, authority_hrn):
     # authorities from user where user_hrn == "ple.upmc.jordan_auge"
-    print "#### actions.py is_pi authority_hrn = ", authority_hrn
+    logger.debug("#### actions.py is_pi authority_hrn = {}".format(authority_hrn))
     try:
         # CACHE PB with fields
         page = Page(wsgi_request)
     try:
         # CACHE PB with fields
         page = Page(wsgi_request)
@@ -187,22 +295,21 @@ def is_pi(wsgi_request, user_hrn, authority_hrn):
         query  = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==',user_hrn)
         #query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
         results = execute_query(wsgi_request, query)
         query  = Query().get('myslice:user').select(user_fields).filter_by('user_hrn','==',user_hrn)
         #query = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn).select('pi_authorities')
         results = execute_query(wsgi_request, query)
-        print "is_pi results = ", results
         for user_detail in results:
             if authority_hrn in user_detail['pi_authorities']:
                 return True
         for user_detail in results:
             if authority_hrn in user_detail['pi_authorities']:
                 return True
-    except Exception,e:
-        print "Exception in actions.py in is_pi %s" % e
+    except Exception as e:
+        logger.error("Exception in actions.py in is_pi {}".format(e))
     return False
     
 # SFA get record
 
     return False
     
 # SFA get record
 
-def sfa_get_user(request, user_hrn, pub):
+def sfa_get_user(request, user_hrn, pub=None):
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query_sfa_user = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn)
     result_sfa_user = execute_admin_query(request, query_sfa_user)
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
     query_sfa_user = Query.get('myslice:user').filter_by('user_hrn', '==', user_hrn)
     result_sfa_user = execute_admin_query(request, query_sfa_user)
-    return result_sfa_user                        
+    return result_sfa_user[0]                        
 
 def sfa_update_user(request, user_hrn, user_params):
     # user_params: keys [public_key] 
 
 def sfa_update_user(request, user_hrn, user_params):
     # user_params: keys [public_key] 
@@ -217,28 +324,50 @@ def sfa_update_user(request, user_hrn, user_params):
 def sfa_add_authority(request, authority_params):
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
 def sfa_add_authority(request, authority_params):
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query = Query.create('authority').set(authority_params).select('authority_hrn')
+    query = Query.create('myslice:authority').set(authority_params).select('authority_hrn')
     results = execute_query(request, query)
     results = execute_query(request, query)
-    print "sfa_add_auth results=",results
+    logger.info("sfa_add_auth results={}".format(results))
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % authority_params['hrn']
     return results
 
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % authority_params['hrn']
     return results
 
-def sfa_add_user_to_slice(request, user_hrn, slice_params):
-# 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'
+def sfa_add_user_to_slice(request, user_hrn, slice_hrn):
+# UPDATE myslice:slice SET users = ['fed4fire.upmc.loic_baron', 'fed4fire.upmc.mohammed-yasin_rahman', 'fed4fire.upmc.demo'] WHERE slice_hrn == 'fed4fire.upmc.project_y.test_under' SELECT slice_hrn, slice_urn
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_current_users = Query.get('myslice:slice').select('users').filter_by('slice_hrn','==',slice_hrn)
+    results_current_users = execute_query(request, query_current_users)
+    current_users = list()
+    for r in results_current_users:
+        current_users.extend(r['users'])
+    users = list(set([user_hrn]) | set(current_users))
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query_current_users = Query.get('myslice:slice').select('user').filter_by('slice_hrn','==',slice_params['hrn'])
+    query = Query.update('myslice:slice').filter_by('slice_hrn', '==', slice_hrn).set({'users':users}).select('slice_hrn')
+    results = execute_query(request, query)
+# Also possible but not supported yet
+# UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
+    if not results:
+        raise Exception, "Could not add user %s to slice %s" % (user_hrn, slice_hrn)
+    return results
+
+def sfa_remove_user_from_slice(request, user_hrn, slice_hrn):
+# UPDATE myslice:slice SET users = ['fed4fire.upmc.loic_baron', 'fed4fire.upmc.demo'] WHERE slice_hrn == 'fed4fire.upmc.project_y.test_under' SELECT slice_hrn, slice_urn
+    # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
+    query_current_users = Query.get('myslice:slice').select('users').filter_by('slice_hrn','==',slice_hrn)
     results_current_users = execute_query(request, query_current_users)
     results_current_users = execute_query(request, query_current_users)
-    slice_params['researcher'] = slice_params['researcher'] | results_current_users
+    current_users = list()
+    for r in results_current_users:
+        current_users.extend(r['users'])
+    if user_hrn in current_users:
+        current_users.remove(user_hrn)
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
 
     # REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-    query = Query.update('myslice:slice').filter_by('user_hrn', '==', user_hrn).set(slice_params).select('slice_hrn')
+    query = Query.update('myslice:slice').filter_by('slice_hrn', '==', slice_hrn).set({'users':current_users}).select('slice_hrn')
     results = execute_query(request, query)
 # Also possible but not supported yet
 # UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
     if not results:
     results = execute_query(request, query)
 # Also possible but not supported yet
 # UPDATE myslice:user SET slice=['ple.upmc.agent','ple.upmc.myslicedemo','ple.upmc.tophat'] where user_hrn=='ple.upmc.azerty'
     if not results:
-        raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
+        raise Exception, "Could not remove user %s to slice %s" % (user_hrn, slice_hrn)
     return results
 
 # Propose hrn
     return results
 
 # Propose hrn
@@ -272,7 +401,7 @@ def manifold_add_user(wsgi_request, request):
     if not results:
         raise Exception, "Failed creating manifold user: %s" % user_params['email']
     result = results[0]
     if not results:
         raise Exception, "Failed creating manifold user: %s" % user_params['email']
     result = results[0]
-    return result['email']
+    return result['user_id']
 
 def manifold_update_user(request, email, user_params):
     # user_params: password, config e.g., 
 
 def manifold_update_user(request, email, user_params):
     # user_params: password, config e.g., 
@@ -300,13 +429,15 @@ def manifold_update_account(request,user_id,account_params):
     return results
 
 #explicitly mention the platform_id
     return results
 
 #explicitly mention the platform_id
-def manifold_delete_account(request, platform_id, user_id, account_params):
-    query = Query.delete('local:account').filter_by('platform_id', '==', platform_id).filter_by('user_id', '==', user_id).set(account_params).select('user_id')
+def manifold_delete_account(request, user_id, platform_id = None):
+    query = Query.delete('local:account').filter_by('user_id', '==', user_id)
+    if platform_id is not None:
+        query.filter_by('platform_id', '==', platform_id)
     results = execute_admin_query(request,query)
     return results
 
     results = execute_admin_query(request,query)
     return results
 
-def manifold_delete_user(request, user_id, user_params):
-    query = Query.delete('local:user').filter_by('user_id', '==', user_id).set(user_params).select('user_id')
+def manifold_delete_user(request, user_id):
+    query = Query.delete('local:user').filter_by('user_id', '==', user_id).select('user_id')
     results = execute_admin_query(request,query)
     return results
 
     results = execute_admin_query(request,query)
     return results
 
@@ -320,6 +451,36 @@ def manifold_add_platform(request, platform_params):
     result, = results
     return result['platform_id']
 
     result, = results
     return result['platform_id']
 
+def delete_local_user(wsgi_request, user_email):
+    user_query = Query().get('local:user') \
+        .filter_by('email', '==', user_email)           \
+        .select('user_id','config')
+    user = execute_admin_query(wsgi_request, user_query)
+    if len(user) == 0:
+        return False
+        #raise Exception, "User not found, check local DB"
+    else:
+        user_id = user[0]['user_id']
+        user_config = json.loads(user[0]['config'])
+        authority_hrn = user_config.get('authority', None)
+        
+        #if is_pi(wsgi_request, '$user_hrn', authority_hrn):
+        try:
+            # removing from Django auth_user
+            UserModel = get_user_model()
+            UserModel._default_manager.filter(email__iexact = user_email).delete()
+
+            # removing manifold account
+            manifold_delete_account(wsgi_request, user_id)           
+                     
+            # removing manifold user
+            manifold_delete_user(wsgi_request, user_id)
+        except Exception, e:
+            #return False
+            print "No sufficient rights on authority = ",authority_hrn
+
+    return True      
+
 
 def make_request_user(user):
     request = {}
 
 def make_request_user(user):
     request = {}
@@ -349,6 +510,29 @@ def make_request_slice(slice):
     request['purpose'] = slice.purpose
     return request
 
     request['purpose'] = slice.purpose
     return request
 
+def make_request_project(project):
+    request = {}
+    request['type'] = 'project'
+    request['id'] = project.id
+    request['user_hrn'] = project.user_hrn
+    request['email'] = project.email
+    request['timestamp'] = project.created
+    request['authority_hrn'] = project.authority_hrn
+    request['project_name'] = project.project_name
+    request['purpose'] = project.purpose
+    return request
+
+def make_request_join(join):
+    request = {}
+    request['type'] = 'join'
+    request['id'] = join.id
+    request['user_hrn'] = join.user_hrn
+    request['email'] = join.email
+    request['timestamp'] = join.created
+    request['authority_hrn'] = join.authority_hrn
+    request['project_name'] = join.project_name
+    return request
+
 def make_request_authority(authority):
     request = {}
     request['type']                  = 'authority'
 def make_request_authority(authority):
     request = {}
     request['type']                  = 'authority'
@@ -370,7 +554,8 @@ def make_request_authority(authority):
     request['timestamp']             = authority.created
     return request
 
     request['timestamp']             = authority.created
     return request
 
-def make_requests(pending_users, pending_slices, pending_authorities):
+def make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins):
+    logger.info("$$$$$$$$$$$$$$$  make_request")
     requests = []
     for user in pending_users:
         requests.append(make_request_user(user))
     requests = []
     for user in pending_users:
         requests.append(make_request_user(user))
@@ -378,10 +563,15 @@ def make_requests(pending_users, pending_slices, pending_authorities):
         requests.append(make_request_slice(slice))
     for authority in pending_authorities:
         requests.append(make_request_authority(authority))
         requests.append(make_request_slice(slice))
     for authority in pending_authorities:
         requests.append(make_request_authority(authority))
+    for project in pending_projects:
+        requests.append(make_request_project(project))
+    for join in pending_joins:
+        requests.append(make_request_join(join))
     return requests   
 
 def get_request_by_id(ids):
     return requests   
 
 def get_request_by_id(ids):
-    sorted_ids = { 'user': [], 'slice': [], 'authority': [] }
+    logger.info("$$$$$$$$$$$$$$$$  get_request_by_id")
+    sorted_ids = { 'user': [], 'slice': [], 'authority': [], 'project': [], 'join': [] }
     for type__id in ids:
         type, id = type__id.split('__')
         sorted_ids[type].append(id)
     for type__id in ids:
         type, id = type__id.split('__')
         sorted_ids[type].append(id)
@@ -390,40 +580,53 @@ def get_request_by_id(ids):
         pending_users  = PendingUser.objects.all()
         pending_slices = PendingSlice.objects.all()
         pending_authorities = PendingAuthority.objects.all()
         pending_users  = PendingUser.objects.all()
         pending_slices = PendingSlice.objects.all()
         pending_authorities = PendingAuthority.objects.all()
+        pending_projects = PendingProject.objects.all()
+        pending_joins = PendingJoin.objects.all()
     else:
         pending_users  = PendingUser.objects.filter(id__in=sorted_ids['user']).all()
         pending_slices = PendingSlice.objects.filter(id__in=sorted_ids['slice']).all()
         pending_authorities = PendingAuthority.objects.filter(id__in=sorted_ids['authority']).all()
     else:
         pending_users  = PendingUser.objects.filter(id__in=sorted_ids['user']).all()
         pending_slices = PendingSlice.objects.filter(id__in=sorted_ids['slice']).all()
         pending_authorities = PendingAuthority.objects.filter(id__in=sorted_ids['authority']).all()
+        pending_projects = PendingProject.objects.filter(id__in=sorted_ids['project']).all()
+        pending_joins = PendingJoin.objects.filter(id__in=sorted_ids['join']).all()
 
 
-    return make_requests(pending_users, pending_slices, pending_authorities)
+    return make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins)
 
 def get_requests(authority_hrns=None):
 
 def get_requests(authority_hrns=None):
-    print "get_request_by_authority auth_hrns = ", authority_hrns
+    logger.info("$$$$$$$$$$$$$   get_request_by_authority auth_hrns = {}".format(authority_hrns))
     if not authority_hrns:
         ## get those pending users who have confirmed their emails
         pending_users  = PendingUser.objects.filter(status__iexact = 'True')
         pending_slices = PendingSlice.objects.all()
         pending_authorities = PendingAuthority.objects.all()
     if not authority_hrns:
         ## get those pending users who have confirmed their emails
         pending_users  = PendingUser.objects.filter(status__iexact = 'True')
         pending_slices = PendingSlice.objects.all()
         pending_authorities = PendingAuthority.objects.all()
+        pending_projects = PendingProject.objects.all()
+        pending_joins = PendingJoin.objects.all()
     else:
         pending_users  = PendingUser.objects
         pending_slices = PendingSlice.objects
         pending_authorities = PendingAuthority.objects
     else:
         pending_users  = PendingUser.objects
         pending_slices = PendingSlice.objects
         pending_authorities = PendingAuthority.objects
+        pending_projects = PendingProject.objects
+        pending_joins = PendingJoin.objects
         from django.db.models import Q
         list_user_Q = list()
         list_slice_Q = list()
         list_auth_Q = list()
         from django.db.models import Q
         list_user_Q = list()
         list_slice_Q = list()
         list_auth_Q = list()
+        list_proj_Q = list()
+        list_join_Q = list()
         for hrn in authority_hrns:
             list_user_Q.append(Q(authority_hrn__startswith=hrn, status__iexact = 'True'))
             list_slice_Q.append(Q(authority_hrn__startswith=hrn))
             list_auth_Q.append(Q(site_authority__startswith=hrn))
         for hrn in authority_hrns:
             list_user_Q.append(Q(authority_hrn__startswith=hrn, status__iexact = 'True'))
             list_slice_Q.append(Q(authority_hrn__startswith=hrn))
             list_auth_Q.append(Q(site_authority__startswith=hrn))
-            print "startswith hrn = ",hrn
+            list_proj_Q.append(Q(authority_hrn__startswith=hrn))
+            list_join_Q.append(Q(authority_hrn__startswith=hrn))
         from operator import __or__ as OR
         pending_users        = pending_users.filter(reduce(OR, list_user_Q))
         pending_slices       = pending_slices.filter(reduce(OR, list_slice_Q))
         pending_authorities  = pending_authorities.filter(reduce(OR, list_auth_Q))
         from operator import __or__ as OR
         pending_users        = pending_users.filter(reduce(OR, list_user_Q))
         pending_slices       = pending_slices.filter(reduce(OR, list_slice_Q))
         pending_authorities  = pending_authorities.filter(reduce(OR, list_auth_Q))
+        pending_projects     = pending_projects.filter(reduce(OR, list_proj_Q))
+        pending_joins        = pending_joins.filter(reduce(OR, list_join_Q))
         #pending_authorities  = pending_authorities.all() #filter(reduce(OR, list_Q))
 
         #pending_authorities  = pending_authorities.all() #filter(reduce(OR, list_Q))
 
-    return make_requests(pending_users, pending_slices, pending_authorities)
+    return make_requests(pending_users, pending_slices, pending_authorities, pending_projects, pending_joins)
 
 # XXX Is it in sync with the form fields ?
 
 
 # XXX Is it in sync with the form fields ?
 
@@ -441,66 +644,128 @@ def portal_validate_request(wsgi_request, request_ids):
         # slice : number of nodes, type of nodes, purpose
         
         request_status = {}
         # slice : number of nodes, type of nodes, purpose
         
         request_status = {}
-
-        if request['type'] == 'user':
-
-            try:
+        try:
+            if request['type'] == 'user':
                 create_user(wsgi_request, request)
                 request_status['SFA user'] = {'status': True }
                 create_user(wsgi_request, request)
                 request_status['SFA user'] = {'status': True }
+                u = PendingUser.objects.get(id=request['id'])
+                ctx = {
+                    'first_name'    : u.first_name, 
+                    'last_name'     : u.last_name,
+                    'email'         : u.email,        
+                }      
+                user_email = u.email
+
                 PendingUser.objects.get(id=request['id']).delete()
                 PendingUser.objects.get(id=request['id']).delete()
-            except Exception, e:
-                 request_status['SFA user'] = {'status': False, 'description': str(e)}
-                       
-#            user_params = {'status':2}
-#            manifold_update_user(request, request['email'], user_params)
-
-            # MANIFOLD user should be added beforehand, during registration
-            #try:
-            #    manifold_user_params = { key: request[key] for key in MANIFOLD_USER_KEYS }
-            #    # XXX # manifold_add_user(manifold_user_params)
-            #    request_status['MySlice user'] = {'status': True }
-            #except Exception, e:
-            #    request_status['MySlice user'] = {'status': False, 'description': str(e)}
-
-            # XXX
-            #manifold_account_params = { key: request[key] for key in MANIFOLD_ACCOUNT_KEYS }
-            #manifold_add_account(manifold_account_params)
-            #request_status['MySlice testbed accounts'] = {'status': False }
-
-        elif request['type'] == 'slice':
-            try:
+
+            elif request['type'] == 'slice':
                 create_slice(wsgi_request, request)
                 request_status['SFA slice'] = {'status': True }
                 create_slice(wsgi_request, request)
                 request_status['SFA slice'] = {'status': True }
+                s = PendingSlice.objects.get(id=request['id'])
+                ctx = {
+                    'slice_name'    : s.slice_name, 
+                    'url'           : s.url,
+                    'purpose'       : s.purpose,        
+                    'email'         : s.email,        
+                }      
+                user_email = s.email
+
                 PendingSlice.objects.get(id=request['id']).delete()
 
                 PendingSlice.objects.get(id=request['id']).delete()
 
-            except Exception, e:
-                request_status['SFA slice'] = {'status': False, 'description': str(e)}
+                # Clear user's Credentials
+                sfa_user = sfa_get_user(wsgi_request, request['user_hrn'])
+                clear_user_creds(wsgi_request,sfa_user['user_email'])
 
 
-        elif request['type'] == 'authority':
-            try:
+            elif request['type'] == 'authority':
                 #hrn = "%s.%s" % (request['authority_hrn'], request['site_authority'])
                 hrn = request['site_authority']
                 #hrn = "%s.%s" % (request['authority_hrn'], request['site_authority'])
                 hrn = request['site_authority']
+                name = request['site_name']
                 # XXX tmp sfa dependency
                 from sfa.util.xrn import Xrn 
                 urn = Xrn(hrn, request['type']).get_urn()
                 
                 # Only hrn is required for Manifold Query 
                 sfa_authority_params = {
                 # XXX tmp sfa dependency
                 from sfa.util.xrn import Xrn 
                 urn = Xrn(hrn, request['type']).get_urn()
                 
                 # Only hrn is required for Manifold Query 
                 sfa_authority_params = {
-                    'authority_hrn'        : hrn,
-                    #'authority_urn'        : urn,
-                    #'type'       : request['type'],
-                    #'pi'        : None,
-                    #'enabled'    : True
+                    'authority_hrn' : hrn,
+                    'name'          : name       
                 }
                 }
-                print "ADD Authority"
+                #logger.info("ADD Authority")
                 sfa_add_authority(wsgi_request, sfa_authority_params)
                 request_status['SFA authority'] = {'status': True }
                 sfa_add_authority(wsgi_request, sfa_authority_params)
                 request_status['SFA authority'] = {'status': True }
+                a = PendingAuthority.objects.get(id=request['id'])
+                ctx = { 
+                    'site_name'     : a.site_name,
+                    #'short_name'    : a.short_name,
+                    #'url'           : a.url,
+                    'city'          : a.address_city,
+                    'country'       : a.address_country,                          
+                    #'portal_url'    : a.current_site,
+                }
+                # address_line1 contains the email of the user in pending_authority table
+                user_email = a.address_line1
+
                 PendingAuthority.objects.get(id=request['id']).delete()
                 PendingAuthority.objects.get(id=request['id']).delete()
+                
+                # Clear Admin Cache as it is used to display the list of authorities in Registration page
+                query = Query.update('myslice:authority').filter_by('authority_hrn', '==', sfa_authority_params['authority_hrn']).set({'authority_hrn':sfa_authority_params['authority_hrn']}).select('authority_hrn')
+                res = execute_admin_query(request, query)
+
+            elif request['type'] == 'project':
+                hrn = request['authority_hrn'] + '.' + request['project_name']
+
+                # Only hrn is required for Manifold Query 
+                sfa_authority_params = {
+                    'authority_hrn'        : hrn
+                }
+                sfa_add_authority(wsgi_request, sfa_authority_params)
+                
+                # Add user as a PI of the project
+                # Clear user's Credentials
+                authority_add_pis(wsgi_request, hrn , request['user_hrn'])
 
 
-            except Exception, e:
-                request_status['SFA authority'] = {'status': False, 'description': str(e)}
+                request_status['SFA project'] = {'status': True }
+                p = PendingProject.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : p.project_name, 
+                    'authority_hrn' : p.authority_hrn,
+                    'email'         : p.email,        
+                    'purpose'       : p.purpose,
+                }      
+                user_email = p.email
+
+                PendingProject.objects.get(id=request['id']).delete()
+
+                # Clear Admin Cache as it is used to display the list of projects in Slice request page
+                query = Query.update('myslice:authority').filter_by('authority_hrn', '==', sfa_authority_params['authority_hrn']).set({'authority_hrn':sfa_authority_params['authority_hrn']}).select('authority_hrn')
+                res = execute_admin_query(request, query)
 
 
-        # XXX Remove from Pendings in database
+
+            elif request['type'] == 'join':
+                # Add user as a PI of the project
+                # Clear user's Credentials
+                authority_add_pis(wsgi_request, request['authority_hrn'] , request['user_hrn'])
+
+                request_status['SFA join'] = {'status': True }
+                j = PendingJoin.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : j.project_name, 
+                    'authority_hrn' : j.authority_hrn,
+                    'email'         : j.email,        
+                    'user_hrn'      : j.user_hrn,
+                }      
+                user_email = j.email
+
+                PendingJoin.objects.get(id=request['id']).delete()
+            else:
+                raise Exception, 'unknown type of request %s' % request['type']
+            # XXX Remove from Pendings in database
+
+            send_status_email(wsgi_request, ctx, user_email, request['type'], 'validated')
+        except Exception, e:
+            request_status['SFA '+request['type']] = {'status': False, 'description': str(e)}
+            logger.error('ERROR - actions.py - portal_validate_request: %s' % e)
+            import traceback
+            logger.error(traceback.format_exc())
 
         status['%s__%s' % (request['type'], request['id'])] = request_status
 
 
         status['%s__%s' % (request['type'], request['id'])] = request_status
 
@@ -510,23 +775,26 @@ def validate_action(request, **kwargs):
     ids = filter(None, kwargs['id'].split('/'))
     status = portal_validate_request(request, ids)
     json_answer = json.dumps(status)
     ids = filter(None, kwargs['id'].split('/'))
     status = portal_validate_request(request, ids)
     json_answer = json.dumps(status)
-    return HttpResponse (json_answer, mimetype="application/json")
+    return HttpResponse (json_answer, content_type="application/json")
 
 
 def reject_action(request, **kwargs):
     ids = filter(None, kwargs['id'].split('/'))
     status = portal_reject_request(request, ids)
     json_answer = json.dumps(status)
 
 
 def reject_action(request, **kwargs):
     ids = filter(None, kwargs['id'].split('/'))
     status = portal_reject_request(request, ids)
     json_answer = json.dumps(status)
-    return HttpResponse (json_answer, mimetype="application/json")
+    return HttpResponse (json_answer, content_type="application/json")
 
 
+def get_current_site(request):
+    if request.is_secure():
+        current_site = 'https://'
+    else:
+        current_site = 'http://'
+    current_site += request.META['HTTP_HOST']
+    return current_site
 
 def portal_reject_request(wsgi_request, request_ids):
     status = {}
 
 def portal_reject_request(wsgi_request, request_ids):
     status = {}
-    # get the domain url    
-    current_site = Site.objects.get_current()
-    current_site = current_site.domain
-
-
+    current_site = get_current_site(wsgi_request)
     if not isinstance(request_ids, list):
         request_ids = [request_ids]
 
     if not isinstance(request_ids, list):
         request_ids = [request_ids]
 
@@ -539,8 +807,8 @@ def portal_reject_request(wsgi_request, request_ids):
         
         request_status = {}
 
         
         request_status = {}
 
-        if request['type'] == 'user':
-            try:
+        try:
+            if request['type'] == 'user':
                 request_status['SFA user'] = {'status': True }
                 # getting user email based on id 
                 ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
                 request_status['SFA user'] = {'status': True }
                 # getting user email based on id 
                 ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
@@ -552,131 +820,122 @@ def portal_reject_request(wsgi_request, request_ids):
                 ctx = {
                     'first_name'    : first_name, 
                     'last_name'     : last_name, 
                 ctx = {
                     'first_name'    : first_name, 
                     'last_name'     : last_name, 
+                    'email'         : user_email,
                     'portal_url'    : current_site,
                     }
                     'portal_url'    : current_site,
                     }
-                try:
-                    theme.template_name = 'user_request_denied.txt'
-                    text_content = render_to_string(theme.template, ctx)
-                    theme.template_name = 'user_request_denied.html'
-                    html_content = render_to_string(theme.template, ctx)
-                    theme.template_name = 'email_default_sender.txt'
-                    sender =  render_to_string(theme.template, ctx)
-                    sender = sender.replace('\n', '')
-                               
-                    subject = 'User request denied.'
-
-                    msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-                    msg.attach_alternative(html_content, "text/html")
-                    msg.send()
-                except Exception, e:
-                    print "Failed to send email, please check the mail templates and the SMTP configuration of your server"   
-            
-                # removing from Django auth_user
-                UserModel = get_user_model()
-                UserModel._default_manager.filter(email__iexact = user_email).delete()
+
                 # removing from Django portal_pendinguser
                 PendingUser.objects.get(id=request['id']).delete()
                 # removing from Django portal_pendinguser
                 PendingUser.objects.get(id=request['id']).delete()
-                # removing from manifold
-                # removing manifold account
-                user_query = Query().get('local:user') \
-                    .filter_by('email', '==', user_email)           \
-                    .select('user_id')
-                user = execute_admin_query(wsgi_request, user_query)
-                user_id = user[0]['user_id']
-        
-                platform_query = Query().get('local:platform') \
-                    .filter_by('platform', '==', 'myslice')           \
-                    .select('platform_id')
-                platform = execute_admin_query(wsgi_request, platform_query)
-                platform_id = platform[0]['platform_id']
-                account_params = {'user_id':user_id}
-                manifold_delete_account(request, platform_id, user_id, account_params)           
-             
-                # removing manifold user
-                user_params = {'user_id':user_id}
-                manifold_delete_user(request, user_id, user_params)
-            except Exception, e:
-                request_status['SFA authority'] = {'status': False, 'description': str(e)}
-                      
-        elif request['type'] == 'slice':
-            request_status['SFA slice'] = {'status': True } 
-
-            # getting user email based on id 
-            ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
-            for user in PendingSlice.objects.raw('SELECT * FROM portal_pendingslice WHERE id = %s', [request['id']]):
-                user_email= user.type_of_nodes # XXX type_of_nodes field contains the email [shd be renamed in DB]
-                slice_name = user.slice_name
-                purpose = user.purpose
-                url = user.number_of_nodes
-
-            ctx = {
-                'slice_name': slice_name,
-                'purpose': purpose,
-                'url': url,
-                'portal_url': current_site,
-                }
-            try:
-                theme.template_name = 'slice_request_denied.txt'
-                text_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'slice_request_denied.html'
-                html_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'email_default_sender.txt'
-                sender =  render_to_string(theme.template, ctx)
-                sender = sender.replace('\n', '')
-                               
-                subject = 'Slice request denied.'
-
-                msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-                msg.attach_alternative(html_content, "text/html")
-                msg.send()
-            except Exception, e:
-                print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-                      
-            PendingSlice.objects.get(id=request['id']).delete()
-
-        elif request['type'] == 'authority':
-            request_status['SFA authority'] = {'status': True }
-            
-            # getting user email based on id 
-            ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
-            for user in PendingAuthority.objects.raw('SELECT * FROM portal_pendingauthority WHERE id = %s', [request['id']]):
-                user_email= user.address_line1 # XXX address_line1 field contains the email [shd be renamed in DB]
-                site_name = user.site_name
-                city = user.address_city
-                country = user.address_country
-                short_name = user.site_abbreviated_name
-                url = user.site_url
-
-            ctx = { 
-                'site_name': site_name,
-                'short_name': short_name,
-                'url': url,
-                'city': city,
-                'country': country,                          
-                'portal_url'    : current_site,
-                }
                 
                 
-            try:
-                theme.template_name = 'authority_request_denied.txt'
-                text_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'authority_request_denied.html'
-                html_content = render_to_string(theme.template, ctx)
-                theme.template_name = 'email_default_sender.txt'
-                sender =  render_to_string(theme.template, ctx)
-                sender = sender.replace('\n', '')
-                subject = 'Authority request denied.'
-                msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-                msg.attach_alternative(html_content, "text/html")
-                msg.send()
-            except Exception, e:
-                print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-
-            PendingAuthority.objects.get(id=request['id']).delete()
+                delete_local_user(wsgi_request, user_email)
+                          
+            elif request['type'] == 'slice':
+                request_status['SFA slice'] = {'status': True } 
+
+                # getting user email based on id 
+                ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
+                for user in PendingSlice.objects.raw('SELECT * FROM portal_pendingslice WHERE id = %s', [request['id']]):
+                    user_email= user.type_of_nodes # XXX type_of_nodes field contains the email [shd be renamed in DB]
+                    slice_name = user.slice_name
+                    purpose = user.purpose
+                    url = user.number_of_nodes
+
+                ctx = {
+                    'slice_name': slice_name,
+                    'purpose': purpose,
+                    'url': url,
+                    'portal_url': current_site,
+                    }
+
+                PendingSlice.objects.get(id=request['id']).delete()
+
+            elif request['type'] == 'authority':
+                request_status['SFA authority'] = {'status': True }
+                
+                # getting user email based on id 
+                ## RAW SQL queries on Django DB- https://docs.djangoproject.com/en/dev/topics/db/sql/
+                for user in PendingAuthority.objects.raw('SELECT * FROM portal_pendingauthority WHERE id = %s', [request['id']]):
+                    user_email= user.address_line1 # XXX address_line1 field contains the email [shd be renamed in DB]
+                    site_name = user.site_name
+                    city = user.address_city
+                    country = user.address_country
+                    short_name = user.site_abbreviated_name
+                    url = user.site_url
+
+                ctx = { 
+                    'site_name': site_name,
+                    'short_name': short_name,
+                    'url': url,
+                    'city': city,
+                    'country': country,                          
+                    'portal_url'    : current_site,
+                    }
+                    
+                PendingAuthority.objects.get(id=request['id']).delete()
+
+            # XXX TMP we should send an email to the user to inform him/her
+            elif request['type'] == 'project':
+                request_status['SFA project'] = {'status': True }
+                p = PendingProject.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : p.project_name, 
+                    'authority_hrn' : p.authority_hrn,
+                    'email'         : p.email,        
+                    'purpose'       : p.purpose,
+                }      
+                user_email = p.email
+                PendingProject.objects.get(id=request['id']).delete()
+
+            elif request['type'] == 'join':
+                request_status['SFA join'] = {'status': True }
+                j = PendingJoin.objects.get(id=request['id'])
+                ctx = {
+                    'project_name'  : j.project_name, 
+                    'authority_hrn' : j.authority_hrn,
+                    'email'         : j.email,        
+                    'user_hrn'      : j.user_hrn,
+                }      
+
+                user_email = j.email
+                PendingJoin.objects.get(id=request['id']).delete()
+            else:
+                raise Exception, 'unknown type of request %s' % request['type']
+
+            send_status_email(wsgi_request, ctx, user_email, request['type'], 'denied')
+        except Exception, e:
+            request_status['SFA '+request['type']] = {'status': False, 'description': str(e)}
+            logger.error('ERROR - actions.py - portal_reject_request: %s' % e)
+            import traceback
+            logger.error(traceback.format_exc())
 
         status['%s__%s' % (request['type'], request['id'])] = request_status
 
     return status
 
 
         status['%s__%s' % (request['type'], request['id'])] = request_status
 
     return status
 
+def send_status_email(request, ctx, user_email, obj_type, status):
+    try:
+        ctx['current_site'] = get_current_site(request)
+        ctx['theme'] = theme
+
+        theme.template_name = obj_type + '_request_' + status + '.txt'
+        text_content = render_to_string(theme.template, ctx)
+        theme.template_name = obj_type + '_request_' + status + '.html'
+        html_content = render_to_string(theme.template, ctx)
+        theme.template_name = 'email_default_sender.txt'
+
+        sender =  render_to_string(theme.template, ctx)
+        sender = sender.replace('\n', '')
+                       
+        subject = obj_type.title() + ' request '+ status
+    
+        msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
+        msg.attach_alternative(html_content, "text/html")
+        msg.send()
+    except Exception as e:
+        print e
+        logger.error("Failed to send email, please check the mail templates and the SMTP configuration of your server")
+
+
 # Django and ajax
 # http://djangosnippets.org/snippets/942/
 
 # Django and ajax
 # http://djangosnippets.org/snippets/942/
 
@@ -723,6 +982,14 @@ def create_slice(wsgi_request, request):
     if not 'number_of_nodes' in request:
         request['number_of_nodes']=""
 
     if not 'number_of_nodes' in request:
         request['number_of_nodes']=""
 
+    # Slice is under a project
+    if len(request['authority_hrn'].split('.')) > 2:
+        pi_list = []
+        pis = authority_get_pis(wsgi_request, request['authority_hrn'])
+        for pi in pis:
+            pi_list = pi['pi_users']
+        user_hrns.extend(pi_list)
+
     # XXX We should create a slice with Manifold terminology
     slice_params = {
         'slice_hrn'        : hrn, 
     # XXX We should create a slice with Manifold terminology
     slice_params = {
         'slice_hrn'        : hrn, 
@@ -740,26 +1007,15 @@ def create_slice(wsgi_request, request):
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
     else:
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
     else:
-        clear_user_creds(wsgi_request,user_email)
+        try:
+            for u_hrn in user_hrns:
+                u_email = get_user_email(wsgi_request, u_hrn)
+                clear_user_creds(wsgi_request, u_email)
+        except Exception as e:
+            logger.error("Failed clear credentials for all users")
+            clear_user_creds(wsgi_request,user_email)
         # log user activity
         activity.slice.validate(request, { "slice" : hrn })
         # log user activity
         activity.slice.validate(request, { "slice" : hrn })
-        try:
-            theme.template_name = 'slice_request_validated.txt'
-            text_content = render_to_string(theme.template, request)
-            theme.template_name = 'slice_request_validated.html'
-            html_content = render_to_string(theme.template, request)
-        
-            theme.template_name = 'email_default_sender.txt'
-            sender =  render_to_string(theme.template, request)
-            sender = sender.replace('\n', '')
-
-            subject = 'Slice request validated'
-
-            msg = EmailMultiAlternatives(subject, text_content, sender, [user_email])
-            msg.attach_alternative(html_content, "text/html")
-            msg.send()
-        except Exception, e:
-            print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
        
     return results
 
        
     return results
 
@@ -778,27 +1034,73 @@ def create_pending_slice(wsgi_request, request, email):
     )
     s.save()
 
     )
     s.save()
 
+    send_email_to_pis(wsgi_request, request, 'slice')
+
+def create_pending_project(wsgi_request, request):
+    """
+    """
+
+    # Insert an entry in the PendingProject table
+    s = PendingProject(
+        project_name    = request['project_name'],
+        user_hrn        = request['user_hrn'],
+        email           = request['email'],
+        authority_hrn   = request['authority_hrn'],
+        purpose         = request['purpose'],
+    )
+    s.save()
+
+    send_email_to_pis(wsgi_request, request, 'project')
+
+def create_pending_join(wsgi_request, request):
+    """
+    """
+
+    # Insert an entry in the PendingJoin table
+    s = PendingJoin(
+        user_hrn        = request['user_hrn'],
+        email           = request['email'],
+        project_name    = request['project_name'],
+        authority_hrn   = request['authority_hrn'],
+    )
+    s.save()
+
+    send_email_to_pis(wsgi_request, request, 'join')
+
+#-------------------------------------------------------------------------------
+# SEND EMAILS
+#-------------------------------------------------------------------------------
+
+def send_email_to_pis(request, context, obj_type):
     try:
     try:
-        # Send an email: the recipients are the PI of the authority
-        recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
+        context['current_site'] = get_current_site(request)
+        context['theme'] = theme
+        # Send an email: the recipients are the PIs of the authority
+        recipients = authority_get_pi_emails(request, context['authority_hrn'])
+
+        theme.template_name = obj_type + '_request_email.txt' 
+        text_content = render_to_string(theme.template, context)
+
+        theme.template_name = obj_type + '_request_email.html' 
+        html_content = render_to_string(theme.template, context)
+
+        #theme.template_name = obj_type + '_request_email_subject.txt'
+        #subject = render_to_string(theme.template, request)
+        #subject = subject.replace('\n', '')
+        subject = "New "+obj_type+" request"
+
+        theme.template_name = 'email_default_sender.txt'
+        sender =  render_to_string(theme.template, context)
+        sender = sender.replace('\n', '')
 
 
-        theme.template_name = 'slice_request_email.txt' 
-        text_content = render_to_string(theme.template, request)
-    
-        theme.template_name = 'slice_request_email.html' 
-        html_content = render_to_string(theme.template, request)
-    
-        theme.template_name = 'slice_request_email_subject.txt'
-        subject = render_to_string(theme.template, request)
-        subject = subject.replace('\n', '')
-    
-        sender = email
         msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
         msg.attach_alternative(html_content, "text/html")
         msg.send()
     except Exception, e:
         msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
         msg.attach_alternative(html_content, "text/html")
         msg.send()
     except Exception, e:
+        print e
         print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
 
         print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
 
+
 #-------------------------------------------------------------------------------
 # REQUESTS - Users
 #-------------------------------------------------------------------------------
 #-------------------------------------------------------------------------------
 # REQUESTS - Users
 #-------------------------------------------------------------------------------
@@ -813,7 +1115,6 @@ def manifold_add_reference_user_accounts(wsgi_request, request):
         .select('user_id', 'config', 'email', 'status') \
         .filter_by('email', '==', request['email'])
     user_details = execute_admin_query(wsgi_request, user_query)
         .select('user_id', 'config', 'email', 'status') \
         .filter_by('email', '==', request['email'])
     user_details = execute_admin_query(wsgi_request, user_query)
-
     # USER MAIN ACCOUNT != reference
     #print 'USER MAIN ACCOUNT != reference'
     list_accounts_query = Query().get('local:account')              \
     # USER MAIN ACCOUNT != reference
     #print 'USER MAIN ACCOUNT != reference'
     list_accounts_query = Query().get('local:account')              \
@@ -885,25 +1186,6 @@ def sfa_create_user(wsgi_request, request, namespace = None, as_admin = False):
 
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % sfa_user_params['user_hrn']
 
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % sfa_user_params['user_hrn']
-    else:
-        try:
-            theme.template_name = 'user_request_validated.txt'
-            text_content = render_to_string(theme.template, request)
-            theme.template_name = 'user_request_validated.html'
-            html_content = render_to_string(theme.template, request)
-        
-            theme.template_name = 'email_default_sender.txt'
-            sender =  render_to_string(theme.template, request)
-            sender = sender.replace('\n', '')
-
-
-            subject = 'User validated'
-
-            msg = EmailMultiAlternatives(subject, text_content, sender, [request['email']])
-            msg.attach_alternative(html_content, "text/html")
-            msg.send()
-        except Exception, e:
-            print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
 
     return results
 
 
     return results
 
@@ -912,10 +1194,11 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
     import requests
     import time
     from requests.auth import HTTPBasicAuth
     import requests
     import time
     from requests.auth import HTTPBasicAuth
-    
-    URL_REST = ConfigEngine.default_iotlab_url
-    LOGIN_ADMIN = ConfigEngine.default_iotlab_admin_user
-    PASSWORD_ADMIN = ConfigEngine.default_iotlab_admin_password
+   
+    engine = ConfigEngine() 
+    URL_REST = engine.iotlab_url()
+    LOGIN_ADMIN = engine.iotlab_admin_user()
+    PASSWORD_ADMIN = engine.iotlab_admin_password()
 
     auth = HTTPBasicAuth(LOGIN_ADMIN,PASSWORD_ADMIN)
     headers = {'content-type': 'application/json'}
 
     auth = HTTPBasicAuth(LOGIN_ADMIN,PASSWORD_ADMIN)
     headers = {'content-type': 'application/json'}
@@ -940,7 +1223,7 @@ def iotlab_create_user (wsgi_request, request, namespace = None, as_admin=False)
    
     iotlab_user_params1 = json.dumps(iotlab_user_params)
     r=requests.post(url=URL_REST, data=iotlab_user_params1, headers=headers, auth=auth)
    
     iotlab_user_params1 = json.dumps(iotlab_user_params)
     r=requests.post(url=URL_REST, data=iotlab_user_params1, headers=headers, auth=auth)
-    print 'Create iotlab user : ', r.status_code, r.text
+    logger.info('Create iotlab user : {} {}'.format(r.status_code, r.text))
     return r.text
 
 def create_user(wsgi_request, request, namespace = None, as_admin = False):
     return r.text
 
 def create_user(wsgi_request, request, namespace = None, as_admin = False):
@@ -983,6 +1266,8 @@ def create_pending_user(wsgi_request, request, user_detail):
     )
     b.save()
     # sends email to user to activate the email
     )
     b.save()
     # sends email to user to activate the email
+    request['current_site'] = get_current_site(wsgi_request)
+    request['theme'] = theme
     theme.template_name = 'activate_user.html'
     html_content = render_to_string(theme.template, request)
     theme.template_name = 'activate_user.txt'
     theme.template_name = 'activate_user.html'
     html_content = render_to_string(theme.template, request)
     theme.template_name = 'activate_user.txt'
@@ -1001,7 +1286,8 @@ def create_pending_user(wsgi_request, request, user_detail):
     msg.send()
    
     # saves the user to django auth_user table [needed for password reset]
     msg.send()
    
     # saves the user to django auth_user table [needed for password reset]
-    user = User.objects.create_user(request['email'], request['email'], request['password'])
+    # Django username must be less than 30 char so we use a hash
+    user = User.objects.create_user(hashlib.sha1(request['email'].hexdigest()), request['email'], request['password'])
 
     # Creating a manifold user
     user_id = manifold_add_user(wsgi_request, request)
 
     # Creating a manifold user
     user_id = manifold_add_user(wsgi_request, request)
@@ -1015,8 +1301,6 @@ def create_pending_user(wsgi_request, request, user_detail):
     if request['private_key']:
         account_config['user_private_key'] = request['private_key']
 
     if request['private_key']:
         account_config['user_private_key'] = request['private_key']
 
-    user_id = user_detail['user_id'] + 1 # the user_id for the newly created user in local:user
-
     # XXX TODO: Require a myslice platform
     # ALERT: this will disapear with ROUTERV2 of Manifold
     # We have to consider the case where several registries can be used
     # XXX TODO: Require a myslice platform
     # ALERT: this will disapear with ROUTERV2 of Manifold
     # We have to consider the case where several registries can be used
@@ -1036,32 +1320,10 @@ def create_pending_user(wsgi_request, request, user_detail):
             'config'        : json.dumps(account_config),
         }
         manifold_add_account(wsgi_request, account_params)
             'config'        : json.dumps(account_config),
         }
         manifold_add_account(wsgi_request, account_params)
-    except Exception, e:
-        print "Failed creating manifold account on platform %s for user: %s" % ('myslice', request['email'])
 
 
-    try:
-        # Send an email: the recipients are the PI of the authority
-        # If No PI is defined for this Authority, send to a default email (different for each theme)
-        recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
-        
-        theme.template_name = 'user_request_email.html'
-        html_content = render_to_string(theme.template, request)
-        theme.template_name = 'user_request_email.txt'
-        text_content = render_to_string(theme.template, request)
-    
-        theme.template_name = 'user_request_email_subject.txt'
-        subject = render_to_string(theme.template, request)
-        subject = subject.replace('\n', '')
-    
-        theme.template_name = 'email_default_sender.txt'
-        sender =  render_to_string(theme.template, request)
-        sender = sender.replace('\n', '')
-    
-        msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
-        msg.attach_alternative(html_content, "text/html")
-        msg.send()
-    except Exception, e:
-        print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
-        import traceback
-        traceback.print_exc()
+    # Email to PIs is sent when the user activates his email
+    # portal/emailactivationview.py
+
+    except Exception as e:
+        logger.error("Failed creating manifold account on platform {} for user: {}".format('myslice', request['email']))
+