Merge pull request #207 from abstract-open-solutions/8.0
[8.0] port users_ldap_groups to 8.0pull/222/head
commit
ef3813e5f5
|
@ -1,108 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# This module copyright (C) 2012 Therp BV (<http://therp.nl>).
|
|
||||||
#
|
|
||||||
# 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 fields, orm
|
|
||||||
import logging
|
|
||||||
import users_ldap_groups_operators
|
|
||||||
import inspect
|
|
||||||
|
|
||||||
|
|
||||||
class CompanyLDAPGroupMapping(orm.Model):
|
|
||||||
_name = 'res.company.ldap.group_mapping'
|
|
||||||
_rec_name = 'ldap_attribute'
|
|
||||||
_order = 'ldap_attribute'
|
|
||||||
|
|
||||||
def _get_operators(self, cr, uid, context=None):
|
|
||||||
operators = []
|
|
||||||
members = inspect.getmembers(
|
|
||||||
users_ldap_groups_operators,
|
|
||||||
lambda cls:
|
|
||||||
inspect.isclass(cls) and
|
|
||||||
cls != users_ldap_groups_operators.LDAPOperator)
|
|
||||||
for name, operator in members:
|
|
||||||
operators.append((name, name))
|
|
||||||
return tuple(operators)
|
|
||||||
|
|
||||||
_columns = {
|
|
||||||
'ldap_id': fields.many2one('res.company.ldap', 'LDAP server', required=True),
|
|
||||||
'ldap_attribute': fields.char(
|
|
||||||
'LDAP attribute', size=64,
|
|
||||||
help='The LDAP attribute to check.\n'
|
|
||||||
'For active directory, use memberOf.'),
|
|
||||||
'operator': fields.selection(
|
|
||||||
_get_operators, 'Operator',
|
|
||||||
help='The operator to check the attribute against the value\n'
|
|
||||||
'For active directory, use \'contains\'', required=True),
|
|
||||||
'value': fields.char(
|
|
||||||
'Value', size=1024,
|
|
||||||
help='The value to check the attribute against.\n'
|
|
||||||
'For active directory, use the dn of the desired group',
|
|
||||||
required=True),
|
|
||||||
'group': fields.many2one(
|
|
||||||
'res.groups', 'OpenERP group',
|
|
||||||
help='The OpenERP group to assign', required=True),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class CompanyLDAP(orm.Model):
|
|
||||||
_inherit = 'res.company.ldap'
|
|
||||||
|
|
||||||
_columns = {
|
|
||||||
'group_mappings': fields.one2many(
|
|
||||||
'res.company.ldap.group_mapping',
|
|
||||||
'ldap_id', 'Group mappings',
|
|
||||||
help='Define how OpenERP groups are assigned to ldap users'),
|
|
||||||
'only_ldap_groups': fields.boolean(
|
|
||||||
'Only ldap groups',
|
|
||||||
help='If this is checked, manual changes to group membership are '
|
|
||||||
'undone on every login (so OpenERP groups are always synchronous '
|
|
||||||
'with LDAP groups). If not, manually added groups are preserved.')
|
|
||||||
}
|
|
||||||
|
|
||||||
_default = {
|
|
||||||
'only_ldap_groups': False,
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_or_create_user(self, cr, uid, conf, login, ldap_entry, context=None):
|
|
||||||
user_id = super(CompanyLDAP, self).get_or_create_user(cr, uid, conf, login,
|
|
||||||
ldap_entry, context)
|
|
||||||
if not user_id:
|
|
||||||
return user_id
|
|
||||||
logger = logging.getLogger('users_ldap_groups')
|
|
||||||
mappingobj = self.pool.get('res.company.ldap.group_mapping')
|
|
||||||
userobj = self.pool.get('res.users')
|
|
||||||
conf_all = self.read(cr, uid, conf['id'], ['only_ldap_groups'])
|
|
||||||
if(conf_all['only_ldap_groups']):
|
|
||||||
logger.debug('deleting all groups from user %d' % user_id)
|
|
||||||
userobj.write(cr, uid, [user_id], {'groups_id': [(5, )]}, context=context)
|
|
||||||
|
|
||||||
for mapping in mappingobj.read(cr, uid, mappingobj.search(
|
|
||||||
cr, uid, [('ldap_id', '=', conf['id'])]), []):
|
|
||||||
operator = getattr(users_ldap_groups_operators, mapping['operator'])()
|
|
||||||
logger.debug('checking mapping %s' % mapping)
|
|
||||||
if operator.check_value(ldap_entry, mapping['ldap_attribute'],
|
|
||||||
mapping['value'], conf, self, logger):
|
|
||||||
logger.debug('adding user %d to group %s' %
|
|
||||||
(user_id, mapping['group'][1]))
|
|
||||||
userobj.write(cr, uid, [user_id],
|
|
||||||
{'groups_id': [(4, mapping['group'][0])]},
|
|
||||||
context=context)
|
|
||||||
return user_id
|
|
|
@ -1,47 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# This module copyright (C) 2012 Therp BV (<http://therp.nl>).
|
|
||||||
#
|
|
||||||
# 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 string import Template
|
|
||||||
|
|
||||||
|
|
||||||
class LDAPOperator:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class contains(LDAPOperator):
|
|
||||||
def check_value(self, ldap_entry, attribute, value, ldap_config, company, logger):
|
|
||||||
return (attribute in ldap_entry[1]) and (value in ldap_entry[1][attribute])
|
|
||||||
|
|
||||||
|
|
||||||
class equals(LDAPOperator):
|
|
||||||
def check_value(self, ldap_entry, attribute, value, ldap_config, company, logger):
|
|
||||||
return attribute in ldap_entry[1] and unicode(value) == unicode(ldap_entry[1][attribute])
|
|
||||||
|
|
||||||
|
|
||||||
class query(LDAPOperator):
|
|
||||||
def check_value(self, ldap_entry, attribute, value, ldap_config, company, logger):
|
|
||||||
query_string = Template(value).safe_substitute(dict(
|
|
||||||
[(attr, ldap_entry[1][attribute][0]) for attr in ldap_entry[1]]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
logger.debug('evaluating query group mapping, filter: %s' % query_string)
|
|
||||||
results = company.query(ldap_config, query_string)
|
|
||||||
logger.debug(results)
|
|
||||||
return bool(results)
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||||
|
:alt: License: AGPL-3
|
||||||
|
|
||||||
|
users_ldap_groups
|
||||||
|
=================
|
||||||
|
|
||||||
|
Adds user accounts to groups based on rules defined by the administrator.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
Define mappings in Settings->Companies->[your company]->tab configuration->[
|
||||||
|
your ldap server].
|
||||||
|
|
||||||
|
Decide whether you want only groups mapped from ldap (Only ldap groups=y) or a
|
||||||
|
mix of manually set groups and ldap groups (Only ldap groups=n). Setting this
|
||||||
|
to 'no' will result in users never losing privileges when you remove them from
|
||||||
|
a ldap group, so that's a potential security issue. It is still the default to
|
||||||
|
prevent losing group information by accident.
|
||||||
|
|
||||||
|
For active directory, use LDAP attribute 'memberOf' and operator 'contains'.
|
||||||
|
Fill in the DN of the windows group as value and choose an OpenERP group users
|
||||||
|
with this windows group are to be assigned to.
|
||||||
|
|
||||||
|
For posix accounts, use operator 'query' and a value like
|
||||||
|
(&(cn=bzr)(objectClass=posixGroup)(memberUid=$uid))
|
||||||
|
|
||||||
|
The operator query matches if the filter in value returns something, and value
|
||||||
|
can contain $[attribute] which will be replaced by the first value of the
|
||||||
|
user's ldap record's attribute named [attribute].
|
||||||
|
|
||||||
|
Bug Tracker
|
||||||
|
===========
|
||||||
|
|
||||||
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_.
|
||||||
|
In case of trouble, please check there if your issue has already been reported.
|
||||||
|
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
|
||||||
|
`here <https://github.com/OCA/server-tools/issues/new?body=module:%20{module_name}%0Aversion:%20{version}%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Credits
|
||||||
|
=======
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Therp BV <info@therp.nl>
|
||||||
|
* Giacomo Spettoli <giacomo.spettoli@gmail.com>
|
||||||
|
|
||||||
|
Maintainer
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. image:: https://odoo-community.org/logo.png
|
||||||
|
:alt: Odoo Community Association
|
||||||
|
:target: https://odoo-community.org
|
||||||
|
|
||||||
|
This module is maintained by the OCA.
|
||||||
|
|
||||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||||
|
mission is to support the collaborative development of Odoo features and
|
||||||
|
promote its widespread use.
|
||||||
|
|
||||||
|
To contribute to this module, please visit http://odoo-community.org.
|
|
@ -19,4 +19,4 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import users_ldap_groups
|
from . import users_ldap_groups
|
|
@ -25,30 +25,8 @@
|
||||||
"depends": ["auth_ldap"],
|
"depends": ["auth_ldap"],
|
||||||
"author": "Therp BV,Odoo Community Association (OCA)",
|
"author": "Therp BV,Odoo Community Association (OCA)",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"description": """
|
"summary": """
|
||||||
Adds user accounts to groups based on rules defined by the administrator.
|
Adds user accounts to groups based on rules defined by the administrator.
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
Define mappings in Settings->Companies->[your company]->tab configuration->[your
|
|
||||||
ldap server].
|
|
||||||
|
|
||||||
Decide whether you want only groups mapped from ldap (Only ldap groups=y) or a
|
|
||||||
mix of manually set groups and ldap groups (Only ldap groups=n). Setting this to
|
|
||||||
'no' will result in users never losing privileges when you remove them from a
|
|
||||||
ldap group, so that's a potential security issue. It is still the default to
|
|
||||||
prevent losing group information by accident.
|
|
||||||
|
|
||||||
For active directory, use LDAP attribute 'memberOf' and operator 'contains'.
|
|
||||||
Fill in the DN of the windows group as value and choose an OpenERP group users
|
|
||||||
with this windows group are to be assigned to.
|
|
||||||
|
|
||||||
For posix accounts, use operator 'query' and a value like
|
|
||||||
(&(cn=bzr)(objectClass=posixGroup)(memberUid=$uid))
|
|
||||||
|
|
||||||
The operator query matches if the filter in value returns something, and value
|
|
||||||
can contain $[attribute] which will be replaced by the first value of the
|
|
||||||
user's ldap record's attribute named [attribute].
|
|
||||||
""",
|
""",
|
||||||
"category": "Tools",
|
"category": "Tools",
|
||||||
"data": [
|
"data": [
|
|
@ -0,0 +1,128 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# OpenERP, Open Source Management Solution
|
||||||
|
# This module copyright (C) 2012 Therp BV (<http://therp.nl>).
|
||||||
|
#
|
||||||
|
# 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 models
|
||||||
|
from openerp import fields
|
||||||
|
from openerp import api
|
||||||
|
import logging
|
||||||
|
from string import Template
|
||||||
|
|
||||||
|
|
||||||
|
class LDAPOperator(models.AbstractModel):
|
||||||
|
_name = "res.company.ldap.operator"
|
||||||
|
|
||||||
|
def operators(self):
|
||||||
|
return ('contains', 'equals', 'query')
|
||||||
|
|
||||||
|
def contains(self, ldap_entry, attribute, value, ldap_config, company,
|
||||||
|
logger):
|
||||||
|
return (attribute in ldap_entry[1]) and \
|
||||||
|
(value in ldap_entry[1][attribute])
|
||||||
|
|
||||||
|
def equals(self, ldap_entry, attribute, value, ldap_config, company,
|
||||||
|
logger):
|
||||||
|
return attribute in ldap_entry[1] and \
|
||||||
|
unicode(value) == unicode(ldap_entry[1][attribute])
|
||||||
|
|
||||||
|
def query(self, ldap_entry, attribute, value, ldap_config, company,
|
||||||
|
logger):
|
||||||
|
query_string = Template(value).safe_substitute(dict(
|
||||||
|
[(attr, ldap_entry[1][attribute][0]) for attr in ldap_entry[1]]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
logger.debug('evaluating query group mapping, filter: %s' %
|
||||||
|
query_string)
|
||||||
|
results = company.query(ldap_config, query_string)
|
||||||
|
logger.debug(results)
|
||||||
|
return bool(results)
|
||||||
|
|
||||||
|
|
||||||
|
class CompanyLDAPGroupMapping(models.Model):
|
||||||
|
_name = 'res.company.ldap.group_mapping'
|
||||||
|
_rec_name = 'ldap_attribute'
|
||||||
|
_order = 'ldap_attribute'
|
||||||
|
|
||||||
|
def _get_operators(self):
|
||||||
|
op_obj = self.env['res.company.ldap.operator']
|
||||||
|
operators = [(op, op) for op in op_obj.operators()]
|
||||||
|
return tuple(operators)
|
||||||
|
|
||||||
|
ldap_id = fields.Many2one('res.company.ldap', 'LDAP server', required=True)
|
||||||
|
ldap_attribute = fields.Char(
|
||||||
|
'LDAP attribute',
|
||||||
|
help='The LDAP attribute to check.\n'
|
||||||
|
'For active directory, use memberOf.')
|
||||||
|
operator = fields.Selection(
|
||||||
|
_get_operators, 'Operator',
|
||||||
|
help='The operator to check the attribute against the value\n'
|
||||||
|
'For active directory, use \'contains\'', required=True)
|
||||||
|
value = fields.Char(
|
||||||
|
'Value',
|
||||||
|
help='The value to check the attribute against.\n'
|
||||||
|
'For active directory, use the dn of the desired group',
|
||||||
|
required=True)
|
||||||
|
group = fields.Many2one(
|
||||||
|
'res.groups', 'OpenERP group',
|
||||||
|
help='The OpenERP group to assign', required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class CompanyLDAP(models.Model):
|
||||||
|
_inherit = 'res.company.ldap'
|
||||||
|
|
||||||
|
group_mappings = fields.One2many(
|
||||||
|
'res.company.ldap.group_mapping',
|
||||||
|
'ldap_id', 'Group mappings',
|
||||||
|
help='Define how OpenERP groups are assigned to ldap users')
|
||||||
|
only_ldap_groups = fields.Boolean(
|
||||||
|
'Only ldap groups',
|
||||||
|
help='If this is checked, manual changes to group membership are '
|
||||||
|
'undone on every login (so OpenERP groups are always synchronous '
|
||||||
|
'with LDAP groups). If not, manually added groups are preserved.')
|
||||||
|
|
||||||
|
_default = {
|
||||||
|
'only_ldap_groups': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def get_or_create_user(self, conf, login, ldap_entry):
|
||||||
|
op_obj = self.env['res.company.ldap.operator']
|
||||||
|
id_ = conf['id']
|
||||||
|
this = self.browse(id_)
|
||||||
|
user_id = super(CompanyLDAP, self).get_or_create_user(
|
||||||
|
conf, login, ldap_entry)
|
||||||
|
if not user_id:
|
||||||
|
return user_id
|
||||||
|
userobj = self.env['res.users']
|
||||||
|
user = userobj.browse(user_id)
|
||||||
|
logger = logging.getLogger('users_ldap_groups')
|
||||||
|
if self.only_ldap_groups:
|
||||||
|
logger.debug('deleting all groups from user %d' % user_id)
|
||||||
|
user.write({'groups_id': [(5, )]})
|
||||||
|
|
||||||
|
for mapping in this.group_mappings:
|
||||||
|
operator = getattr(op_obj, mapping.operator)
|
||||||
|
logger.debug('checking mapping %s' % mapping)
|
||||||
|
if operator(ldap_entry, mapping['ldap_attribute'],
|
||||||
|
mapping['value'], conf, self, logger):
|
||||||
|
logger.debug('adding user %d to group %s' %
|
||||||
|
(user_id, mapping.group.name))
|
||||||
|
user.write({'groups_id': [(4, mapping.group.id)]})
|
||||||
|
return user_id
|
Loading…
Reference in New Issue