From bda8bff7686628fe1a1002cc78fc68294bcdfea1 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Fri, 10 Aug 2012 13:16:16 +0200 Subject: [PATCH 01/22] [ADD] First commit bzr revid: vta@openerp.com-20120810111616-irbkp26p1oi3pbwu --- addons/auth_oauth/__init__.py | 20 +++++++++ addons/auth_oauth/__openerp__.py | 45 +++++++++++++++++++ .../auth_oauth/static/src/css/auth_oauth.css | 2 + addons/auth_oauth/static/src/js/auth_oauth.js | 18 ++++++++ .../auth_oauth/static/src/xml/auth_oauth.xml | 14 ++++++ 5 files changed, 99 insertions(+) create mode 100644 addons/auth_oauth/__init__.py create mode 100644 addons/auth_oauth/__openerp__.py create mode 100644 addons/auth_oauth/static/src/css/auth_oauth.css create mode 100644 addons/auth_oauth/static/src/js/auth_oauth.js create mode 100644 addons/auth_oauth/static/src/xml/auth_oauth.xml diff --git a/addons/auth_oauth/__init__.py b/addons/auth_oauth/__init__.py new file mode 100644 index 00000000000..a55097cb836 --- /dev/null +++ b/addons/auth_oauth/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-2011 OpenERP s.a. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## \ No newline at end of file diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py new file mode 100644 index 00000000000..68f4d2ccd87 --- /dev/null +++ b/addons/auth_oauth/__openerp__.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-2012 OpenERP s.a. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'OAuth2 Authentication', + 'version': '1.0', + 'category': 'Tools', + 'description': """Allow users to login through Google OAuth2.""", + 'author': 'Victor Tabuenca', + 'maintainer': 'OpenERP s.a.', + 'website': 'http://www.openerp.com', + 'depends': ['base', 'web'], + 'data': [ + ], + 'js': [ + 'static/src/js/auth_oauth.js', + ], + 'css': [ + 'static/src/css/auth_oauth.css', + ], + 'qweb': [ + 'static/src/xml/auth_oauth.xml', + ], + 'installable': True, + 'auto_install': False, +} diff --git a/addons/auth_oauth/static/src/css/auth_oauth.css b/addons/auth_oauth/static/src/css/auth_oauth.css new file mode 100644 index 00000000000..c8e0efe4c32 --- /dev/null +++ b/addons/auth_oauth/static/src/css/auth_oauth.css @@ -0,0 +1,2 @@ +.oe_login_oauth { +} \ No newline at end of file diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js new file mode 100644 index 00000000000..fddd4c78ae9 --- /dev/null +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -0,0 +1,18 @@ +openerp.auth_oauth = function(instance) { + + var QWeb = instance.web.qweb; + + instance.web.Login = instance.web.Login.extend({ + start: function() { + console.log("Tu puta madre!"); + this._super.apply(this, arguments); + }, + on_submit: function(ev) { + }, + do_warn: function(title, msg) { + }, + reset_error_message: function() { + } + }); + +}; \ No newline at end of file diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml new file mode 100644 index 00000000000..01cf51da9a2 --- /dev/null +++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file From d0ff62372965ce74984e5b0c1f5a416e1bd580bf Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Sun, 12 Aug 2012 17:07:39 +0200 Subject: [PATCH 02/22] [ADD] Basic functionality. bzr revid: vta@openerp.com-20120812150739-nrdwvxmnnnw8yr54 --- addons/auth_oauth/static/src/js/auth_oauth.js | 59 ++++++++++++++++--- .../auth_oauth/static/src/xml/auth_oauth.xml | 3 +- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index fddd4c78ae9..a49d6777e7d 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -3,16 +3,61 @@ openerp.auth_oauth = function(instance) { var QWeb = instance.web.qweb; instance.web.Login = instance.web.Login.extend({ - start: function() { - console.log("Tu puta madre!"); + start: function(parent, params) { this._super.apply(this, arguments); + var self = this; + self.$element.on('click', '.oe_login_oauth a', this.on_google_oauth); }, - on_submit: function(ev) { + on_google_oauth: function(ev) { + var url = this._oauth_url(); + window.location = url; }, - do_warn: function(title, msg) { + _oauth_url: function() { + var endpoint = 'https://accounts.google.com/o/oauth2/auth'; + var params = { + response_type: 'token', + client_id: '108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com', + redirect_uri: 'https://localhost/', + scope: 'https://www.googleapis.com/auth/userinfo.email', + state: 'TEST', + }; + var url = endpoint + '?' + $.param(params); + return url; }, - reset_error_message: function() { - } + // do_warn: function(title, msg) { + // }, + // reset_error_message: function() { + // } }); -}; \ No newline at end of file + instance.web.WebClient = instance.web.WebClient.extend({ + start: function() { + this._super.apply(this, arguments); + // console.log($.deparam(window.location.hash)); + var params = $.deparam(window.location.hash); + if (params.hasOwnProperty('access_token')) { + console.log(params); + // Do login using Google User credentials + var url = { + + }; + } + }, + bind_hashchange: function() { + var state = $.bbq.getState(true); + if (state.hasOwnProperty("access_token")) { + state.action = "login"; + $.bbq.setState(state); + } + this._super(); + + }, + // on_hashchange: function(event) { + // console.log(event); + // this._super.apply(this, arguments); + // }, + }); + +}; + +// https://accounts.google.com/o/oauth2/auth?state=%2Fprofile&redirect_uri=http%3A%2F%2Foauth2-login-demo.appspot.com%2Fcode&response_type=code&client_id=812741506391.apps.googleusercontent.com&approval_prompt=force&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile \ No newline at end of file diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml index 01cf51da9a2..75f168d6c9a 100644 --- a/addons/auth_oauth/static/src/xml/auth_oauth.xml +++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml @@ -5,8 +5,7 @@ From 875d7541d99fd9bd9eb01d0a2bb7599e8911cf96 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sun, 12 Aug 2012 19:06:03 +0200 Subject: [PATCH 03/22] sign up with controller bzr revid: al@openerp.com-20120812170603-mnp54q5xn9htg6vj --- addons/auth_signup/__init__.py | 3 +- addons/auth_signup/__openerp__.py | 5 +- addons/auth_signup/auth_signup.py | 39 -------- addons/auth_signup/controllers/__init__.py | 3 + addons/auth_signup/controllers/main.py | 37 ++++++++ addons/auth_signup/res_users.py | 47 ++++++++++ .../static/src/css/auth_signup.css | 9 -- .../auth_signup/static/src/js/auth_signup.js | 90 +++++-------------- .../static/src/xml/auth_signup.xml | 8 +- 9 files changed, 117 insertions(+), 124 deletions(-) delete mode 100644 addons/auth_signup/auth_signup.py create mode 100644 addons/auth_signup/controllers/__init__.py create mode 100644 addons/auth_signup/controllers/main.py create mode 100644 addons/auth_signup/res_users.py delete mode 100644 addons/auth_signup/static/src/css/auth_signup.css diff --git a/addons/auth_signup/__init__.py b/addons/auth_signup/__init__.py index 2e404949550..8b5f4d767b5 100644 --- a/addons/auth_signup/__init__.py +++ b/addons/auth_signup/__init__.py @@ -1,2 +1,3 @@ +import controllers import res_config -import auth_signup +import res_users diff --git a/addons/auth_signup/__openerp__.py b/addons/auth_signup/__openerp__.py index a869c623db0..3dbe97394a0 100644 --- a/addons/auth_signup/__openerp__.py +++ b/addons/auth_signup/__openerp__.py @@ -6,16 +6,13 @@ 'category': 'Authentication', 'website': 'http://www.openerp.com', 'installable': True, - 'depends': ['auth_anonymous', 'base_setup'], + 'depends': ['base_setup'], 'data': [ 'res_config.xml', ], 'js': [ 'static/src/js/auth_signup.js', ], - 'css': [ - 'static/src/css/auth_signup.css', - ], 'qweb': [ 'static/src/xml/auth_signup.xml', ], diff --git a/addons/auth_signup/auth_signup.py b/addons/auth_signup/auth_signup.py deleted file mode 100644 index ebc72b3aeac..00000000000 --- a/addons/auth_signup/auth_signup.py +++ /dev/null @@ -1,39 +0,0 @@ -from openerp.osv import osv, fields - -class res_users(osv.Model): - _inherit = 'res.users' - - _sql_constraints = [ - ('email_uniq', 'UNIQUE (user_email)', 'You can not have two users with the same email!') - ] - -class signup_signup(osv.TransientModel): - _name = 'auth.signup' - - # TODO add captcha - _columns = { - 'name': fields.char('Name', size=64), - 'email': fields.char('Email', size=64), - 'password': fields.char('Password', size=64), - } - - def create(self, cr, uid, values, context=None): - # NOTE here, invalid values raises exceptions to avoid storing - # sensitive data into the database (which then are available to anyone) - - new_user = { - 'name': values['name'], - 'login': values['email'], - 'user_email': values['email'], - 'password': values['password'], - 'active': True, - } - - user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) - if user_template_id: - self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) - else: - self.pool.get('res.users').create(cr, 1, new_user, context=context) - - # Dont store anything - return 0 diff --git a/addons/auth_signup/controllers/__init__.py b/addons/auth_signup/controllers/__init__.py new file mode 100644 index 00000000000..e11f9ba81bb --- /dev/null +++ b/addons/auth_signup/controllers/__init__.py @@ -0,0 +1,3 @@ +import main + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py new file mode 100644 index 00000000000..7b84c2e2214 --- /dev/null +++ b/addons/auth_signup/controllers/main.py @@ -0,0 +1,37 @@ +import logging + +import werkzeug.urls + +import openerp.modules.registry +import openerp.addons.web.controllers.main +import openerp.addons.web.common.http as openerpweb + +_logger = logging.getLogger(__name__) + +class OpenIDController(openerpweb.Controller): + _cp_path = '/auth_signup' + + @openerpweb.httprequest + def signup(self, req, dbname, name, login, password): + registry = openerp.modules.registry.RegistryManager.get(dbname) + cr = registry.db.cursor() + try: + try: + u = registry.get('res.users') + r = u.auth_signup(cr, 1, name, login, password) + cr.commit() + return openerp.addons.web.controllers.main.login_and_redirect(req, dbname, login, password) + # or + req.authenticate(*r) + url = "/" + except AttributeError: + # auth_signup is not installed + url = "/#action=auth_signup&error=1" + except Exception,e: + # signup error + url = "/#action=auth_signup&error=2" + finally: + cr.close() + return werkzeug.utils.redirect(url) + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py new file mode 100644 index 00000000000..46f264c6729 --- /dev/null +++ b/addons/auth_signup/res_users.py @@ -0,0 +1,47 @@ +import openerp +from openerp.osv import osv, fields + +class res_users(osv.Model): + _inherit = 'res.users' + + def auth_signup_create(self, cr, uid, new_user, context=None): + user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) + if user_template_id: + self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) + else: + self.pool.get('res.users').create(cr, 1, new_user, context=context) + + def auth_signup_check(self, cr, uid, login, key, context=None): + res = self.search(cr, uid, [("login","=",login)]) + if res: + user_id = res[0]['id'] + self.check(cr.dbname, user_id, key) + return user_id + return False + + def auth_signup(self, cr, uid, name, login, password, context=None): + r = (cr.dbname, login, password) + try: + # check for existing user + if not self.auth_signup_check(cr, uid, login, password): + print "NEW USER" + # new user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'password': password, + 'active': True, + } + self.auth_signup_create(cr,uid, new_user) + return r + else: + print "Existing same" + # already existing with same password + return r + except openerp.exceptions.AccessDenied: + print "Existing different" + # already existing with diffrent password + raise + +# diff --git a/addons/auth_signup/static/src/css/auth_signup.css b/addons/auth_signup/static/src/css/auth_signup.css deleted file mode 100644 index 1e8d7d9d8d8..00000000000 --- a/addons/auth_signup/static/src/css/auth_signup.css +++ /dev/null @@ -1,9 +0,0 @@ -.openerp .oe_login .oe_login_pane ul.oe_signup a { - color: #eeeeee; - margin: 0 8px; -} -.openerp .oe_login .oe_login_pane ul.oe_signup a:hover { - text-decoration: underline; -} - - diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js index 7384fe1e5f5..aba6822739d 100644 --- a/addons/auth_signup/static/src/js/auth_signup.js +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -1,65 +1,38 @@ openerp.auth_signup = function(instance) { + instance.auth_signup = instance.auth_signup || {}; var _t = instance.web._t; instance.web.Login.include({ start: function() { var self = this; - this.$('a.oe_signup').click(function() { - var db = self.$("form [name=db]").val(); - if (!db) { - self.do_warn(_t("Login"), _t("No database selected!")); - return false; - } - - var cnx = instance.connection; - if (cnx.session_is_valid()) { - self._signup(); - } else { - cnx.session_authenticate(db, 'anonymous', 'anonymous', true).then(function() { - self._signup(); - }).fail(function(error, event) { - console.log(error); - // cannot log as anonymous or auth_signup not installed - self.do_warn(_t('Sign Up'), _.str.sprintf(_t('Signup functionnality is not available for database %s'), db), true); - }); - } + var dbname = self.$("form [name=db]").val(); + self.do_action({ + type: 'ir.actions.client', + tag: 'auth_signup.signup', + params: {'dbname': dbname}, + target: 'new', + name: 'Sign up' + }); return true; }); return this._super(); - }, - - _signup: function() { - this.do_action({ - type: 'ir.actions.client', - tag: 'auth_signup.signup', - target: 'new', - name: 'Sign up' - }); - } }); - instance.auth_signup = instance.auth_signup || {}; instance.auth_signup.Signup = instance.web.Widget.extend({ template: 'auth_signup.signup', - init: function() { - this._super.apply(this, arguments); - this.dataset = new instance.web.DataSet(this, 'auth.signup'); + init: function(parent, params) { + this.params = params; + return this._super(); }, start: function() { var self = this; - this.$('input[type=password]').change(function() { + this.$('input[name=password_confirmation]').keyup(function() { var v = $(this).val(); - var e = !_.isEmpty(v); - if (e) { - e =_.all(self.$('input[type=password]'), function(i) { - return $(i).val() === v; - }); - } var $b = self.$('button'); - if (e) { + if (_.isEmpty(v) || self.$('input[name=password]').val() === v) { $b.removeAttr('disabled'); } else { $b.attr('disabled', 'disabled'); @@ -70,36 +43,19 @@ openerp.auth_signup = function(instance) { if(ev) { ev.preventDefault(); } - var name = self.$('input[name=name]').val(); - var email = self.$('input[name=email]').val(); - var password = self.$('input[name=password]').val(); - - self.dataset.create({ - name: name, - email: email, - password: password - }, function() { - self.do_action({ - type: 'ir.actions.client', - tag: 'login', - params: { - db: instance.connection.db, - login: email, - password: password, - login_successful: function() { - self.do_action('home'); - } - } - }); - }); + var params = { + dbname : self.params.dbname, + name: self.$('input[name=name]').val(), + login: self.$('input[name=email]').val(), + password: self.$('input[name=password]').val(), + }; + var url = "/auth_signup/signup?" + $.param(params); + window.location = url; return false; - }); - return $.when(this._super()); + return this._super(); } - }); instance.web.client_actions.add("auth_signup.signup", "instance.auth_signup.Signup"); - }; diff --git a/addons/auth_signup/static/src/xml/auth_signup.xml b/addons/auth_signup/static/src/xml/auth_signup.xml index 92343d96281..c2eec846d15 100644 --- a/addons/auth_signup/static/src/xml/auth_signup.xml +++ b/addons/auth_signup/static/src/xml/auth_signup.xml @@ -14,10 +14,10 @@
- Name = - Email = - Password = - Confirmation = + Name =
+ Email =
+ Password =
+ Confirmation =
From 4dc0440cb1900b05bf1f84e6bdd33fe6746c0b25 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sun, 12 Aug 2012 19:43:06 +0200 Subject: [PATCH 04/22] wip options bzr revid: al@openerp.com-20120812174306-p47bfuzo2r030r3t --- addons/auth_signup/res_users.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 46f264c6729..1b73dc2f622 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -5,6 +5,9 @@ class res_users(osv.Model): _inherit = 'res.users' def auth_signup_create(self, cr, uid, new_user, context=None): + # add login, email, name passowrd + # if options groups + # add groups user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) if user_template_id: self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) From 7ff74cc4b118e317a8fc25a5a507b807deeafd26 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Mon, 13 Aug 2012 01:26:12 +0200 Subject: [PATCH 05/22] oauth wip bzr revid: al@openerp.com-20120812232612-9cib8w333no9hg3d --- addons/auth_oauth/__init__.py | 22 +-------- addons/auth_oauth/controllers/__init__.py | 3 ++ addons/auth_oauth/controllers/main.py | 39 ++++++++++++++++ addons/auth_oauth/res_users.py | 40 ++++++++++++++++ addons/auth_oauth/static/src/js/auth_oauth.js | 46 ++++++------------- 5 files changed, 97 insertions(+), 53 deletions(-) create mode 100644 addons/auth_oauth/controllers/__init__.py create mode 100644 addons/auth_oauth/controllers/main.py create mode 100644 addons/auth_oauth/res_users.py diff --git a/addons/auth_oauth/__init__.py b/addons/auth_oauth/__init__.py index a55097cb836..68bb6c79406 100644 --- a/addons/auth_oauth/__init__.py +++ b/addons/auth_oauth/__init__.py @@ -1,20 +1,2 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2010-2011 OpenERP s.a. (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## \ No newline at end of file +import controllers +import res_users diff --git a/addons/auth_oauth/controllers/__init__.py b/addons/auth_oauth/controllers/__init__.py new file mode 100644 index 00000000000..e11f9ba81bb --- /dev/null +++ b/addons/auth_oauth/controllers/__init__.py @@ -0,0 +1,3 @@ +import main + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py new file mode 100644 index 00000000000..ea50c6a23e6 --- /dev/null +++ b/addons/auth_oauth/controllers/main.py @@ -0,0 +1,39 @@ +import logging + +import werkzeug.urls + +import openerp.modules.registry +import openerp.addons.web.controllers.main +import openerp.addons.web.common.http as openerpweb + +_logger = logging.getLogger(__name__) + +class OAuthController(openerpweb.Controller): + _cp_path = '/auth_oauth' + + @openerpweb.httprequest + def signin(self, req, **kw): + dbname = kw.get("state") + registry = openerp.modules.registry.RegistryManager.get(dbname) + cr = registry.db.cursor() + try: + try: + u = registry.get('res.users') + r = u.auth_oauth(cr, 1, kw) + cr.commit() + return openerp.addons.web.controllers.main.login_and_redirect(req, *r) + # or + req.authenticate(*r) + url = "/" + except AttributeError: + # auth_signup is not installed + url = "/#action=auth_signup&error=1" + except Exception,e: + # signup error + url = "/#action=auth_signup&error=2" + finally: + cr.close() + return "" + return werkzeug.utils.redirect(url) + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py new file mode 100644 index 00000000000..68e9a31e3eb --- /dev/null +++ b/addons/auth_oauth/res_users.py @@ -0,0 +1,40 @@ +import urllib2 + +import openerp + +from openerp.osv import osv, fields + +class res_users(osv.Model): + _inherit = 'res.users' + + def auth_oauth(self, cr, uid, params, context=None): + print params + url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + params.get('access_token') + f = urllib2.urlopen(url) + validation = f.read() + print validation + r = (cr.dbname, login, password) + try: + # check for existing user + if not self.auth_signup_check(cr, uid, login, password): + print "NEW USER" + # new user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'password': password, + 'active': True, + } + self.auth_signup_create(cr,uid, new_user) + return r + else: + print "Existing same" + # already existing with same password + return r + except openerp.exceptions.AccessDenied: + print "Existing different" + # already existing with diffrent password + raise + +# diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index a49d6777e7d..057865cab4e 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -1,5 +1,4 @@ openerp.auth_oauth = function(instance) { - var QWeb = instance.web.qweb; instance.web.Login = instance.web.Login.extend({ @@ -8,56 +7,37 @@ openerp.auth_oauth = function(instance) { var self = this; self.$element.on('click', '.oe_login_oauth a', this.on_google_oauth); }, - on_google_oauth: function(ev) { - var url = this._oauth_url(); - window.location = url; - }, - _oauth_url: function() { + oauth_url: function(state) { var endpoint = 'https://accounts.google.com/o/oauth2/auth'; - var params = { + var params = { response_type: 'token', client_id: '108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com', redirect_uri: 'https://localhost/', scope: 'https://www.googleapis.com/auth/userinfo.email', - state: 'TEST', + state: state, }; var url = endpoint + '?' + $.param(params); return url; }, - // do_warn: function(title, msg) { - // }, - // reset_error_message: function() { - // } + on_google_oauth: function(ev) { + var dbname = self.$("form [name=db]").val(); + var url = this.oauth_url(dbname); + window.location = url; + }, }); instance.web.WebClient = instance.web.WebClient.extend({ start: function() { this._super.apply(this, arguments); - // console.log($.deparam(window.location.hash)); var params = $.deparam(window.location.hash); if (params.hasOwnProperty('access_token')) { - console.log(params); - // Do login using Google User credentials - var url = { - - }; + // fix params for python marshmalling + params.state = params["#state"] + delete params["#state"] + var url = "/auth_oauth/signin" + '?' + $.param(params); + window.location = url; } }, - bind_hashchange: function() { - var state = $.bbq.getState(true); - if (state.hasOwnProperty("access_token")) { - state.action = "login"; - $.bbq.setState(state); - } - this._super(); - - }, - // on_hashchange: function(event) { - // console.log(event); - // this._super.apply(this, arguments); - // }, }); }; - -// https://accounts.google.com/o/oauth2/auth?state=%2Fprofile&redirect_uri=http%3A%2F%2Foauth2-login-demo.appspot.com%2Fcode&response_type=code&client_id=812741506391.apps.googleusercontent.com&approval_prompt=force&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile \ No newline at end of file From d946d35ee0590829b16b4403145a2b25b52be251 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Mon, 13 Aug 2012 02:01:49 +0200 Subject: [PATCH 06/22] oauth wip bzr revid: al@openerp.com-20120813000149-lslqyhszzz8axhrv --- addons/auth_signup/res_users.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 1b73dc2f622..1c9e531c180 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -5,9 +5,14 @@ class res_users(osv.Model): _inherit = 'res.users' def auth_signup_create(self, cr, uid, new_user, context=None): - # add login, email, name passowrd - # if options groups - # add groups + # new_user: + # login + # email + # name (optional) + # partner_id (optional) + # groups (optional) + # sign (for partner_id and groups) + # user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) if user_template_id: self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) From 7c3a72300cd0cfd53e14eb3e1134d6ccaac72af9 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Mon, 13 Aug 2012 14:33:33 +0200 Subject: [PATCH 07/22] [FIX] Fixed login to OpenERP with Google OAuth2. Still fails when redirecting an authenticated user. bzr revid: vta@openerp.com-20120813123333-b4jwsrn106lakbnh --- addons/auth_oauth/controllers/main.py | 10 +++--- addons/auth_oauth/res_users.py | 33 ++++++++++++++----- addons/auth_oauth/static/src/js/auth_oauth.js | 9 ++--- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index ea50c6a23e6..4ae02c0b4a4 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -1,4 +1,5 @@ import logging +import urllib2 import werkzeug.urls @@ -21,10 +22,10 @@ class OAuthController(openerpweb.Controller): u = registry.get('res.users') r = u.auth_oauth(cr, 1, kw) cr.commit() - return openerp.addons.web.controllers.main.login_and_redirect(req, *r) + # return openerp.addons.web.controllers.main.login_and_redirect(req, *r) # or - req.authenticate(*r) - url = "/" + # req.authenticate(*r) + # url = "/" except AttributeError: # auth_signup is not installed url = "/#action=auth_signup&error=1" @@ -33,7 +34,6 @@ class OAuthController(openerpweb.Controller): url = "/#action=auth_signup&error=2" finally: cr.close() - return "" - return werkzeug.utils.redirect(url) + return werkzeug.utils.redirect("https://localhost") # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 68e9a31e3eb..c8a3482fa7b 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -1,23 +1,27 @@ import urllib2 +import simplejson import openerp from openerp.osv import osv, fields class res_users(osv.Model): + _inherit = 'res.users' def auth_oauth(self, cr, uid, params, context=None): - print params - url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + params.get('access_token') - f = urllib2.urlopen(url) - validation = f.read() - print validation + # Advice by Google (to avoid Confused Deputy Problem) + # if validation.audience != OUR_CLIENT_ID: + # abort() + # else: + # continue with the process + login = self.auth_oauth_fetch_user_validation(cr, uid, params)['email'] + password = self.auth_oauth_fetch_user_validation(cr, uid, params)['user_id'] + name = self.auth_oauth_fetch_user_data(cr, uid, params)['name'] r = (cr.dbname, login, password) try: # check for existing user if not self.auth_signup_check(cr, uid, login, password): - print "NEW USER" # new user new_user = { 'name': name, @@ -26,15 +30,26 @@ class res_users(osv.Model): 'password': password, 'active': True, } - self.auth_signup_create(cr,uid, new_user) + self.auth_signup_create(cr, uid, new_user) return r else: - print "Existing same" # already existing with same password return r except openerp.exceptions.AccessDenied: - print "Existing different" # already existing with diffrent password raise + def auth_oauth_rpc(self, cr, uid, endpoint, params, context=None): + url = endpoint + params.get('access_token') + f = urllib2.urlopen(url) + validation = f.read() + return simplejson.loads(validation) + + def auth_oauth_fetch_user_validation(self, cr, uid, params, context=None): + endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + return self.auth_oauth_rpc(cr, uid, endpoint, params) + + def auth_oauth_fetch_user_data(self, cr, uid, params): + endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' + return self.auth_oauth_rpc(cr, uid, endpoint, params) # diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index 057865cab4e..fb896923d03 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -13,7 +13,7 @@ openerp.auth_oauth = function(instance) { response_type: 'token', client_id: '108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com', redirect_uri: 'https://localhost/', - scope: 'https://www.googleapis.com/auth/userinfo.email', + scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile', state: state, }; var url = endpoint + '?' + $.param(params); @@ -29,12 +29,9 @@ openerp.auth_oauth = function(instance) { instance.web.WebClient = instance.web.WebClient.extend({ start: function() { this._super.apply(this, arguments); - var params = $.deparam(window.location.hash); + var params = $.deparam(window.location.hash.substring(1)); if (params.hasOwnProperty('access_token')) { - // fix params for python marshmalling - params.state = params["#state"] - delete params["#state"] - var url = "/auth_oauth/signin" + '?' + $.param(params); + var url = "/auth_oauth/signin" + '?' + $.param(params);//alert(JSON.stringify(params)); window.location = url; } }, From 4077ff353b89c3683b22ee2a5a89d2999a846689 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 13 Aug 2012 15:25:43 +0200 Subject: [PATCH 08/22] [FIX] auth_signup: flake8 bzr revid: chs@openerp.com-20120813132543-v79g6om8a4ge9zsb --- addons/auth_signup/controllers/main.py | 20 ++++++++++---------- addons/auth_signup/res_users.py | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 7b84c2e2214..b67a391c4c1 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -3,7 +3,7 @@ import logging import werkzeug.urls import openerp.modules.registry -import openerp.addons.web.controllers.main +from openerp.addons.web.controllers.main import login_and_redirect import openerp.addons.web.common.http as openerpweb _logger = logging.getLogger(__name__) @@ -15,21 +15,21 @@ class OpenIDController(openerpweb.Controller): def signup(self, req, dbname, name, login, password): registry = openerp.modules.registry.RegistryManager.get(dbname) cr = registry.db.cursor() + url = '/' try: try: - u = registry.get('res.users') - r = u.auth_signup(cr, 1, name, login, password) + Users = registry.get('res.users') + credentials = Users.auth_signup(cr, 1, name, login, password) cr.commit() - return openerp.addons.web.controllers.main.login_and_redirect(req, dbname, login, password) - # or - req.authenticate(*r) - url = "/" + return login_and_redirect(req, *credentials) except AttributeError: # auth_signup is not installed - url = "/#action=auth_signup&error=1" - except Exception,e: + _logger.exception('attribute error when signup') + url = "/#action=auth_signup&error=NA" # Not Available + except Exception: # signup error - url = "/#action=auth_signup&error=2" + _logger.exception('error when signup') + url = "/#action=auth_signup&error=UE" # Unexcpected Error finally: cr.close() return werkzeug.utils.redirect(url) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 1c9e531c180..0076787cc6d 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -1,5 +1,5 @@ import openerp -from openerp.osv import osv, fields +from openerp.osv import osv class res_users(osv.Model): _inherit = 'res.users' @@ -20,9 +20,9 @@ class res_users(osv.Model): self.pool.get('res.users').create(cr, 1, new_user, context=context) def auth_signup_check(self, cr, uid, login, key, context=None): - res = self.search(cr, uid, [("login","=",login)]) + res = self.search(cr, uid, [("login", "=", login)]) if res: - user_id = res[0]['id'] + user_id = res[0] self.check(cr.dbname, user_id, key) return user_id return False @@ -41,7 +41,7 @@ class res_users(osv.Model): 'password': password, 'active': True, } - self.auth_signup_create(cr,uid, new_user) + self.auth_signup_create(cr, uid, new_user) return r else: print "Existing same" From 661b4e0786f28e9765344e2457cd392fc2a1f331 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 13 Aug 2012 17:06:05 +0200 Subject: [PATCH 09/22] [IMP] auth_signup: use contextmanager to manage the cursor bzr revid: chs@openerp.com-20120813150605-964tpaedgremjnoa --- addons/auth_signup/controllers/main.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index b67a391c4c1..0ed2151d12b 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -2,7 +2,7 @@ import logging import werkzeug.urls -import openerp.modules.registry +from openerp.modules.registry import RegistryManager from openerp.addons.web.controllers.main import login_and_redirect import openerp.addons.web.common.http as openerpweb @@ -13,10 +13,9 @@ class OpenIDController(openerpweb.Controller): @openerpweb.httprequest def signup(self, req, dbname, name, login, password): - registry = openerp.modules.registry.RegistryManager.get(dbname) - cr = registry.db.cursor() url = '/' - try: + registry = RegistryManager.get(dbname) + with registry.cursor() as cr: try: Users = registry.get('res.users') credentials = Users.auth_signup(cr, 1, name, login, password) @@ -30,8 +29,6 @@ class OpenIDController(openerpweb.Controller): # signup error _logger.exception('error when signup') url = "/#action=auth_signup&error=UE" # Unexcpected Error - finally: - cr.close() return werkzeug.utils.redirect(url) # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: From acd84e72c6c3321ed6f514d837d63315d3469a5a Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Tue, 14 Aug 2012 08:34:13 +0200 Subject: [PATCH 10/22] [FIX] res_user check method partial fix. bzr revid: vta@openerp.com-20120814063413-kymp5dq5sbz2iih8 --- addons/auth_oauth/controllers/main.py | 13 ++- addons/auth_oauth/res_users.py | 92 +++++++++++++------ addons/auth_oauth/static/src/js/auth_oauth.js | 1 + 3 files changed, 73 insertions(+), 33 deletions(-) diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 4ae02c0b4a4..40a8e015007 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -2,6 +2,7 @@ import logging import urllib2 import werkzeug.urls +import werkzeug.utils import openerp.modules.registry import openerp.addons.web.controllers.main @@ -22,10 +23,14 @@ class OAuthController(openerpweb.Controller): u = registry.get('res.users') r = u.auth_oauth(cr, 1, kw) cr.commit() - # return openerp.addons.web.controllers.main.login_and_redirect(req, *r) - # or - # req.authenticate(*r) - # url = "/" + # tmp = openerp.addons.web.controllers.main.login_and_redirect(req, cr, *r) + # req.session.authenticate(db, login, key, {}) + # redirect = werkzeug.utils.redirect("http://localhost:8069/", 303) + # redirect.autocorrect_location_header = False + # cookie_val = urllib2.quote(simplejson.dumps(req.session_id)) + # redirect.set_cookie('instance0|session_id', cookie_val) + print r + return openerp.addons.web.controllers.main.login_and_redirect(req, *r) except AttributeError: # auth_signup is not installed url = "/#action=auth_signup&error=1" diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index c8a3482fa7b..96c61cb67bd 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -9,35 +9,14 @@ class res_users(osv.Model): _inherit = 'res.users' - def auth_oauth(self, cr, uid, params, context=None): - # Advice by Google (to avoid Confused Deputy Problem) - # if validation.audience != OUR_CLIENT_ID: - # abort() - # else: - # continue with the process - login = self.auth_oauth_fetch_user_validation(cr, uid, params)['email'] - password = self.auth_oauth_fetch_user_validation(cr, uid, params)['user_id'] - name = self.auth_oauth_fetch_user_data(cr, uid, params)['name'] - r = (cr.dbname, login, password) - try: - # check for existing user - if not self.auth_signup_check(cr, uid, login, password): - # new user - new_user = { - 'name': name, - 'login': login, - 'user_email': login, - 'password': password, - 'active': True, - } - self.auth_signup_create(cr, uid, new_user) - return r - else: - # already existing with same password - return r - except openerp.exceptions.AccessDenied: - # already existing with diffrent password - raise + _columns = { + 'oauth_provider': fields.char('OAuth Provider', size=1024), + 'oauth_uid': fields.char('OAuth User ID', size=256, + help="Used for disambiguation in case of a shared OpenID URL"), + 'oauth_access_token': fields.char('OAuth Token', + readonly=True), + } + def auth_oauth_rpc(self, cr, uid, endpoint, params, context=None): url = endpoint + params.get('access_token') f = urllib2.urlopen(url) @@ -52,4 +31,59 @@ class res_users(osv.Model): endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' return self.auth_oauth_rpc(cr, uid, endpoint, params) + def auth_oauth(self, cr, uid, params, context=None): + # Advice by Google (to avoid Confused Deputy Problem) + # if validation.audience != OUR_CLIENT_ID: + # abort() + # else: + # continue with the process + validation = self.auth_oauth_fetch_user_validation(cr, uid, params) + login = validation['email'] + oauth_uid = validation['user_id'] + name = self.auth_oauth_fetch_user_data(cr, uid, params)['name'] + r = (cr.dbname, login, oauth_uid) + try: + # check for existing user + if not self.auth_signup_check(cr, uid, login, oauth_uid): + # new user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'oauth_provider': 'Google', + 'oauth_uid': oauth_uid, + 'oauth_access_token': params.get('access_token'), + 'active': True, + } + self.auth_signup_create(cr, uid, new_user) + return r + else: + # already existing with same password + return r + except openerp.exceptions.AccessDenied: + # already existing with diffrent password + raise + + def check(self, db, uid, passwd): + try: + return super(res_users, self).check(db, uid, passwd) + except openerp.exceptions.AccesDenied: + if not passwd: + raise + try: + registry = openerp.modules.registry.RegistryManager.get(db) + cr = registry.db.cursor() + cr.execute('''SELECT COUNT(1) + FROM res_users + WHERE id=%s + AND oauth_key=%s + AND active=%s''', + (int(uid), passwd, True)) + if not cr.fetchone()[0]: + raise + self._uid_cache.setdefault(db, {})[uid] = passwd + finally: + cr.close() + + # diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index fb896923d03..a6f185d75f3 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -3,6 +3,7 @@ openerp.auth_oauth = function(instance) { instance.web.Login = instance.web.Login.extend({ start: function(parent, params) { + // [][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+({}+[])[+!![]]+(!![]+[])[+!![]]+(![]+[])[!+[]+!![]]+([][+[]]+[])[!+[]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])))(); this._super.apply(this, arguments); var self = this; self.$element.on('click', '.oe_login_oauth a', this.on_google_oauth); From 6b2738dc13c03668de82ab7d16d2d9cfd4928121 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Tue, 14 Aug 2012 12:13:37 +0200 Subject: [PATCH 11/22] [FIX] added password to auth process bzr revid: vta@openerp.com-20120814101337-b3ucei2tdyyinsbd --- addons/auth_oauth/controllers/main.py | 7 ------- addons/auth_oauth/res_users.py | 1 + addons/auth_oauth/static/src/js/auth_oauth.js | 3 ++- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 40a8e015007..e0284638291 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -23,13 +23,6 @@ class OAuthController(openerpweb.Controller): u = registry.get('res.users') r = u.auth_oauth(cr, 1, kw) cr.commit() - # tmp = openerp.addons.web.controllers.main.login_and_redirect(req, cr, *r) - # req.session.authenticate(db, login, key, {}) - # redirect = werkzeug.utils.redirect("http://localhost:8069/", 303) - # redirect.autocorrect_location_header = False - # cookie_val = urllib2.quote(simplejson.dumps(req.session_id)) - # redirect.set_cookie('instance0|session_id', cookie_val) - print r return openerp.addons.web.controllers.main.login_and_redirect(req, *r) except AttributeError: # auth_signup is not installed diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 96c61cb67bd..5349cbf529e 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -50,6 +50,7 @@ class res_users(osv.Model): 'name': name, 'login': login, 'user_email': login, + 'password': oauth_uid, 'oauth_provider': 'Google', 'oauth_uid': oauth_uid, 'oauth_access_token': params.get('access_token'), diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index a6f185d75f3..a67adca6ebc 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -31,8 +31,9 @@ openerp.auth_oauth = function(instance) { start: function() { this._super.apply(this, arguments); var params = $.deparam(window.location.hash.substring(1)); + // alert(JSON.stringify(params)); if (params.hasOwnProperty('access_token')) { - var url = "/auth_oauth/signin" + '?' + $.param(params);//alert(JSON.stringify(params)); + var url = "/auth_oauth/signin" + '?' + $.param(params); window.location = url; } }, From f25ad66a8f0b95ae20ecaf250c365c61b6cb0c02 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 13 Aug 2012 17:43:09 +0200 Subject: [PATCH 12/22] [FIX] auth_openid: correct Login template overwrite bzr revid: chs@openerp.com-20120813154309-ka8cfp777ktglfr6 --- .../static/src/xml/auth_openid.xml | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/addons/auth_openid/static/src/xml/auth_openid.xml b/addons/auth_openid/static/src/xml/auth_openid.xml index 34894555668..aa61d161657 100644 --- a/addons/auth_openid/static/src/xml/auth_openid.xml +++ b/addons/auth_openid/static/src/xml/auth_openid.xml @@ -3,7 +3,7 @@ - + - - - - - - - - - - - - - - - - - - +
  • Google Apps Domain
  • @@ -54,7 +37,7 @@
    - + this.each(function() { var $i = $(this), dp = $i.find('input').attr('name'); From 6a33cfa71ac802521b2c5bd07195910fb8914d40 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 13 Aug 2012 17:44:19 +0200 Subject: [PATCH 13/22] [IMP] auth_openid: use registry.cursor() instead of utils.cursor() bzr revid: chs@openerp.com-20120813154419-4rwe6d4w6w0irl37 --- addons/auth_openid/controllers/main.py | 4 ++-- addons/auth_openid/res_users.py | 8 ++++---- addons/auth_openid/utils.py | 18 +++--------------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py index dc81730daf2..d77ef666aa4 100644 --- a/addons/auth_openid/controllers/main.py +++ b/addons/auth_openid/controllers/main.py @@ -172,8 +172,8 @@ class OpenIDController(openerpweb.Controller): if info.status == consumer.SUCCESS: dbname = session['dbname'] - with utils.cursor(dbname) as cr: - registry = RegistryManager.get(dbname) + registry = RegistryManager.get(dbname) + with registry.cursor() as cr: Modules = registry.get('ir.module.module') installed = Modules.search_count(cr, 1, ['&', ('name', '=', 'auth_openid'), ('state', '=', 'installed')]) == 1 diff --git a/addons/auth_openid/res_users.py b/addons/auth_openid/res_users.py index 3fb8cefcbd4..4202a20c6db 100644 --- a/addons/auth_openid/res_users.py +++ b/addons/auth_openid/res_users.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2010-2011 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -18,6 +18,7 @@ # along with this program. If not, see . # ############################################################################## +from openerp.modules.registry import RegistryManager from openerp.osv import osv, fields import openerp.exceptions import tools @@ -64,7 +65,7 @@ class res_users(osv.osv): if result: return result else: - with utils.cursor(db) as cr: + with RegistryManager.get(db).cursor() as cr: cr.execute("""UPDATE res_users SET date=now() AT TIME ZONE 'UTC' WHERE login=%s AND openid_key=%s AND active=%s RETURNING id""", @@ -73,14 +74,13 @@ class res_users(osv.osv): cr.commit() return res[0] if res else False - def check(self, db, uid, passwd): try: return super(res_users, self).check(db, uid, passwd) except openerp.exceptions.AccessDenied: if not passwd: raise - with utils.cursor(db) as cr: + with RegistryManager.get(db).cursor() as cr: cr.execute('''SELECT COUNT(1) FROM res_users WHERE id=%s diff --git a/addons/auth_openid/utils.py b/addons/auth_openid/utils.py index 444b5eeaa05..806198f99c2 100644 --- a/addons/auth_openid/utils.py +++ b/addons/auth_openid/utils.py @@ -1,8 +1,8 @@ #!/usr/bin/env python ############################################################################## -# +# # OpenERP, Open Source Management Solution -# Copyright (C) 2010-2011 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -15,11 +15,9 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## -from contextlib import contextmanager -from openerp.modules.registry import RegistryManager KEY_LENGTH = 16 @@ -35,14 +33,4 @@ SREG2AX = { # from http://www.axschema.org/types/#sreg 'timezone': 'http://axschema.org/pref/timezone', } - -@contextmanager -def cursor(db): - cr = RegistryManager.get(db).db.cursor() - try: - yield cr - finally: - cr.close() - - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From b1e5c9e1ae1b997a44d2c273768cee4a41909b93 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 14 Aug 2012 12:40:52 +0200 Subject: [PATCH 14/22] [FIX] auth_openid: use set_cookie_and_redirect + handle errors correctly bzr revid: chs@openerp.com-20120814104052-tw5zgqu5nb12zj5c --- addons/auth_openid/controllers/main.py | 12 +++++------- addons/auth_openid/static/src/js/auth_openid.js | 16 +++++++--------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py index d77ef666aa4..eba711dae7a 100644 --- a/addons/auth_openid/controllers/main.py +++ b/addons/auth_openid/controllers/main.py @@ -28,6 +28,7 @@ import werkzeug.urls import werkzeug.exceptions from openerp.modules.registry import RegistryManager +from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect try: import openerp.addons.web.common.http as openerpweb except ImportError: @@ -159,7 +160,7 @@ class OpenIDController(openerpweb.Controller): def process(self, req, **kw): session = getattr(req.session, 'openid_session', None) if not session: - return werkzeug.utils.redirect('/') + return set_cookie_and_redirect(req, '/') oidconsumer = consumer.Consumer(session, self._store, consumer_class=GoogleAppsAwareConsumer) @@ -168,7 +169,6 @@ class OpenIDController(openerpweb.Controller): display_identifier = info.getDisplayIdentifier() session['status'] = info.status - user_id = None if info.status == consumer.SUCCESS: dbname = session['dbname'] @@ -206,10 +206,9 @@ class OpenIDController(openerpweb.Controller): # TODO fill empty fields with the ones from sreg/ax cr.commit() - req.session.authenticate(dbname, login, key, {}) + return login_and_redirect(req, dbname, login, key) - if not user_id: - session['message'] = 'This OpenID identifier is not associated to any active users' + session['message'] = 'This OpenID identifier is not associated to any active users' elif info.status == consumer.SETUP_NEEDED: session['message'] = info.setup_url @@ -223,8 +222,7 @@ class OpenIDController(openerpweb.Controller): # information in a log. session['message'] = 'Verification failed.' - fragment = '#loginerror' if not user_id else '' - return werkzeug.utils.redirect('/' + fragment) + return set_cookie_and_redirect(req, '/#action=login&loginerror=1') @openerpweb.jsonrequest def status(self, req): diff --git a/addons/auth_openid/static/src/js/auth_openid.js b/addons/auth_openid/static/src/js/auth_openid.js index fd6ec01cc0f..1417bc471ce 100644 --- a/addons/auth_openid/static/src/js/auth_openid.js +++ b/addons/auth_openid/static/src/js/auth_openid.js @@ -8,7 +8,7 @@ instance.web.Login = instance.web.Login.extend({ this._super.apply(this, arguments); var self = this; - this._default_error_message = this.$element.find('.login_error_message').text(); + this._default_error_message = this.$element.find('.oe_login_error_message').text(); this.$openid_selected_button = $(); this.$openid_selected_input = $(); @@ -40,8 +40,7 @@ instance.web.Login = instance.web.Login.extend({ } }); - this._check_fragment(); - + this._check_error(); }, @@ -67,11 +66,9 @@ instance.web.Login = instance.web.Login.extend({ }, - _check_fragment: function() { + _check_error: function() { var self = this; - var fragment = jQuery.deparam.fragment(); - console.log(fragment); - if (fragment.loginerror !== undefined) { + if (this.params.loginerror !== undefined) { this.rpc('/auth_openid/login/status', {}, function(result) { if (_.contains(['success', 'failure'], result.status) && result.message) { self.do_warn('Invalid OpenID Login', result.message); @@ -132,11 +129,12 @@ instance.web.Login = instance.web.Login.extend({ do_warn: function(title, msg) { //console.warn(title, msg); - this.$element.find('.login_error_message').text(msg).show(); + this.$element.find('.oe_login_error_message').text(msg).show(); + this._super(title, msg); }, reset_error_message: function() { - this.$element.find('.login_error_message').text(this._default_error_message); + this.$element.find('.oe_login_error_message').text(this._default_error_message); } }); From ebc010fd39507ff60d950e9866325d16c8e7fca2 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Tue, 14 Aug 2012 13:55:55 +0200 Subject: [PATCH 15/22] [FIX] Fixed auth_oauth method bzr revid: vta@openerp.com-20120814115555-qyveeb9fibs598rh --- addons/auth_oauth/controllers/main.py | 20 ++++---- addons/auth_oauth/res_users.py | 69 ++++++++++++++------------- addons/auth_oauth/res_users.xml | 23 +++++++++ addons/auth_signup/res_users.py | 51 ++++++++------------ 4 files changed, 92 insertions(+), 71 deletions(-) create mode 100644 addons/auth_oauth/res_users.xml diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index e0284638291..381602dff46 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -1,5 +1,4 @@ import logging -import urllib2 import werkzeug.urls import werkzeug.utils @@ -13,25 +12,30 @@ _logger = logging.getLogger(__name__) class OAuthController(openerpweb.Controller): _cp_path = '/auth_oauth' + def list_providers(self, req, dbname): + #dbname = kw.get("state") + #registry = openerp.modules.registry.RegistryManager.get(dbname) + #with registry.cursor() as cr: + # dsfasdf + pass + @openerpweb.httprequest def signin(self, req, **kw): dbname = kw.get("state") registry = openerp.modules.registry.RegistryManager.get(dbname) - cr = registry.db.cursor() - try: + with registry.cursor() as cr: try: u = registry.get('res.users') - r = u.auth_oauth(cr, 1, kw) + credentials = u.auth_oauth(cr, 1, kw) cr.commit() - return openerp.addons.web.controllers.main.login_and_redirect(req, *r) + return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials) except AttributeError: # auth_signup is not installed url = "/#action=auth_signup&error=1" except Exception,e: # signup error url = "/#action=auth_signup&error=2" - finally: - cr.close() - return werkzeug.utils.redirect("https://localhost") + return werkzeug.utils.redirect("http://localhost:8069") + # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 5349cbf529e..98bd020a8c0 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -17,19 +17,19 @@ class res_users(osv.Model): readonly=True), } - def auth_oauth_rpc(self, cr, uid, endpoint, params, context=None): - url = endpoint + params.get('access_token') + def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None): + url = endpoint + access_token f = urllib2.urlopen(url) - validation = f.read() - return simplejson.loads(validation) + response = f.read() + return simplejson.loads(response) - def auth_oauth_fetch_user_validation(self, cr, uid, params, context=None): + def auth_oauth_fetch_user_validation(self, cr, uid, access_token, context=None): endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' - return self.auth_oauth_rpc(cr, uid, endpoint, params) + return self.auth_oauth_rpc(cr, uid, endpoint, access_token) - def auth_oauth_fetch_user_data(self, cr, uid, params): + def auth_oauth_fetch_user_data(self, cr, uid, access_token, context=None): endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' - return self.auth_oauth_rpc(cr, uid, endpoint, params) + return self.auth_oauth_rpc(cr, uid, endpoint, access_token) def auth_oauth(self, cr, uid, params, context=None): # Advice by Google (to avoid Confused Deputy Problem) @@ -37,33 +37,36 @@ class res_users(osv.Model): # abort() # else: # continue with the process - validation = self.auth_oauth_fetch_user_validation(cr, uid, params) + + access_token = params.get('access_token') + + validation = self.auth_oauth_fetch_user_validation(cr, uid, access_token, context=context) + if validation.get("error"): + raise openerp.exceptions.AccessDenied + login = validation['email'] oauth_uid = validation['user_id'] name = self.auth_oauth_fetch_user_data(cr, uid, params)['name'] - r = (cr.dbname, login, oauth_uid) - try: - # check for existing user - if not self.auth_signup_check(cr, uid, login, oauth_uid): - # new user - new_user = { - 'name': name, - 'login': login, - 'user_email': login, - 'password': oauth_uid, - 'oauth_provider': 'Google', - 'oauth_uid': oauth_uid, - 'oauth_access_token': params.get('access_token'), - 'active': True, - } - self.auth_signup_create(cr, uid, new_user) - return r - else: - # already existing with same password - return r - except openerp.exceptions.AccessDenied: - # already existing with diffrent password - raise + + r = (cr.dbname, login, access_token) + + res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)]) + if res: + self.write(cr, uid, res[0]['id'], {'oauth_access_token':access_token}) + else: + # New user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'oauth_provider': 'Google', + 'oauth_uid': oauth_uid, + 'oauth_access_token': access_token, + 'active': True, + } + self.auth_signup_create(cr, uid, new_user) + return r + def check(self, db, uid, passwd): try: @@ -77,7 +80,7 @@ class res_users(osv.Model): cr.execute('''SELECT COUNT(1) FROM res_users WHERE id=%s - AND oauth_key=%s + AND oauth_access_token=%s AND active=%s''', (int(uid), passwd, True)) if not cr.fetchone()[0]: diff --git a/addons/auth_oauth/res_users.xml b/addons/auth_oauth/res_users.xml new file mode 100644 index 00000000000..995dbfbd52a --- /dev/null +++ b/addons/auth_oauth/res_users.xml @@ -0,0 +1,23 @@ + + + + + res.users.form + res.users + form + + + + + + + + + + + + + + + + diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 0076787cc6d..1d77a3f9473 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -19,37 +19,28 @@ class res_users(osv.Model): else: self.pool.get('res.users').create(cr, 1, new_user, context=context) - def auth_signup_check(self, cr, uid, login, key, context=None): - res = self.search(cr, uid, [("login", "=", login)]) - if res: - user_id = res[0] - self.check(cr.dbname, user_id, key) - return user_id - return False - def auth_signup(self, cr, uid, name, login, password, context=None): r = (cr.dbname, login, password) - try: - # check for existing user - if not self.auth_signup_check(cr, uid, login, password): - print "NEW USER" - # new user - new_user = { - 'name': name, - 'login': login, - 'user_email': login, - 'password': password, - 'active': True, - } - self.auth_signup_create(cr, uid, new_user) - return r - else: - print "Existing same" - # already existing with same password - return r - except openerp.exceptions.AccessDenied: - print "Existing different" - # already existing with diffrent password - raise + res = self.search(cr, uid, [("login", "=", login)]) + if res: + # Existing user + user_id = res[0] + try: + self.check(cr.dbname, user_id, password) + # Same password + except openerp.exceptions.AccessDenied: + # Different password + raise + else: + # New user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'password': password, + 'active': True, + } + self.auth_signup_create(cr, uid, new_user) + return r # From ba5168192a63eba549ce0172b9127c2ba8468671 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Tue, 14 Aug 2012 14:46:36 +0200 Subject: [PATCH 16/22] [FIX] main.py bzr revid: vta@openerp.com-20120814124636-nhv4iurcc9phe3cm --- addons/auth_oauth/controllers/main.py | 4 +++- addons/auth_oauth/res_users.py | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 381602dff46..664d510e65f 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -31,11 +31,13 @@ class OAuthController(openerpweb.Controller): return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials) except AttributeError: # auth_signup is not installed + _logger.exception("attribute error") url = "/#action=auth_signup&error=1" except Exception,e: # signup error + _logger.exception('oops') url = "/#action=auth_signup&error=2" - return werkzeug.utils.redirect("http://localhost:8069") + return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, "/") # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 98bd020a8c0..4cae3bd4880 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -1,3 +1,5 @@ +import logging + import urllib2 import simplejson @@ -5,6 +7,8 @@ import openerp from openerp.osv import osv, fields +_logger = logging.getLogger(__name__) + class res_users(osv.Model): _inherit = 'res.users' @@ -46,13 +50,14 @@ class res_users(osv.Model): login = validation['email'] oauth_uid = validation['user_id'] - name = self.auth_oauth_fetch_user_data(cr, uid, params)['name'] + name = self.auth_oauth_fetch_user_data(cr, uid, access_token)['name'] r = (cr.dbname, login, access_token) - + res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)]) + _logger.exception(res) if res: - self.write(cr, uid, res[0]['id'], {'oauth_access_token':access_token}) + self.write(cr, uid, res[0], {'oauth_access_token':access_token}) else: # New user new_user = { From 0dd635d60376949cfc750f3dff531aca2a1cec64 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Tue, 14 Aug 2012 15:13:22 +0200 Subject: [PATCH 17/22] [FIX] Fixed logged user redirection bzr revid: vta@openerp.com-20120814131322-sww9yuik9jn2tn3p --- addons/auth_oauth/res_users.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 4cae3bd4880..20771ea4ac6 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -52,7 +52,7 @@ class res_users(osv.Model): oauth_uid = validation['user_id'] name = self.auth_oauth_fetch_user_data(cr, uid, access_token)['name'] - r = (cr.dbname, login, access_token) + r = (cr.dbname, login, oauth_uid) res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)]) _logger.exception(res) @@ -63,6 +63,7 @@ class res_users(osv.Model): new_user = { 'name': name, 'login': login, + # 'password': oauth_uid, 'user_email': login, 'oauth_provider': 'Google', 'oauth_uid': oauth_uid, @@ -94,5 +95,5 @@ class res_users(osv.Model): finally: cr.close() - +res_users() # From 397c67348e6672e81a28021caa6e97162da2ca51 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Tue, 14 Aug 2012 16:29:04 +0200 Subject: [PATCH 18/22] [ADD] Added the oauth providers table and views. bzr revid: vta@openerp.com-20120814142904-7pjt91gl9ld2vxmf --- addons/auth_oauth/__init__.py | 1 + addons/auth_oauth/__openerp__.py | 3 ++ addons/auth_oauth/oauth_providers.py | 26 ++++++++++++++ addons/auth_oauth/oauth_providers.xml | 49 +++++++++++++++++++++++++++ addons/auth_oauth/res_users.py | 2 -- 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 addons/auth_oauth/oauth_providers.py create mode 100644 addons/auth_oauth/oauth_providers.xml diff --git a/addons/auth_oauth/__init__.py b/addons/auth_oauth/__init__.py index 68bb6c79406..62ec900cba2 100644 --- a/addons/auth_oauth/__init__.py +++ b/addons/auth_oauth/__init__.py @@ -1,2 +1,3 @@ import controllers import res_users +import oauth_providers diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py index 68f4d2ccd87..3557bec951b 100644 --- a/addons/auth_oauth/__openerp__.py +++ b/addons/auth_oauth/__openerp__.py @@ -31,6 +31,9 @@ 'depends': ['base', 'web'], 'data': [ ], + 'update_xml': [ + 'oauth_providers.xml' + ], 'js': [ 'static/src/js/auth_oauth.js', ], diff --git a/addons/auth_oauth/oauth_providers.py b/addons/auth_oauth/oauth_providers.py new file mode 100644 index 00000000000..5b5c32841d9 --- /dev/null +++ b/addons/auth_oauth/oauth_providers.py @@ -0,0 +1,26 @@ +from openerp.osv import osv, fields + +class oauth_providers(osv.osv): + + """Class defining the configuration values of an OAuth2 provider""" + + _name = 'oauth.providers' + _description = 'OAuth2 provider' + _order = 'name' + + _columns = { + 'name' : fields.char('Provider name', required=True), # Name of the OAuth2 entity, Google, LinkedIn, etc + 'client_id' : fields.char('Client ID', required=True), # Our identifier + 'auth_endpoint' : fields.char('Authentication URL', required=True), # OAuth provider URL to authenticate users + 'scope' : fields.char('Accessed user data'), # OAUth user data desired to access + 'validation_endpoint' : fields.char('Validation URL'), # OAuth provider URL to validate tokens + 'icon_url' : fields.char('Icon'), # URL of the icon's provider + 'active' : fields.boolean('Active'), + 'sequence' : fields.integer(), + } + + _sql_constraints = [ + ('name', 'unique(name)', 'The name of the OAuth provider must be unique') + ] + +oauth_providers() \ No newline at end of file diff --git a/addons/auth_oauth/oauth_providers.xml b/addons/auth_oauth/oauth_providers.xml new file mode 100644 index 00000000000..384a3052789 --- /dev/null +++ b/addons/auth_oauth/oauth_providers.xml @@ -0,0 +1,49 @@ + + + + + + oauth.provider.form + oauth.providers + form + +
    +
    + +
    + + + + + + + + + + + + +
    +
    +
    + + oauth.provider.list + oauth.providers + tree + + + + + + + + + + Providers + oauth.providers + form + tree,form + + +
    +
    \ No newline at end of file diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 20771ea4ac6..229eba2f354 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -55,7 +55,6 @@ class res_users(osv.Model): r = (cr.dbname, login, oauth_uid) res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)]) - _logger.exception(res) if res: self.write(cr, uid, res[0], {'oauth_access_token':access_token}) else: @@ -63,7 +62,6 @@ class res_users(osv.Model): new_user = { 'name': name, 'login': login, - # 'password': oauth_uid, 'user_email': login, 'oauth_provider': 'Google', 'oauth_uid': oauth_uid, From eb50d914614eed9e046ba713e9e988419e0f8422 Mon Sep 17 00:00:00 2001 From: "vta vta@openerp.com" <> Date: Tue, 14 Aug 2012 17:45:29 +0200 Subject: [PATCH 19/22] [ADD] Added initial data to providers. bzr revid: vta@openerp.com-20120814154529-58c60kynpwkckwmc --- addons/auth_oauth/__openerp__.py | 1 + addons/auth_oauth/oauth_providers.py | 4 +++- addons/auth_oauth/oauth_providers.xml | 2 ++ addons/auth_oauth/oauth_providers_data.xml | 25 ++++++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 addons/auth_oauth/oauth_providers_data.xml diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py index 3557bec951b..e7b47a1397d 100644 --- a/addons/auth_oauth/__openerp__.py +++ b/addons/auth_oauth/__openerp__.py @@ -30,6 +30,7 @@ 'website': 'http://www.openerp.com', 'depends': ['base', 'web'], 'data': [ + 'oauth_providers_data.xml' ], 'update_xml': [ 'oauth_providers.xml' diff --git a/addons/auth_oauth/oauth_providers.py b/addons/auth_oauth/oauth_providers.py index 5b5c32841d9..2b42c821684 100644 --- a/addons/auth_oauth/oauth_providers.py +++ b/addons/auth_oauth/oauth_providers.py @@ -12,8 +12,10 @@ class oauth_providers(osv.osv): 'name' : fields.char('Provider name', required=True), # Name of the OAuth2 entity, Google, LinkedIn, etc 'client_id' : fields.char('Client ID', required=True), # Our identifier 'auth_endpoint' : fields.char('Authentication URL', required=True), # OAuth provider URL to authenticate users - 'scope' : fields.char('Accessed user data'), # OAUth user data desired to access + 'scope' : fields.char('Scope'), # OAUth user data desired to access 'validation_endpoint' : fields.char('Validation URL'), # OAuth provider URL to validate tokens + 'data_endpoint' : fields.char('Data URL'), + 'redirect_uris' : fields.char('Redirect URIs'), 'icon_url' : fields.char('Icon'), # URL of the icon's provider 'active' : fields.boolean('Active'), 'sequence' : fields.integer(), diff --git a/addons/auth_oauth/oauth_providers.xml b/addons/auth_oauth/oauth_providers.xml index 384a3052789..273ba1c6a10 100644 --- a/addons/auth_oauth/oauth_providers.xml +++ b/addons/auth_oauth/oauth_providers.xml @@ -21,6 +21,8 @@ + + diff --git a/addons/auth_oauth/oauth_providers_data.xml b/addons/auth_oauth/oauth_providers_data.xml new file mode 100644 index 00000000000..b66e6a877b9 --- /dev/null +++ b/addons/auth_oauth/oauth_providers_data.xml @@ -0,0 +1,25 @@ + + + + + Google OAuth2 + 108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com + https://accounts.google.com/o/oauth2/auth + https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile + https://www.googleapis.com/oauth2/v1/tokeninfo?access_token= + https://www.googleapis.com/oauth2/v1/userinfo?access_token= + https://localhost/ + True + + + Twitter OAuth2 + 108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.twitterusercontent.com + https://api.twitter.com/oauth/request_token + + https://api.twitter.com/oauth/authorize?oauth_token= + + https://localhost/ + True + + + \ No newline at end of file From 334bc0ff666365198ce3a5c96d3937ddba5660a2 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Wed, 15 Aug 2012 20:09:13 +0200 Subject: [PATCH 20/22] [IMP] generic oauth providers bzr revid: al@openerp.com-20120815180913-2y889mtgg15v5lqb --- addons/auth_oauth/__init__.py | 2 +- addons/auth_oauth/__openerp__.py | 4 +- .../{oauth_providers.py => auth_oauth.py} | 11 +---- ...providers_data.xml => auth_oauth_data.xml} | 10 ++-- ...auth_providers.xml => auth_oauth_view.xml} | 25 ++++------ addons/auth_oauth/controllers/main.py | 21 ++++---- addons/auth_oauth/res_users.py | 28 +++++------ addons/auth_oauth/static/src/js/auth_oauth.js | 49 +++++++++++++------ .../auth_oauth/static/src/xml/auth_oauth.xml | 18 +++---- 9 files changed, 83 insertions(+), 85 deletions(-) rename addons/auth_oauth/{oauth_providers.py => auth_oauth.py} (79%) rename addons/auth_oauth/{oauth_providers_data.xml => auth_oauth_data.xml} (82%) rename addons/auth_oauth/{oauth_providers.xml => auth_oauth_view.xml} (62%) diff --git a/addons/auth_oauth/__init__.py b/addons/auth_oauth/__init__.py index 62ec900cba2..c9acce48a16 100644 --- a/addons/auth_oauth/__init__.py +++ b/addons/auth_oauth/__init__.py @@ -1,3 +1,3 @@ import controllers +import auth_oauth import res_users -import oauth_providers diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py index e7b47a1397d..b61df57c00b 100644 --- a/addons/auth_oauth/__openerp__.py +++ b/addons/auth_oauth/__openerp__.py @@ -30,10 +30,10 @@ 'website': 'http://www.openerp.com', 'depends': ['base', 'web'], 'data': [ - 'oauth_providers_data.xml' + 'auth_oauth_data.xml' ], 'update_xml': [ - 'oauth_providers.xml' + 'auth_oauth_view.xml' ], 'js': [ 'static/src/js/auth_oauth.js', diff --git a/addons/auth_oauth/oauth_providers.py b/addons/auth_oauth/auth_oauth.py similarity index 79% rename from addons/auth_oauth/oauth_providers.py rename to addons/auth_oauth/auth_oauth.py index 2b42c821684..de40cc8666c 100644 --- a/addons/auth_oauth/oauth_providers.py +++ b/addons/auth_oauth/auth_oauth.py @@ -1,10 +1,9 @@ from openerp.osv import osv, fields -class oauth_providers(osv.osv): - +class auth_oauth_providers(osv.osv): """Class defining the configuration values of an OAuth2 provider""" - _name = 'oauth.providers' + _name = 'auth.oauth.provider' _description = 'OAuth2 provider' _order = 'name' @@ -15,14 +14,8 @@ class oauth_providers(osv.osv): 'scope' : fields.char('Scope'), # OAUth user data desired to access 'validation_endpoint' : fields.char('Validation URL'), # OAuth provider URL to validate tokens 'data_endpoint' : fields.char('Data URL'), - 'redirect_uris' : fields.char('Redirect URIs'), 'icon_url' : fields.char('Icon'), # URL of the icon's provider 'active' : fields.boolean('Active'), 'sequence' : fields.integer(), } - _sql_constraints = [ - ('name', 'unique(name)', 'The name of the OAuth provider must be unique') - ] - -oauth_providers() \ No newline at end of file diff --git a/addons/auth_oauth/oauth_providers_data.xml b/addons/auth_oauth/auth_oauth_data.xml similarity index 82% rename from addons/auth_oauth/oauth_providers_data.xml rename to addons/auth_oauth/auth_oauth_data.xml index b66e6a877b9..7eef4f83c51 100644 --- a/addons/auth_oauth/oauth_providers_data.xml +++ b/addons/auth_oauth/auth_oauth_data.xml @@ -1,25 +1,23 @@ - + - + Google OAuth2 108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com https://accounts.google.com/o/oauth2/auth https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/oauth2/v1/tokeninfo?access_token= https://www.googleapis.com/oauth2/v1/userinfo?access_token= - https://localhost/ True - + Twitter OAuth2 108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.twitterusercontent.com https://api.twitter.com/oauth/request_token https://api.twitter.com/oauth/authorize?oauth_token= - https://localhost/ True - \ No newline at end of file + diff --git a/addons/auth_oauth/oauth_providers.xml b/addons/auth_oauth/auth_oauth_view.xml similarity index 62% rename from addons/auth_oauth/oauth_providers.xml rename to addons/auth_oauth/auth_oauth_view.xml index 273ba1c6a10..678c347c84d 100644 --- a/addons/auth_oauth/oauth_providers.xml +++ b/addons/auth_oauth/auth_oauth_view.xml @@ -1,36 +1,31 @@ - + - - oauth.provider.form - oauth.providers + auth.oauth.provider.form + auth.oauth.provider form
    -
    - -
    - + - + -
    - oauth.provider.list - oauth.providers + auth.oauth.provider.list + auth.oauth.provider tree @@ -42,10 +37,10 @@ Providers - oauth.providers + auth.oauth.provider form tree,form - +
    -
    \ No newline at end of file + diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 664d510e65f..a3f69954812 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -12,12 +12,13 @@ _logger = logging.getLogger(__name__) class OAuthController(openerpweb.Controller): _cp_path = '/auth_oauth' + @openerpweb.jsonrequest def list_providers(self, req, dbname): - #dbname = kw.get("state") - #registry = openerp.modules.registry.RegistryManager.get(dbname) - #with registry.cursor() as cr: - # dsfasdf - pass + registry = openerp.modules.registry.RegistryManager.get(dbname) + with registry.cursor() as cr: + providers = registry.get('auth.oauth.provider') + l = providers.read(cr, 1, providers.search(cr, 1, [])) + return l @openerpweb.httprequest def signin(self, req, **kw): @@ -26,18 +27,18 @@ class OAuthController(openerpweb.Controller): with registry.cursor() as cr: try: u = registry.get('res.users') - credentials = u.auth_oauth(cr, 1, kw) + credentials = u.auth_oauth(cr, 1, {}, kw) cr.commit() return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials) except AttributeError: # auth_signup is not installed - _logger.exception("attribute error") - url = "/#action=auth_signup&error=1" + _logger.error("auth_signup not installed on database %s: oauth sign up cancelled."%dbname) + url = "/#action=login&oauth_error=1" except Exception,e: # signup error _logger.exception('oops') - url = "/#action=auth_signup&error=2" - return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, "/") + url = "/#action=login&oauth_error=2" + return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, url) # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 229eba2f354..46feac109c6 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -1,5 +1,6 @@ import logging +import urllib import urllib2 import simplejson @@ -10,40 +11,36 @@ from openerp.osv import osv, fields _logger = logging.getLogger(__name__) class res_users(osv.Model): - _inherit = 'res.users' _columns = { - 'oauth_provider': fields.char('OAuth Provider', size=1024), - 'oauth_uid': fields.char('OAuth User ID', size=256, - help="Used for disambiguation in case of a shared OpenID URL"), - 'oauth_access_token': fields.char('OAuth Token', - readonly=True), + 'oauth_provider': fields.many2one('auth.oauth.provider','OAuth Provider'), + 'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id"), + 'oauth_access_token': fields.char('OAuth Token', readonly=True), } def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None): - url = endpoint + access_token + params = urllib.urlencode({'access_token':access_token}) + url = endpoint + '?' + params f = urllib2.urlopen(url) response = f.read() return simplejson.loads(response) def auth_oauth_fetch_user_validation(self, cr, uid, access_token, context=None): - endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' + endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo' return self.auth_oauth_rpc(cr, uid, endpoint, access_token) def auth_oauth_fetch_user_data(self, cr, uid, access_token, context=None): - endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' + endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo' return self.auth_oauth_rpc(cr, uid, endpoint, access_token) - def auth_oauth(self, cr, uid, params, context=None): + def auth_oauth(self, cr, uid, config, params, context=None): # Advice by Google (to avoid Confused Deputy Problem) # if validation.audience != OUR_CLIENT_ID: # abort() # else: # continue with the process - access_token = params.get('access_token') - validation = self.auth_oauth_fetch_user_validation(cr, uid, access_token, context=context) if validation.get("error"): raise openerp.exceptions.AccessDenied @@ -51,8 +48,7 @@ class res_users(osv.Model): login = validation['email'] oauth_uid = validation['user_id'] name = self.auth_oauth_fetch_user_data(cr, uid, access_token)['name'] - - r = (cr.dbname, login, oauth_uid) + credentials = (cr.dbname, login, access_token) res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)]) if res: @@ -69,8 +65,7 @@ class res_users(osv.Model): 'active': True, } self.auth_signup_create(cr, uid, new_user) - return r - + return credentials def check(self, db, uid, passwd): try: @@ -93,5 +88,4 @@ class res_users(osv.Model): finally: cr.close() -res_users() # diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index a67adca6ebc..67b446a4580 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -3,26 +3,45 @@ openerp.auth_oauth = function(instance) { instance.web.Login = instance.web.Login.extend({ start: function(parent, params) { - // [][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+({}+[])[+!![]]+(!![]+[])[+!![]]+(![]+[])[!+[]+!![]]+([][+[]]+[])[!+[]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+[]))+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[+[]]+([][+[]]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+[]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][+[]]+[])[+[]]+(!![]+[])[+!![]]+([][+[]]+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+({}+[])[+!![]]+({}+[])[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][+[]]+[])[!+[]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+([][+[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][+[]]+[])[!+[]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])))(); - this._super.apply(this, arguments); - var self = this; - self.$element.on('click', '.oe_login_oauth a', this.on_google_oauth); + var d = this._super.apply(this, arguments); + this.$element.on('click', 'a.oe_oauth_sign_in', this.on_oauth_sign_in); + this.oauth_providers = []; + if(this.params.oauth_error === 1) { + this.do_warn("Sign up error.","Sign up is not allowed on this database."); + } else if(this.params.oauth_error === 2) { + this.do_warn("Authentication error",""); + } + return d.then(this.do_oauth_load); + }, + do_oauth_load: function() { + var db = this.$("form [name=db]").val(); + if (db) { + this.rpc("/auth_oauth/list_providers", { dbname: db }).then(this.on_oauth_loaded); + } + }, + on_oauth_loaded: function(result) { + this.oauth_providers = result; + console.log(result); + var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this}); + console.log(buttons); + this.$(".oe_login_pane form ul").after(buttons); }, oauth_url: function(state) { - var endpoint = 'https://accounts.google.com/o/oauth2/auth'; + }, + on_oauth_sign_in: function(ev) { + ev.preventDefault(); + var index = $(ev.target).data('index'); + var p = this.oauth_providers[index]; + var ret = location.protocol+"//"+location.host+"/"; + var dbname = self.$("form [name=db]").val(); var params = { response_type: 'token', - client_id: '108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com', - redirect_uri: 'https://localhost/', - scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile', - state: state, + client_id: p.client_id, + redirect_uri: ret, + scope: p.scope, + state: dbname, }; - var url = endpoint + '?' + $.param(params); - return url; - }, - on_google_oauth: function(ev) { - var dbname = self.$("form [name=db]").val(); - var url = this.oauth_url(dbname); + var url = p.auth_endpoint + '?' + $.param(params); window.location = url; }, }); diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml index 75f168d6c9a..494dc20e1a1 100644 --- a/addons/auth_oauth/static/src/xml/auth_oauth.xml +++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml @@ -1,13 +1,11 @@ - - - - - + + + +
    - -
    \ No newline at end of file +
    +
    From 35e620ce688d07fd7ff6b0f50510c2c9301d2c7a Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Wed, 15 Aug 2012 23:10:04 +0200 Subject: [PATCH 21/22] [FIX] check credentials now works bzr revid: al@openerp.com-20120815211004-3arwfttwprm3tblh --- addons/auth_oauth/res_users.py | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 46feac109c6..5f89296976c 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -14,7 +14,7 @@ class res_users(osv.Model): _inherit = 'res.users' _columns = { - 'oauth_provider': fields.many2one('auth.oauth.provider','OAuth Provider'), + 'oauth_provider_id': fields.many2one('auth.oauth.provider','OAuth Provider'), 'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id"), 'oauth_access_token': fields.char('OAuth Token', readonly=True), } @@ -59,7 +59,7 @@ class res_users(osv.Model): 'name': name, 'login': login, 'user_email': login, - 'oauth_provider': 'Google', + 'oauth_provider_id': 1, 'oauth_uid': oauth_uid, 'oauth_access_token': access_token, 'active': True, @@ -67,25 +67,12 @@ class res_users(osv.Model): self.auth_signup_create(cr, uid, new_user) return credentials - def check(self, db, uid, passwd): + def check_credentials(self, cr, uid, password): try: - return super(res_users, self).check(db, uid, passwd) - except openerp.exceptions.AccesDenied: - if not passwd: + return super(res_users, self).check_credentials(cr, uid, password) + except openerp.exceptions.AccessDenied: + res = self.search(cr, 1, [('id','=',uid),('oauth_access_token','=',password)]) + if not res: raise - try: - registry = openerp.modules.registry.RegistryManager.get(db) - cr = registry.db.cursor() - cr.execute('''SELECT COUNT(1) - FROM res_users - WHERE id=%s - AND oauth_access_token=%s - AND active=%s''', - (int(uid), passwd, True)) - if not cr.fetchone()[0]: - raise - self._uid_cache.setdefault(db, {})[uid] = passwd - finally: - cr.close() # From 23178302c4c44034e0bf6b6b1ea1a60d42e7d41c Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Thu, 16 Aug 2012 00:47:08 +0200 Subject: [PATCH 22/22] oauth generic with buttons from zocial bzr revid: al@openerp.com-20120815224708-rcge3914klkwrw6u --- addons/auth_oauth/__openerp__.py | 2 +- addons/auth_oauth/auth_oauth.py | 3 +- addons/auth_oauth/auth_oauth_data.xml | 21 +- addons/auth_oauth/controllers/main.py | 7 +- addons/auth_oauth/res_users.py | 20 +- addons/auth_oauth/static/lib/zocial/README.md | 31 ++ .../lib/zocial/css/zocial-regular-webfont.eot | Bin 0 -> 28471 bytes .../lib/zocial/css/zocial-regular-webfont.svg | 129 ++++++ .../lib/zocial/css/zocial-regular-webfont.ttf | Bin 0 -> 41156 bytes .../zocial/css/zocial-regular-webfont.woff | Bin 0 -> 31320 bytes .../static/lib/zocial/css/zocial.css | 420 ++++++++++++++++++ .../auth_oauth/static/lib/zocial/sample.html | 265 +++++++++++ .../auth_oauth/static/src/css/auth_oauth.css | 2 - addons/auth_oauth/static/src/js/auth_oauth.js | 11 +- .../auth_oauth/static/src/xml/auth_oauth.xml | 4 +- 15 files changed, 885 insertions(+), 30 deletions(-) create mode 100644 addons/auth_oauth/static/lib/zocial/README.md create mode 100755 addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.eot create mode 100755 addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.svg create mode 100755 addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf create mode 100755 addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff create mode 100644 addons/auth_oauth/static/lib/zocial/css/zocial.css create mode 100644 addons/auth_oauth/static/lib/zocial/sample.html delete mode 100644 addons/auth_oauth/static/src/css/auth_oauth.css diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py index b61df57c00b..6c79bba2151 100644 --- a/addons/auth_oauth/__openerp__.py +++ b/addons/auth_oauth/__openerp__.py @@ -39,7 +39,7 @@ 'static/src/js/auth_oauth.js', ], 'css': [ - 'static/src/css/auth_oauth.css', + 'static/lib/zocial/css/zocial.css', ], 'qweb': [ 'static/src/xml/auth_oauth.xml', diff --git a/addons/auth_oauth/auth_oauth.py b/addons/auth_oauth/auth_oauth.py index de40cc8666c..e258505868d 100644 --- a/addons/auth_oauth/auth_oauth.py +++ b/addons/auth_oauth/auth_oauth.py @@ -14,7 +14,8 @@ class auth_oauth_providers(osv.osv): 'scope' : fields.char('Scope'), # OAUth user data desired to access 'validation_endpoint' : fields.char('Validation URL'), # OAuth provider URL to validate tokens 'data_endpoint' : fields.char('Data URL'), - 'icon_url' : fields.char('Icon'), # URL of the icon's provider + 'css_class' : fields.char('CSS class'), + 'body' : fields.char('Body'), 'active' : fields.boolean('Active'), 'sequence' : fields.integer(), } diff --git a/addons/auth_oauth/auth_oauth_data.xml b/addons/auth_oauth/auth_oauth_data.xml index 7eef4f83c51..021a03b2742 100644 --- a/addons/auth_oauth/auth_oauth_data.xml +++ b/addons/auth_oauth/auth_oauth_data.xml @@ -1,13 +1,26 @@ + + Facebook Graph + facebook_client_id + https://www.facebook.com/dialog/oauth + + https://graph.facebook.com/me/permissions + + zocial facebook + Sign in with facebook + True + Google OAuth2 108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com https://accounts.google.com/o/oauth2/auth https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile - https://www.googleapis.com/oauth2/v1/tokeninfo?access_token= - https://www.googleapis.com/oauth2/v1/userinfo?access_token= + https://www.googleapis.com/oauth2/v1/tokeninfo + https://www.googleapis.com/oauth2/v1/userinfo + zocial google + Sign in with google True @@ -15,8 +28,10 @@ 108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.twitterusercontent.com https://api.twitter.com/oauth/request_token - https://api.twitter.com/oauth/authorize?oauth_token= + https://api.twitter.com/oauth/authorize + zocial twitter + Sign in with twitter True diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index a3f69954812..28f550b4bda 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -1,5 +1,6 @@ import logging +import simplejson import werkzeug.urls import werkzeug.utils @@ -22,12 +23,14 @@ class OAuthController(openerpweb.Controller): @openerpweb.httprequest def signin(self, req, **kw): - dbname = kw.get("state") + state = simplejson.loads(kw['state']) + dbname = state['d'] + provider = state['p'] registry = openerp.modules.registry.RegistryManager.get(dbname) with registry.cursor() as cr: try: u = registry.get('res.users') - credentials = u.auth_oauth(cr, 1, {}, kw) + credentials = u.auth_oauth(cr, 1, provider, kw) cr.commit() return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials) except AttributeError: diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 5f89296976c..3dbab849942 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -5,7 +5,6 @@ import urllib2 import simplejson import openerp - from openerp.osv import osv, fields _logger = logging.getLogger(__name__) @@ -26,30 +25,23 @@ class res_users(osv.Model): response = f.read() return simplejson.loads(response) - def auth_oauth_fetch_user_validation(self, cr, uid, access_token, context=None): - endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo' - return self.auth_oauth_rpc(cr, uid, endpoint, access_token) - - def auth_oauth_fetch_user_data(self, cr, uid, access_token, context=None): - endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo' - return self.auth_oauth_rpc(cr, uid, endpoint, access_token) - - def auth_oauth(self, cr, uid, config, params, context=None): + def auth_oauth(self, cr, uid, provider, params, context=None): # Advice by Google (to avoid Confused Deputy Problem) # if validation.audience != OUR_CLIENT_ID: # abort() # else: # continue with the process access_token = params.get('access_token') - validation = self.auth_oauth_fetch_user_validation(cr, uid, access_token, context=context) + p = self.pool.get('auth.oauth.provider').browse(cr, uid, provider, context=context) + + validation = self.auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token) if validation.get("error"): raise openerp.exceptions.AccessDenied - login = validation['email'] oauth_uid = validation['user_id'] - name = self.auth_oauth_fetch_user_data(cr, uid, access_token)['name'] - credentials = (cr.dbname, login, access_token) + name = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)['name'] + credentials = (cr.dbname, login, access_token) res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)]) if res: self.write(cr, uid, res[0], {'oauth_access_token':access_token}) diff --git a/addons/auth_oauth/static/lib/zocial/README.md b/addons/auth_oauth/static/lib/zocial/README.md new file mode 100644 index 00000000000..213132677af --- /dev/null +++ b/addons/auth_oauth/static/lib/zocial/README.md @@ -0,0 +1,31 @@ +# Zocial CSS social buttons + +I basically rewrote this entire set so they are full vector buttons, meaning: + +- @font-face icons +- custom font file for all social icons +- icon font use private unicode spaces for accessibility +- em sizing based on button font-size +- support for about 83 different services +- buttons and icons supported +- no raster images (sweet) +- works splendidly on any browser supporting @font-face +- CSS3 degrades gracefully in IE8 and below etc. +- also includes generic icon-less primary and secondary buttons + +## How to use these buttons + + + +or + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..94809d3a57ffcbfa1f3760420d745b2381574a05 GIT binary patch literal 41156 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 literal 0 HcmV?d00001 diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..1d6c4abc9d902c0f8662cadf3646810bd03639b7 GIT binary patch literal 31320 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 literal 0 HcmV?d00001 diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial.css b/addons/auth_oauth/static/lib/zocial/css/zocial.css new file mode 100644 index 00000000000..89fc7450631 --- /dev/null +++ b/addons/auth_oauth/static/lib/zocial/css/zocial.css @@ -0,0 +1,420 @@ +@charset "UTF-8"; + +/*! +Code written by Sam Collins (@smcllns) of www.eventasaur.us +You are free to use this work commercially +You are free to extend this work without permissions from the author (just do so tastefully eh?) +Enjoy +*/ + +/* Reference icons from font-files */ + +@font-face { + font-family: 'zocial'; + font-style: normal; + font-weight: normal; + src: url('zocial-regular-webfont.eot'); + src: url('zocial-regular-webfont.eot?#iefix') format('embedded-opentype'), + url('zocial-regular-webfont.woff') format('woff'), + url('zocial-regular-webfont.ttf') format('truetype'), + url('zocial-regular-webfont.svg#ZocialRegular') format('svg'); + unicode-range: U+0-U+10FFFF; +} + +/* Button structure */ + +.zocial, +a.zocial { + border: 1px solid #777; + border-color: rgba(0,0,0,0.2); + border-bottom-color: #333; + border-bottom-color: rgba(0,0,0,0.4); + color: #fff; + -moz-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9); + -webkit-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9); + box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9); + cursor: pointer; + display: inline-block; + font: bold 100%/2.1 "Lucida Grande", Tahoma, sans-serif; + padding: 0 .95em 0 0; + text-align: center; + text-decoration: none; + text-shadow: 0 1px 0 rgba(0,0,0,0.5); + white-space: nowrap; + + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + + position: relative; + + -moz-border-radius: .3em; + -webkit-border-radius: .3em; + border-radius: .3em; +} + +.zocial:before { + content: ""; + border-right: 0.075em solid rgba(0,0,0,0.1); + float: left; + font: 120%/1.65 zocial; + font-style: normal; + font-weight: normal; + margin: 0 0.5em 0 0; + padding: 0 0.5em; + text-align: center; + text-decoration: none; + text-transform: none; + + -moz-box-shadow: 0.075em 0 0 rgba(255,255,255,0.25); + -webkit-box-shadow: 0.075em 0 0 rgba(255,255,255,0.25); + box-shadow: 0.075em 0 0 rgba(255,255,255,0.25); + + -webkit-font-smoothing: antialiased; +} + +.zocial:active { + outline: none; /* outline is visible on :focus */ +} + +/* Buttons can be displayed as standalone icons by adding a class of "icon" */ + +.zocial.icon { + overflow: hidden; + max-width: 2.4em; + padding-left: 0; + padding-right: 0; + max-height: 2.15em; + white-space: nowrap; +} +.zocial.icon:before { + padding: 0; + width: 2em; + height: 2em; + + box-shadow: none; + border: none; +} + +/* Gradients */ + +.zocial { + background-image: -moz-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: -ms-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: -o-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.1)), color-stop(49%, rgba(255,255,255,.05)), color-stop(51%, rgba(0,0,0,.05)), to(rgba(0,0,0,.1))); + background-image: -webkit-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); +} + +.zocial:hover, .zocial:focus { + background-image: -moz-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: -ms-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: -o-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.15)), color-stop(49%, rgba(255,255,255,.15)), color-stop(51%, rgba(0,0,0,.1)), to(rgba(0,0,0,.15))); + background-image: -webkit-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); +} + +.zocial:active { + background-image: -moz-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: -ms-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: -o-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.1)), color-stop(30%, rgba(255,255,255,0)), color-stop(50%, transparent), to(rgba(0,0,0,.1))); + background-image: -webkit-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); +} + +/* Adjustments for light background buttons */ + +.zocial.bitcoin, +.zocial.cloudapp, +.zocial.dropbox, +.zocial.email, +.zocial.eventful, +.zocial.github, +.zocial.gmail, +.zocial.instapaper, +.zocial.itunes, +.zocial.ninetyninedesigns, +.zocial.openid, +.zocial.plancast, +.zocial.posterous, +.zocial.reddit, +.zocial.secondary, +.zocial.viadeo, +.zocial.weibo, +.zocial.wikipedia { + border: 1px solid #aaa; + border-color: rgba(0,0,0,0.3); + border-bottom-color: #777; + border-bottom-color: rgba(0,0,0,0.5); + -moz-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5); + -webkit-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5); + box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5); + text-shadow: 0 1px 0 rgba(255,255,255,0.8); +} + +/* :hover adjustments for light background buttons */ + +.zocial.bitcoin:focus, +.zocial.bitcoin:hover, +.zocial.dropbox:focus, +.zocial.dropbox:hover, +.zocial.email:focus, +.zocial.email:hover, +.zocial.eventful:focus, +.zocial.eventful:hover, +.zocial.github:focus, +.zocial.github:hover, +.zocial.gmail:focus, +.zocial.gmail:hover, +.zocial.instapaper:focus, +.zocial.instapaper:hover, +.zocial.itunes:focus, +.zocial.itunes:hover, +.zocial.ninetyninedesigns:focus, +.zocial.ninetyninedesigns:hover, +.zocial.openid:focus, +.zocial.openid:hover, +.zocial.plancast:focus, +.zocial.plancast:hover, +.zocial.posterous:focus, +.zocial.posterous:hover, +.zocial.reddit:focus, +.zocial.reddit:hover, +.zocial.secondary:focus, +.zocial.secondary:hover, +.zocial.twitter:focus, +.zocial.viadeo:focus, +.zocial.viadeo:hover, +.zocial.weibo:focus, +.zocial.weibo:hover, +.zocial.wikipedia:focus, +.zocial.wikipedia:hover { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.5)), color-stop(49%, rgba(255,255,255,0.2)), color-stop(51%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.15))); + background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: -o-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); +} + +/* :active adjustments for light background buttons */ + +.zocial.bitcoin:active, +.zocial.dropbox:active, +.zocial.email:active, +.zocial.eventful:active, +.zocial.github:active, +.zocial.gmail:active, +.zocial.instapaper:active, +.zocial.itunes:active, +.zocial.ninetyninedesigns:active, +.zocial.openid:active, +.zocial.plancast:active, +.zocial.posterous:active, +.zocial.reddit:active, +.zocial.secondary:active, +.zocial.viadeo:active, +.zocial.weibo:active, +.zocial.wikipedia:active { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0)), color-stop(30%, rgba(255,255,255,0)), color-stop(50%, rgba(0,0,0,0)), to(rgba(0,0,0,0.1))); + background-image: -moz-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: -webkit-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: -o-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: -ms-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); +} + +/* Button icon and color */ +/* Icon characters are stored in unicode private area */ +.zocial.amazon:before {content: "\E040";} +.zocial.android:before {content: "\E005";} +.zocial.angellist:before {content: "\E06C";} +.zocial.aol:before {content: "\E001";} +.zocial.appstore:before {content: "\E020";} +.zocial.bitcoin:before {content: "\E011"; color: #f7931a;} +.zocial.blogger:before {content: "\E021";} +.zocial.call:before {content: "\E016";} +.zocial.cal:before {content: "\E00D";} +.zocial.cart:before {content: "\E06A";} +.zocial.chrome:before {content: "\E03A";} +.zocial.cloudapp:before {content: "\E042";} +.zocial.creativecommons:before {content: "\E022";} +.zocial.delicious:before {content: "\E002";} +.zocial.digg:before {content: "\E01A";} +.zocial.disqus:before {content: "\E030";} +.zocial.dribbble:before {content: "\E023";} +.zocial.dropbox:before {content: "\E043"; color: #1f75cc;} +.zocial.email:before {content: "\E03C"; color: #312c2a;} +.zocial.eventasaurus:before {content: "\E055"; color: #9de428;} +.zocial.eventbrite:before {content: "\E05B";} +.zocial.eventful:before {content: "\E006"; color: #0066CC;} +.zocial.evernote:before {content: "\E024";} +.zocial.facebook:before {content: "\E045";} +.zocial.fivehundredpx:before {content: "\E00F"; color: #29b6ff;} +.zocial.flattr:before {content: "\E004";} +.zocial.flickr:before {content: "\E025";} +.zocial.forrst:before {content: "\E019"; color: #50894f;} +.zocial.foursquare:before {content: "\E013";} +.zocial.github:before {content: "\E046";} +.zocial.gmail:before {content: "\E04C"; color: #f00;} +.zocial.google:before {content: "\E026";} +.zocial.googleplay:before {content: "\E05E";} +.zocial.googleplus:before {content: "\E00A";} +.zocial.gowalla:before {content: "\E01F";} +.zocial.grooveshark:before {content: "\E017";} +.zocial.guest:before {content: "\E01E";} +.zocial.html5:before {content: "\E014";} +.zocial.ie:before {content: "\E015";} +.zocial.instagram:before {content: "\E06D";} +.zocial.instapaper:before {content: "\E028";} +.zocial.intensedebate:before {content: "\E05A";} +.zocial.itunes:before {content: "\E048"; color: #1a6dd2;} +.zocial.klout:before {content: "\E02A"; } +.zocial.lanyrd:before {content: "\E00C";} +.zocial.lastfm:before {content: "\E04B";} +.zocial.linkedin:before {content: "\E02B";} +.zocial.macstore:before {content: "\E03D";} +.zocial.meetup:before {content: "\E02C";} +.zocial.myspace:before {content: "\E03E";} +.zocial.ninetyninedesigns:before {content: "\E018"; color: #f50;} +.zocial.openid:before {content: "\E04E"; color: #ff921d;} +.zocial.opentable:before {content: "\E05F";} +.zocial.paypal:before {content: "\E003";} +.zocial.pinboard:before {content: "\E04D";} +.zocial.pinterest:before {content: "\E010";} +.zocial.plancast:before {content: "\E02F";} +.zocial.plurk:before {content: "\E049";} +.zocial.podcast:before {content: "\E03F";} +.zocial.posterous:before {content: "\E05D";} +.zocial.print:before {content: "\E06B";} +.zocial.quora:before {content: "\E050";} +.zocial.reddit:before {content: "\E01D"; color: red;} +.zocial.rss:before {content: "\E031";} +.zocial.scribd:before {content: "\E05C"; color: #00d5ea;} +.zocial.skype:before {content: "\E032";} +.zocial.smashing:before {content: "\E009";} +.zocial.songkick:before {content: "\E04A";} +.zocial.soundcloud:before {content: "\E052";} +.zocial.spotify:before {content: "\E01C";} +.zocial.stumbleupon:before {content: "\E00E";} +.zocial.tumblr:before {content: "\E053";} +.zocial.twitter:before {content: "\E033";} +.zocial.viadeo:before {content: "\E027"; color: #f59b20;} +.zocial.vimeo:before {content: "\E035";} +.zocial.weibo:before {content: "\E029"; color: #e6162d;} +.zocial.wikipedia:before {content: "\E00B";} +.zocial.windows:before {content: "\E036";} +.zocial.xing:before {content: "\E037"} +.zocial.wordpress:before {content: "\E056";} +.zocial.yahoo:before {content: "\E038";} +.zocial.yelp:before {content: "\E058";} +.zocial.youtube:before {content: "\E034";} + +/* Button background and text color */ + +.zocial.amazon {background-color: #ffad1d; color: #030037; text-shadow: 0 1px 0 rgba(255,255,255,0.5);} +.zocial.android {background-color: #a4c639;} +.zocial.angellist {background-color: #000;} +.zocial.aol {background-color: #f00;} +.zocial.appstore {background-color: #000;} +.zocial.bitcoin {background-color: #efefef; color: #4d4d4d;} +.zocial.blogger {background-color: #ee5a22;} +.zocial.call {background-color: #008000;} +.zocial.cal {background-color: #d63538;} +.zocial.cart {background-color: #333;} +.zocial.chrome {background-color: #006cd4;} +.zocial.cloudapp {background-color: #fff; color: #312c2a;} +.zocial.creativecommons {background-color: #000;} +.zocial.delicious {background-color: #3271cb;} +.zocial.digg {background-color: #164673;} +.zocial.disqus {background-color: #5d8aad;} +.zocial.dribbble {background-color: #ea4c89;} +.zocial.dropbox {background-color: #fff; color: #312c2a;} +.zocial.email {background-color: #f0f0eb; color: #312c2a;} +.zocial.eventasaurus {background-color: #192931; color: #fff;} +.zocial.eventbrite {background-color: #ff5616;} +.zocial.eventful {background-color: #fff; color: #47ab15;} +.zocial.evernote {background-color: #6bb130; color: #fff;} +.zocial.facebook {background-color: #4863ae;} +.zocial.fivehundredpx {background-color: #333;} +.zocial.flattr {background-color: #8aba42;} +.zocial.flickr {background-color: #ff0084;} +.zocial.forrst {background-color: #1e360d;} +.zocial.foursquare {background-color: #44a8e0;} +.zocial.github {background-color: #fbfbfb; color: #050505;} +.zocial.gmail {background-color: #efefef; color: #222;} +.zocial.google {background-color: #4e6cf7;} +.zocial.googleplay {background-color: #000;} +.zocial.googleplus {background-color: #dd4b39;} +.zocial.gowalla {background-color: #ff720a;} +.zocial.grooveshark {background-color: #111; color:#eee;} +.zocial.guest {background-color: #1b4d6d;} +.zocial.html5 {background-color: #ff3617;} +.zocial.ie {background-color: #00a1d9;} +.zocial.instapaper {background-color: #eee; color: #222;} +.zocial.instagram {background-color: #3f729b;} +.zocial.intensedebate {background-color: #0099e1;} +.zocial.klout {background-color: #e34a25;} +.zocial.itunes {background-color: #efefeb; color: #312c2a;} +.zocial.lanyrd {background-color: #2e6ac2;} +.zocial.lastfm {background-color: #dc1a23;} +.zocial.linkedin {background-color: #0083a8;} +.zocial.macstore {background-color: #007dcb} +.zocial.meetup {background-color: #ff0026;} +.zocial.myspace {background-color: #000;} +.zocial.ninetyninedesigns {background-color: #fff; color: #072243;} +.zocial.openid {background-color: #f5f5f5; color: #333;} +.zocial.opentable {background-color: #990000;} +.zocial.paypal {background-color: #fff; color: #32689a; text-shadow: 0 1px 0 rgba(255,255,255,0.5);} +.zocial.pinboard {background-color: blue;} +.zocial.pinterest {background-color: #c91618;} +.zocial.plancast {background-color: #e7ebed; color: #333;} +.zocial.plurk {background-color: #cf682f;} +.zocial.podcast {background-color: #9365ce;} +.zocial.posterous {background-color: #ffd959; color: #bc7134;} +.zocial.print {background-color: #f0f0eb; color: #222; text-shadow: 0 1px 0 rgba(255,255,255,0.8);} +.zocial.quora {background-color: #a82400;} +.zocial.reddit {background-color: #fff; color: #222;} +.zocial.rss {background-color: #ff7f25;} +.zocial.scribd {background-color: #231c1a;} +.zocial.skype {background-color: #00a2ed;} +.zocial.smashing {background-color: #ff4f27;} +.zocial.songkick {background-color: #ff0050;} +.zocial.soundcloud {background-color: #ff4500;} +.zocial.spotify {background-color: #60af00;} +.zocial.stumbleupon {background-color: #eb4924;} +.zocial.tumblr {background-color: #374a61;} +.zocial.twitter {background-color: #46c0fb;} +.zocial.viadeo {background-color: #fff; color: #000;} +.zocial.vimeo {background-color: #00a2cd;} +.zocial.weibo {background-color: #faf6f1; color: #000;} +.zocial.wikipedia {background-color: #fff; color: #000;} +.zocial.windows {background-color: #0052a4; color: #fff;} +.zocial.wordpress {background-color: #464646;} +.zocial.xing {background-color: #0A5D5E;} +.zocial.yahoo {background-color: #a200c2;} +.zocial.yelp {background-color: #e60010;} +.zocial.youtube {background-color: #f00;} + +/* +The Miscellaneous Buttons +These button have no icons and can be general purpose buttons while ensuring consistent button style +Credit to @guillermovs for suggesting +*/ + +.zocial.primary, .zocial.secondary {margin: 0.1em 0; padding: 0 1em;} +.zocial.primary:before, .zocial.secondary:before {display: none;} +.zocial.primary {background-color: #333;} +.zocial.secondary {background-color: #f0f0eb; color: #222; text-shadow: 0 1px 0 rgba(255,255,255,0.8);} + +/* Any browser-specific adjustments */ + +button:-moz-focus-inner { + border: 0; + padding: 0; +} + + diff --git a/addons/auth_oauth/static/lib/zocial/sample.html b/addons/auth_oauth/static/lib/zocial/sample.html new file mode 100644 index 00000000000..98dec554ff1 --- /dev/null +++ b/addons/auth_oauth/static/lib/zocial/sample.html @@ -0,0 +1,265 @@ + + + + + Zocial CSS3 Buttons + + + + + + + + + + + + + Sign in with Google+ + + Sign in with LinkedIn + +

    The Cool Kids

    + Sync with Dropbox + Clip to Evernote + Follow me on Forrst + Sign in with Dribbble + Sign in to CloudApp + Fork me on Github + Play on Spotify + Read It Later + Follow me on Soundcloud + Follow me on Tumblr + Read on Smashing Magazine + Available on iTunes + Available on the App Store + Available on the Mac App Store + Available on Android Market + Follow me on Pinterest + Follow me on Quora + Attend on Lanyrd + +

    The Not-So-Cool But Have-To-Be-Invited Kids

    + Pay with Paypal + Sign in with Amazon + Call me on Skype + Sign in with Last.fm + Write a review on Yelp + Check in with foursquare + Influence with Klout + +

    The Older (but Solid) Kids

    + View on Wikipedia + Sign in with Disqus + Sign in with IntenseDebate + Sign in with Google + Sign in with Gmail + Upload to Vimeo + Read more on Scribd + Subscribe on YouTube + Sign in with WordPress + Sign in with Songkick + Sign in with Posterous + Sign in with Eventbrite + Tip with Flattr + Follow me on Plancast + + +

    The Kids That Kinda Smell but Some People Don't Mind

    + Submit resume for CEO + Download Internet Explorer 5 + Report bugs with Meetup.com + Learn how-to-use OpenID + Register now for HTML6 + Chat with your parents + +

    The Kids That Nobody Normally Notices

    + Sign in as guest + View Creative Commons Licence + Subscribe to RSS + Add to Chrome + +

    The He's-My-Son-So-Of-Course-He's-Here Kid

    + Sign up for Eventasaurus + +

    Kids By Request

    + Join me on Weibo + Sign in with Plurk + Play on Grooveshark + Post on Blogger + Sign in with Viadeo + Subscribe to this Podcast + View Portfolio on 500px + Bitcoin accepted here + View Portfolio on 99Designs + Bookmark with Pinboard + Stumble! + Find me on Myspace + Sign in with Windows Live + Find Events with Eventful + Sign in with Xing + Upload to Flickr + Sign in with Del.icio.us + Download from Google Play + Reserve with OpenTable + Digg this + Share on Reddit + Fund us on AngelList + Sign-in with Instagram + +

    The Multi-Purpose Kids (Credit: Pictos Icons)

    + + Call a phone + + Add to calendar + Add to cart + Print this page + Primary action + Secondary action + + +

    Icon versions of the above

    + + Sign in with Google+ + + Sign in with Google + Sign in with LinkedIn + Pay with Paypal + Sign in with Amazon + Sync with Dropbox + Clip to Evernote + Call me on Skype + Sign in as guest + Play on Spotify + Sign in with Last.fm + Sign in with Songkick + Follow me on Forrst + Sign in with Dribbble + Sign in to CloudApp + Fork me on Github + Follow me on Pinterest + Follow me on Quora + Bookmark with Pinboard + Attend on Lanyrd + Download on iTunes + Download on Android + Sign in with Disqus + Sign in with Yahoo + Upload to Vimeo + Add to Chrome + Get a new browser + Made from HTML5 + Read It Later + Read more on Scribd + View on Wikipedia + Tip with Flattr + Follow me on Tumblr + Subscribe to my Posterous + Check in with Gowalla + Check in with foursquare + Write a review on Yelp + Follow me on Soundcloud + Read on Smashing Magazine + Sign in with WordPress + Sign in with IntenseDebate + Sign in with OpenID + Sign in with Gmail + Sign in with Eventbrite + Sign in with Eventasaurus + Sign in with Meetup.com + Sign in with AIM + Follow me on Plancast + Subscribe on YouTube + Available on the Mac App Store + View Creative Commons Licence + Subscribe to RSS + Follow me on Weibo + Follow me on Plurk + Follow me on Grooveshark + Post on Blogger + Sign in with Viadeo + Subscribe to this Podcast + View Portfolio on 500px + Bitcoin accepted here + View Portfolio on 99Designs + Stumble! + Download on iTunes + Find me on Myspace + Sign in with Windows Live + Find Events with Eventful + Influence with Klout + Sign in with Xing + Upload to Flickr + Sign in with Del.icio.us + Download from Google Play + Reserve with OpenTable + Digg this + Share on Reddit + Fund us on AngelList + Sign-in with Instagram + Call a phone + + Add to calendar + Print this page + Add to cart + + + +

    Thanks to @guillermovs, @kamens, @vizualover, and @leaverou for code refinements and suggestions.

    + +

    Massive thanks to @drewwilson for making the multi-purpose buttons possible with his incredible Pictos icons.

    + +

    See code samples at zocial.smcllns.com — ask questions to @smcllns

    + + + + + + + + diff --git a/addons/auth_oauth/static/src/css/auth_oauth.css b/addons/auth_oauth/static/src/css/auth_oauth.css deleted file mode 100644 index c8e0efe4c32..00000000000 --- a/addons/auth_oauth/static/src/css/auth_oauth.css +++ /dev/null @@ -1,2 +0,0 @@ -.oe_login_oauth { -} \ No newline at end of file diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index 67b446a4580..eae423fae1f 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -4,7 +4,7 @@ openerp.auth_oauth = function(instance) { instance.web.Login = instance.web.Login.extend({ start: function(parent, params) { var d = this._super.apply(this, arguments); - this.$element.on('click', 'a.oe_oauth_sign_in', this.on_oauth_sign_in); + this.$element.on('click', 'a.zocial', this.on_oauth_sign_in); this.oauth_providers = []; if(this.params.oauth_error === 1) { this.do_warn("Sign up error.","Sign up is not allowed on this database."); @@ -26,20 +26,23 @@ openerp.auth_oauth = function(instance) { console.log(buttons); this.$(".oe_login_pane form ul").after(buttons); }, - oauth_url: function(state) { - }, on_oauth_sign_in: function(ev) { ev.preventDefault(); var index = $(ev.target).data('index'); var p = this.oauth_providers[index]; var ret = location.protocol+"//"+location.host+"/"; var dbname = self.$("form [name=db]").val(); + var state_object = { + d: dbname, + p: p.id + } + var state = JSON.stringify(state_object); var params = { response_type: 'token', client_id: p.client_id, redirect_uri: ret, scope: p.scope, - state: dbname, + state: state, }; var url = p.auth_endpoint + '?' + $.param(params); window.location = url; diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml index 494dc20e1a1..c2693804e59 100644 --- a/addons/auth_oauth/static/src/xml/auth_oauth.xml +++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml @@ -2,9 +2,7 @@ - +