Merge branch 'jordan' of ssh://git.onelab.eu/git/myslice into jordan
authorJordan Augé <jordan.auge@lip6.fr>
Wed, 28 Aug 2013 08:42:11 +0000 (10:42 +0200)
committerJordan Augé <jordan.auge@lip6.fr>
Wed, 28 Aug 2013 08:42:11 +0000 (10:42 +0200)
Conflicts:
portal/views.py

1  2 
manifold/manifoldapi.py
portal/urls.py
portal/views.py

diff --combined manifold/manifoldapi.py
@@@ -62,7 -62,7 +62,7 @@@ class ManifoldAPI
          return func
  
  def execute_query(request, query):
-     if not 'manifold' in request.session:
+     if not 'manifold' in request.session or not 'auth' in request.session['manifold']:
          print "W: Used hardcoded demo account for execute_query"
          manifold_api_session_auth = {'AuthMethod': 'password', 'Username': 'demo', 'AuthString': 'demo'}
      else:
      print "-"*80
      result = manifold_api.forward(query.to_dict())
      if result['code'] == 2:
 -        raise Exception, 'Error running query'
 +        raise Exception, 'Error running query: %r' % result
 +
 +    # XXX Handle errors
 +    #Error running query: {'origin': [0, 'XMLRPCAPI'], 'code': 2, 'description': 'No such session: No row was found for one()', 'traceback': 'Traceback (most recent call last):\n  File "/usr/local/lib/python2.7/dist-packages/manifold/core/xmlrpc_api.py", line 68, in xmlrpc_forward\n    user = Auth(auth).check()\n  File "/usr/local/lib/python2.7/dist-packages/manifold/auth/__init__.py", line 245, in check\n    return self.auth_method.check()\n  File "/usr/local/lib/python2.7/dist-packages/manifold/auth/__init__.py", line 95, in check\n    raise AuthenticationFailure, "No such session: %s" % e\nAuthenticationFailure: No such session: No row was found for one()\n', 'type': 2, 'ts': None, 'value': None}
 +
 +
      return result['value'] 
diff --combined portal/urls.py
@@@ -22,7 -22,7 +22,7 @@@
  
  from django.conf.urls import patterns, include, url
  from portal           import views
- from portal.views     import DashboardView, PresViewView, PlatformsView, PlatformView, ValidatePendingView # UserRegisterView, UserValidateView
+ from portal.views     import DashboardView, PresViewView, PlatformsView, PlatformView, ValidatePendingView, AccountView # UserRegisterView, UserValidateView
  from portal.util      import TemplateView
  
  # DEPRECATED #named_register_forms = (
@@@ -43,11 -43,11 +43,11 @@@ urlpatterns = patterns(''
      #url(r'^user/validate/?$', UserValidateView.as_view(), name='user_validate'),
      url(r'^dashboard/?$', DashboardView.as_view(), name='dashboard'),
      #url(r'^my_account/?$', MyAccountView.as_view(), name='my_account'),
-     url(r'^account/?$', views.my_account),
+     url(r'^account/?$', AccountView.as_view(), name='account'),
      url(r'^platforms/?$', PlatformsView.as_view(), name='platforms'),
      #url(r'^portal/platform/?$', PlatformView.platform_view(), name='platform'),
      url(r'^platform/(?P<platformname>[\w\.]+)/?$', PlatformView.as_view(), name='platform'),
-     url(r'^acc_process/?$', views.acc_process),
+     url(r'^account/acc_process/?$', views.acc_process),
      url(r'^register/?$', views.register_4m_f4f),
      #url(r'^reg_process/?$', views.reg_4m_f4f_process),
      url(r'^contact/?$', views.contact),
@@@ -55,9 -55,6 +55,9 @@@
      url(r'^slice_request/?$', views.slice_request),
      # Validate pending requests
      url(r'^validate/?$', ValidatePendingView.as_view()),
 +    # http://stackoverflow.com/questions/2360179/django-urls-how-to-pass-a-list-of-items-via-clean-urls
 +    # (r'^validate_action/(?P<constraints>[^/]+)/(?P<id>\w+)/?$', 'portal.views.pres_view_static'),
 +     (r'^validate_action(?P<id>(?:/\w+)+)/?$', 'portal.actions.validate_action'),
  
      url(r'^pres_view/?$', PresViewView.as_view(), name='pres_view'),
      (r'^methods/(?P<type>\w+)/?$', 'portal.views.pres_view_methods'),
diff --combined portal/views.py
@@@ -27,8 -27,8 +27,10 @@@ from django.contrib              impor
  from django.views.generic        import View
  from django.views.generic.base   import TemplateView
  from django.shortcuts            import render
 +from django.template.loader      import render_to_string
 +from django.core.mail            import send_mail
+ from django.utils.decorators     import method_decorator
+ from django.contrib.auth.decorators import login_required
  
  from plugins.lists.simplelist    import SimpleList
  from plugins.hazelnut            import Hazelnut
@@@ -40,7 -40,6 +42,7 @@@ from portal                      impor
  from portal.forms                import SliceRequestForm, ContactForm
  from portal.util                 import RegistrationView, ActivationView
  from portal.models               import PendingUser, PendingSlice
 +from portal.actions              import authority_get_pi_emails, get_request_by_authority
  from manifold.core.query         import Query
  from manifold.manifoldapi        import execute_query
  from unfold.page                 import Page
@@@ -52,6 -51,11 +54,11 @@@ import os, r
  
  class DashboardView(TemplateView):
      template_name = "dashboard.html"
+     
+     #This view requires login 
+     @method_decorator(login_required)
+     def dispatch(self, *args, **kwargs):
+         return super(DashboardView, self).dispatch(*args, **kwargs)
  
      def get_context_data(self, **kwargs):
          # We might have slices on different registries with different user accounts 
  # 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)
-     })
  # View for platforms
  class PlatformsView(TemplateView):
      template_name = "platforms.html"
      def get_context_data(self, **kwargs):
          page = Page(self.request)
  
-         network_query  = Query().get('local:platform').filter_by('disabled', '==', '0').select('platform','platform_longname','gateway_type')
+         #network_query  = Query().get('local:platform').filter_by('disabled', '==', '0').select('platform','platform_longname','gateway_type')
+         network_query  = Query().get('local:platform').select('platform','platform_longname','gateway_type')
          page.enqueue_query(network_query)
  
          page.expose_js_metadata()
  
          return context
  
  # View for 1 platform and its details
  class PlatformView(TemplateView):
      template_name = "platform.html"
  
          return context
  
+ #class for my_account
+ class AccountView(TemplateView):
+     template_name = "my_account.html"
+     
+     #This view requires login 
+     @method_decorator(login_required)
+     def dispatch(self, *args, **kwargs):
+         return super(AccountView, self).dispatch(*args, **kwargs)
+     def get_context_data(self, **kwargs):
+         page = Page(self.request)
+         #network_query  = Query().get('local:platform').filter_by('disabled', '==', '0').select('platform','platform_longname','gateway_type')
+         network_query  = Query().get('local:user').select('user_id','email','config')
+         page.enqueue_query(network_query)
+         page.expose_js_metadata()
+         page.expose_queries()
+         userlist = SimpleList(
+             title = None,
+             page  = page,
+             key   = 'user_id',
+             query = network_query,
+         )
+         context = super(AccountView, self).get_context_data(**kwargs)
+         context['person']   = self.request.user
+         context['users'] = userlist.render(self.request)
+         
+         # XXX This is repeated in all pages
+         # more general variables expected in the template
+         context['title'] = 'Platforms connected to MySlice'
+         # 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
+ @login_required
+ # 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)
+ #    })
+ @login_required
  #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
+     # getting user info from manifold
      if 'submit_name' in request.POST:
          edited_first_name =  request.POST['fname']
          edited_last_name =  request.POST['lname']
          get_user.last_name = edited_last_name
          get_user.save() 
  
-         return HttpResponse('Success: Name Updated!!')       
+         return HttpResponse('Sucess: First Name and Last 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.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()
+         # Generate public and private keys using SFA Library
+         from sfa.trust.certificate  import Keypair
+         k = Keypair(create=True)
+         public_key = k.get_pubkey_string()
+         private_key = k.as_pem()
+        
+ # DEPRECATED
+ #        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()
+         private_key = ''.join(private_key.split())
+         public_key = "ssh-rsa " + public_key
          # 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())
#        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)
@@@ -693,8 -757,6 +760,8 @@@ def register_4m_f4f(request)
      authorities = execute_query(request, authorities_query)
  
      if request.method == 'POST':
 +        # We shall use a form here
 +
          #get_email = PendingUser.objects.get(email)
          reg_fname = request.POST.get('firstname', '')
          reg_lname = request.POST.get('lastname', '')
              #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()
+             # Generate public and private keys using SFA Library
+             from sfa.trust.certificate  import Keypair
+             k = Keypair(create=True)
+             public_key = k.get_pubkey_string()
+             private_key = k.as_pem()
+ # DEPRECATED
+ #            #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()
+             private_key = ''.join(private_key.split())
+             public_key = "ssh-rsa " + public_key
              # 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)
+ #            keypair = re.sub("\r", "", keypair)
+ #            keypair = re.sub("\n", "\\n", keypair)
+ #            #keypair = keypair.rstrip('\r\n')
+ #            keypair = ''.join(keypair.split())
          else:
              up_file = request.FILES['user_public_key']
              file_content =  up_file.read()
          #                email=reg_email, password=request.POST['password'], keypair=keypair)
          #b.save()
          if not errors:
 -            b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
 -                            authority_hrn=reg_auth,
 -                            email=reg_email, password=request.POST['password'], keypair=keypair)
 +            b = PendingUser(
 +                first_name=reg_fname, 
 +                last_name=reg_lname, 
 +                affiliation=reg_aff,
 +                authority_hrn=reg_auth,
 +                email=reg_email, 
 +                password=request.POST['password'],
 +                keypair=keypair
 +            )
              b.save()
 +
 +            # Send email
 +            ctx = {
 +                first_name   : reg_fname, 
 +                last_name    : reg_lname, 
 +                affiliation  : reg_aff,
 +                authority_hrn: reg_auth,
 +                email        : reg_email, 
 +                keypair      : keypair,
 +                cc_myself    : True # form.cleaned_data['cc_myself']
 +            }
 +
 +            recipients = authority_get_pi_emails(authority_hrn)
 +            if ctx['cc_myself']:
 +                recipients.append(ctx['email'])
 +
 +            msg = render_to_string('user_request_email.txt', ctx)
 +            send_mail("Onelab New User request submitted", msg, email, recipients)
 +
              return render(request, 'user_register_complete.html')
  
      return render(request, 'register_4m_f4f.html',{
@@@ -826,7 -872,6 +902,7 @@@ def contact(request)
              email = form.cleaned_data['email'] # email of the sender
              cc_myself = form.cleaned_data['cc_myself']
  
 +            #recipients = authority_get_pi_emails(authority_hrn)
              recipients = ['yasin.upmc@gmail.com']
              if cc_myself:
                  recipients.append(email)
  
      })
  
+ @login_required
  def slice_request(request):
 -    if request.method == 'POST': # If the form has been submitted...
 -        form = SliceRequestForm(request.POST) # A form bound to the POST data
 -        if form.is_valid(): # All validation rules pass
 -            # Process the data in form.cleaned_data
 -            slice_name = form.cleaned_data['slice_name']
 +    errors = []
 +
 +    authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
 +    #authorities_query = Query.get('authority').select('authority_hrn')
 +    authorities = execute_query(request, authorities_query)
 +
 +    authority_hrn_tuple = []
 +    for authority in authorities:
 +        authority_hrn_tuple.append((authority['authority_hrn'], authority['name']))
 +    authority_hrn_initial = {'authority_hrn': authority_hrn_tuple}
 +        
 +    # request.POST or None ?
 +    if request.method == 'POST':
 +        # The form has been submitted
 +        form = SliceRequestForm(request.POST, initial=authority_hrn_initial) 
 +
 +        if form.is_valid():
 +            slice_name      = form.cleaned_data['slice_name']
 +            authority_hrn   = form.cleaned_data['authority_hrn']
              number_of_nodes = form.cleaned_data['number_of_nodes']
 -            type_of_nodes = form.cleaned_data['type_of_nodes']
 -            purpose = form.cleaned_data['purpose']
 +            type_of_nodes   = form.cleaned_data['type_of_nodes']
 +            purpose         = form.cleaned_data['purpose']
 +            
 +            s = PendingSlice(
 +                slice_name      = slice_name,
 +                authority_hrn   = authority_hrn,
 +                number_of_nodes = number_of_nodes,
 +                type_of_nodes   = type_of_nodes,
 +                purpose         = purpose
 +            )
 +            s.save()
 +
 +            # All validation rules pass; process data in form.cleaned_data
 +            # slice_name, number_of_nodes, type_of_nodes, purpose
              email = form.cleaned_data['email'] # email of the sender
              cc_myself = form.cleaned_data['cc_myself']
  
 -            recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
 +            # The recipients are the PI of the authority
 +            recipients = authority_get_pi_emails(authority_hrn)
 +            #recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
              if cc_myself:
                  recipients.append(email)
 +            msg = render_to_string('slice_request_email.txt', form.cleaned_data)
 +            send_mail("Onelab New Slice request form submitted", msg, email, recipients)
  
 -            from django.core.mail import send_mail
 -            send_mail("Onelab New Slice request form submitted", [slice_name,number_of_nodes,type_of_nodes,purpose], email, recipients)
              return render(request,'slicereq_recvd.html') # Redirect after POST
      else:
 -        form = SliceRequestForm() # An unbound form
 +        form = SliceRequestForm(initial=authority_hrn_initial)
  
  #    template_env = {}
  #    template_env['form'] = form
@@@ -1199,10 -1216,26 +1275,10 @@@ class ValidatePendingView(TemplateView)
              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
  
 -                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)
 +            requests = get_request_by_authority(queried_pending_authorities)
 +            for request in requests:
 +                auth_hrn = request['authority_hrn']
  
                  if auth_hrn in pi_my_authorities:
                      dest = ctx_my_authorities
  
                  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