Merge branch 'fibre' of ssh://git.onelab.eu/git/myslice into fibre
authorRezende <rezende@land.ufrj.br>
Thu, 24 Jul 2014 19:50:27 +0000 (16:50 -0300)
committerRezende <rezende@land.ufrj.br>
Thu, 24 Jul 2014 19:50:27 +0000 (16:50 -0300)
Conflicts:
portal/registrationview.py

19 files changed:
manifoldapi/static/css/manifold.css
manifoldapi/static/js/manifold.js
manifoldapi/static/js/plugin.js
plugins/columns_editor/templates/columns_editor.html
plugins/filter_status/static/js/filter_status.js
plugins/filter_status/templates/filter_status.html
plugins/testbeds/templates/testbeds.html
portal/accountview.py
portal/actions.py
portal/joinview.py
portal/registrationview.py
portal/slicerequestview.py
portal/static/css/fibre.css
portal/static/css/onelab.css
portal/templates/base.html
portal/templates/fibre/fibre_activate_user.html [new file with mode: 0644]
portal/templates/fibre/fibre_institution.html
portal/templates/fibre/fibre_registration_view.html
portal/templates/slice-resource-view.html

index 42c034d..535950e 100644 (file)
@@ -2,3 +2,18 @@
        visibility: hidden;
        position: absolute;
 }
+
+.loading {
+    background-color:white;
+    color:black;
+    position:fixed;
+    top:160px;
+    left:50%;
+    width:30%;
+    margin: 0 0 0 -15%;
+    padding:25px 50px;
+    box-shadow: 4px 4px 5px #888;
+    border:1pt solid #30196D;
+    display:none;
+    z-index:100;
+}
index fe76629..e0cf338 100644 (file)
@@ -17,6 +17,32 @@ function debug_query (msg, query) {
     else messages.debug ("debug_query: " + msg + " query= " + query);
 }
 
+// http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript
+// attach the .equals method to Array's prototype to call it on any array
+Array.prototype.equals = function (array) {
+    // if the other array is a falsy value, return
+    if (!array)
+        return false;
+
+    // compare lengths - can save a lot of time 
+    if (this.length != array.length)
+        return false;
+
+    for (var i = 0, l=this.length; i < l; i++) {
+        // Check if we have nested arrays
+        if (this[i] instanceof Array && array[i] instanceof Array) {
+            // recurse into the nested arrays
+            if (!this[i].equals(array[i]))
+                return false;       
+        }           
+        else if (this[i] != array[i]) { 
+            // Warning - two different object instances will never be equal: {x:20} != {x:20}
+            return false;   
+        }           
+    }       
+    return true;
+}
+
 // http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
 Object.toType = (function toType(global) {
   return function(obj) {
@@ -463,7 +489,7 @@ function QueryStore() {
     {
         var query_ext = this.find_analyzed_query_ext(query_uuid);
         query_ext.filters = $.grep(query_ext.filters, function(x) {
-            return x == filter;
+            return !(x.equals(filter));
         });
 
         this.apply_filters(query_uuid);
@@ -1833,6 +1859,7 @@ case TYPE_LIST_OF_VALUES:
             // FILTERS
 
             case FILTER_ADDED: 
+                console.log("FILTER ADDED", data);
                 /* Update internal record state */
                 manifold.query_store.add_filter(query_uuid, data);
 
@@ -1842,6 +1869,7 @@ case TYPE_LIST_OF_VALUES:
                 break;
 
             case FILTER_REMOVED:
+                console.log("FILTER REMOVED", data);
                 /* Update internal record state */
                 manifold.query_store.remove_filter(query_uuid, data);
 
index 76e1cb5..324c8c4 100644 (file)
@@ -316,15 +316,18 @@ var Plugin = Class.extend({
     // use spin() to get our default spin settings (called presets)
     // use spin(true) to get spin's builtin defaults
     // you can also call spin_presets() yourself and tweak what you need to, like topmenuvalidation does
-    spin: function (presets) {
-       var presets = ( presets === undefined ) ? spin_presets() : presets;
-       try { this.$element.spin(presets); }
-       catch (err) { messages.debug("Cannot turn on spin " + err); }
+    spin: function (message) {
+       if (!message) {
+               message = 'Please be patient, this can take a few seconds.';
+       }
+       $('div.loading').fadeIn('fast');
+       $('div.loading').find('.message').text(message);
+
     },
 
     unspin: function() {
-       try { this.$element.spin(false); }
-       catch (err) { messages.debug("Cannot turn off spin " + err); }
+       $('div.loading').fadeOut('fast');
+
     },
 
     /* TEMPLATE */
index 1d66e98..57a7831 100644 (file)
@@ -10,7 +10,7 @@ EOF; -->
   <table id='{{domid}}__table' class='query-editor'>
     <thead>
       <tr>
-        <th class='center'>Info</th>
+        <!--<th class='center'>Info</th> -->
         <th class='center'>Field</th>
         <!--
         <th class='center'>Resource</th>
@@ -26,7 +26,7 @@ EOF; -->
     {% for field in fields %}
 
       <tr>
-        <td class='center'><span class='glyphicon glyphicon-chevron-right' style='cursor:pointer'></span></td>
+        <!--<td class='center'><span class='glyphicon glyphicon-chevron-right' style='cursor:pointer'></span></td> -->
         <td class='center'>{{ field.name }}</td>
         <!--
         <td class='center'>{{ field.resource_type }}</td>
index 3bcd15c..9c1c244 100644 (file)
 
             // ... and communicate the appropriate filters to the manager
             // NOTE: we use the manifold namespace for internal filters 
-            if (self.prev_filter_status)
-                manifold.raise_event(self.options.query_uuid, FILTER_REMOVED, self.prev_filter_status);
-
+            if (self.prev_filter_status) {
+                var filter = ['manifold:status', '==', self.prev_filter_status];
+                manifold.raise_event(self.options.query_uuid, FILTER_REMOVED, filter);
+            }
             // XXX The datatables will be refreshed twice !
             if (filter_status != 'all') {
                 // No filter for 'all'
index 654d280..8350eb1 100644 (file)
@@ -1,5 +1,5 @@
 <div id={{ domid }}>
-  <span class="list-group-item-heading sl-resources">View:</span>
+  <span class="list-group-item-heading sl-resources" style='font-size:inherit;'>View:</span>
   
   <a href="#" 
      class="list-group-item sl-resources active" 
@@ -22,7 +22,7 @@
   </a>
   
   <a href="#" class="list-group-item sl-resources"
-     style='display: inline-block !important; font-size: inherit;' 
+     style='display: inline-block !important; font-size: inherit; width:130px;
      id="{{ domid }}__unconfigured" 
      data-status="unconfigured"
      title="View resources that you have selected to add to your slice, that require configuration before they can be reserved. Hover you mouse over the symbol next to the checkbox for more details."
index 1b84a5f..22f7f0a 100644 (file)
           id="testbeds-filter_{[{ testbed.network_hrn }]}"
           data-platform="{[{ testbed.network_hrn }]}">
        <span class="list-group-item-heading">{[{ testbed.platform }]}</span>
-       <!--<p class="list-group-item-heading">{[{ testbed.network_hrn }]}</p></a> -->
+       <!--<p class="list-group-item-heading">{[{ testbed.network_hrn }]}</p>-->
+       </a>
 </div>
 
+<style>
+a.sl-platform  {
+    text-transform: uppercase;
+}
+
+</style>
+
 </div>
index c179a0e..fb9f642 100644 (file)
@@ -348,6 +348,8 @@ def account_process(request):
         return HttpResponseRedirect("/portal/account/")
 
 # XXX TODO: Factorize with portal/registrationview.py
+# XXX TODO: Factorize with portal/registrationview.py
+# XXX TODO: Factorize with portal/joinview.py
 
     elif 'generate' in request.POST:
         for account_detail in account_details:
index 0e77e59..b399ca2 100644 (file)
@@ -325,13 +325,14 @@ def portal_validate_request(wsgi_request, request_ids):
                 # XXX tmp sfa dependency
                 from sfa.util.xrn import Xrn 
                 urn = Xrn(hrn, request['type']).get_urn()
-
+                
+                # Only hrn is required for Manifold Query 
                 sfa_authority_params = {
-                    'hrn'        : hrn,
-                    'urn'        : urn,
-                    'type'       : request['type'],
+                    'authority_hrn'        : hrn,
+                    #'authority_urn'        : urn,
+                    #'type'       : request['type'],
                     #'pi'        : None,
-                    'enabled'    : True
+                    #'enabled'    : True
                 }
                 print "ADD Authority"
                 sfa_add_authority(wsgi_request, sfa_authority_params)
@@ -380,6 +381,8 @@ def create_slice(wsgi_request, request):
     # Add User to Slice if we have the user_hrn in pendingslice table
     user_hrn = request.get('user_hrn', None)
     user_hrns = list([user_hrn]) if user_hrn else list()
+    
+    user_email = request.get
 
     # XXX We should create a slice with Manifold terminology
     slice_params = {
@@ -395,6 +398,13 @@ def create_slice(wsgi_request, request):
     results = execute_query(wsgi_request, query)
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % slice_params['hrn']
+    ## We do not store the email in pendingslice table. As a result receiver's email is unknown ##
+    ## Need modification in pendingslice table ###
+    #else:
+    #    subject = 'Slice created'
+    #    msg = 'A manager of your institution has validated your slice request. You can now add resources to the slice and start experimenting.'
+    #    send_mail(subject, msg, 'support@onelab.eu',['yasin.upmc@gmail.com'], fail_silently=False)
+       
     return results
 
 def create_pending_slice(wsgi_request, request, email):
@@ -509,6 +519,10 @@ def sfa_create_user(wsgi_request, request):
     results = execute_query(wsgi_request, query)
     if not results:
         raise Exception, "Could not create %s. Already exists ?" % sfa_user_params['user_hrn']
+    else:
+        subject = 'User validated'
+        msg = 'A manager of your institution has validated your account. You have now full user access to the portal.'
+        send_mail(subject, msg, 'support@onelab.eu',[request['email']], fail_silently=False)       
     return results
 
 def ldap_create_user(wsgi_request, request, user_detail):
index 8356dec..f9eed28 100644 (file)
@@ -74,6 +74,8 @@ class JoinView (FreeAccessView, ThemeView):
             #prepare user_hrn 
             split_email = reg_email.split("@")[0] 
             split_email = split_email.replace(".", "_")
+            # Replace + by _ => more convenient for testing and validate with a real email
+            split_email = split_email.replace("+", "_")
             user_hrn = reg_auth + '.' + split_email
             
             UserModel = get_user_model()
@@ -108,18 +110,15 @@ class JoinView (FreeAccessView, ThemeView):
                     errors.append('Email already registered in Manifold. Please provide a new email address.')
 
 # XXX TODO: Factorize with portal/accountview.py
+# XXX TODO: Factorize with portal/registrationview.py
+# XXX TODO: Factorize with portal/joinview.py
 #            if 'generate' in request.POST['question']:
             from Crypto.PublicKey import RSA
             private = RSA.generate(1024)
-            private_key = json.dumps(private.exportKey())
-            public  = private.publickey()
-            public_key = json.dumps(public.exportKey(format='OpenSSH'))
-
+            private_key = private.exportKey()
+            public_key = private.publickey().exportKey(format='OpenSSH')
             # Saving to DB
-            account_config = '{"user_public_key":'+ public_key + ', "user_private_key":'+ private_key + ', "user_hrn":"'+ user_hrn + '"}'
             auth_type = 'managed'
-            public_key = public_key.replace('"', '');
-            private_key = private_key.replace('"', '');
 
             if not errors:
                 reg_password = request.POST['pi_password']
index cf85725..909f2a1 100644 (file)
@@ -39,7 +39,7 @@ class RegistrationView (FreeAccessView, ThemeView):
         """
         """
         errors = []
-
+        authority_hrn = None
         authorities_query = Query.get('authority').select('name','authority_hrn')
         authorities = execute_admin_query(wsgi_request, authorities_query)
         if authorities is not None:
@@ -67,8 +67,8 @@ class RegistrationView (FreeAccessView, ThemeView):
                     authority_hrn = authority['authority_hrn']     
 
             # Handle the case when the template uses only hrn and not name
-            #if not authority_hrn:
-            authority_hrn = wsgi_request.POST.get('org_name', '')
+            if authority_hrn is None:
+                authority_hrn = wsgi_request.POST.get('org_name', '')
 
             post_email = wsgi_request.POST.get('email','').lower()
             salt = randint(1,100000)
@@ -95,6 +95,9 @@ class RegistrationView (FreeAccessView, ThemeView):
             
             split_email = user_request['email'].split("@")[0] 
             split_email = split_email.replace(".", "_")
+            # Replace + by _ => more convenient for testing and validate with a real email
+            split_email = split_email.replace("+", "_")
+
             split_authority = user_request['authority_hrn'].split(".")[1]
             username = split_email + '@' + split_authority
             split_authority = user_request['authority_hrn'].split(".")[0]
@@ -132,6 +135,8 @@ class RegistrationView (FreeAccessView, ThemeView):
                             + '.' + split_email + str(randint(1,1000000))
                 
             # XXX TODO: Factorize with portal/accountview.py
+            # XXX TODO: Factorize with portal/registrationview.py
+            # XXX TODO: Factorize with portal/joinview.py
             if 'generate' in wsgi_request.POST['question']:
                 user_request['auth_type'] = 'managed'
 
index bd711d5..a94f650 100644 (file)
@@ -34,6 +34,8 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
         slice_name =''
         purpose=''
         exp_url=''
+        authority_hrn = None
+        authority_name = None
         # Retrieve the list of authorities
         authorities_query = Query.get('authority').select('name', 'authority_hrn')
         authorities = execute_admin_query(wsgi_request, authorities_query)
@@ -53,6 +55,9 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             if authority['authority_hrn'] == user_authority:
                 authority_name = authority['name']
 
+        # Handle the case when we use only hrn and not name
+        if authority_name is None:
+            authority_name = user_authority
         #
         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
         account_details = execute_query(wsgi_request, account_query)
@@ -97,8 +102,8 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
                 if authority['name'] == wsgi_request.POST.get('org_name', ''):
                     authority_hrn = authority['authority_hrn']
 
-            # Handle the case when the template uses only hrn and not name
-            if not authority_hrn:
+            # Handle the case when we use only hrn and not name
+            if authority_hrn is None:
                 authority_hrn = wsgi_request.POST.get('org_name', '')
 
             slice_request = {
index 639b040..05526c8 100644 (file)
@@ -369,6 +369,8 @@ a.sl-resources, a.sl-resources:hover {
     padding:2px 4px;
     -moz-border-radius: 4px;
     border-radius: 4px;
+    width:125px;
+    text-align: center;
 }
 a.sl-resources.active, a.sl-resources.active:hover, a.sl-resources.active:focus {
     border:0;
index 1104c98..5be1bf3 100644 (file)
@@ -12,6 +12,7 @@ body {
 a, a:active, a:focus {
     outline: 0;
     text-decoration:none;
+    color:#201E62;
 }
 
 h1 {
@@ -26,13 +27,20 @@ h1 img {
     margin-right:10px;
 }
 h2 {
+    margin:0 0 15px 0;
     font-size:14pt;
     color:#333333;
 }
 h3 {
+    margin:0 0 5px 0;
     font-size:13pt;
     color:#201E62;
 }
+h4 {
+    margin:0 0 5px 0;
+    font-size:12pt;
+    color:#333333;
+}
 input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number], select, option {
     min-width:260px;
     padding:6px;
@@ -61,6 +69,9 @@ div.breadcrumbs {
     color:gray;
     font-size:10pt;
 }
+.tab-pane {
+    padding-top:15px;
+}
 /* buttons */
 button.btn, input.btn {
     padding:6px 10px;
@@ -369,6 +380,8 @@ a.sl-resources, a.sl-resources:hover {
     padding:2px 4px;
     -moz-border-radius: 4px;
     border-radius: 4px;
+    width:125px;
+    text-align: center;
 }
 a.sl-resources.active, a.sl-resources.active:hover, a.sl-resources.active:focus {
     border:0;
@@ -692,4 +705,4 @@ div.slogan {
     color:white;
     padding-top:60px;
     text-shadow: 1px 1px #013540;
-}
\ No newline at end of file
+}
index b282727..750b427 100644 (file)
@@ -92,5 +92,14 @@ $(document).ready(function() {
        {% block base_content %}
        {% endblock %}
 {% endblock container %}
+<div class="loading">
+       <div class="row">
+               <div class="col-xs-11">Loading...</div>
+               <div class="col-xs-1"><img src="{{ STATIC_URL }}/img/loading.gif" /></div>
+       </div>
+       <div class="row">
+               <div class="col-xs-12 message"></div>
+       </div>
+</div>
 </body>
 </html>
diff --git a/portal/templates/fibre/fibre_activate_user.html b/portal/templates/fibre/fibre_activate_user.html
new file mode 100644 (file)
index 0000000..e14b018
--- /dev/null
@@ -0,0 +1,28 @@
+<img src="https://146.164.47.246:27486/static/img/fibre-logo.gif" width="200" height="100">
+<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>
+
+Organization: {{organization}}<br>
+First name: {{first_name}}<br>
+Last name: {{last_name}}<br>
+Email: {{email}}<br>
+
+<p></p>
+<p>
+You may now log in to the portal using your email address and the password that you provided, but your access will be limited. To gain full access, two steps are required:
+</p>
+
+<ul>
+<li>1. You confirm that you have indeed made this request by clicking on the following link: <br>
+       <a href={{validation_link}}>{{validation_link}}</a> 
+               <ul><li>If you did not make this request, we apologise. You may disregard this email or you may advise us the error by replying to this email.</li></ul>
+</li>
+<li>
+2. A manager from your organization validates your request. Upon confirmation of your signup request, we will send an email to the managers at your organization with a validation request.
+</li>
+</ul>
+<p>
+We look forward to welcoming you to OneLab. You will find answers to frequently asked questions <a href="http://{{current_site}}/portal/support/">here</a>. 
+Please don't hesitate to <a href="http://{{current_site}}/portal/contact/">contact us</a> with any additional questions that you might have.
+</p>
index c8a668f..c7d5c01 100644 (file)
@@ -18,8 +18,8 @@
        <div class="row">
                <div class="col-md-12">
                        <ul class="nav nav-tabs nav-section">
-                               <li class="active"><a href="#about">About</a></li>
-                               <li><a href="#users">Users</a></li>
+                               <!-- <li class="active"><a href="#about">About</a></li>-->
+                               <li class="active"><a href="#users">Users</a></li>
                                <li><a href="#slices">Slices</a></li>
                                <li><a href="#requests">Requests</a></li>
                        </ul>
        </div>
 </div>
 <div class="container tab-content">
+<!--
        <div class="tab-pane active row" id="about">
        </div>
-       
+-->
        <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
                <div class="col-md-12 el">
                        <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
index 474a1b8..4b57f8b 100644 (file)
@@ -164,7 +164,11 @@ $(document).ready(function(){
             {% if authority.name %}
                 {value:"{{ authority.name }}",label:"{{authority.name}}"},
             {% else %}
-                {value:"{{ authority.authority_hrn }}",label:"{{authority.authority_hrn}}"},
+               {% if authority.authority_hrn == "fibre.ufrj" %}
+                       {value:"{{ authority.authority_hrn }}",label:"UNIVERSIDADE FEDERAL DO RIO DE JANEIRO"},
+               {% else %}
+                       {value:"{{ authority.authority_hrn }}",label:"FIBRE"},
+               {% endif %}
             {% endif %}
         {% endfor %}    
     {% else %}
index 6b7fa4c..626b7f5 100644 (file)
@@ -47,7 +47,7 @@ $(document).ready(function() {
                </div>
        
                <div class="row">
-                       <div class="col-md-4">
+                       <div class="col-md-6">
                                {{ filter_status }}
                        </div>
                        <div class="col-md-2">