← Back to team overview

openerp-dev-web team mailing list archive

lp:~openerp-dev/openobject-client-web/proto61-login-and-session-persistence-xmo into lp:~openerp-dev/openobject-client-web/trunk-proto61

 

Xavier (Open ERP) has proposed merging lp:~openerp-dev/openobject-client-web/proto61-login-and-session-persistence-xmo into lp:~openerp-dev/openobject-client-web/trunk-proto61.

Requested reviews:
  Antony Lesuisse (al-openerp)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-client-web/proto61-login-and-session-persistence-xmo/+merge/54003

Fixed session name generation, login process (including reload of menu) and backed OpenERP sessions in CherryPy sessions so they don't die when the server does (and are harder to highjack)
-- 
https://code.launchpad.net/~openerp-dev/openobject-client-web/proto61-login-and-session-persistence-xmo/+merge/54003
Your team OpenERP R&D Team is subscribed to branch lp:~openerp-dev/openobject-client-web/trunk-proto61.
=== modified file 'addons/base/controllers/main.py'
--- addons/base/controllers/main.py	2011-03-17 15:01:53 +0000
+++ addons/base/controllers/main.py	2011-03-18 14:33:10 +0000
@@ -95,11 +95,10 @@
     @openerpweb.jsonrequest
     def login(self, req, db, login, password):
         req.session.login(db, login, password)
-        res = {
+        return {
             "session_id" : req.session_id,
             "uid": req.session._uid,
         }
-        return res
 
     @openerpweb.jsonrequest
     def modules(self, req):

=== modified file 'addons/base/static/openerp/js/base_chrome.js'
--- addons/base/static/openerp/js/base_chrome.js	2011-03-17 17:08:08 +0000
+++ addons/base/static/openerp/js/base_chrome.js	2011-03-18 14:33:10 +0000
@@ -124,10 +124,12 @@
         this.password = "";
         this.uid = false;
         this.session_id = false;
+        this.load_local();
         this.module_list = [];
         this.module_loaded = {"base": true};
         this.context = {};
     },
+<<<<<<< TREE
     on_log: function() {
         // TODO this should move to Console and be active only in debug
         // TODO $element should be for error not log
@@ -140,6 +142,82 @@
             }
         });
     },
+=======
+    /**
+     * Reloads uid and session_id from local storage, if they exist
+     */
+    load_local: function () {
+        this.uid = this.get_cookie('uid');
+        this.session_id = this.get_cookie('session_id');
+    },
+    /**
+     * Saves the session id and uid locally
+     */
+    save_local: function () {
+        this.set_local('uid', this.uid);
+        this.set_local('session_id', this.session_id);
+    },
+    // TODO: clear_local
+
+    /**
+     * Retrieves and return the value indexed by the key name from local
+     * storage, if it finds it.
+     * @param name the name of the value to get
+     */
+    get_local: function (name) {
+        if(window.localStorage) {
+            return localStorage.getItem(name);
+        }
+        return this.get_cookie(name);
+    },
+    /**
+     * Sets the value at the key name in local storage.
+     *
+     * The value has to be a String.
+     *
+     * @param name key to set the value at
+     * @param value value to store
+     */
+    set_local: function (name, value) {
+        if(window.localStorage) {
+            localStorage.setItem(name, String(value));
+        }
+        return this.set_cookie(name, value);
+    },
+
+    /**
+     * Fetches a cookie stored by an openerp session
+     *
+     * @param name the cookie's name
+     */
+    get_cookie: function (name) {
+        var nameEQ = this.element_id + '|' + name + '=';
+        var cookies = document.cookie.split(';');
+        for(var i=0; i<cookies.length; ++i) {
+            var cookie = cookies[i].replace(/^\s*/, '');
+            if(cookie.indexOf(nameEQ) === 0) {
+                return decodeURIComponent(cookie.substring(nameEQ.length));
+            }
+        }
+        return null;
+    },
+    /**
+     * Create a new secure cookie with the provided name and value
+     *
+     * @param name the cookie's name
+     * @param value the cookie's value
+     * @param ttl the cookie's time to live, 1 year by default, set to
+     *            -1 to delete
+     */
+    set_cookie: function (name, value, ttl) {
+        ttl = ttl || 24*60*60*365;
+        document.cookie = [
+            this.element_id + '|' + name + '=' + encodeURIComponent(value),
+            'max-age=' + ttl,
+            'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
+        ].join(';');
+    },
+>>>>>>> MERGE-SOURCE
     rpc: function(url, params, success_callback, error_callback) {
         // Construct a JSON-RPC2 request, method is currently unused
         params.session_id = this.session_id;
@@ -172,7 +250,7 @@
                     if (response.error.data.type == "session_invalid") {
                         self.uid = false;
                         self.on_session_invalid(function() {
-                            self.rpc(url, params, success_callback, error_callback);
+                            self.rpc(url, payload.params, success_callback, error_callback);
                         });
                     } else {
                         error_callback(response.error);
@@ -214,6 +292,7 @@
         this.rpc("/base/session/login", params, function(result) {
             self.session_id = result.session_id;
             self.uid = result.uid;
+            self.save_local();
             self.session_check_modules();
             if (success_callback)
                 success_callback();
@@ -230,7 +309,6 @@
             self.rpc('/base/session/jslist', {"mods": self.module_list.join(',')}, self.debug ? self.do_session_load_modules_debug : self.do_session_load_modules_prod);
             openerp._modules_loaded = true;
         });
-        this.uid = false;
     },
     do_session_load_modules_debug: function(result) {
         var self = this;
@@ -320,22 +398,22 @@
     },
     start: function() {
         this.$element.html(QWeb.render("Login", {}));
-        //this.on_login_invalid();
         this.$element.find("form").submit(this.on_submit);
     },
     on_login_invalid: function() {
-        var $e = this.$element;
-        $e.removeClass("login_valid");
-        $e.addClass("login_invalid");
-        $e.show();
+        this.$element
+            .removeClass("login_valid")
+            .addClass("login_invalid")
+            .show();
     },
     on_login_valid: function() {
-        var $e = this.$element;
-        $e.removeClass("oe_login_invalid");
-        $e.addClass("login_valid");
-        $e.hide();
+        this.$element
+            .addClass("login_valid")
+            .removeClass("login_invalid")
+            .hide();
     },
     on_submit: function(ev) {
+        ev.preventDefault();
         var self = this;
         var $e = this.$element;
         var db = $e.find("form input[name=db]").val();
@@ -350,17 +428,14 @@
                 self.on_login_invalid();
             }
         });
-        return false;
     },
     do_ask_login: function(continuation) {
         this.on_login_invalid();
-        this.on_submit.add({
+        this.on_login_valid.add({
             position: "last",
             unique: true,
-            callback: function() {
-                if(continuation) continuation();
-                return false;
-            }});
+            callback: continuation
+        });
     }
 });
 

=== modified file 'openerpweb/openerpweb.py'
--- openerpweb/openerpweb.py	2011-03-17 15:47:46 +0000
+++ openerpweb/openerpweb.py	2011-03-18 14:33:10 +0000
@@ -2,6 +2,7 @@
 import functools
 
 import optparse, os, re, sys, traceback, xmlrpclib
+import uuid
 
 import cherrypy
 import cherrypy.lib.static
@@ -64,7 +65,6 @@
 #----------------------------------------------------------
 # OpenERP Web RequestHandler
 #----------------------------------------------------------
-session_store = {}
 
 class JsonRequest(object):
     """ JSON-RPC2 over HTTP POST using non standard POST encoding.
@@ -84,8 +84,8 @@
 
     def parse(self, request):
         self.params = request.get("params",{})
-        self.session_id = self.params.pop("session_id", None) or "random.random"
-        self.session = session_store.setdefault(self.session_id, OpenERPSession())
+        self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
+        self.session = cherrypy.session.setdefault(self.session_id, OpenERPSession())
         self.context = self.params.pop('context', None)
         return self.params
 
@@ -148,7 +148,11 @@
 
         print "<--",  response
         print
-        return simplejson.dumps(response)
+
+        content = simplejson.dumps(response)
+        cherrypy.response.headers['Content-Type'] = 'application/json'
+        cherrypy.response.headers['Content-Length'] = len(content)
+        return content
 
 def jsonrequest(f):
     @cherrypy.expose
@@ -245,17 +249,24 @@
                         return m(**kw)
 
         else:
-            return '<a href="/base/static/openerp/base.html">/base/static/openerp/base.html</a>'
+            raise cherrypy.HTTPRedirect('/base/static/openerp/base.html', 301)
     default.exposed = True
 
 def main(argv):
     # optparse
 
+    SESSIONS_STORAGE_DIRECTORY = '/tmp/cpsessions'
+    if not os.path.exists(SESSIONS_STORAGE_DIRECTORY):
+        # 10#448 == 8#700
+        os.mkdir(SESSIONS_STORAGE_DIRECTORY, 448)
     config = {
         'server.socket_port': 8002,
         #'server.socket_host': '64.72.221.48',
         #'server.thread_pool' = 10,
         'tools.sessions.on': True,
+        'tools.sessions.storage_type': 'file',
+        'tools.sessions.storage_path': SESSIONS_STORAGE_DIRECTORY,
+        'tools.sessions.timeout': 60
     }
     cherrypy.tree.mount(Root())
 


Follow ups