diff --git a/__unported__/users_ldap_groups/users_ldap_groups.py b/__unported__/users_ldap_groups/users_ldap_groups.py deleted file mode 100644 index bca79a05a..000000000 --- a/__unported__/users_ldap_groups/users_ldap_groups.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2012 Therp BV (). -# -# 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 . -# -############################################################################## - -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 diff --git a/__unported__/users_ldap_groups/users_ldap_groups_operators.py b/__unported__/users_ldap_groups/users_ldap_groups_operators.py deleted file mode 100644 index 4de745fbf..000000000 --- a/__unported__/users_ldap_groups/users_ldap_groups_operators.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2012 Therp BV (). -# -# 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 . -# -############################################################################## -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) diff --git a/users_ldap_groups/README.rst b/users_ldap_groups/README.rst new file mode 100644 index 000000000..2dbc81de3 --- /dev/null +++ b/users_ldap_groups/README.rst @@ -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 `_. +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 `_. + + +Credits +======= + +Contributors +------------ + +* Therp BV +* Giacomo Spettoli + +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. diff --git a/__unported__/users_ldap_groups/__init__.py b/users_ldap_groups/__init__.py similarity index 96% rename from __unported__/users_ldap_groups/__init__.py rename to users_ldap_groups/__init__.py index d359182a2..d1066f41b 100644 --- a/__unported__/users_ldap_groups/__init__.py +++ b/users_ldap_groups/__init__.py @@ -19,4 +19,4 @@ # ############################################################################## -import users_ldap_groups +from . import users_ldap_groups diff --git a/__unported__/users_ldap_groups/__openerp__.py b/users_ldap_groups/__openerp__.py similarity index 58% rename from __unported__/users_ldap_groups/__openerp__.py rename to users_ldap_groups/__openerp__.py index 190917a88..39ca3893c 100644 --- a/__unported__/users_ldap_groups/__openerp__.py +++ b/users_ldap_groups/__openerp__.py @@ -25,30 +25,8 @@ "depends": ["auth_ldap"], "author": "Therp BV,Odoo Community Association (OCA)", "license": "AGPL-3", - "description": """ + "summary": """ 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", "data": [ diff --git a/__unported__/users_ldap_groups/i18n/users_ldap_groups.pot b/users_ldap_groups/i18n/users_ldap_groups.pot similarity index 100% rename from __unported__/users_ldap_groups/i18n/users_ldap_groups.pot rename to users_ldap_groups/i18n/users_ldap_groups.pot diff --git a/__unported__/users_ldap_groups/security/ir.model.access.csv b/users_ldap_groups/security/ir.model.access.csv similarity index 100% rename from __unported__/users_ldap_groups/security/ir.model.access.csv rename to users_ldap_groups/security/ir.model.access.csv diff --git a/users_ldap_groups/users_ldap_groups.py b/users_ldap_groups/users_ldap_groups.py new file mode 100644 index 000000000..4d08d8aaf --- /dev/null +++ b/users_ldap_groups/users_ldap_groups.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2012 Therp BV (). +# +# 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 . +# +############################################################################## + +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 diff --git a/__unported__/users_ldap_groups/users_ldap_groups.xml b/users_ldap_groups/users_ldap_groups.xml similarity index 100% rename from __unported__/users_ldap_groups/users_ldap_groups.xml rename to users_ldap_groups/users_ldap_groups.xml