[ADD] This module initialize the session by looking for the field HTTP_REMOTE_USER in the HEADER of the HTTP request and trying^Co bind the given value to a user
parent
f83737f6e8
commit
7dd5bc685e
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import controllers
|
||||
from . import res_config
|
||||
from . import res_users
|
|
@ -0,0 +1,133 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
{
|
||||
'name': 'Authenticate via HTTP Remote User',
|
||||
'version': '1.0',
|
||||
'category': 'Tools',
|
||||
'description': """
|
||||
Allow users to be automatically logged in.
|
||||
==========================================
|
||||
|
||||
This module initialize the session by looking for the field HTTP_REMOTE_USER in
|
||||
the HEADER of the HTTP request and trying to bind the given value to a user
|
||||
This module must be loaded at startup; Add the *--load* parameter to the startup
|
||||
command: ::
|
||||
|
||||
--load=web,web_kanban,auth_from_http_remote_user, ...
|
||||
|
||||
If the field is not found or no user matches the given one, it can lets the
|
||||
system redirect to the login page (default) or issue a login error page depending
|
||||
of the configuration.
|
||||
|
||||
How to test the module with Apache [#]_
|
||||
----------------------------------------
|
||||
|
||||
Apache can be used as a reverse proxy providing the authentication and adding the
|
||||
required field in the Http headers.
|
||||
|
||||
Install apache: ::
|
||||
|
||||
$ sudo apt-get install apache2
|
||||
|
||||
|
||||
Define a new vhost to Apache by putting a new file in /etc/apache2/sites-available: ::
|
||||
|
||||
$ sudo vi /etc/apache2/sites-available/MY_VHOST.com
|
||||
|
||||
with the following content: ::
|
||||
|
||||
<VirtualHost *:80>
|
||||
ServerName MY_VHOST.com
|
||||
ProxyRequests Off
|
||||
<Location />
|
||||
AuthType Basic
|
||||
AuthName "Test OpenErp auth_from_http_remote_user"
|
||||
AuthBasicProvider file
|
||||
AuthUserFile /etc/apache2/MY_VHOST.htpasswd
|
||||
Require valid-user
|
||||
|
||||
RewriteEngine On
|
||||
RewriteCond %{LA-U:REMOTE_USER} (.+)
|
||||
RewriteRule . - [E=RU:%1]
|
||||
RequestHeader set Remote-User "%{RU}e" env=RU
|
||||
</Location>
|
||||
|
||||
ProxyPass / http://127.0.0.1:8069/ retry=10
|
||||
ProxyPassReverse / http://127.0.0.1:8069/
|
||||
ProxyPreserveHost On
|
||||
</VirtualHost>
|
||||
|
||||
.. important:: The *RequestHeader* directive is used to add the *Remote-User* field
|
||||
in the http headers. By default an *'Http-'* prefix is added to the field name.
|
||||
In OpenErp, header's fields name are normalized. As result of this normalization,
|
||||
the 'Http-Remote-User' is available as 'HTTP_REMOTE_USER'. If you don't know how
|
||||
your specified field is seen by OpenErp, run your server in debug mode once the
|
||||
module is activated and look for an entry like: ::
|
||||
|
||||
DEBUG openerp1 openerp.addons.auth_from_http_remote_user.controllers.session:
|
||||
Field 'HTTP_MY_REMOTE_USER' not found in http headers
|
||||
{'HTTP_AUTHORIZATION': 'Basic YWRtaW46YWRtaW4=', ..., 'HTTP_REMOTE_USER': 'demo')
|
||||
|
||||
Enable the required apache modules: ::
|
||||
|
||||
$ sudo a2enmod headers
|
||||
$ sudo a2enmod proxy
|
||||
$ sudo a2enmod rewrite
|
||||
$ sudo a2enmod proxy_http
|
||||
|
||||
Enable your new vhost: ::
|
||||
|
||||
$ sudo a2ensite MY_VHOST.com
|
||||
|
||||
Create the *htpassword* file used by the configured basic authentication: ::
|
||||
|
||||
$ sudo htpasswd -cb /etc/apache2/MY_VHOST.htpasswd admin admin
|
||||
$ sudo htpasswd -b /etc/apache2/MY_VHOST.htpasswd demo demo
|
||||
|
||||
For local test, add the *MY_VHOST.com* in your /etc/vhosts file.
|
||||
|
||||
Finally reload the configuration: ::
|
||||
|
||||
$ sudo service apache2 reload
|
||||
|
||||
Open your browser and go to MY_VHOST.com. If everything is well configured, you are prompted
|
||||
for a login and password outside OpenErp and are automatically logged in the system.
|
||||
|
||||
.. [#] Based on a ubuntu 12.04 env
|
||||
|
||||
""",
|
||||
'author': 'Acsone SA/NV',
|
||||
'maintainer': 'ACSONE SA/NV',
|
||||
'website': 'http://www.acsone.eu',
|
||||
'depends': ['web'],
|
||||
"license": "AGPL-3",
|
||||
"js": ['static/src/js/auth_from_http_remote_user.js'],
|
||||
'data': [
|
||||
'res_config_view.xml',
|
||||
'res_config_data.xml'],
|
||||
"demo": [],
|
||||
"test": [],
|
||||
"active": False,
|
||||
"license": "AGPL-3",
|
||||
"installable": True,
|
||||
"auto_install": False,
|
||||
"application": False,
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import session
|
|
@ -0,0 +1,129 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.controllers import main
|
||||
from openerp.modules.registry import RegistryManager
|
||||
from .. import utils
|
||||
|
||||
import random
|
||||
import logging
|
||||
import openerp.tools.config as config
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Session(main.Session):
|
||||
_cp_path = "/web/session"
|
||||
|
||||
_REQUIRED_ATTRIBUTES = ['HTTP_REMOTE_USER']
|
||||
_OPTIONAL_ATTRIBUTES = []
|
||||
|
||||
def _get_db(self, db):
|
||||
if db is not None and len(db) > 0:
|
||||
return db
|
||||
db = config['db_name']
|
||||
if db is None or len(db) == 0:
|
||||
_logger.error("No db found for SSO. Specify one in the URL using parameter "
|
||||
"db=? or provide a default one in the configuration")
|
||||
raise http.AuthenticationError()
|
||||
|
||||
def _get_user_id_from_attributes(self, res_users, cr, attrs):
|
||||
login = attrs.get('HTTP_REMOTE_USER', None)
|
||||
user_ids = res_users.search(cr, SUPERUSER_ID, [('login', '=', login), ('active', '=', True)])
|
||||
assert len(user_ids) < 2
|
||||
if user_ids:
|
||||
return user_ids[0]
|
||||
return None
|
||||
|
||||
def _get_attributes_form_header(self, req):
|
||||
attrs = {}
|
||||
|
||||
all_attrs = self._REQUIRED_ATTRIBUTES + self._OPTIONAL_ATTRIBUTES
|
||||
|
||||
headers = req.httprequest.headers.environ
|
||||
|
||||
for attr in all_attrs:
|
||||
value = headers.get(attr, None)
|
||||
if value is not None:
|
||||
attrs[attr] = value
|
||||
|
||||
attrs_found = set(attrs.keys())
|
||||
attrs_missing = set(all_attrs) - attrs_found
|
||||
if len(attrs_found) > 0:
|
||||
_logger.debug("Fields '%s' not found in http headers\n %s", attrs_missing, headers)
|
||||
|
||||
missings = set(self._REQUIRED_ATTRIBUTES) - attrs_found
|
||||
if len(missings) > 0:
|
||||
_logger.error("Required fields '%s' not found in http headers\n %s", missings, headers)
|
||||
return attrs
|
||||
|
||||
def _bind_http_remote_user(self, req, db_name):
|
||||
db_name = self._get_db(db_name)
|
||||
try:
|
||||
registry = RegistryManager.get(db_name)
|
||||
with registry.cursor() as cr:
|
||||
modules = registry.get('ir.module.module')
|
||||
installed = modules.search_count(cr, SUPERUSER_ID, ['&',
|
||||
('name', '=', 'auth_from_http_remote_user'),
|
||||
('state', '=', 'installed')]) == 1
|
||||
if not installed:
|
||||
return
|
||||
config = registry.get('auth_from_http_remote_user.config.settings')
|
||||
# get parameters for SSO
|
||||
default_login_page_disabled = config.is_default_login_page_disabled(cr, SUPERUSER_ID, None)
|
||||
|
||||
# get the user
|
||||
res_users = registry.get('res.users')
|
||||
attrs = self._get_attributes_form_header(req)
|
||||
user_id = self._get_user_id_from_attributes(res_users, cr, attrs)
|
||||
|
||||
if user_id is None:
|
||||
if default_login_page_disabled:
|
||||
raise http.AuthenticationError()
|
||||
return
|
||||
|
||||
# generate a specific key for authentication
|
||||
key = randomString(utils.KEY_LENGTH, '0123456789abcdef')
|
||||
res_users.write(cr, SUPERUSER_ID, [user_id], {'sso_key': key})
|
||||
login = res_users.browse(cr, SUPERUSER_ID, user_id).login
|
||||
req.session.bind(db_name, user_id, login, key)
|
||||
except http.AuthenticationError, e:
|
||||
raise e
|
||||
except Exception, e:
|
||||
_logger.error("Error binding Http Remote User session", exc_info=True)
|
||||
raise e
|
||||
|
||||
@http.jsonrequest
|
||||
def get_http_remote_user_session_info(self, req, db):
|
||||
if not req.session._login:
|
||||
self._bind_http_remote_user(req, db)
|
||||
return self.session_info(req)
|
||||
|
||||
randrange = random.SystemRandom().randrange
|
||||
|
||||
|
||||
def randomString(length, chrs):
|
||||
"""Produce a string of length random bytes, chosen from chrs."""
|
||||
n = len(chrs)
|
||||
return ''.join([chrs[randrange(n)] for _ in xrange(length)])
|
|
@ -0,0 +1,60 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
import types
|
||||
|
||||
|
||||
class auth_from_http_remote_user_configuration(orm.TransientModel):
|
||||
_name = 'auth_from_http_remote_user.config.settings'
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
_columns = {
|
||||
'default_login_page_disabled': fields.boolean("Disable login page",
|
||||
help="""
|
||||
Disable the default login page.
|
||||
If the HTTP_REMOTE_HEADER field is not found or no user matches the given one,
|
||||
the system will display a login error page if the login page is disabled.
|
||||
Otherwise the normal login page will be displayed.
|
||||
"""),
|
||||
}
|
||||
|
||||
def is_default_login_page_disabled(self, cr, uid, fields, context=None):
|
||||
ir_config_obj = self.pool['ir.config_parameter']
|
||||
default_login_page_disabled = ir_config_obj.get_param(cr,
|
||||
uid,
|
||||
'auth_from_http_remote_user.default_login_page_disabled')
|
||||
if isinstance(default_login_page_disabled, types.BooleanType):
|
||||
return default_login_page_disabled
|
||||
return safe_eval(default_login_page_disabled)
|
||||
|
||||
def get_default_default_login_page_disabled(self, cr, uid, fields, context=None):
|
||||
default_login_page_disabled = self.is_default_login_page_disabled(cr, uid, fields, context)
|
||||
return {'default_login_page_disabled': default_login_page_disabled}
|
||||
|
||||
def set_default_default_login_page_disabled(self, cr, uid, ids, context=None):
|
||||
config = self.browse(cr, uid, ids[0], context)
|
||||
ir_config_parameter_obj = self.pool['ir.config_parameter']
|
||||
ir_config_parameter_obj.set_param(cr,
|
||||
uid,
|
||||
'auth_from_http_remote_user.default_login_page_disabled',
|
||||
repr(config.default_login_page_disabled))
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record model="ir.config_parameter" id="auth_from_http_remote_user.default_login_page_disabled">
|
||||
<field name="key">auth_from_http_remote_user.default_login_page_disabled</field>
|
||||
<field name="value">False</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="help_view_config_settings">
|
||||
<field name="name">Auth HTTP_REMOTE_USER settings</field>
|
||||
<field name="model">auth_from_http_remote_user.config.settings</field>
|
||||
<field name="priority" eval="20" />
|
||||
<field name="arch" type="xml">
|
||||
<form string="Configure Auth HTTP_REMOTE_USER" version="7.0"
|
||||
class="oe_form_configuration">
|
||||
<header>
|
||||
<header>
|
||||
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" type="object" name="cancel" class="oe_link"/>
|
||||
</header>
|
||||
</header>
|
||||
<separator string="Auth HTTP_REMOTE_USER" />
|
||||
<group>
|
||||
<field name="default_login_page_disabled" />
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="auth_from_http_remote_user_action_config_settings">
|
||||
<field name="name">Configure Auth HTTP_REMOTE_USER</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">auth_from_http_remote_user.config.settings</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">inline</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="base.menu_auth_from_http_remote_user_config" name="Auth HTTP_REMOTE_USER"
|
||||
parent="base.menu_config" sequence="10"
|
||||
action="auth_from_http_remote_user_action_config_settings" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,64 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.modules.registry import RegistryManager
|
||||
from openerp.osv import orm, fields
|
||||
from openerp import SUPERUSER_ID
|
||||
import openerp.exceptions
|
||||
from openerp.addons.auth_from_http_remote_user import utils
|
||||
|
||||
|
||||
class res_users(orm.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
_columns = {
|
||||
'sso_key': fields.char('SSO Key', size=utils.KEY_LENGTH,
|
||||
readonly=True),
|
||||
}
|
||||
|
||||
def copy(self, cr, uid, rid, defaults=None, context=None):
|
||||
defaults = defaults or {}
|
||||
defaults['sso_key'] = False
|
||||
return super(res_users, self).copy(cr, uid, rid, defaults, context)
|
||||
|
||||
def check_credentials(self, cr, uid, password):
|
||||
try:
|
||||
return super(res_users, self).check_credentials(cr, uid, password)
|
||||
except openerp.exceptions.AccessDenied:
|
||||
res = self.search(cr, SUPERUSER_ID, [('id', '=', uid), ('sso_key', '=', password)])
|
||||
if not res:
|
||||
raise openerp.exceptions.AccessDenied()
|
||||
|
||||
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 RegistryManager.get(db).cursor() as cr:
|
||||
cr.execute('''SELECT COUNT(1)
|
||||
FROM res_users
|
||||
WHERE id=%s
|
||||
AND sso_key=%s
|
||||
AND active=%s''', (int(uid), passwd, True))
|
||||
if not cr.fetchone()[0]:
|
||||
raise
|
||||
self._uid_cache.setdefault(db, {})[uid] = passwd
|
|
@ -0,0 +1,36 @@
|
|||
openerp.auth_from_http_remote_user = function(instance) {
|
||||
|
||||
instance.web.Session.include({
|
||||
session_load_response : function(response) {
|
||||
//unregister the event since it must be called only if the rpc call
|
||||
//is made by session_reload
|
||||
this.off('response', this.session_load_response);
|
||||
if (response.error && response.error.data.type === "session_invalid") {
|
||||
$("body").html("<h1>Access Denied</h1>");
|
||||
}
|
||||
|
||||
console.log("session_load_response called");
|
||||
},
|
||||
|
||||
session_reload : function() {
|
||||
var self = this;
|
||||
// we need to register an handler for 'response' since
|
||||
// by default, the rpc doesn't call callback function
|
||||
// if the response is of error type 'session_invalid'
|
||||
this.on('response', this, this.session_load_response);
|
||||
return this.rpc("/web/session/get_http_remote_user_session_info", {
|
||||
db : $.deparam.querystring().db
|
||||
}).done(function(result) {
|
||||
// If immediately follows a login (triggered by trying to
|
||||
// restore
|
||||
// an invalid session or no session at all), refresh session
|
||||
// data
|
||||
// (should not change, but just in case...)
|
||||
_.extend(self, result);
|
||||
}).fail(function(result){
|
||||
$("body").html("<h1>Server error</h1>");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import test_res_users
|
||||
fast_suite = [
|
||||
]
|
||||
|
||||
checks = [
|
||||
test_res_users,
|
||||
]
|
|
@ -0,0 +1,83 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tests import common
|
||||
import mock
|
||||
import os
|
||||
from contextlib import contextmanager
|
||||
import unittest
|
||||
|
||||
|
||||
@contextmanager
|
||||
def mock_cursor(cr):
|
||||
with mock.patch('openerp.sql_db.Connection.cursor') as mocked_cursor_call:
|
||||
org_close = cr.close
|
||||
org_autocommit = cr.autocommit
|
||||
try:
|
||||
cr.close = mock.Mock()
|
||||
cr.autocommit = mock.Mock()
|
||||
mocked_cursor_call.return_value = cr
|
||||
yield
|
||||
finally:
|
||||
cr.close = org_close
|
||||
cr.autocommit = org_autocommit
|
||||
|
||||
|
||||
class test_res_users(common.TransactionCase):
|
||||
|
||||
def test_login(self):
|
||||
res_users_obj = self.registry('res.users')
|
||||
uid = res = res_users_obj.login(common.DB, 'admin', 'admin')
|
||||
self.assertTrue(res, "Basic login must works as expected")
|
||||
token = "123456"
|
||||
res = res_users_obj.login(common.DB, 'admin', token)
|
||||
self.assertFalse(res)
|
||||
# mimic what the new controller do when it find a value in
|
||||
# the http header (HTTP_REMODE_USER)
|
||||
res_users_obj.write(self.cr, self.uid, uid, {'sso_key': token})
|
||||
|
||||
# Here we need to mock the cursor since the login is natively done inside
|
||||
# its own connection
|
||||
with mock_cursor(self.cr):
|
||||
# We can verifies that the given (uid, token) is authorized for the database
|
||||
res_users_obj.check(common.DB, uid, token)
|
||||
|
||||
# we are able to login with the new token
|
||||
res = res_users_obj.login(common.DB, 'admin', token)
|
||||
self.assertTrue(res)
|
||||
|
||||
@unittest.skipIf(os.environ.get('TRAVIS'),
|
||||
'When run by travis, tests runs on a database with all required addons from server-tools and '
|
||||
'their dependencies installed. Even if `auth_from_http_remote_user` does not require the `mail`'
|
||||
'module, The previous installation of the mail module has created the column '
|
||||
'`notification_email_send` as REQUIRED into the table res_partner. BTW, it\'s no more possible '
|
||||
'to copy a res_user without an intefirty error')
|
||||
def test_copy(self):
|
||||
'''Check that the sso_key is not copied on copy
|
||||
'''
|
||||
res_users_obj = self.registry('res.users')
|
||||
vals = {'sso_key': '123'}
|
||||
res_users_obj.write(self.cr, self.uid, self.uid, vals)
|
||||
read_vals = res_users_obj.read(self.cr, self.uid, self.uid, ['sso_key'])
|
||||
self.assertDictContainsSubset(vals, read_vals)
|
||||
copy = res_users_obj.copy(self.cr, self.uid, self.uid)
|
||||
read_vals = res_users_obj.read(self.cr, self.uid, copy, ['sso_key'])
|
||||
self.assertFalse(read_vals.get('sso_key'))
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Laurent Mignon
|
||||
# Copyright 2014 'ACSONE SA/NV'
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
KEY_LENGTH = 16
|
Loading…
Reference in New Issue