portal: added wip for PI validation page
[myslice.git] / portal / views.py
index afed7e8..980265c 100644 (file)
@@ -27,32 +27,47 @@ from django.contrib              import messages
 from django.views.generic        import View
 from django.views.generic.base   import TemplateView
 from django.shortcuts            import render
 from django.views.generic        import View
 from django.views.generic.base   import TemplateView
 from django.shortcuts            import render
+
 from plugins.lists.simplelist    import SimpleList
 from plugins.lists.simplelist    import SimpleList
+
+from plugins.pres_view           import PresView
+from portal.event import Event
+import json
+
 from portal                      import signals
 from portal.forms                import UserRegisterForm, SliceRequestForm, ContactForm
 from portal.util                 import RegistrationView, ActivationView
 from portal.models               import PendingUser, PendingSlice
 from manifold.core.query         import Query
 from portal                      import signals
 from portal.forms                import UserRegisterForm, SliceRequestForm, ContactForm
 from portal.util                 import RegistrationView, ActivationView
 from portal.models               import PendingUser, PendingSlice
 from manifold.core.query         import Query
+from manifold.manifoldapi        import execute_query
 from unfold.page                 import Page
 from myslice.viewutils           import topmenu_items, the_user
 from unfold.page                 import Page
 from myslice.viewutils           import topmenu_items, the_user
-from django.http                 import HttpResponseRedirect
+from django.http                 import HttpResponseRedirect, HttpResponse
+
+from M2Crypto                    import Rand, RSA, BIO
+import os, re
 
 class DashboardView(TemplateView):
     template_name = "dashboard.html"
 
     def get_context_data(self, **kwargs):
 
 class DashboardView(TemplateView):
     template_name = "dashboard.html"
 
     def get_context_data(self, **kwargs):
-        user_hrn = 'ple.upmc.jordan_auge'
+        # We might have slices on different registries with different user accounts 
+        # We note that this portal could be specific to a given registry, to which we register users, but i'm not sure that simplifies things
+        # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
 
         #messages.info(self.request, 'You have logged in')
         page = Page(self.request)
 
         # Slow...
         #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
 
         #messages.info(self.request, 'You have logged in')
         page = Page(self.request)
 
         # Slow...
         #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
-        slice_query = Query().get('user').filter_by('user_hrn', '==', user_hrn).select('slice.slice_hrn')
+        slice_query = Query().get('user').filter_by('user_hrn', '==', '$user_hrn').select('user_hrn', 'slice.slice_hrn')
         auth_query  = Query().get('network').select('network_hrn')
         auth_query  = Query().get('network').select('network_hrn')
+        print "AUTH QUERY =====================", auth_query
+        print "filter", auth_query.filters
         page.enqueue_query(slice_query)
         page.enqueue_query(auth_query)
 
         page.enqueue_query(slice_query)
         page.enqueue_query(auth_query)
 
+        page.expose_js_metadata()
         page.expose_queries()
 
         slicelist = SimpleList(
         page.expose_queries()
 
         slicelist = SimpleList(
@@ -78,7 +93,7 @@ class DashboardView(TemplateView):
         # more general variables expected in the template
         context['title'] = 'Test view that combines various plugins'
         # the menu items on the top
         # more general variables expected in the template
         context['title'] = 'Test view that combines various plugins'
         # the menu items on the top
-        context['topmenu_items'] = topmenu_items('dashboard', self.request) 
+        context['topmenu_items'] = topmenu_items('Dashboard', self.request) 
         # so we can sho who is logged
         context['username'] = the_user(self.request) 
 
         # so we can sho who is logged
         context['username'] = the_user(self.request) 
 
@@ -117,7 +132,7 @@ class UserRegisterView(RegistrationView):
     setting ``REGISTRATION_OPEN`` and setting it to
     ``False``. Omitting this setting, or setting it to ``True``, will
     be interpreted as meaning that registration is currently open and
     setting ``REGISTRATION_OPEN`` and setting it to
     ``False``. Omitting this setting, or setting it to ``True``, will
     be interpreted as meaning that registration is currently open and
-    permitted.
+    permitt ed.
 
     Internally, this is accomplished via storing an activation key in
     an instance of ``registration.models.RegistrationProfile``. See
 
     Internally, this is accomplished via storing an activation key in
     an instance of ``registration.models.RegistrationProfile``. See
@@ -172,6 +187,12 @@ class UserRegisterView(RegistrationView):
                                      request=request)
         return new_user
 
                                      request=request)
         return new_user
 
+    def get_context_data(self, **kwargs):
+        context = super(UserRegisterView, self).get_context_data(**kwargs)
+        context['topmenu_items'] = topmenu_items('Register', self.request)
+        context['username'] = the_user (self.request)
+        return context
+
     def registration_allowed(self, request):
         """
         Indicate whether account registration is currently permitted,
     def registration_allowed(self, request):
         """
         Indicate whether account registration is currently permitted,
@@ -423,60 +444,215 @@ class UserValidateView(ActivationView):
 # DEPRECATED #
 # DEPRECATED #    return p.render()
 
 # DEPRECATED #
 # DEPRECATED #    return p.render()
 
-class MyAccountView(TemplateView):
-    template_name = "my_account.html"
-
-    def get_context_data(self, **kwargs):
-        #user_hrn = 'ple.upmc.jordan_auge'
-
-        #messages.info(self.request, 'You have logged in')
-        page = Page(self.request)
-
-        # Slow...
-        #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
-        #slice_query = Query().get('user').filter_by('user_hrn', '==', user_hrn).select('slice.slice_hrn')
-        #auth_query  = Query().get('network').select('network_hrn')
-        #page.enqueue_query(slice_query)
-        #page.enqueue_query(auth_query)
-
-        #page.expose_queries()
-
-        #slicelist = SimpleList(
-        #    title = None,
-        #    page  = page,
-        #    key   = 'slice.slice_hrn',
-        #    query = slice_query,
-        #)
-
-        #authlist = SimpleList(
-        #    title = None,
-        #    page  = page,
-        #    key   = 'network_hrn',
-        #    query = auth_query,
-        #)
-
-        context = super(MyAccountView, self).get_context_data(**kwargs)
-        context['person']   = self.request.user
-        #context['networks'] = authlist.render(self.request)
-        #context['slices']   = slicelist.render(self.request)
-
-        # XXX This is repeated in all pages
-        # more general variables expected in the template
-        context['title'] = 'User Profile Page'
-        # the menu items on the top
-        context['topmenu_items'] = topmenu_items('my_account', self.request)
-        # so we can sho who is logged
-        context['username'] = the_user(self.request)
-
-        context.update(page.prelude_env())
-
-        return context
-
-
-
 
 
+# DEPRECATED ## view for my_account
+# DEPRECATED # class MyAccountView(TemplateView):
+# DEPRECATED #    template_name = "my_account.html"
+# DEPRECATED #    
+# DEPRECATED #    def from_process(self, request, **cleaned_data): 
+# DEPRECATED #        #if request.method == 'POST':
+# DEPRECATED #         #       if request.POST['submit_name']:
+# DEPRECATED #        if 'fname' in request.POST:            
+# DEPRECATED #                messsag= "Got Name"
+# DEPRECATED #                #return render(request, 'portal/my_account.html')
+# DEPRECATED #                #response = HttpResponse("Here's the text of the Web page.")    
+# DEPRECATED #                return HttpResponse(message)
+# DEPRECATED #            
+# DEPRECATED #    def get_context_data(self, **kwargs):
+# DEPRECATED #        page = Page(self.request)
+# DEPRECATED #        context = super(MyAccountView, self).get_context_data(**kwargs)
+# DEPRECATED #        context['person']   = self.request.user
+# DEPRECATED #        # XXX This is repeated in all pages
+# DEPRECATED #        # more general variables expected in the template
+# DEPRECATED #        context['title'] = 'User Profile Page'
+# DEPRECATED #        # the menu items on the top
+# DEPRECATED #        context['topmenu_items'] = topmenu_items('my_account', self.request)
+# DEPRECATED #        # so we can sho who is logged
+# DEPRECATED #        context['username'] = the_user(self.request)
+# DEPRECATED #        context.update(page.prelude_env())
+# DEPRECATED #        return context
+
+
+
+# View for my_account form
+def my_account(request):
+    return render(request, 'my_account.html', {
+        #'form': form,
+        'topmenu_items': topmenu_items('My Account', request),
+        'username': the_user (request)
+    })
 
 
 
 
+#my_acc form value processing
+def acc_process(request):
+    # getting the user_id from the session [now hardcoded]
+    get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
+    if 'submit_name' in request.POST:
+        edited_first_name =  request.POST['fname']
+        edited_last_name =  request.POST['lname']
+        #email = 'test_email@gmail.com'
+        #password = 'test_pp'
+        #message = 'F_Name: %s L_name: %s dummy_pp: %s' % (first_name, last_name, password)
+        #site = None
+        
+        # insert into DB [needed for registration page]
+        #approach borrowed from register view     
+        #new_user = PendingUser.objects.create_inactive_user(edited_first_name, edited_last_name, email,  password, site) 
+        #conventional approach
+        #b = PendingUser(first_name=edited_first_name, last_name=edited_last_name)
+        #b.save()
+        
+        # select and update [will be used throughout this view]
+        # select the logged in user [for the moment hard coded]
+        #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
+        # update first and last name
+        get_user.first_name = edited_first_name
+        get_user.last_name = edited_last_name
+        get_user.save() 
+
+        return HttpResponse('Success: Name Updated!!')       
+    elif 'submit_pass' in request.POST:
+        edited_password = request.POST['password']
+        # select the logged in user [for the moment hard coded]
+        #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
+        # update password
+        get_user.password = edited_password
+        get_user.save()
+        return HttpResponse('Success: Password Changed!!')
+    elif 'generate' in request.POST:
+        #import os
+        #from M2Crypto import Rand, RSA, BIO
+
+        KEY_LENGTH = 2048
+
+        def blank_callback():
+            "Replace the default dashes"
+            return
+
+        # Random seed
+        Rand.rand_seed (os.urandom (KEY_LENGTH))
+        # Generate key pair
+        key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
+        # Create memory buffers
+        pri_mem = BIO.MemoryBuffer()
+        pub_mem = BIO.MemoryBuffer()
+        # Save keys to buffers
+        key.save_key_bio(pri_mem, None)
+        key.save_pub_key_bio(pub_mem)
+
+        # Get keys 
+        public_key = pub_mem.getvalue()
+        private_key = pri_mem.getvalue()
+        # Saving to DB
+        keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
+        keypair = re.sub("\r", "", keypair)
+        keypair = re.sub("\n", "\\n", keypair)
+        #keypair = keypair.rstrip('\r\n')
+        keypair = ''.join(keypair.split())
+        get_user.keypair = keypair
+        get_user.save()
+        return HttpResponse('Success: New Keypair Generated! %s' % keypair)
+
+    elif 'upload_key' in request.POST:
+        up_file = request.FILES['pubkey']
+        file_content =  up_file.read()
+        file_name = up_file.name
+        file_extension = os.path.splitext(file_name)[1] 
+        allowed_extension =  ['.pub','.txt']
+        if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
+            file_content = '{"user_public_key":"'+ file_content +'"}'
+            file_content = re.sub("\r", "", file_content)
+            file_content = re.sub("\n", "\\n",file_content)
+            file_content = ''.join(file_content.split())
+            get_user.keypair = file_content
+            get_user.save()
+            return HttpResponse('Success: Publickey uploaded! Old records overwritten')
+        else:
+            return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')    
+        
+    else:
+        message = 'You submitted an empty form.'
+        return HttpResponse(message)
+
+def register_4m_f4f(request):
+    #return render(request, 'register_4m_f4f.html')
+
+#def reg_4m_f4f_process(request):
+    if 'submit' in request.POST:
+        #get_email = PendingUser.objects.get(email)
+        reg_fname = request.POST['firstname']
+        reg_lname = request.POST['lastname']
+        reg_aff = request.POST['affiliation']
+        reg_email = request.POST['email'].lower()
+        
+        #POST value validation  
+        if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
+            messages.error(request, 'First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
+            #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
+            return render(request, 'register_4m_f4f.html')
+        if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
+            messages.error(request, 'Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
+            #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
+            return render(request, 'register_4m_f4f.html')
+        if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
+            messages.error(request, 'Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
+            #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
+            return render(request, 'register_4m_f4f.html')
+        if PendingUser.objects.filter(email__iexact=reg_email):
+            messages.error(request, 'Email already registered.Please provide a new email address.')
+            #return HttpResponse("Email Already exists")
+            return render(request, 'register_4m_f4f.html')
+        if 'generate' in request.POST['question']:
+            #import os
+            #from M2Crypto import Rand, RSA, BIO
+            
+            KEY_LENGTH = 2048
+
+            def blank_callback():
+                "Replace the default dashes"
+                return
+
+            # Random seed
+            Rand.rand_seed (os.urandom (KEY_LENGTH))
+            # Generate key pair
+            key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
+            # Create memory buffers
+            pri_mem = BIO.MemoryBuffer()
+            pub_mem = BIO.MemoryBuffer()
+            # Save keys to buffers
+            key.save_key_bio(pri_mem, None)
+            key.save_pub_key_bio(pub_mem)
+            # Get keys 
+            public_key = pub_mem.getvalue()
+            private_key = pri_mem.getvalue()
+            # Saving to DB
+            keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
+            keypair = re.sub("\r", "", keypair)
+            keypair = re.sub("\n", "\\n", keypair)
+            #keypair = keypair.rstrip('\r\n')
+            keypair = ''.join(keypair.split())
+            #return HttpResponse(keypair)
+        else:
+            up_file = request.FILES['user_public_key']
+            file_content =  up_file.read()
+            file_name = up_file.name
+            file_extension = os.path.splitext(file_name)[1]
+            allowed_extension =  ['.pub','.txt']
+            if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
+                keypair = '{"user_public_key":"'+ file_content +'"}'
+                keypair = re.sub("\r", "", keypair)
+                keypair = re.sub("\n", "\\n",keypair)
+                keypair = ''.join(keypair.split())
+            else:
+                return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')
+
+        b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff, 
+                        email=reg_email, password=request.POST['password'], keypair=keypair)
+        b.save()
+
+        return render(request, 'user_register_complete.html')
+    return render(request, 'register_4m_f4f.html')        
+    
 
 # view for contact form
 def contact(request):
 
 # view for contact form
 def contact(request):
@@ -501,9 +677,12 @@ def contact(request):
             return render(request,'contact_sent.html') # Redirect after POST
     else:
         form = ContactForm() # An unbound form
             return render(request,'contact_sent.html') # Redirect after POST
     else:
         form = ContactForm() # An unbound form
-
+    
     return render(request, 'contact.html', {
         'form': form,
     return render(request, 'contact.html', {
         'form': form,
+        'topmenu_items': topmenu_items('Contact Us', request),
+        'username': the_user (request)
+
     })
 
 
     })
 
 
@@ -529,7 +708,406 @@ def slice_request(request):
     else:
         form = SliceRequestForm() # An unbound form
 
     else:
         form = SliceRequestForm() # An unbound form
 
+#    template_env = {}
+#    template_env['form'] = form
+#    template_env['topmenu_items'] = topmenu_items('Request a slice', request) 
+#    template_env['unfold1_main'] = render(request, 'slice_request_.html', {
+#        'form': form,
+#    })
+#    from django.shortcuts                import render_to_response
+#    from django.template                 import RequestContext
+#    return render_to_response ('view-unfold1.html',template_env,
+#                               context_instance=RequestContext(request))
+
     return render(request, 'slice_request.html', {
         'form': form,
     return render(request, 'slice_request.html', {
         'form': form,
+        'topmenu_items': topmenu_items('Request a slice', request),
+        'username': the_user (request) 
     })
 
     })
 
+
+class PresViewView(TemplateView):
+    template_name = "view-unfold1.html"
+
+    def get_context_data(self, **kwargs):
+
+        page = Page(self.request)
+
+        pres_view = PresView(page = page)
+
+        context = super(PresViewView, self).get_context_data(**kwargs)
+
+        #context['ALL_STATIC'] = "all_static"
+        context['unfold1_main'] = pres_view.render(self.request)
+
+        # XXX This is repeated in all pages
+        # more general variables expected in the template
+        context['title'] = 'Test view that combines various plugins'
+        # the menu items on the top
+        context['topmenu_items'] = topmenu_items('PresView', self.request)
+        # so we can sho who is logged
+        context['username'] = the_user(self.request)
+
+        prelude_env = page.prelude_env()
+        context.update(prelude_env)
+
+        return context
+
+def json_me(config_file,type):
+    json_answer = ''
+    for ligne in config_file:
+        if not ligne.startswith('#'):
+            args = ligne.split(';')
+            json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1]  + '" ,"descriptif":"' + args[2]+'"')
+            if type!="dynamic":
+                json_answer += str(',"contraints":')
+                if args[3]=="":
+                    json_answer += str('""')
+                else:
+                    json_answer += str(args[3])
+            json_answer += str('},')
+    return json_answer[:-1]
+
+
+DIR = '/var/myslice/'
+STATIC = '%s/config_method_static' % DIR
+DYNAMIC = '%s/config_method_dynamic' % DIR
+ANIMATION = '%s/config_method_animation' % DIR
+
+def pres_view_methods(request, type):
+
+    if type ==None:
+        return 0
+    elif type =="static":
+        config = open(STATIC, "r")
+        json_answer = str('{ "options": [')
+        json_answer += str(json_me(config,"static"))
+        json_answer += str('] }')
+        config.close()
+    elif type =="dynamic":
+        config = open(DYNAMIC, "r")
+        json_answer = str('{ "options": [')
+        json_answer += str(json_me(config,"dynamic"))
+        json_answer += str('] }')
+        config.close()
+    elif type =="animation":
+        config = open(ANIMATION, "r")
+        json_answer = str('{ "options": [')
+        json_answer += str(json_me(config,"animation"))
+        json_answer += str('] }')
+        config.close()
+    elif type =="all":
+        config = open(STATIC, "r")
+        json_answer = str('{ "static": [')
+        json_answer += str(json_me(config,"static"))
+        json_answer += str('],')
+        json_answer += str('"dynamic": [')
+        config.close()
+        config = open(DYNAMIC, "r")
+        json_answer += str(json_me(config,"dynamic"))
+        json_answer += str('],')
+        json_answer += str('"animation": [')
+        config.close()
+        config = open(ANIMATION, "r")
+        json_answer += str(json_me(config,"animation"))
+        json_answer += str('] }')
+        config.close()
+    else:
+        return 0
+    return HttpResponse (json_answer, mimetype="application/json")
+
+def pres_view_animation(request, constraints, id):
+
+# sites crees depuis 2008
+# static.py?contraints=']date_created':1262325600&id='name_id"'
+
+    # method = request.getvalue('method') #ex : GetSites
+    #constraints = "']date_created':1262325600"
+    #id = "2"
+
+    if id == None:
+        return 0
+
+    # method = 'GetSites'#request.getvalue('method') #ex : GetSites
+    # constraints = {}#request.getvalue('constraints') // nul = {}
+    # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
+
+    config_file = open(ANIMATION, "r")
+    for ligne in config_file:
+        if not ligne.startswith('#'):
+            ligne = ligne.split('\n')
+            first = ligne[0].split(';')
+            if (str(first[1]) == str(id)):
+                save = first
+    config_file.close()
+
+    #Les print_method, print_option sont definis par le client (js)
+    #Les animations acceptent que les connexions anonymous
+    # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
+    args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
+
+
+    #Creation d'un objet event
+    event = Event(args)
+    cmd = [{"params": {
+            "data": {
+                "print_options": event.print_options,
+                "print_method": event.print_method,
+                "message": event.data
+            }
+        }
+    }]
+
+    json_answer = json.dumps(cmd)
+    return HttpResponse (json_answer, mimetype="application/json")
+
+def pres_view_static(request, constraints, id):
+    #constraints = "']date_created':1262325600"
+    #id = "2"
+
+    # method = 'GetSites'#request.getvalue('method') #ex : GetSites
+    # constraints = {}#request.getvalue('constraints') // nul = {}
+    # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
+
+    config_file = open(STATIC, "r")
+    for ligne in config_file:
+        if not ligne.startswith('#'):
+            ligne = ligne.split('\n')
+            first = ligne[0].split(';')
+            if (str(first[1]) == str(id)):
+                save = first
+    config_file.close()
+
+    #Les print_method, print_option sont definis par le client (js)
+    #Les animations acceptent que les connexions anonymous
+    # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
+    args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
+
+
+    #Creation d'un objet event
+    event = Event(args)
+    cmd = [{"params": {
+            "data": {
+                "print_options": event.print_options,
+                "print_method": event.print_method,
+                "message": event.data
+            }
+        }
+    }]
+
+    json_answer = json.dumps(cmd)
+    return HttpResponse (json_answer, mimetype="application/json")
+
+class ValidatePendingView(TemplateView):
+    template_name = "validate_pending.html"
+
+    def get_context_data(self, **kwargs):
+        # We might have slices on different registries with different user accounts 
+        # We note that this portal could be specific to a given registry, to which we register users, but i'm not sure that simplifies things
+        # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
+
+        #messages.info(self.request, 'You have logged in')
+        page = Page(self.request)
+
+        ctx_my_authorities = {}
+        ctx_delegation_authorities = {}
+
+
+        # The user need to be logged in
+        if the_user(self.request):
+            # Who can a PI validate:
+            # His own authorities + those he has credentials for.
+            # In MySlice we need to look at credentials also.
+            
+
+            # XXX This will have to be asynchroneous. Need to implement barriers,
+            # for now it will be sufficient to have it working statically
+
+            # get user_id to later on query accounts
+            # XXX Having real query plan on local tables would simplify all this
+            # XXX $user_email is still not available for local tables
+            #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id')
+            user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id')
+            user, = execute_query(self.request, user_query)
+            user_id = user['user_id']
+
+            # Query manifold to learn about available SFA platforms for more information
+            # In general we will at least have the portal
+            # For now we are considering all registries
+            all_authorities = []
+            platform_ids = []
+            sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
+            sfa_platforms = execute_query(self.request, sfa_platforms_query)
+            for sfa_platform in sfa_platforms:
+                print "SFA PLATFORM > ", sfa_platform['platform']
+                if not 'auth_type' in sfa_platform:
+                    continue
+                auth = sfa_platform['auth_type']
+                if not auth in all_authorities:
+                    all_authorities.append(auth)
+                platform_ids.append(sfa_platform['platform_id'])
+
+            # We can check on which the user has authoritity credentials = PI rights
+            credential_authorities = set()
+            credential_authorities_expired = set()
+
+            # User account on these registries
+            user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config')
+            user_accounts = execute_query(self.request, user_accounts_query)
+            #print "=" * 80
+            #print user_accounts
+            #print "=" * 80
+            for user_account in user_accounts:
+                config = json.loads(user_account['config'])
+                creds = []
+                if 'authority_credentials' in config:
+                    for authority_hrn, credential in config['authority_credentials'].items():
+                        #if credential is not expired:
+                        credential_authorities.add(authority_hrn)
+                        #else
+                        #    credential_authorities_expired.add(authority_hrn)
+                if 'delegated_authority_credentials' in config:
+                    for authority_hrn, credential in config['delegated_authority_credentials'].items():
+                        #if credential is not expired:
+                        credential_authorities.add(authority_hrn)
+                        #else
+                        #    credential_authorities_expired.add(authority_hrn)
+
+            print 'credential_authorities =', credential_authorities
+            print 'credential_authorities_expired =', credential_authorities_expired
+
+            # ** Where am I a PI **
+            # For this we need to ask SFA (of all authorities) = PI function
+            pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
+            pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
+            pi_authorities = set()
+            for pa in pi_authorities_tmp:
+                pi_authorities |= set(pa['pi_authorities'])
+
+            print "pi_authorities =", pi_authorities
+            
+            # My authorities + I have a credential
+            pi_credential_authorities = pi_authorities & credential_authorities
+            pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
+            pi_expired_credential_authorities = pi_authorities & credential_authorities_expired
+            # Authorities I've been delegated PI rights
+            pi_delegation_credential_authorities = credential_authorities - pi_authorities
+            pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities
+
+            print "pi_credential_authorities =", pi_credential_authorities
+            print "pi_no_credential_authorities =", pi_no_credential_authorities
+            print "pi_expired_credential_authorities =", pi_expired_credential_authorities
+            print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities
+            print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities
+
+            # Summary intermediary
+            pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities
+            pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities
+
+            print "--"
+            print "pi_my_authorities = ", pi_my_authorities
+            print "pi_delegation_authorities = ", pi_delegation_authorities
+
+            # Summary all
+            queried_pending_authorities = pi_my_authorities | pi_delegation_authorities
+            print "----"
+            print "queried_pending_authorities = ", queried_pending_authorities
+            
+            # Pending requests + authorities
+            #pending_users = PendingUser.objects.filter(authority_hrn__in = queried_pending_authorities).all() 
+            #pending_slices = PendingSlice.objects.filter(authority_hrn__in = queried_pending_authorities).all() 
+            pending_users = PendingUser.objects.all()
+            pending_slices = PendingSlice.objects.all()
+
+            # Dispatch requests and build the proper structure for the template:
+
+            print "pending users =", pending_users
+            print "pending slices =", pending_slices
+
+            for user in pending_users:
+                auth_hrn = user.authority_hrn
+                if not auth_hrn:
+                    auth_hrn = "ple.upmc" # XXX HARDCODED
+
+                request = {}
+                request['type'] = 'user'
+                request['id'] = 'TODO' # XXX in DB ?
+                request['timestamp'] = 'TODO' # XXX in DB ?
+                request['details'] = "%s %s <%s>" % (user.first_name, user.last_name, user.email)
+
+                if auth_hrn in pi_my_authorities:
+                    dest = ctx_my_authorities
+
+                    # define the css class
+                    if auth_hrn in pi_credential_authorities:
+                        request['allowed'] = 'allowed'
+                    elif auth_hrn in pi_expired_credential_authorities:
+                        request['allowed'] = 'expired'
+                    else: # pi_no_credential_authorities
+                        request['allowed'] = 'denied'
+
+                elif auth_hrn in pi_delegation_authorities:
+                    dest = ctx_delegation_authorities
+
+                    if auth_hrn in pi_delegation_credential_authorities:
+                        request['allowed'] = 'allowed'
+                    else: # pi_delegation_expired_authorities
+                        request['allowed'] = 'expired'
+
+                else:
+                    continue
+                    
+                if not auth_hrn in dest:
+                    dest[auth_hrn] = []
+                print "auth_hrn [%s] was added %r" % (auth_hrn, request)
+                dest[auth_hrn].append(request) 
+
+            for slice in pending_slices:
+                auth_hrn = slice.authority_hrn
+                if not auth_hrn:
+                    auth_hrn = "ple.upmc" # XXX HARDCODED
+
+                request = {}
+                request['type'] = 'slice'
+                request['id'] = 'TODO' # XXX in DB ?
+                request['timestamp'] = 'TODO' # XXX in DB ?
+                request['details'] = "Number of nodes: %d -- Type of nodes: %s<br/>%s" % ('TODO', 'TODO', 'TODO') # XXX 
+                if auth_hrn in pi_my_authorities:
+                    dest = ctx_my_authorities
+
+                    # define the css class
+                    if auth_hrn in pi_credential_authorities:
+                        request['allowed'] = 'allowed'
+                    elif auth_hrn in pi_expired_credential_authorities:
+                        request['allowed'] = 'expired'
+                    else: # pi_no_credential_authorities
+                        request['allowed'] = 'denied'
+
+                elif auth_hrn in pi_delegation_authorities:
+                    dest = ctx_delegation_authorities
+
+                    if auth_hrn in pi_delegation_credential_authorities:
+                        request['allowed'] = 'allowed'
+                    else: # pi_delegation_expired_authorities
+                        request['allowed'] = 'expired'
+                    
+                if not auth_hrn in dest:
+                    dest[auth_hrn] = []
+                dest[auth_hrn].append(request) 
+
+        context = super(ValidatePendingView, self).get_context_data(**kwargs)
+        context['my_authorities']   = ctx_my_authorities
+        context['delegation_authorities'] = ctx_delegation_authorities
+
+        # XXX This is repeated in all pages
+        # more general variables expected in the template
+        context['title'] = 'Test view that combines various plugins'
+        # the menu items on the top
+        context['topmenu_items'] = topmenu_items('Dashboard', self.request) 
+        # so we can sho who is logged
+        context['username'] = the_user(self.request) 
+
+        # XXX We need to prepare the page for queries
+        #context.update(page.prelude_env())
+
+        return context