Browse Source

Therp's modules to sync OpenERP with LDAP directories

pull/2/head
Daniel Reis 11 years ago
parent
commit
8f373af1f6
  1. 22
      users_ldap_groups/__init__.py
  2. 62
      users_ldap_groups/__openerp__.py
  3. 2
      users_ldap_groups/security/ir.model.access.csv
  4. 98
      users_ldap_groups/users_ldap_groups.py
  5. 28
      users_ldap_groups/users_ldap_groups.xml
  6. 44
      users_ldap_groups/users_ldap_groups_operators.py
  7. 1
      users_ldap_populate/__init__.py
  8. 49
      users_ldap_populate/__openerp__.py
  9. 56
      users_ldap_populate/i18n/nl.po
  10. 2
      users_ldap_populate/model/__init__.py
  11. 42
      users_ldap_populate/model/populate_wizard.py
  12. 96
      users_ldap_populate/model/users_ldap.py
  13. 18
      users_ldap_populate/view/populate_wizard.xml
  14. 20
      users_ldap_populate/view/users_ldap.xml

22
users_ldap_groups/__init__.py

@ -0,0 +1,22 @@
# -*- 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/>.
#
##############################################################################
import users_ldap_groups

62
users_ldap_groups/__openerp__.py

@ -0,0 +1,62 @@
# -*- 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/>.
#
##############################################################################
{
"name" : "Groups assignment",
"version" : "1.0",
"depends" : ["auth_ldap"],
"author" : "Therp BV",
"description": """
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" : [
'users_ldap_groups.xml',
'security/ir.model.access.csv',
],
"installable": True,
"external_dependencies" : {
'python' : ['ldap'],
},
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

2
users_ldap_groups/security/ir.model.access.csv

@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_res_company_ldap_groups,res_company_ldap_groups,model_res_company_ldap_group_mapping,base.group_system,1,1,1,1

98
users_ldap_groups/users_ldap_groups.py

@ -0,0 +1,98 @@
# -*- 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
import sys
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=[]
for name, operator in inspect.getmembers(users_ldap_groups_operators,
lambda cls: inspect.isclass(cls)
and cls!=users_ldap_groups_operators.LDAPOperator):
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, )]})
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])]})
return user_id

28
users_ldap_groups/users_ldap_groups.xml

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="company_form_view">
<field name="name">res.company.form.inherit.users_ldap_groups</field>
<field name="model">res.company</field>
<field name="type">form</field>
<field name="inherit_id" ref="auth_ldap.company_form_view"/>
<field name="arch" type="xml">
<xpath expr="//form[@string='LDAP Configuration']" position="inside">
<group string="Map User Groups" >
<field name="only_ldap_groups" />
<field name="group_mappings" colspan="4" nolabel="1">
<tree editable="top">
<field name="ldap_attribute" attrs="{'required': [('operator','not in',['query'])], 'readonly': [('operator','in',['query'])]}" />
<field name="operator" />
<field name="value" />
<field name="group" />
</tree>
</field>
</group>
</xpath>
</field>
</record>
</data>
</openerp>

44
users_ldap_groups/users_ldap_groups_operators.py

@ -0,0 +1,44 @@
# -*- 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 (str(value)==str(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([(attribute,
ldap_entry[1][attribute][0]) for attribute 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)

1
users_ldap_populate/__init__.py

@ -0,0 +1 @@
import model

49
users_ldap_populate/__openerp__.py

@ -0,0 +1,49 @@
# -*- 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/>.
#
##############################################################################
{
"name": "LDAP Populate",
"version": "1.0",
"author": "Therp BV",
"category": 'Tools',
"description": """
This module allows to prepopulate the user database with all entries in the LDAP
database.
In order to schedule the population of the user database on a regular basis,
create a new scheduled action with the following properties:
- Object: res.company.ldap
- Function: action_populate
- Arguments: [res.company.ldap.id]
Substitute res.company.ldap.id with the actual id of the res.company.ldap object you want to query.
""",
"depends": [
'auth_ldap',
],
"data": [
'view/users_ldap.xml',
'view/populate_wizard.xml',
],
'installable': True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

56
users_ldap_populate/i18n/nl.po

@ -0,0 +1,56 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * users_ldap_populate
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 6.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-07-31 13:08+0000\n"
"PO-Revision-Date: 2012-07-31 13:08+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: users_ldap_populate
#: field:res.company.ldap.populate_wizard,ldap_id:0
msgid "LDAP Configuration"
msgstr "LDAP configuratie"
#. module: users_ldap_populate
#: view:res.company:0
msgid "Populate user database"
msgstr "Gebruikersbestand bevolken"
#. module: users_ldap_populate
#: field:res.company.ldap.populate_wizard,name:0
msgid "Name"
msgstr "Naam"
#. module: users_ldap_populate
#: view:res.company:0
msgid "Populate"
msgstr "Bevolken"
#. module: users_ldap_populate
#: model:ir.model,name:users_ldap_populate.model_res_company_ldap_populate_wizard
msgid "Populate users from LDAP"
msgstr "Gebruikersbestand bevolken op basis van LDAP"
#. module: users_ldap_populate
#: field:res.company.ldap.populate_wizard,users_created:0
msgid "Number of users created"
msgstr "Aantal aangemaakte gebruikers"
#. module: users_ldap_populate
#: model:ir.model,name:users_ldap_populate.model_res_company_ldap
msgid "res.company.ldap"
msgstr "res.company.ldap"
#. module: users_ldap_populate
#: view:res.company.ldap.populate_wizard:0
msgid "OK"
msgstr "OK"

2
users_ldap_populate/model/__init__.py

@ -0,0 +1,2 @@
import users_ldap
import populate_wizard

42
users_ldap_populate/model/populate_wizard.py

@ -0,0 +1,42 @@
# -*- 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 osv import osv, fields
class CompanyLDAPPopulateWizard(osv.TransientModel):
_name = 'res.company.ldap.populate_wizard'
_description = 'Populate users from LDAP'
_columns = {
'name': fields.char('Name', size=16),
'ldap_id': fields.many2one(
'res.company.ldap', 'LDAP Configuration'),
'users_created': fields.integer(
'Number of users created', readonly=True),
}
def create(self, cr, uid, vals, context=None):
ldap_pool = self.pool.get('res.company.ldap')
users_pool = self.pool.get('res.users')
if 'ldap_id' in vals:
vals['users_created'] = ldap_pool.action_populate(
cr, uid, vals['ldap_id'], context=context)
return super(CompanyLDAPPopulateWizard, self).create(
cr, uid, vals, context=None)

96
users_ldap_populate/model/users_ldap.py

@ -0,0 +1,96 @@
# -*- 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/>.
#
##############################################################################
import re
from ldap.filter import filter_format
from openerp.osv import orm, fields
import openerp.exceptions
import logging
class CompanyLDAP(orm.Model):
_inherit = 'res.company.ldap'
def action_populate(self, cr, uid, ids, context=None):
"""
Prepopulate the user table from one or more LDAP resources.
Obviously, the option to create users must be toggled in
the LDAP configuration.
Return the number of users created (as far as we can tell).
"""
if isinstance(ids, (int, float)):
ids = [ids]
users_pool = self.pool.get('res.users')
users_no_before = users_pool.search(
cr, uid, [], context=context, count=True)
logger = logging.getLogger('orm.ldap')
logger.debug("action_populate called on res.company.ldap ids %s", ids)
for conf in self.get_ldap_dicts(cr, ids):
if not conf['create_user']:
continue
attribute_match = re.search(
'([a-zA-Z_]+)=\%s', conf['ldap_filter'])
if attribute_match:
login_attr = attribute_match.group(1)
else:
raise osv.except_osv(
"No login attribute found",
"Could not extract login attribute from filter %s" %
conf['ldap_filter'])
ldap_filter = filter_format(conf['ldap_filter'] % '*', ())
for result in self.query(conf, ldap_filter):
self.get_or_create_user(
cr, uid, conf, result[1][login_attr][0], result)
users_no_after = users_pool.search(
cr, uid, [], context=context, count=True)
users_created = users_no_after - users_no_before
logger.debug("%d users created", users_created)
return users_created
def populate_wizard(self, cr, uid, ids, context=None):
"""
GUI wrapper for the populate method that reports back
the number of users created.
"""
if not ids:
return
if isinstance(ids, (int, float)):
ids = [ids]
wizard_obj = self.pool.get('res.company.ldap.populate_wizard')
res_id = wizard_obj.create(
cr, uid, {'ldap_id': ids[0]}, context=context)
return {
'name': wizard_obj._description,
'view_type': 'form',
'view_mode': 'form',
'res_model': wizard_obj._name,
'domain': [],
'context': context,
'type': 'ir.actions.act_window',
'target': 'new',
'res_id': res_id,
'nodestroy': True,
}

18
users_ldap_populate/view/populate_wizard.xml

@ -0,0 +1,18 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="populate_wizard_view">
<field name="name">Add populate button to ldap view</field>
<field name="model">res.company.ldap.populate_wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Add populate button to ldap view" version="7.0">
<group col="4">
<field name="users_created"/>
<button icon="gtk-ok" string="OK" special="cancel"/>
</group>
</form>
</field>
</record>
</data>
</openerp>

20
users_ldap_populate/view/users_ldap.xml

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="company_form_view">
<field name="name">Add populate button to ldap view</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="auth_ldap.company_form_view"/>
<field name="arch" type="xml">
<xpath expr="//form[@string='LDAP Configuration']" position="inside">
<separator string="Populate user database" colspan="4"/>
<button name="populate_wizard"
string="Populate"
type="object"
colspan="2"/>
</xpath>
</field>
</record>
</data>
</openerp>
Loading…
Cancel
Save