Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorLoic Baron <loic.baron@lip6.fr>
Tue, 21 Apr 2015 09:52:35 +0000 (11:52 +0200)
committerLoic Baron <loic.baron@lip6.fr>
Tue, 21 Apr 2015 09:52:35 +0000 (11:52 +0200)
42 files changed:
.settings/org.eclipse.core.resources.prefs
activity/__init__.py
influxdb/client.py
localauth/manifoldbackend.py
manifoldapi/manifoldapi.py
manifoldapi/manifoldproxy.py
manifoldapi/static/js/manifold.js
plugins/filter_status/__init__.py
plugins/filter_status/static/js/filter_status.js
plugins/scheduler2/static/js/scheduler2.js
portal/accountview.py
portal/actions.py
portal/homeview.py
portal/institution.py
portal/projectrequestview.py
portal/sliceresourceview.py
portal/slicetabmeasurements.py
portal/static/css/fed4fire.css
portal/static/css/onelab.css
portal/static/js/common.functions.js
portal/static/js/myslice.js
portal/templates/base.html
portal/templates/fed4fire/fed4fire_activate_user.html
portal/templates/fed4fire/fed4fire_contact_support_email.html
portal/templates/fed4fire/fed4fire_home-view.html
portal/templates/fed4fire/fed4fire_institution.html
portal/templates/fed4fire/fed4fire_projectrequest_view.html
portal/templates/fed4fire/fed4fire_registration_view.html
portal/templates/fed4fire/fed4fire_slice_request_denied.html
portal/templates/fed4fire/fed4fire_slice_request_email.html
portal/templates/fed4fire/fed4fire_slice_request_validated.html
portal/templates/fed4fire/fed4fire_slicerequest_view.html
portal/templates/fed4fire/fed4fire_user_request_denied.html
portal/templates/fed4fire/fed4fire_user_request_email.html
portal/templates/fed4fire/fed4fire_user_request_validated.html
portal/templates/fed4fire/fed4fire_user_request_validated_subject.txt [new file with mode: 0644]
portal/templates/fed4fire/fed4fire_widget-topmenu.html
portal/templates/onelab/onelab_slice-view.html
portal/templates/onelab/onelab_widget-slice-sections.html
portal/templates/slice-view.html
portal/templates/user_request_validated_subject.txt [new file with mode: 0644]
unfold/page.py

index dad9009..00f180d 100644 (file)
@@ -1,4 +1,6 @@
 eclipse.preferences.version=1
+encoding//forge/forms.py=utf-8
+encoding//forge/views.py=utf-8
 encoding//portal/django_passresetview.py=utf-8
 encoding//portal/forms.py=utf-8
 encoding//portal/migrations/0002_extend_slice.py=utf-8
@@ -6,6 +8,8 @@ encoding//portal/migrations/0005_extend_user.py=utf-8
 encoding//portal/migrations/0008_extend_user.py=utf-8
 encoding//portal/migrations/0009_initial.py=utf-8
 encoding//portal/migrations/0010_project.py=utf-8
+encoding//portal/migrations/0011_join.py=utf-8
 encoding//portal/models.py=utf-8
 encoding//portal/urls.py=utf-8
 encoding//portal/validationview.py=utf-8
+encoding//portal/views/__init__.py=utf-8
index 62fbc9e..b749672 100644 (file)
@@ -84,10 +84,10 @@ def log(request, action, message, objects = None):
     t.start()
 
 def getClientIp(request):
-    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
-    if x_forwarded_for:
+    try :
+        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
         ip = x_forwarded_for.split(',')[0]
-    else:
+    except:
         ip = request.META.get('REMOTE_ADDR')
     return ip
 
index 50daa30..8d28dd8 100644 (file)
@@ -1,15 +1,19 @@
 from django.http import HttpResponse
 from rest import error
-import os,json
-import ConfigParser
-import string, random
+import os,json,string,random
+import logging,ConfigParser
 
 from portal.models import MeasurementsDB
 
 from manifold.core.query             import Query, AnalyzedQuery
 from manifoldapi.manifoldapi         import execute_query
 
-from influxdb import InfluxDBClient
+logger = logging.getLogger(__name__)
+
+try :
+    from influxdb import InfluxDBClient
+except :
+    logger.error('can\'t import InfluxDBClient module')
 
 def createDatabase(request, slicename):
     result = {}
index c2899e9..e52b175 100644 (file)
@@ -7,7 +7,7 @@ from manifold.core.query        import Query
 
 from myslice.settings import config, logger, DEBUG
 
-from unfold.sessioncache import SessionCache
+from unfold.sessioncache import SessionCache
 
 # Name my backend 'ManifoldBackend'
 class ManifoldBackend:
@@ -33,11 +33,11 @@ class ManifoldBackend:
                 logger.error("GetSession failed: {}".format(sessions_result.error()))
                 return
             session = sessions[0]
-            logger.debug("SESSION : {}".format(session))
+            logger.debug("SESSION : {}".format(session.keys()))
             
             # Change to session authentication
-            session_auth = {'AuthMethod': 'session', 'session': session['session']}
-            api.auth = session_auth
+            api.auth = {'AuthMethod': 'session', 'session': session['session']}
+            #api.auth = session_auth
             self.api = api
 
             # Get account details
@@ -49,10 +49,13 @@ class ManifoldBackend:
                 return
             person = persons[0]
             logger.debug("PERSON : {}".format(person))
+            
+            request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
+
             #logger.info("{} {} <{}> logged in"\
             #    .format(person['config']['first_name'], person['config']['last_name'], person['config']['email']))
 
-            SessionCache().store_auth(request, session_auth)
+            #SessionCache().store_auth(request, session_auth)
 
         except ManifoldException as e:
             logger.error("ManifoldException in Auth Backend: {}".format(e.manifold_result))
index c215b6c..29236c0 100644 (file)
@@ -9,7 +9,7 @@ from django.shortcuts import redirect
 from manifold.core.result_value import ResultValue
 from manifoldresult import ManifoldResult, ManifoldCode, ManifoldException, truncate_result
 
-from unfold.sessioncache import SessionCache
+from unfold.sessioncache import SessionCache
 
 from myslice.settings import config, logger
 
@@ -92,8 +92,10 @@ def _execute_query(request, query, manifold_api_session_auth):
         # but most importantly there is a need to refine that test, since 
         # code==2 does not necessarily mean an expired session
         # XXX only if we know it is the issue
-        SessionCache().end_session(request)
+        #SessionCache().end_session(request)
         # Flush django session
+        del request.session['manifold']
+
         request.session.flush()
         #raise Exception, 'Error running query: {}'.format(result)
     
@@ -107,13 +109,18 @@ def _execute_query(request, query, manifold_api_session_auth):
 
 def execute_query(request, query):
     
-    manifold_api_session_auth = SessionCache().get_auth(request)
-    if not manifold_api_session_auth:
+    logger.debug("EXECUTE QUERY: request - {}".format(request.session.items()))
+    
+    if not 'manifold' in request.session or not 'auth' in request.session['manifold']:
+    #manifold_api_session_auth = SessionCache().get_auth(request)
+    #if not manifold_api_session_auth:
         request.session.flush()
         #raise Exception, "User not authenticated"
         host = request.get_host()
         return redirect('/')
     
+    manifold_api_session_auth = request.session['manifold']['auth']
+
     return _execute_query(request, query, manifold_api_session_auth)
 
 def execute_admin_query(request, query):
index a5bc20d..eba37bb 100644 (file)
@@ -12,7 +12,7 @@ from manifoldapi                import ManifoldAPI
 from manifoldresult             import ManifoldException
 from manifold.util.log          import Log
 
-from unfold.sessioncache import SessionCache
+from unfold.sessioncache import SessionCache
 
 from myslice.settings import config, logger
 
@@ -61,8 +61,11 @@ def proxy (request,format):
             admin_user, admin_password = config.manifold_admin_user_password()
             manifold_api_session_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password}
         else:
-            manifold_api_session_auth = SessionCache().get_auth(request)
-            if not manifold_api_session_auth:
+            if 'manifold' in request.session:
+                manifold_api_session_auth = request.session['manifold']['auth']
+            else:
+            #manifold_api_session_auth = SessionCache().get_auth(request)
+            #if not manifold_api_session_auth:
                 return HttpResponse (json.dumps({'code':0,'value':[]}), content_type="application/json")
                 
         if debug_empty and manifold_query.action.lower()=='get':
index 517ab69..d7e5688 100644 (file)
@@ -141,10 +141,10 @@ var QUERY_STATE_DONE        = 2;
  * RECORD STATES (for query_store)
  ******************************************************************************/
 
-var STATE_SET       = 0;
-var STATE_VALUE     = 1;
-var STATE_WARNINGS  = 2;
-var STATE_VISIBLE   = 3;
+var STATE_SET       = 20;
+var STATE_VALUE     = 21;
+var STATE_WARNINGS  = 22;
+var STATE_VISIBLE   = 23;
 
 // ACTIONS
 var STATE_SET_CHANGE = 0;
@@ -1708,6 +1708,17 @@ case TYPE_LIST_OF_VALUES:
                             // XXX Need for a better function to manage warnings
                             var warn = CONSTRAINT_RESERVABLE_LEASE_MSG;
                             warnings[CONSTRAINT_RESERVABLE_LEASE] = warn;
+
+                            manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
+                            // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
+                            data = {
+                                state:  STATE_WARNINGS,
+                                key   : record_key,
+                                op    : null,
+                                value : warnings
+                            }
+                            manifold.raise_record_event(query.query_uuid, FIELD_STATE_CHANGED, data);
+
                         } else {
                             // Lease are defined, delete the warning in case it was set previously
                             delete warnings[CONSTRAINT_RESERVABLE_LEASE];
@@ -1716,21 +1727,11 @@ case TYPE_LIST_OF_VALUES:
                         // Remove warnings attached to this resource
                         delete warnings[CONSTRAINT_RESERVABLE_LEASE];
                     }
-
-                    manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
                 }
 
                 /* This was redundant */
                 // manifold.query_store.recount(query.query_uuid); 
 
-                // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
-                data = {
-                    state:  STATE_WARNINGS,
-                    key   : record_key,
-                    op    : null,
-                    value : warnings
-                }
-                manifold.raise_record_event(query.query_uuid, FIELD_STATE_CHANGED, data);
                 break;
 
             case 'lease':
@@ -1738,7 +1739,7 @@ case TYPE_LIST_OF_VALUES:
                 var resource_query = query_ext.parent_query_ext.query.subqueries['resource'];
                 var warnings = manifold.query_store.get_record_state(resource_query.query_uuid, resource_key, STATE_WARNINGS);
 
-                if (event_type == STATE_SET_ADD) {
+                if (event_type == STATE_SET_ADD || event_type == STATE_SET_IN_PENDING) {
                      // A lease is added, it removes the constraint
                     delete warnings[CONSTRAINT_RESERVABLE_LEASE];
                 } else {
@@ -1749,23 +1750,22 @@ case TYPE_LIST_OF_VALUES:
                         // XXX Need for a better function to manage warnings
                         var warn = CONSTRAINT_RESERVABLE_LEASE_MSG;
                         warnings[CONSTRAINT_RESERVABLE_LEASE] = warn;
+
+                        // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
+                        data = {
+                            state:  STATE_WARNINGS,
+                            key   : resource_key,
+                            op    : null,
+                            value : warnings
+                        }
+                        manifold.raise_record_event(resource_query.query_uuid, FIELD_STATE_CHANGED, data);
                     } else {
                         // Lease are defined, delete the warning in case it was set previously
                         delete warnings[CONSTRAINT_RESERVABLE_LEASE];
                     }
-                    
                 }
-
+                /* Adding a lease can remove a warning and reduce the unconfigured resources  */
                 manifold.query_store.recount(resource_query.query_uuid); 
-
-                // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
-                data = {
-                    state:  STATE_WARNINGS,
-                    key   : resource_key,
-                    op    : null,
-                    value : warnings
-                }
-                manifold.raise_record_event(resource_query.query_uuid, FIELD_STATE_CHANGED, data);
                 break;
         }
 
@@ -1806,6 +1806,9 @@ case TYPE_LIST_OF_VALUES:
         query = query_ext.query;
 
         switch(event_type) {
+            case STATUS_REMOVE_WARNING:
+                record = manifold.query_store.get_record(query_uuid, data.value);
+                this._enforce_constraints(query_ext, record, data.value, STATE_SET_ADD);
 
             // XXX At some point, should be renamed to RECORD_STATE_CHANGED
             case FIELD_STATE_CHANGED:
index a0d269b..38a5ffc 100644 (file)
@@ -2,10 +2,13 @@ from unfold.plugin import Plugin
 
 class FilterStatusPlugin(Plugin):
     
-    def __init__ (self, query=None, **settings):
+    def __init__ (self, query=None, query_lease=None, **settings):
         Plugin.__init__ (self, **settings)
         self.query              = query
 
+        self.query_lease = query_lease
+        self.query_lease_uuid = query_lease.query_uuid
+
     def template_file (self):
         return "filter_status.html"
 
@@ -24,7 +27,7 @@ class FilterStatusPlugin(Plugin):
         # query_uuid will pass self.query results to the javascript
         # and will be available as "record" in :
         # on_new_record: function(record)
-        return ['plugin_uuid', 'domid', 'query_uuid']
+        return ['plugin_uuid', 'domid', 'query_uuid', 'query_lease_uuid']
 
     def export_json_settings (self):
         return True
index 9c1c244..324634c 100644 (file)
@@ -28,6 +28,7 @@
 
             /* Setup query and record handlers */
             this.listen_query(options.query_uuid);
+            this.listen_query(options.query_lease_uuid, 'leases');
 
             /* Setup click handlers */
             this.elts('list-group-item').click({'instance': this}, this._on_click);
         // XXX
     },
 
+    on_leases_field_state_changed: function(data) 
+    {
+        console.log('leases_field_state_changed');
+        this.on_field_state_changed(data);
+    },
     on_field_state_changed: function(data) 
     {
         var query_ext;
index 6ef2549..933f32f 100755 (executable)
@@ -196,6 +196,7 @@ var SCHEDULER_COLWIDTH = 50;
                 op   : STATE_SET_ADD,
                 value: new_lease
             }
+            prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, resource_urn, STATE_SET);
             manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
 
             /* Add to local cache also, unless we listen to events from outside */
@@ -208,7 +209,13 @@ var SCHEDULER_COLWIDTH = 50;
                     op   : STATE_SET_ADD,
                     value: resource_urn
                 };
-                manifold.raise_event($scope.instance.options.query_uuid, FIELD_STATE_CHANGED, data_resource);
+                /* Send the message to the list of resources, depending on the previous state */
+                prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, data_resource.value, STATE_SET);
+                if(jQuery.inArray(prev_state,[STATE_SET_OUT,STATE_SET_OUT_SUCCESS,STATE_SET_OUT_PENDING,STATE_SET_IN_FAILURE])>-1){
+                    manifold.raise_event($scope.instance.options.query_uuid, FIELD_STATE_CHANGED, data_resource);
+                }
+                /* Remove the warning on resource as we have added Leases to it */
+                //manifold.raise_event($scope.instance.options.query_uuid, STATUS_REMOVE_WARNING, data_resource);
             }
             $scope._leases_by_resource[resource_urn].push(new_lease);
 
@@ -235,8 +242,9 @@ var SCHEDULER_COLWIDTH = 50;
                 op   : STATE_SET_REMOVE,
                 value: other_key
             }
+            prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, other.resource, STATE_SET);
             manifold.raise_event($scope.instance.options.query_lease_uuid, FIELD_STATE_CHANGED, data);
-            /* Remove from local cache also, unless we listen to events from outside */
+            /* Remove Lease from local cache also, unless we listen to events from outside */
             $scope._leases_by_resource[other.resource] = $.grep($scope._leases_by_resource[other.resource], function(x) { return x != other; });
             /* Last lease removed for this resource -> remove the resource from the list */
             if($scope._leases_by_resource.hasOwnProperty(other.resource) && $scope._leases_by_resource[other.resource].length == 0){
@@ -247,7 +255,15 @@ var SCHEDULER_COLWIDTH = 50;
                     op   : STATE_SET_REMOVE,
                     value: other.resource
                 };
-                manifold.raise_event($scope.instance.options.query_uuid, FIELD_STATE_CHANGED, data_resource);
+
+                prev_state = manifold.query_store.get_record_state($scope.instance.options.query_uuid, data_resource.value, STATE_SET);
+                /* Remove Resource from local cache */
+                delete $scope._leases_by_resource[data_resource.value]
+                /* Send the message to the list of resources, depending on the previous state */
+                if(jQuery.inArray(prev_state,[STATE_SET_IN,STATE_SET_IN_SUCCESS,STATE_SET_IN_PENDING,STATE_SET_OUT_FAILURE])>-1){
+                    manifold.raise_event($scope.instance.options.query_uuid, FIELD_STATE_CHANGED, data_resource);
+                    //manifold.raise_event($scope.instance.options.query_uuid, STATUS_REMOVE_WARNING, data_resource);
+                }
                
             }
         }
@@ -698,26 +714,42 @@ var SCHEDULER_COLWIDTH = 50;
             on_leases_filter_removed:    function(filter) { this._get_scope().$apply(); },
             on_leases_filter_clear:      function()       { this._get_scope().$apply(); },
 
-            on_field_state_changed: function(data)
+            on_resources_field_state_changed: function(data)
             {
-                /*
-                this._set_lease_slots(lease_key, lease);
-
+                console.log('on_resources_field_state_changed');
+                console.log(data);
                 switch(data.state) {
                     case STATE_SET:
                         switch(data.op) {
+                            /*
                             case STATE_SET_IN:
                             case STATE_SET_IN_SUCCESS:
                             case STATE_SET_OUT_FAILURE:
-                                this.set_checkbox_from_data(data.value, true);
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+                                //this.set_checkbox_from_data(data.value, true);
+                                //this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
                                 break;  
+                            */
                             case STATE_SET_OUT:
                             case STATE_SET_OUT_SUCCESS:
                             case STATE_SET_IN_FAILURE:
-                                this.set_checkbox_from_data(data.value, false);
-                                this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_RESET);
+                                // A resource has been removed
+                                console.log(this._get_scope()._leases_by_resource);
+                                s = this._get_scope();
+                                // loop over the list of leases by resource cached
+                                $.each(this._get_scope()._leases_by_resource, function(k,v){
+                                    // if the resource removed is in the list
+                                    // we need to remove all the leases corresponding to that resoruce
+                                    if(k == data.value){
+                                        console.log(k,v);
+                                        // loop each lease should be removed
+                                        $.each(v, function(i,lease){
+                                            console.log(i,lease);
+                                            s._remove_lease(lease);
+                                        });
+                                    }
+                                });
                                 break;
+                            /*
                             case STATE_SET_IN_PENDING:
                                 this.set_checkbox_from_data(data.key, true);
                                 this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_ADDED);
@@ -726,14 +758,15 @@ var SCHEDULER_COLWIDTH = 50;
                                 this.set_checkbox_from_data(data.key, false);
                                 this.set_bgcolor(data.value, QUERYTABLE_BGCOLOR_REMOVED);
                                 break;
+                            */
                         }
                         break;
-
+                    /*
                     case STATE_WARNINGS:
                         this.change_status(data.key, data.value);
                         break;
+                    */
                 }
-                */
             },
 
 
index c43d160..076f993 100644 (file)
@@ -18,7 +18,7 @@ from ui.topmenu                         import topmenu_items_live, the_user
 
 from portal.actions                     import (
     manifold_update_user, manifold_update_account, manifold_add_account,
-    manifold_delete_account, sfa_update_user, sfa_get_user, clear_user_creds )
+    manifold_delete_account, sfa_update_user, sfa_get_user, clear_user_creds, get_myslice_account, get_myslice_platform, get_registry_url, get_jfed_identity )
 from portal.account                     import Account, get_expiration
 
 from myslice.settings                   import logger
@@ -262,26 +262,6 @@ class AccountView(LoginRequiredAutoLogoutView, ThemeView):
         return context
 
 @login_required
-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)
-    for platform_detail in platform_details:
-        return platform_detail
-
-@login_required
-def get_myslice_account(request):
-    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
-
-@login_required
-#my_acc form value processing
 def account_process(request):
     from sfa.trust.credential               import Credential
     from sfa.trust.certificate              import Keypair
@@ -370,7 +350,7 @@ def account_process(request):
                 response['Content-Disposition'] = 'attachment; filename="auth_credential.txt"'
                 return response
 
-
+    account_detail = get_myslice_account(request)
              
     if 'submit_name' in request.POST:
         edited_first_name =  request.POST['fname']
@@ -413,185 +393,136 @@ def account_process(request):
 # XXX TODO: Factorize with portal/joinview.py
 
     elif 'generate' in request.POST:
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        private = RSA.generate(1024)
-                        private_key = json.dumps(private.exportKey())
-                        public  = private.publickey()
-                        public_key = json.dumps(public.exportKey(format='OpenSSH'))
-                        # updating manifold local:account table
-                        account_config = json.loads(account_detail['config'])
-                        # preserving user_hrn
-                        user_hrn = account_config.get('user_hrn','N/A')
-                        keypair = '{{"user_public_key":{}, "user_private_key":{}, "user_hrn":"{}"}}'\
-                                  .format(public_key, private_key, user_hrn)
-                        #updated_config = json.dumps(account_config) 
-                        # updating manifold
-                        #user_params = { 'config': keypair, 'auth_type':'managed'}
-                        #manifold_update_account(request, user_id, user_params)
-                        # updating sfa
-                        public_key = public_key.replace('"', '');
-                        user_pub_key = {'keys': public_key}
-
-                        sfa_update_user(request, user_hrn, user_pub_key)
-                        result_sfa_user = sfa_get_user(request, user_hrn, public_key)
-                        try:
-                            if 'keys' in result_sfa_user and result_sfa_user['keys'][0] == public_key:
-                                # updating manifold
-                                updated_config = json.dumps(account_config) 
-                                user_params = {'config' : keypair, 'auth_type' : 'managed'}
-                                manifold_update_account(request, user_id, user_params)
-                                messages.success(request,
-                                                 'Success: New Keypair Generated! '
-                                                 'Delegation of your credentials will be automatic.')
-                            else:
-                                raise Exception,"Keys are not matching"
-                        except Exception as e:
-                            messages.error(request,
-                                           'Error: An error occured during the update '
-                                           'of your public key at the Registry, or your '
-                                           'public key is not matching the one stored.')
-                            logger.error("Exception in accountview {}".format(e))
-                        return HttpResponseRedirect("/portal/account/")
-        else:
-            messages.error(request,
-                           'Account error: You need an account in '
-                           'myslice platform to perform this action')
+        try:
+            private = RSA.generate(1024)
+            private_key = json.dumps(private.exportKey())
+            public  = private.publickey()
+            public_key = json.dumps(public.exportKey(format='OpenSSH'))
+            # updating manifold local:account table
+            account_config = json.loads(account_detail['config'])
+            # preserving user_hrn
+            user_hrn = account_config.get('user_hrn','N/A')
+            keypair = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + ', "user_hrn":"'+ user_hrn + '"}'
+            #updated_config = json.dumps(account_config) 
+            # updating manifold
+            #user_params = { 'config': keypair, 'auth_type':'managed'}
+            #manifold_update_account(request, user_id, user_params)
+            # updating sfa
+            public_key = public_key.replace('"', '');
+            user_pub_key = {'keys': public_key}
+
+            sfa_update_user(request, user_hrn, user_pub_key)
+            result_sfa_user = sfa_get_user(request, user_hrn, public_key)
+            try:
+                if 'keys' in result_sfa_user and result_sfa_user['keys'][0] == public_key:
+                    # updating manifold
+                    updated_config = json.dumps(account_config) 
+                    user_params = { 'config': keypair, 'auth_type':'managed'}
+                    manifold_update_account(request, user_id, user_params)
+                    messages.success(request, 'Sucess: New Keypair Generated! Delegation of your credentials will be automatic.')
+                else:
+                    raise Exception,"Keys are not matching"
+            except Exception as e:
+                messages.error(request, 'Error: An error occured during the update of your public key at the Registry, or your public key is not matching the one stored.')
+                logger.error("Exception in accountview {}".format(e))
+            return HttpResponseRedirect("/portal/account/")
+        except Exception as e:
+            messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
                        
     elif 'upload_key' in request.POST:
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        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):
-                            account_config = json.loads(account_detail['config'])
-                            # preserving user_hrn
-                            user_hrn = account_config.get('user_hrn','N/A')
-                            file_content = '{"user_public_key":"{}", "user_hrn":"{}"}'\
-                                           .format(file_content, user_hrn)
-                            #file_content = re.sub("\r", "", file_content)
-                            #file_content = re.sub("\n", "\\n",file_content)
-                            file_content = ''.join(file_content.split())
-                            #update manifold local:account table
-                            user_params = {'config' : file_content, 'auth_type':'user'}
-                            manifold_update_account(request, user_id, user_params)
-                            # updating sfa
-                            user_pub_key = {'keys': file_content}
-                            sfa_update_user(request, user_hrn, user_pub_key)
-                            messages.success(request,
-                                             'Publickey uploaded! Please delegate your '
-                                             'credentials using SFA: '
-                                             'http://trac.myslice.info/wiki/DelegatingCredentials')
-                            return HttpResponseRedirect("/portal/account/")
-                        else:
-                            messages.error(request,
-                                           'RSA key error: Please upload '
-                                           'a valid RSA public key [.txt or .pub].')
-                            return HttpResponseRedirect("/portal/account/")
-        else:
-            messages.error(request,
-                           'Account error: You need an account '
-                           'in myslice platform to perform this action')
+        try:
+            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):
+                account_config = json.loads(account_detail['config'])
+                # preserving user_hrn
+                user_hrn = account_config.get('user_hrn','N/A')
+                file_content = '{"user_public_key":"'+ file_content + '", "user_hrn":"'+ user_hrn +'"}'
+                #file_content = re.sub("\r", "", file_content)
+                #file_content = re.sub("\n", "\\n",file_content)
+                file_content = ''.join(file_content.split())
+                #update manifold local:account table
+                user_params = { 'config': file_content, 'auth_type':'user'}
+                manifold_update_account(request, user_id, user_params)
+                # updating sfa
+                user_pub_key = {'keys': file_content}
+                sfa_update_user(request, user_hrn, user_pub_key)
+                messages.success(request, 'Publickey uploaded! Please delegate your credentials using SFA: http://trac.myslice.info/wiki/DelegatingCredentials')
+                return HttpResponseRedirect("/portal/account/")
+            else:
+                messages.error(request, 'RSA key error: Please upload a valid RSA public key [.txt or .pub].')
+                return HttpResponseRedirect("/portal/account/")
+
+        except Exception as e:
+            messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
 
     elif 'dl_pubkey' in request.POST or request.POST['button_value'] == 'dl_pubkey':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        public_key = account_config['user_public_key'] 
-                        response = HttpResponse(public_key, content_type='text/plain')
-                        response['Content-Disposition'] = 'attachment; filename="pubkey.txt"'
-                        return response
-                        break
-        else:
-            messages.error(request,
-                           'Account error: You need an account '
-                           'in myslice platform to perform this action')
+        try:
+            account_config = json.loads(account_detail['config'])
+            public_key = account_config['user_public_key'] 
+            response = HttpResponse(public_key, content_type='text/plain')
+            response['Content-Disposition'] = 'attachment; filename="pubkey.txt"'
+            return response
+        except Exception as e:
+            messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
                
     elif 'dl_pkey' in request.POST or request.POST['button_value'] == 'dl_pkey':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        if 'user_private_key' in account_config:
-                            private_key = account_config['user_private_key']
-                            response = HttpResponse(private_key, content_type='text/plain')
-                            response['Content-Disposition'] = 'attachment; filename="privkey.txt"'
-                            return response
-                        else:
-                            messages.error(request,
-                                           'Download error: '
-                                           'Private key is not stored in the server')
-                            return HttpResponseRedirect("/portal/account/")
+        try:
+            account_config = json.loads(account_detail['config'])
+            if 'user_private_key' in account_config:
+                private_key = account_config['user_private_key']
+                response = HttpResponse(private_key, content_type='text/plain')
+                response['Content-Disposition'] = 'attachment; filename="privkey.txt"'
+                return response
+            else:
+                messages.error(request, 'Download error: Private key is not stored in the server')
+                return HttpResponseRedirect("/portal/account/")
 
-        else:
-            messages.error(request,
-                           'Account error: You need an account '
-                           'in myslice platform to perform this action')
+        except Exception as e:
+            messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
     
     elif 'delete' in request.POST or request.POST['button_value'] == 'delete':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        account_config = json.loads(account_detail['config'])
-                        if 'user_private_key' in account_config:
-                            for key in account_config.keys():
-                                if key == 'user_private_key':    
-                                    del account_config[key]
-                                
-                            updated_config = json.dumps(account_config)
-                            user_params = { 'config': updated_config, 'auth_type':'user'}
-                            manifold_update_account(request, user_id, user_params)
-                            messages.success(request,
-                                             'Private Key deleted. You need to delegate '
-                                             'credentials manually once it expires.')
-                            messages.success(request,
-                                             'Once your credentials expire, Please delegate '
-                                             'manually using SFA: '
-                                             'http://trac.myslice.info/wiki/DelegatingCredentials')
-                            return HttpResponseRedirect("/portal/account/")
-                        else:
-                            messages.error(request, 'Delete error: Private key is not stored in the server')
-                            return HttpResponseRedirect("/portal/account/")
-                           
-        else:
+        try:
+            account_config = json.loads(account_detail['config'])
+            if 'user_private_key' in account_config:
+                for key in account_config.keys():
+                    if key == 'user_private_key':    
+                        del account_config[key]
+                    
+                updated_config = json.dumps(account_config)
+                user_params = { 'config': updated_config, 'auth_type':'user'}
+                manifold_update_account(request, user_id, user_params)
+                messages.success(request, 'Private Key deleted. You need to delegate credentials manually once it expires.')
+                messages.success(request, 'Once your credentials expire, Please delegate manually using SFA: http://trac.myslice.info/wiki/DelegatingCredentials')
+                return HttpResponseRedirect("/portal/account/")
+            else:
+                messages.error(request, 'Delete error: Private key is not stored in the server')
+                return HttpResponseRedirect("/portal/account/")
+                          
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')    
             return HttpResponseRedirect("/portal/account/")
     
     # download identity for jfed
     elif 'dl_identity' in request.POST or request.POST['button_value'] == 'dl_identity':
-        for account_detail in account_details:
-            for platform_detail in platform_details:
-                if platform_detail['platform_id'] == account_detail['platform_id']:
-                    if 'myslice' in platform_detail['platform']:
-                        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')
-                            registry = 'http://sfa-fed4fire.pl.sophia.inria.fr:12345/'
-                            jfed_identity = user_hrn + '\n' + registry + '\n' + private_key 
-                            response = HttpResponse(jfed_identity, content_type='text/plain')
-                            response['Content-Disposition'] = 'attachment; filename="jfed_identity.txt"'
-                            return response
-                        else:
-                            messages.error(request, 'Download error: Private key is not stored in the server')
-                            return HttpResponseRedirect("/portal/account/")
+        try:
+            jfed_identity = get_jfed_identity(request)
+            if jfed_identity is not None:
+                response = HttpResponse(jfed_identity, content_type='text/plain')
+                response['Content-Disposition'] = 'attachment; filename="jfed_identity.txt"'
+                return response
+            else:
+                messages.error(request, 'Download error: Private key is not stored in the server')
+                return HttpResponseRedirect("/portal/account/")
 
-        else:
+        except Exception as e:
             messages.error(request, 'Account error: You need an account in myslice platform to perform this action')
             return HttpResponseRedirect("/portal/account/")
 
@@ -605,13 +536,10 @@ def account_process(request):
         user_hrn = account_config.get('user_hrn','N/A')
         t_user_hrn = user_hrn.split('.')
         authority_hrn = t_user_hrn[0] + '.' + t_user_hrn[1]
+        registry = get_registry_url(request)
         import socket
         hostname = socket.gethostbyaddr(socket.gethostname())[0]
-        registry = platform_config.get('registry','N/A')
         admin_user = platform_config.get('user','N/A')
-        if 'localhost' in registry:
-            port = registry.split(':')[-1:][0]
-            registry = "http://" + hostname +':'+ port
         manifold_host = ConfigEngine().manifold_url()
         if 'localhost' in manifold_host:
             manifold_host = manifold_host.replace('localhost',hostname)
index f364bf2..aa156a5 100644 (file)
@@ -25,6 +25,51 @@ import activity.slice
 # 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)
+    for platform_detail in platform_details:
+        return platform_detail
+
+def get_myslice_account(request):
+    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
+
+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
 
 # Get the list of pis in a given authority
 def authority_get_pis(request, authority_hrn):
index 6d33d0e..1dc87c1 100644 (file)
@@ -21,7 +21,7 @@ from myslice.theme                      import ThemeView
 
 from portal.account                     import Account, get_expiration
 from portal.models                      import PendingSlice
-from portal.actions                     import authority_check_pis
+from portal.actions                     import authority_check_pis, get_jfed_identity
 
 import activity.user
 
@@ -57,7 +57,6 @@ class HomeView (FreeAccessView, ThemeView):
             # let's use ManifoldResult.__repr__
             env['state']="%s"%manifoldresult
 
-            return render_to_response(self.template,env, context_instance=RequestContext(request))
         # user was authenticated at the backend
         elif auth_result is not None:
             user=auth_result
@@ -117,25 +116,40 @@ class HomeView (FreeAccessView, ThemeView):
                     env['user_cred'] = user_cred
                 else:
                     env['person'] = None
-                return render_to_response(self.template,env, context_instance=RequestContext(request))
             else:
                 # log user activity
                 activity.user.login(self.request, "notactive")
                 env['state'] = "Your account is not active, please contact the site admin."
                 env['layout_1_or_2']="layout-unfold2.html"
 
-                return render_to_response(self.template,env, context_instance=RequestContext(request))
+            jfed_identity = get_jfed_identity(request)
+            if jfed_identity is not None:
+                import base64
+                encoded_jfed_identity = base64.b64encode(jfed_identity)
+                env['jfed_identity'] = encoded_jfed_identity 
+            else:
+                env['jfed_identity'] = None
+
         # otherwise
         else:
             # log user activity
             activity.user.login(self.request, "error")
             env['state'] = "Your username and/or password were incorrect."
 
-            return render_to_response(self.template, env, context_instance=RequestContext(request))
+        return render_to_response(self.template,env, context_instance=RequestContext(request))
 
     def get (self, request, state=None):
         env = self.default_env()
         acc_auth_cred={}
+
+        jfed_identity = get_jfed_identity(request)
+        if jfed_identity is not None:
+            import base64
+            encoded_jfed_identity = base64.b64encode(jfed_identity)
+            env['jfed_identity'] = encoded_jfed_identity 
+        else:
+            env['jfed_identity'] = None
+
         if request.user.is_authenticated():
 
             ## check user is pi or not
@@ -197,47 +211,5 @@ class HomeView (FreeAccessView, ThemeView):
         elif not env['username']: env['state'] = None
         # use one or two columns for the layout - not logged in users will see the login prompt
 
-#         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-#         account_details = execute_query(self.request, account_query)
-#         for account_detail in account_details:
-#             account_config = json.loads(account_detail['config'])
-#             platform_name = platform_detail['platform']
-#             if 'myslice' in platform_detail['platform']:
-#                 acc_user_cred = account_config.get('delegated_user_credential','N/A')
-#                 acc_slice_cred = account_config.get('delegated_slice_credentials','N/A')
-#                 acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-#
-#                 if 'N/A' not in acc_user_cred:
-#                     exp_date = re.search('<expires>(.*)</expires>', acc_user_cred)
-#                     if exp_date:
-#                         user_exp_date = exp_date.group(1)
-#                         user_cred_exp_list.append(user_exp_date)
-#
-#                     my_users = [{'cred_exp': t[0]}
-#                         for t in zip(user_cred_exp_list)]
-#
-#
-#                 if 'N/A' not in acc_slice_cred:
-#                     for key, value in acc_slice_cred.iteritems():
-#                         slice_list.append(key)
-#                         # get cred_exp date
-#                         exp_date = re.search('<expires>(.*)</expires>', value)
-#                         if exp_date:
-#                             exp_date = exp_date.group(1)
-#                             slice_cred_exp_list.append(exp_date)
-#
-#                     my_slices = [{'slice_name': t[0], 'cred_exp': t[1]}
-#                         for t in zip(slice_list, slice_cred_exp_list)]
-#
-#                 if 'N/A' not in acc_auth_cred:
-#                     for key, value in acc_auth_cred.iteritems():
-#                         auth_list.append(key)
-#                         #get cred_exp date
-#                         exp_date = re.search('<expires>(.*)</expires>', value)
-#                         if exp_date:
-#                             exp_date = exp_date.group(1)
-#                             auth_cred_exp_list.append(exp_date)
-
-
         return render_to_response(self.template, env, context_instance=RequestContext(request))
 
index 503a22a..332acbc 100644 (file)
@@ -69,12 +69,12 @@ class InstitutionView (LoginRequiredAutoLogoutView, ThemeView):
                 env['project'] = True
                 env['user_details'] = {'parent_authority': authority_hrn}
 
+            logger.debug("BEFORE  ####------####  is_pi")
+            logger.debug("is_pi = {}".format(is_pi))
+            pi = is_pi(self.request, '$user_hrn', env['user_details']['parent_authority']) 
         else: 
             env['person'] = None
-        logger.debug("BEFORE  ####------####  is_pi")
-        pi = is_pi(self.request, '$user_hrn', env['user_details']['parent_authority']) 
-        logger.debug("is_pi = {}".format(is_pi))
-
+            pi = False
         env['theme'] = self.theme
         env['section'] = "Institution"
         env['pi'] = pi 
index ac3cf9a..5fd7d8c 100644 (file)
@@ -109,9 +109,13 @@ class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
                     'project_name'      : wsgi_request.POST.get('project_name', ''),
                     'purpose'           : wsgi_request.POST.get('purpose', ''),
                 }
+                
+                # for new projects max project_name length is 10
+                if (len(post['project_name']) >10):
+                    errors.append('Project name can be maximum 10 characters long')
 
-                if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
-                    errors.append('Organization is mandatory')
+                #if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
+                #    errors.append('Organization is mandatory')
     
                 if (post['purpose'] is None or post['purpose'] == ''):
                     errors.append('Project purpose is mandatory')
@@ -121,12 +125,7 @@ class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
 
             # What kind of project name is valid?
             if (post['project_name'] is None or post['project_name'] == ''):
-                errors.append('Project name is mandatory')
-
-            # max project_name length is 10
-            if (len(post['project_name']) >10):
-                errors.append('Project name can be maximum 10 characters long')
-
+                errors.append('Project name is mandatory')   
             
             if not errors:
                 logger.info("is_pi on auth_hrn = {}".format(user_authority))
index 8bdc6e6..2451600 100644 (file)
@@ -283,6 +283,7 @@ class SliceResourceView (LoginRequiredView, ThemeView):
             page            = page,
             domid           = "filter-status",
             query           = sq_resource,
+            query_lease     = sq_lease,
         )
         apply = ApplyPlugin(
             page            = page,
index 49afc69..a62067f 100644 (file)
@@ -6,7 +6,7 @@ from unfold.loginrequired           import LoginRequiredView
 from myslice.theme import ThemeView
 
 class SliceTabMeasurements (LoginRequiredView, ThemeView):
-    template_name = "slice-tab-measurement.html"
+    template_name = "slice-tab-measurements.html"
     
     def get(self, request, slicename):
-        return render_to_response(self.template, {"theme": self.theme, "username": request.user, "slice" : slicename, "section":"measurements"}, context_instance=RequestContext(request))
+        return render_to_response(self.template, {"theme": self.theme, "username": request.user, "slicename" : slicename, "section":"measurements"}, context_instance=RequestContext(request))
index 70de2a8..712c723 100644 (file)
@@ -27,7 +27,18 @@ h2 {
     color:#333333;
 }
 h3 {
-    font-size:13pt;
+    font-size:12pt;
+    letter-spacing:0.6pt;
+    color:#201E62;
+}
+h4 {
+    font-size:12pt;
+    letter-spacing:0.6pt;
+    color:#201E62;
+}
+label {
+    font-weight:normal;
+    font-size:13px;
     color:#201E62;
 }
 input[type=checkbox] {
@@ -651,17 +662,97 @@ div.secondary .account span {
 div.secondary .account a {
     color:black;
 }
-div.dashboard div {
-    margin:25px 0;
+
+div.home {
+    padding-top:50px;
+}
+div.home h1 {
+    font-size:22pt;
+    border:0;
+}
+div.home h3, div.home h4 {
+    color:#424242;
+    line-height:1.4em;
+}
+
+div.home h3 a {
+    color:#FD6D2C;
 }
 div.dashboard {
-    text-align:center;
+}
+div.dashboard a {
+    color:#206090;
+}
+
+div.dashboard a:hover {
+    text-decoration:underline;
+}
+div.dashboard div.projects-tree {
+    margin-left:49px;
 }
 div.dashboard ul {
+    list-style-type:disc;
+    list-style-position:inside;
     text-align:left;
-    margin-left:24px;
+    margin:0 0 15px 0;
+    padding:0;
+    
+}
+div.dashboard ul ul {
+    margin:5px 0 15px 25px;
     list-style:none;
 }
+div.dashboard li {
+    margin:0 0 5px 0;
+    padding:0;
+}
+div.dashboard ul ul li {
+    margin:0;
+}
+div.dashboard ul ul a {
+}
+div.dashboard h3 {
+    border-bottom:1px solid #E0E0E0;
+    margin-right:15px;
+    margin-bottom:25px;
+}
+div.dashboard h3 a {
+     color:#201E62;
+}
+div.dashboard h3 img {
+    margin:15px 15px 15px 0;
+}
+div.dashboard span.glyphicon {
+    text-align:center;
+    width:45px;
+    height:25px;
+}
+div.dashboard-create-slice {
+    display:none;
+}
+div.experiment-tools {
+}
+div.experiment-tools h4 {
+    border-bottom:1px solid #E0E0E0;
+    margin:25px 15px 25px 0;
+    padding-bottom:5px;
+}
+div.experiment-tools .jfed {
+    text-align:center;
+    margin-right:25px;
+}
+div.experiment-tools button {
+    margin:0;
+    padding:7px 10px 4px 0;
+    color:white;
+    vertical-align:middle;
+}
+
+div.experiment-tools button span {
+    margin:0;
+    padding:0;
+}
+
 div.dataTables_filter label{
     float:left;
     width:400px;
@@ -671,6 +762,15 @@ div.breadcrumbs {
     color:gray;
     font-size:10pt;
 }
+
+.sublabel {
+    color:gray;
+    font-style:italic;
+    font-weight:normal;
+}
+.tab-pane {
+    padding-top:25px;
+}
 /* Service Directory */
 
 div#appservices div.row {
index 45f5efc..4023e6c 100644 (file)
@@ -56,6 +56,12 @@ h4 {
     font-size:12pt;
     color:#333333;
 }
+ul {
+    margin:0 0 0 15px;
+    padding:0;
+}
+li {
+}
 span.subtitle {
     color:#454545;
     font-size:9pt;
@@ -121,7 +127,6 @@ div.breadcrumbs a:hover {
     text-decoration:underline;
 }
 .tab-pane {
-    padding-top:15px;
 }
 /* buttons */
 button.btn, input.btn {
@@ -389,6 +394,31 @@ div.sl-filter-facilities {
 div.sl-filter-facilities h4 {
     margin-bottom:15px;
     
+}
+.sl-menu {
+    padding:0;
+}
+.sl-menu h4 {
+    margin:0 0 15px 0;
+    padding:0;
+}
+.sl-menu ul {
+    list-style:none;
+    margin:0;
+    padding:0;
+}
+.sl-menu li {
+    color:gray;
+    cursor:pointer;
+    padding:4px 8px;
+}
+.sl-menu li img {
+    vertical-align:top;
+}
+.sl-menu li.active {
+    color:black;
+}
+.sl-menu-item {
 }
 img.sl-image {
     margin:0 5px 5px 0;
index 481e947..a74132e 100644 (file)
@@ -19,13 +19,13 @@ function getKeySplitId(id,separator){
 if ( typeof String.prototype.startsWith != 'function' ) {
   String.prototype.startsWith = function( str ) {
     return this.substring( 0, str.length ) === str;
-  }
+  };
 };
 
 if ( typeof String.prototype.endsWith != 'function' ) {
   String.prototype.endsWith = function( str ) {
     return this.substring( this.length - str.length, this.length ) === str;
-  }
+  };
 };
 // http://stackoverflow.com/questions/646628/javascript-startswith
 
@@ -58,15 +58,19 @@ jQuery.fn.spin = function(opts) {
 // FROM Triptych : http://stackoverflow.com/users/43089/triptych
 // http://stackoverflow.com/questions/979256/how-to-sort-an-array-of-javascript-objects
 // data.sort(sort_by('city', false, function(a){return a.toUpperCase()}));
-var sort_by = function(field, reverse, primer){
+var sort_by = function(field, reverse, primer) {
 
-   var key = function (x) {return primer ? primer(x[field]) : x[field]};
+   var key = function(x) { return primer ? primer(x[field]) : x[field]; };
    //var key = primer ? function (x) { return primer(x[field]); } : function (x) { return x[field]; }
    
-   return function (a,b) {
+   return function(a,b) {
        var A = key(a), B = key(b);
        return (A < B ? -1 : (A > B ? 1 : 0)) * [1,-1][+!!reverse];
        //return ((A < B) ? -1 :
        //        (A > B) ? +1 : 0)) * [-1,1][+!!reverse];                  
-   }
+   };
+};
+
+function escapeRegExp(str) {
+  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
 }
index 548d5da..80b4d17 100644 (file)
@@ -107,7 +107,7 @@ user.prototype.list = function() {
 var myslice = {
        user: {},
        
-       user: function() {
+       get_user: function() {
                if ($.isEmptyObject(this.user)) {
                        //this.login(function() { return this.user; });
             if(localStorage.getItem('user')!='undefined'){
@@ -120,7 +120,7 @@ var myslice = {
        },
        projects: {},
        
-       projects: function() {
+       get_projects: function() {
                if ($.isEmptyObject(this.projects)) {
                        //this.login(function() { return this.user; });
             if(localStorage.getItem('projects')!='undefined'){
@@ -208,7 +208,6 @@ var myslice = {
                 fn();
             }
         }
-
        },
 
 
index 82fa444..c83c2bd 100644 (file)
@@ -1,6 +1,7 @@
 {% load portal_filters %}
 {# This is required by insert_above #}{% insert_handler %}<!DOCTYPE html>
-<html lang="en"><head>
+<html lang="en">
+<head>
 <title>{{theme}} portal - {{ section }}</title>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
@@ -20,7 +21,7 @@
 <script src="{{ STATIC_URL }}js/jquery.dataTables.min.js"></script>
 <script src="{{ STATIC_URL }}js/jquery.qtip.min.js"></script>
 <script src="{{ STATIC_URL }}js/bootstrap.datatables.js"></script>
-<!-- <script src="{{ STATIC_URL }}js/stash.min.js"></script> -->
+<script src="{{ STATIC_URL }}js/common.functions.js"></script>
 <script src="{{ STATIC_URL }}js/myslice.js"></script>
 <script src="{{ STATIC_URL }}js/myslice-ui.js"></script>
 
@@ -65,7 +66,7 @@ This list of slices should go into SESSION !
 $(document).ready(function() {
 {% if username %}
     myslice.login(function(){
-        user = myslice.user();
+        user = myslice.get_user();
 
         var slices = [];
         if($.isEmptyObject(user)){
@@ -75,12 +76,13 @@ $(document).ready(function() {
             slices.push("no slice");
         }else{
             slices = user.slices;
-            drawSlices(slices);
+            //drawSlices(slices);
         }
         {% if theme == "fed4fire" %}
-        p = myslice.projects();
+        p = myslice.get_projects();
         if(p != null){
-            drawProjects(p);
+            //drawProjects(p);
+            drawProjectsTree(p,slices);
         }
         {% endif %}
     });
@@ -105,6 +107,33 @@ $(document).ready(function() {
         $("div#home-project-list").html($( "<ul/>", { html: items.join( "" ) }));
         $("ul#dropdown-project-list").append(items.join( "" ));
     }
+    function drawProjectsTree(projects,slices) {
+        var items = [];
+        var items_sl = [];
+        $.each( projects, function(i, p) {
+            $.each( slices, function(y, s) {
+                console.log(escapeRegExp(p));
+                if (s.match('^' + escapeRegExp(p))) {
+                     items_sl.push( "<li><a href=\"/resources/" + s + "\">" + s.replace(p + '.','') + "</a></li>" );
+                }
+            });
+            el = "<li><a href=\"/portal/project/" + p + "\">" + p + "</a>";
+            if (items_sl.length > 0) {
+                el += "<ul>" + items_sl.join( "" ) + "</ul>";
+            }
+            el += "</li>";
+            items.push(el);
+            items_sl = [];
+        });
+        $("div#home-project-tree").html($( "<ul/>", { html: items.join( "" ) }));
+        if (projects.length > 0) {
+            $('.dashboard-create-slice').show();
+        }
+    }
+    
+    window.setTimeout(function() {
+        $('.projects-loading').hide();
+    },10000);
     {% endif %}
 {% endif %}
        jQuery('[title!=""]').qtip();
index 3d7e749..e1fa009 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>We have received a user signup request for your email address at {{current_site}}</p>
 <p>You have the following user details:</p>
index 0e62c78..74ca3da 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <b>Email        :</b> {{email}}
 
index 53f353c..5e6a510 100644 (file)
 {% widget '_widget-news.html' %}
 </div> -->
 {% if username %}
+
 {% block head %} 
-<script type="text/javascript" src="https://java.com/js/dtjava.js"/>
-<script type="text/javascript">
-</script>
+<script type="text/javascript" src="https://java.com/js/dtjava.js"></script>
 {% endblock head %}
 
 {% widget "_widget-no_credentials.html" %}
 <div class="container dashboard">
        <div class="row">
+           <div class="col-md-12">
        {%if 'no_creds'  in user_cred %}
        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">NO CREDENTIALS</a> are delegated to the portal!</p>
        {%endif%}
        {%if 'creds_expired'  in user_cred %}
        <p class="command"><a href="#" style="color:red" data-toggle="modal" data-target="#myModal">EXPIRED CREDENTIALS</a> Please delegate again your credentials to the portal!</p>
     {%endif%}
-               <div class="col-md-3">
-                       <h3>
-                               EXPERIMENT
-                       </h3>
-                       <div>
-                               <a href="/portal/slice_request"><img src="{{ STATIC_URL }}img/icon_slices.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="slicerequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
-                       </div>
-                       <div>
-                               <p><strong>Your slices </strong>
-                                       <span title="A slice is a set of testbed resources on which you can conduct an experiment. 
-                                       Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
-                                       However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
-                                       those slices will not appear here."
-                                       class="glyphicon glyphicon-info-sign">
-                               </span>
-
-                               </p>
-                       </div>
-                       <div>   
-                               <div id="home-slice-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
-                       </div>
-                       <h3 title="Some tools do their own slice creation and management.">Experiment now</h3>
-                       <a class="btn btn-primary" id="webstart-button" style="width: 150px;" 
-                    href='http://jfed.iminds.be/releases/5.4-dev/r2314/webstart/experimenter/jfed-experimenter.jnlp'
-                                       title="Click here to start your experiment with jFed">
-                    <span class="glyphicon glyphicon-cloud"></span> jFed</a>
-               </div>
-               <div class="col-md-3">
-                       <h3>MANAGEMENT</h3>
-                       <div>
-                               <a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="projectrequestbtn" type="button" class="btn btn-default" style="width:165px;"><span class="glyphicon glyphicon-plus"></span> Create/Join project</button>
-                       </div>
-                       <div>
-                               <button id="validaterequestbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Validate Requests</button>
-                       </div>
-                       <div>
-                               <p><strong>Your projects </strong>
-                                       <span title="A project is a sub-authority under the responsability of your institution gathering users, who will be able to create slices for their experiments."
-                                       class="glyphicon glyphicon-info-sign">
-                               </span>
-                               </p>
-                       </div>
-                       <div>   
-                               <div id="home-project-list"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
-                       </div>
-
-               </div>
-               <div class="col-md-3">
-                       <h3>
-                               SUPPORT
-                       </h3>
-                       <div>
-                               <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span> Contact</button>
-                       </div>
-                       <p></p>
-                       <div>
-                       <button id="statbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats" style="margin-right: 10px;"></span>Testbeds' status</button>
-                       </div>
-                       <div>
-                       <button id="repbtn" type="button" style="width: 170px;" class="btn btn-default"><span class="glyphicon glyphicon-stats"></span>Testbeds' reputation</button>
-                       </div>
-               </div>
-               
-               <div class="col-md-3">
-                       <h3>
-                               ACCOUNT
-                       </h3>
-                       <div>
-                               <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_color.png" alt="" /></a>
-                       </div>
-                       <div>
-                               <button id="logoutbtn" type="button" class="btn btn-default" data-username="{{ username }}"><span class="glyphicon glyphicon-off"></span> Logout</button>
-                       </div>
-                       <div>
-                               {% if person.last_name %}
-                                       {{person.first_name}} {{person.last_name}}<br />
-                               {% endif %}
-                       <span class="label">Username:</span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
-               </div>
-               </div>
-       </div>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-sm-4">
+            <h3>
+                <img src="{{ STATIC_URL }}img/icon_slices_small.png" alt="" />EXPERIMENT
+            </h3>
+            <div>
+                <span class="glyphicon glyphicon-cog"></span> <a href="/portal/project_request/">Create/Join project</a>
+            </div>
+            <div class="dashboard-create-slice">
+                <span class="glyphicon glyphicon-plus"></span> <a href="/portal/slice_request/">Create slice</a>
+            </div>
+            <div class="projects-tree">
+                Your projects and slices
+                <span title="A <b>slice</b> is a set of testbed resources on which you can conduct an experiment. 
+                Either ask your colleagues to give you access to an existing slice or request a new slice by clicking 'Request Slice'. 
+                However, on the Fed4FIRE portal, you will only see slices that you have created through Fed4FIRE. If you have created slices elsewhere, 
+                those slices will not appear here. <br /><br /> A <b>project</b> is a sub-authority under the responsability of your institution gathering users, 
+                who will be able to create slices for their experiments." class="glyphicon glyphicon-info-sign">&nbsp;</span> 
+             
+                <div id="home-project-tree"><img class="projects-loading" src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div>
+            </div>
+                        
+            <div class="experiment-tools">
+                <h4 title="Some tools do their own slice creation and management.">Experiment now</h4>
+                
+                <p class="jfed">
+                    <button id="start" class="btn btn-primary" type="button" onclick="launchjFed()"><span class="glyphicon glyphicon-cloud"></span> Start jFed</button>
+                </p>
+                <div id='java7Dialog' title="Old Java version detected" >
+                <p>The latest version of jFed is only compatible with Java 8 or higher. We detected that you are using an older version.</p>
+                <p>Please upgrade to Java 8 to get access to the newest version of jFed. Otherwise, you can use jFed 5.3.2, which is Java 7-compatible.</p>
+                </div>
+                
+                <div id='noJavaDialog' title="No Java detected" >
+                <p>jFed requires Java to run. We however couldn't detect a Java installation in your browser.</p>
+                <p>Please install the latest version of Java to continue.</p>
+                </div>
 
+            </div>
+        </div>
+        <div class="col-sm-4">
+            <div class="row">
+                <div class="col-sm-12">
+                    <h3>
+                        <a href="/portal/account/"><img src="{{ STATIC_URL }}img/icon_user_small.png" alt="" /></a><a href="/portal/account/">ACCOUNT</a>
+                    </h3>
+                    {% if person.last_name %}
+                    <p>
+                        {{person.first_name}} {{person.last_name}}
+                    </p>
+                    {% endif %}
+                    <p>
+                        <span class="glyphicon glyphicon-user"></span> <a href='/portal/account/' title="Click here to see and edit your account details.">{{person.email}}</a>
+                    </p>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-12">
+                    <h3>
+                        <a href="/portal/institution"><img src="{{ STATIC_URL }}img/icon_authority_color_small.png" alt="" /></a><a href="/portal/institution">MANAGEMENT</a>
+                    </h3>
+                   
+                    <div>
+                        <span class="glyphicon glyphicon-ok"></span> <a href="/portal/institution#requests">Validate Requests</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="col-sm-4">
+            <div class="row">
+                <div class="col-sm-12">
+                    <h3>
+                        <a href="/portal/support"><img src="{{ STATIC_URL }}img/icon_support_small.png" alt="" /></a><a href="/portal/support">SUPPORT</a>
+                    </h3>
+                    <p>
+                        <span class="glyphicon glyphicon-envelope"></span> <a href="/portal/contact/">Contact</a>
+                    </p>
+                    <p>
+                        <span class="glyphicon glyphicon-stats"></span> <a target="_blank" href="https://flsmonitor.fed4fire.eu">Testbeds' status</a>
+                        </br />
+                        <span class="glyphicon glyphicon-stats"></span> <a href="/portal/reputation">Testbeds' reputation</a>
+                        
+                    </p>
+                    <p>
+                        <span class="glyphicon glyphicon-book"></span> <a target="_blank" href="http://doc.fed4fire.eu/">Documentation</a>
+                    </p>
+                </div>
+            </div>            
+        </div>
+    </div>
 </div>
 {% else %}
-<div class="container-fluid home">
+<div class="container home">
        <div class="">
-               <div class="col-sm-2"></div>
-               <div class="col-sm-4 slogan">
-                       <h2>
+               <div class="col-sm-4 col-sm-offset-1 slogan">
+                       <h1>
                                Fed4FIRE Portal
-                       </h2>
+                       </h1>
                        <h3>
-                               Your easy access to Future Internet Research and Experimentation testbeds belonging to the Fed4FIRE federation.
+                               Your easy access to Future Internet Research and Experimentation testbeds belonging to the 
+                               <a target="_blank" href="http://www.fed4fire.eu/">Fed4FIRE</a> federation.
                        </h3>
-                       <h3>
+                       <br />
+                       <h4>
                                 <a href='http://doc.fed4fire.eu'>Want to learn more?</a>
-                       </h3>
+                       </h4>
                </div>
                <div class="col-sm-4 col-sm-offset-1" style="width:400px; top:16px; float:left;">
                        <div class="row">
                                {% widget '_widget-login-user.html' %}
                        </div>
                </div>
-               <div class="col-sm-1"></div>
        </div>
 </div>
 {% endif %}
 
 
 <script type="text/javascript">
-       $(document).ready(function() {
-        $('#webstart-button').click(function(){
-            var platform8 = new dtjava.Platform({javafx: '8+', jvm: '1.8+'});
-            var config = {
-                java8_jnlp: 'http://jfed.iminds.be/releases/5.4-dev/r2314/webstart/experimenter/jfed-experimenter.jnlp',
-                java7_jnlp: 'http://jfed.iminds.be/releases/r2269/webstart/experimenter/jfed-experimenter.jnlp'
-            };
-            var certkey = "{{jfed_identity}}";
+   var config = {
+       java8_jnlp: 'http://jfed.iminds.be/jfed-f4f-java8.jnlp',
+       java7_jnlp: 'http://jfed.iminds.be/jfed-f4f-java7.jnlp'
+   };
 
-            dtjava.launch({url: config.java8_jnlp, params: {'login-certificate-string' : certkey } } , platform8, {});
-            //launchjFed();
-        });
+   var certkey = "{{jfed_identity}}";
+
+       $(document).ready(function() {
            {%if 'no_creds' in user_cred or 'creds_expired' in user_cred %}
         localStorage.clear();
         $.post("/cache/clear/", function( data ) {
                        $('div.home-panel').hide();
                        $('div#'+$(this).data('panel')).show();
                });
-               $('button#validaterequestbtn').click(function() {
-                       window.location="/portal/institution#requests";
-               });
-               $('button#ticketbtn').click(function() {
-                       window.location="/portal/contact/";
-               });
-               $('button#statbtn').click(function() {
-               window.location="https://flsmonitor.fed4fire.eu";
-               });
-                $('button#repbtn').click(function() {
-               window.location="/portal/reputation";
-                });
-               $('button#signupbtn').click(function() {
-                       window.location="/portal/register/";
-               });
-               $('button#slicerequestbtn').click(function() {
-                       window.location="/portal/slice_request/";
-               });
-               $('button#projectrequestbtn').click(function() {
-                       window.location="/portal/project_request/";
-               });
-
-        myslice.loadSlices();
-});
-</script>
-
-<!--
-for jfed tool
-<script type="text/javascript" src="{{STATIC_URL}}js/fed4fire_dtjava_orig.js"></script>
-<script>
-       function launchApplication(jnlpfile) {
-       dtjava.launch(
-               { url : jnlpfile },
-            {
-               javafx : '2.2+',
-                toolkit: 'swing'
-               },
-                {}
-        );
-        return false;
-     }
+               
+    });
 </script>
--->
-{# widget "_widget-monitor.html" #}
-{# widget "_widget-stats-top-slices.html" #}
+<script src='https://authority.ilabt.iminds.be/js/jquery/jquery-ui.min.js'></script>
+<script src="//java.com/js/dtjava.js"></script>
+<script src='https://authority.ilabt.iminds.be/js/jfed_webstart_f4fportal.js'></script>
 
 {% endblock %}
index e523c81..182030d 100644 (file)
           </div>
        </div>
        <div class="tab-pane row" id="requests">
-        <div id="spinner" style="padding-top:40px; padding-left:40px;"/>
+        <div id="spinner" style="padding-top:40px; padding-left:40px;"></div>
        </div>
 </div>
 <script>
index be59750..1da22fa 100644 (file)
@@ -1,12 +1,19 @@
 {% extends "layout.html" %}
 {% load i18n %}
-
-{% block content %}
+{% block head %}
 <script src="{{ STATIC_URL }}js/jquery-ui.js"></script>
 <script src="{{ STATIC_URL }}js/jquery-ui-combobox.js"></script>
 <link rel='stylesheet' type='text/css' href="{{ STATIC_URL }}css/jquery-ui.css">
 <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/jquery.ui.combobox.css">
-<br />
+{% endblock head %}
+{% block content %}
+<div class="row">
+    <div class="col-md-12">
+         <div class="breadcrumbs" style="line-height: 3;">
+             Experiment &nbsp;>&nbsp; Create or join a Project
+         </div>
+    </div>
+</div>
 <div class="row">
     <div class="col-md-12">
         <ul class="nav nav-tabs nav-section">
 <div class="container tab-content">
 
     <div class="tab-pane active" id="new"> 
-        <div class="row">
-            <div class="col-md-12">
-                 <h3>Create a new Project</h3>
-            </div>
-        </div>
-    
         
         <div class="row">
-            <div class="col-md-12">
+            <div class="col-sm-6 col-sm-offset-3">
                 <form role="form" method="post" action="/portal/project_request">
                 {% csrf_token %}
-                  <div class="form-group">
-                    <input type="text" name="project_name" value="" style="width:380px;" placeholder="Name" required>
-                  </div>
-                  <div class="form-group">
-                    <select id="org_name" name="authority_name" class="form-control" style="width:380px" value="{{ organization }}" required> 
-                    {% if authorities %}
-                        {% for authority in authorities %}
-                            {% if authority.name %}
-                                <option value="{{ authority.authority_hrn }}" {% if authority.authority_hrn == authority_hrn %}selected{% endif %}>{{authority.name}}</option>
-                            {% else %}
-                                <option value="{{ authority.authority_hrn }}" {% if authority.authority_hrn == authority_hrn %}selected{% endif %}>{{authority.authority_hrn}}</option>
-                            {% endif %}
-                        {% endfor %} 
-                    {% endif %}
-                    </select>
-                  </div>
-                  
+                    <label>
+                        Please insert a name for your project under which you will be able to create slices <br />
+                        <span class="sublabel">
+                         The project name should only contain letters, numbers and the underscore "_"  (10 max length)<br />
+                        </span>
+                    </label>
+                    <div class="form-group">
+                        <input type="text" name="project_name" value="" class="form-control" maxlength="10"  style="width:100%;" title="The project name should not contain spaces but only letters, numbers and the underscore character" placeholder="Project name" required>
+                    </div>
+                    
+                    <label>
+                        The authority under which your project will be managed <br />
+                        <span class="sublabel">
+                        Before you can access your project a manager of this authority should approve the request
+                        </span>
+                    </label>
+                    <div class="form-group">
+                        <select id="org_name" name="authority_name" class="form-control" style="width:100%" value="{{ organization }}" required> 
+                        {% if authorities %}
+                            {% for authority in authorities %}
+                                {% if authority.name %}
+                                    <option value="{{ authority.authority_hrn }}" {% if authority.authority_hrn == authority_hrn %}selected{% endif %}>{{authority.name}}</option>
+                                {% else %}
+                                    <option value="{{ authority.authority_hrn }}" {% if authority.authority_hrn == authority_hrn %}selected{% endif %}>{{authority.authority_hrn}}</option>
+                                {% endif %}
+                            {% endfor %} 
+                        {% endif %}
+                        </select>
+                    </div>
                   
-                  <div class="form-group">
-                    <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Description" style="width:380px" title="Purpose of your project (informative)" required="required"></textarea>
-                  </div>
-                  <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Send Request</button>
+                    <label>
+                        Please provide a description of the purpose for your project
+                    </label>
+                    <div class="form-group">
+                        <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Project description" style="width:100%" title="Purpose of your project (informative)" required="required"></textarea>
+                    </div>
+                    <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Send Request</button>
                 </form>
         
             </div>
                 <form role="form" method="post" action="/portal/project_request">
                 {% csrf_token %}
                 <div id="project_loading" style="display:inline;"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading projects" /></div> 
-                <select id="projects" name="project_name" style="display:none;"></select> <div style="display:none;" id="projects_button"><input type="submit" id="join" name="join" value="Join" class="btn"/></div>
+                <select id="projects" name="project_name" style="display:none;"></select> 
+                <div style="display:none;" id="projects_button">
+                    <input type="submit" id="join" name="join" value="Join" class="btn"/>
+                </div>
                 </form>
             </div>
             <div class="col-md-6">
index 50b7fff..fd2c968 100644 (file)
                        </div>
                        <div class="modal-body">
                                <p align="left">
-                                       The exact terms and conditions for Fed4FIRE are currently under development.
+<div style="text-align: left;" class="mk-text-block  "><h4>Fed4FIRE Umbrella Terms and Conditions</h4>
+<h4><span style="color: #f97352;">Purpose of this document</span></h4>
+<p>These Terms and Conditions are provided to inform the user (hereinafter â€˜You’) about what constitutes acceptable and permitted use of testbed resources and tools (hereinafter â€˜the Platform’) in the Fed4FIRE federation (hereinafter â€˜Fed4FIRE’).</p>
+<p>The regulations are not intended to constrain You unnecessarily, but to make You aware and protect You, along with all the participating institutions, from the consequences of any misuse or illegal activity as far as is reasonable.</p>
+<p>It is important to understand that when You use the Platform You are bound by these global Fed4FIRE terms and conditions (as provided online at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>), and also by the ICT regulations of Your own institution and the Acceptable Use Policy of the network providers connecting You to the testbed and interconnecting the resources You use. Thus You must have read and understood these before using Platform resources.</p>
+<p>This policy may be updated as necessary. The current version in force will be available at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>.</p>
+<h4><span style="color: #f97352;">Context</span></h4>
+<p>Fed4FIRE provides an experimental platform for testing new ideas and technologies in the area of computer networking (<a href="http://www.fed4fire.eu">http://www.fed4fire.eu</a>). The federated facility consists of individual testbeds and tools, with different owners. The Fed4FIRE consortium is coordinated by iMinds.</p>
+<p>Fed4FIRE provides You with basic access (through a single account, common tools, support and documentation) to the Platform, while each individual testbed provider determines the specifics of this access in terms of available resources, access policies, etc.</p>
+<h4><span style="color: #f97352;">Scope</span></h4>
+<p>These Terms and Conditions apply to every user of the Platform.</p>
+<p>The Terms and Conditions apply to the use of all equipment connected to the Platform. This includes servers, network(s), and Your workstations (whether owned by You, a company or an institution) and any other equipment or facilities connected to the Platform.</p>
+<p>These Terms and Conditions apply to all use of the Platform.</p>
+<p>These Terms and Conditions apply to third parties using the Platform through services You have made available through the Platform as part of an experiment. You will have to inform these third parties of the Terms and Conditions.</p>
+<h4><span style="color: #f97352;">Limitation of Liability</span></h4>
+<p>No liability is assumed by service providers involved on the Platform or any member of the Fed4FIRE consortium in regards to interruption, corruption, loss or disclosure of the services, tools, processes and data hosted<strong>, </strong>unless it is explicitly mentioned otherwise.</p>
+<h4><span style="color: #f97352;">Service Provision</span></h4>
+<p>You are granted Resources within the Fed4FIRE testbed so that You can use the Platform for the purposes described in the experiment projects You are taking part in. These resources can not be used for any other purposes.</p>
+<p>Platform resource providers aim to provide a stable, high-quality service. If there is evidence that the actions of users are adversely impacting this, resource providers are empowered to take reasonable measures to terminate or reprioritise usage in order to protect the overall operation of their services. Implicated users will be contacted by testbed providers as early as is reasonable.</p>
+<h4><span style="color: #f97352;">Acceptable Usage Policy</span></h4>
+<p>You are granted an account solely for Your own and personal use. You should take appropriate measure to protect Your credentials and prevent their use by third parties. The information You provide when requesting an account should be correct to the best of Your knowledge. You shall be responsible for all loss or damages to any part of the Platform as a result of any use of Your credentials to access the Platform, whether they are authorised or unauthorised by You.</p>
+<p>You shall be liable for actions performed on the Platform, by You, at your request or at the request of any other user invited or permitted by You to use services running on Fed4FIRE. In case of any loss or damage to the Platform originating from Your account, You are responsible for repairing or compensating for all damages to the Platform. In addition, You must respect the regulations of the various testbed resources You use in Your work, as described at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>. Your need to do this arises from co-operative agreements that have been made between all the organisations participating in the Platform.</p>
+<p>You may not interfere with others’ work or attempt to invade their privacy.</p>
+<p>You may not attempt to disrupt the working of the Platform.</p>
+<p>You must respect all Copyright for any software and data used on the Platform.</p>
+<p>The terms of software and data licences must be respected.</p>
+<p>You are not entitled to move proprietary data to, from, or via Platform systems without the prior agreement of its owner.</p>
+<p>Once You have registered to use the Platform, it is Your responsibility to remain aware of these regulations and of any changes made to them, and your continued use of the Platform means that you shall abide by the latest version of these terms and conditions.</p>
+<p>In order to keep the Platform operating correctly in both the technical and legal senses, it may become necessary to investigate network traffic (including, for example, e-mails) as well as examine information held on systems that are, or have been, connected to the Platform. You are deemed to have agreed to this.</p>
+<p>You must ensure that all known or obvious threats and vulnerabilities of the systems You run are adequately addressed.</p>
+<p>Should Your usage imply giving access to the Platform to third parties, You understand You will need to gather explicit consent from the operators of the individual testbed providers You will use, and You agree to enforce any restrictions imposed by an individual testbed provider and accept to fulfil Your legal obligations regarding data protection and retention laws.</p>
+<p>The following are explicitly forbidden on the Platform:</p>
+<ul>
+<li>Any military usage, including the development and production of weapons of mass destruction.</li>
+<li>Any activity resulting in compromising the security or integrity of any sites or networks connected to the Fed4FIRE facility</li>
+<li>Distribution of documents or materials containing insults or defamation, racial hatred or revisionism, terrorism, advertising, or distribution of material in a way that infringes the copyright of another person.</li>
+<li>Any illegal activity.</li>
+</ul>
+<p>You must comply to any additional national regulations from the government of the operators of the local testbeds.</p>
+<h4><span style="color: #f97352;">Enforcement</span></h4>
+<p>Whenever You use the Platform, You are bound by all the regulations in the current form of these terms and conditions and the legislation in force at the time.</p>
+<p>The regulations and legislation which applies to You will be enforced by iMinds, as leader of the Fed4FIRE consortium, or/and by the affected testbed providers, even if a breach of either has been evidenced from elsewhere.</p>
+<p>Note that for breaches of some legislation, the law enforcement can be involved.</p>
+<p>Ignorance of regulations or legislation is not a defence.</p>
+<p>Penalties, as defined in the individual testbed regulations at <a href="http://www.fed4fire.eu/terms">http://www.fed4fire.eu/terms</a>, will be levied for confirmed breaches of regulations.</p>
+<p>Disciplinary and investigative processes may also involve any Fed4FIRE partners, users and testbed providers involved in or affected by Your actions.</p>
+<p>Note that all testbed providers have agreed to co-operate in investigating disciplinary cases.</p>
+<p>You agree that the testbed and network providers in Fed4FIRE may monitor the systems and traffic for vulnerabilities and conformance to the acceptable uses, and You will collaborate with Fed4FIRE and any third party involved should any violations or breaches be noticed. The testbed providers involved may suspend or stop systems or suspend network connectivity without notice if such violations are found or suspected. To fulfil legal and contractual requirements, they may communicate to authorized third parties the owner and user of any resource provisioned and connected to the internet.</p>
+<h4><span style="color: #f97352;">Non-research use of Platform resources</span></h4>
+<p>The Fed4FIRE federation Platform has been constructed for experiment-driven research activities, where experiment-driven research is defined as any activity that furthers the user’s knowledge and/or understanding of algorithms, complex data structures or user behaviour.</p>
+<p>If You wish to use the Platform for any other purpose this must be authorized in advance by the Fed4FIRE testbed providers You will use. You will be expected to provide detailed information in support of Your request.</p>
+<p>Experiments must obtain prior agreement from the providers of all resources (e.g. computers, software, data, networks, and any other facilities) before these are used for any purposes other than experiment-driven research activities.</p>
+<p>The use of Fed4FIRE to host commercial services is explicitly disallowed.</p>
+<p>Experimenters that wish to use additional resources also have to agree with the policies of the testbed providers that offer the requested resources (when applicable). The individual testbed policies can be found here:</p>
+<p><a href="http://www.fed4fire.eu/terms/" target="_blank">fed4fire testbeds</a></p>
+<div class="clearboth"></div></div>
                                </p>
 
                        </div>
index 5a74ddd..7a1c12c 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear Fed4FIRE user,</p>
 <p></p>
index 5bd94a3..5a217d8 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <h1>NEW SLICE REQUEST</h1>
 <br>
index d65603d..6fdcbbf 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear Fed4FIRE user,</p>
 <p></p>
index 729616d..4f8546e 100644 (file)
@@ -9,7 +9,7 @@
                         </div>
                </div>
        </div>
-
+       
        {% if errors %}
        <div class="row">
                <div class="col-md-12">
        {% endif %}
        
        <div class="row">
-               <div class="col-md-8 el">
+               <div class="col-md-5 col-md-offset-3">
                        <form role="form" method="post">
                        {% csrf_token %}
-                         <div class="form-group" style="display:none">
-                           <input type="email" class="form-control" id="email" style="width:300px" value="{{ email }}" readonly="readonly">
-                         </div>
                          <div class="form-group">
-                           <input type="text" class="form-control" name="slice_name" id="slice_name" style="width:300px" placeholder="Slice name" value="{{slice_name}}" 
-                               title="Please enter a name for your slice"required="required">
+                            <input type="hidden" id="email" value="{{ email }}" readonly="readonly">
+                            <label>
+                                Please enter a name for your slice <br />
+                                <span class="sublabel">
+                                    The slice name should only contain letters, numbers and the underscore "_" (19 max length) <br />
+                                </span>
+                            </label>
+                            <input type="text" class="form-control" name="slice_name" id="slice_name" maxlength="19" style="width:100%" placeholder="Slice name" value="{{slice_name}}" required="required">
                          </div>
                          <div class="form-group">
-                               <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:300px" placeholder="Project" 
-                               title="Select a project under which you want to create your slice. Don't have any project yet! Create/Join project from the dashboard." required="required">
+                             <label>
+                                 Select a project under which you want your slice to be created <br />
+                                 If your are not part of any projects you can <a href="/portal/project_request/">join or create one</a>
+                             </label>
+                               <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:100%" placeholder="Project" 
+                                       title="Select a project under which you want to create your slice" required="required">
                          </div>
                          <div class="form-group">
-                           <input type="text" class="form-control" name="url" id="url" style="width:300px" placeholder="Experiment URL (if one exists)"
-                               title="Please provide the url of your experiment if you have one." value="{{url}}">
+                             <label>
+                                 Provide an URL for your experiment (not required)
+                             </label>
+                             <input type="text" class="form-control" name="url" id="url" style="width:100%" placeholder="Experiment URL (if one exists)"
+                                       title="Please provide the url of your experiment" value="{{url}}">
                          </div>
                          <div class="form-group">
-                               <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment purpose" style="width:300px" 
-                               title="Purpose of your experiment (informative)" required="required">{{ purpose }}</textarea>
+                             <label>
+                        Please provide a description of the purpose for your experiment
+                   </label>
+                                 <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment description" style="width:100%" 
+                                       title="Description of your experiment" required="required">{{ purpose }}</textarea>
                          </div>
                          <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
                        </form>
@@ -55,6 +68,7 @@
 jQuery(document).ready(function(){
     var myprojects = JSON.parse(localStorage.getItem('projects'));
     $( "#authority_hrn" ).autocomplete({
+        minLength: 0,
         source: myprojects,
         change: function (event, ui) {
                 if(!ui.item){
@@ -64,7 +78,7 @@ jQuery(document).ready(function(){
                     $("#authority_hrn").val("");
                 }
         }
-    });
+    }).bind('focus', function(){ $(this).autocomplete("search"); } );
 });
 
 /*function draw_projects(authority_hrn){
index 673ec5c..9245cbd 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear {{first_name}} {{last_name}},</p>
 <p></p>
index bbd6875..b9b090f 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <h1>NEW USER REQUEST</h1>
 <br>
index ad18740..b3cda42 100644 (file)
@@ -1,4 +1,4 @@
-<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png">
+<img src="https://portal.fed4fire.eu/static/img/f4f-logo.png" width="80px">
 <br>
 <p>Dear {{first_name}} {{last_name}},</p>
 <p></p>
diff --git a/portal/templates/fed4fire/fed4fire_user_request_validated_subject.txt b/portal/templates/fed4fire/fed4fire_user_request_validated_subject.txt
new file mode 100644 (file)
index 0000000..4c2582b
--- /dev/null
@@ -0,0 +1 @@
+Fed4FIRE portal: Account validated
index 680163e..3f2bd7a 100644 (file)
@@ -9,7 +9,6 @@
         
            <div id="secondary" class="col-sm-8 col-md-8 secondary">
                        <ul>
-                           <li><a href="/">Home</a></li>
                                <li><a href="/portal/about">About</a></li>
                                <li><a href="http://doc.fed4fire.eu/">Documentation</a></li>
                                <li><a target="_blank" href="http://www.fed4fire.eu">Project website</a></li>
@@ -23,7 +22,7 @@
           {% if username %}
         <div class="col-md-12 navigation">
             <ul>
-                <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
+                <li><a href="/">DASHBOARD</a></li>
                 <li>|</li>
                 <!--<li id="nav-institution" class=""><a href="/portal/institution">AUTHORITY</a></li>-->
                 <li class="slices">
@@ -38,6 +37,7 @@
                 <li id="nav-service"><a href="/portal/servicedirectory">SERVICES</a></li>
                 <li id="nav-support"><a href="http://doc.fed4fire.eu/support.html">SUPPORT</a></li>
                 <li>|</li>
+                <li id="nav-account"><a href="/portal/account/">{{ username }}</a></li>
                 <li id="nav-logout"><span class="glyphicon glyphicon-off iconlogout"></span> <a id="logout" data-username="{{ username }}" href="#">LOGOUT</a></li>
             </ul>
         </div>
index c8b6b44..21a7dae 100644 (file)
@@ -5,15 +5,14 @@
 
 {% block content %}
 {% include theme|add:"_widget-slice-sections.html" %}
-         
 <div class="container-fluid tab-content container-slice">
-  <div class="tab-pane active row" id="info">...</div>
-  <div class="tab-pane row" id="testbeds">...</div>
-  <div class="tab-pane row" id="resources">...</div>
-  <div class="tab-pane row" id="users">...</div>
-  <!-- <div class="tab-pane row" id="statistics">...</div> -->
-  <!-- <div class="tab-pane row" id="measurements">...</div> -->
-  <div class="tab-pane row" id="experiment">...</div>
-  <!-- <div class="tab-pane row" id="studentslabs">...</div> -->
+  <div class="tab-pane active row" id="info"></div>
+  <div class="tab-pane row" id="testbeds"></div>
+  <div class="tab-pane row" id="resources"></div>
+  <div class="tab-pane row" id="users"></div>
+  <!-- <div class="tab-pane row" id="statistics"></div> -->
+  <div class="tab-pane row" id="measurements"></div>
+  <div class="tab-pane row" id="experiment"></div>
+  <!-- <div class="tab-pane row" id="studentslabs"></div> -->
 </div>         
 {% endblock %}
index e03a53c..44b5d63 100644 (file)
@@ -18,7 +18,7 @@
        <li><a href="/slice/{{ slice }}#users">Users</a></li>
        <li><a href="/slice/{{ slice }}#info">Information</a></li>
        <!-- <li><a href="/slice/{{ slice }}#experiment">Statistics</a></li> -->
-       <!-- <li><a href="/slice/{{ slice }}#experiment">Measurements</a></li> -->
+       <li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
        <li><a href="/slice/{{ slice }}#experiment">Tools</a></li>
        <!-- <li><a href="/slice/{{ slice }}#studentslabs">Students Labs</a></li> -->
 </ul>
@@ -29,7 +29,7 @@
        <li class="users"><a href="#users">Users</a></li>
        <li class="active"><a href="#info">Information</a></li>
        <!-- <li class="statistics"><a href="#experiment">Statistics</a></li> -->
-       <!-- <li class="measurements"><a href="#experiment">Measurements</a></li> -->
+       <li class="measurements"><a href="#measurements">Measurements</a></li>
        <li class="experiment"><a href="#experiment">Tools</a></li>
        <!-- <li class="studentslabs"><a href="#studentslabs">Students Labs</a></li> -->
 </ul>
index 91d3f73..4aebe06 100644 (file)
@@ -6,7 +6,6 @@
 {% endblock %}
 
 {% block content %}
-
 <div class="container">
        <div class="row">
                <div class="col-md-12">
        </div>
 </div>
 <div class="container-fluid tab-content">
-  <div class="tab-pane active row" id="info">...</div>
-  <div class="tab-pane row" id="testbeds">...</div>
-  <div class="tab-pane row" id="resources">...</div>
-  <div class="tab-pane row" id="users">...</div>
+  <div class="tab-pane active row" id="info"></div>
+  <div class="tab-pane row" id="testbeds"></div>
+  <div class="tab-pane row" id="resources"></div>
+  <div class="tab-pane row" id="users"></div>
   <!-- <div class="tab-pane row" id="statistics">...</div> -->
-  <div class="tab-pane row" id="measurements">...</div>
-  <div class="tab-pane row" id="experiment">...</div>
-  <div class="tab-pane row" id="sla">...</div>
+  <div class="tab-pane row" id="measurements"></div>
+  <div class="tab-pane row" id="experiment"></div>
+  <div class="tab-pane row" id="sla"></div>
 </div>         
 {% endblock %}
diff --git a/portal/templates/user_request_validated_subject.txt b/portal/templates/user_request_validated_subject.txt
new file mode 100644 (file)
index 0000000..da9ce74
--- /dev/null
@@ -0,0 +1 @@
+Account validated
index f8f4eb3..a9228ec 100644 (file)
@@ -99,16 +99,29 @@ class Page:
     # needs to be called explicitly and only when metadata is actually required
     # in particular user needs to be logged
     def get_metadata (self):
-        cached_metadata = SessionCache().get_metadata(self.request)
-        if cached_metadata and isinstance(cached_metadata, MetaData):
+        # look in session's cache - we don't want to retrieve this for every request
+        session=self.request.session
+
+        if 'manifold' not in session:
+            session['manifold'] = {}
+        manifold = session['manifold']
+
+        # if cached, use it
+        if 'metadata' in manifold and isinstance(manifold['metadata'],MetaData):
+
+#         cached_metadata = SessionCache().get_metadata(self.request)
+#         if cached_metadata and isinstance(cached_metadata, MetaData):
             logger.debug("Page.get_metadata: return cached value")
-            return cached_metadata
+            return manifold['metadata']
+#             return cached_metadata
 
         metadata_auth = {'AuthMethod':'anonymous'}
 
         metadata = MetaData (metadata_auth)
         metadata.fetch(self.request)
-        SessionCache().store_metadata(self.request, metadata)
+        # store it for next time
+        manifold['metadata']=metadata
+#         SessionCache().store_metadata(self.request, metadata)
         logger.debug("Page.get_metadata: return new value")
         return metadata