diff --git a/pdsl_ldap_membership/ldap_membership.py b/pdsl_ldap_membership/ldap_membership.py
index 492564823cff0f1f935dc4a59df0d297c4cc2003..86b9503e1e1184f5f176e183f67c8becd0735eff 100644
--- a/pdsl_ldap_membership/ldap_membership.py
+++ b/pdsl_ldap_membership/ldap_membership.py
@@ -6,10 +6,9 @@
#
##############################################################################
-
import base64
import hashlib
-from ldap import modlist
+from ldap import modlist
import ldap
import logging
import os
@@ -22,21 +21,19 @@ from openerp.exceptions import Warning, ValidationError
from openerp.osv import fields
from openerp.osv import osv
-
_logger = logging.getLogger(__name__)
-
ACTIVE_STATES = ('paid', 'invoiced', 'free')
class Invoice(osv.Model):
'''Invoice'''
_inherit = 'account.invoice'
-
+
# ----------------------------------------
# Invoice state management vs membership
# ----------------------------------------
-
+
def invoice_validate(self, cr, uid, ids, context=None):
"""
Override to update membership line.
@@ -51,8 +48,8 @@ class Invoice(osv.Model):
[l.id for l in invoice.invoice_line])])
if mlines:
member_line_obj.write(cr, uid, mlines, {'date_cancel': None})
- return res
-
+ return res
+
def action_cancel_draft(self, cr, uid, ids, context=None):
"""
Override to update membership lines.
@@ -80,7 +77,7 @@ class Invoice(osv.Model):
# TODO Check if the invoice contains any membership lines ?
return True
return False
-
+
@api.multi
def write(self, vals):
res = super(Invoice, self).write(vals)
@@ -89,6 +86,7 @@ class Invoice(osv.Model):
self.partner_id.pdsl_update_ldap_membership()
return res
+
class ProductTemplate(osv.osv):
"""Add column to product"""
_inherit = "product.template"
@@ -99,7 +97,7 @@ class ProductTemplate(osv.osv):
_defaults = {
'ldap_membership_group': False,
}
-
+
@api.multi
def pdsl_update_ldap_group(self):
"""
@@ -110,7 +108,7 @@ class ProductTemplate(osv.osv):
return
_logger.info('updating LDAP product [%s]' % self.ldap_membership_group)
-
+
# Connect to LDAP server
ldap_obj = self.env['res.company.ldap']
for conf in ldap_obj.get_ldap_dicts():
@@ -122,7 +120,7 @@ class ProductTemplate(osv.osv):
_logger.warn('connection to LDAP server failed', exc_info=1)
if not l:
raise ValueError('LDAP execution failed')
-
+
def _new_gid():
"""Query the ldap directory for a new gidNumber."""
# Get list of uid. Pick Max +1
@@ -132,9 +130,9 @@ class ProductTemplate(osv.osv):
filterstr='(&(objectClass=posixGroup)(gidNumber=*))',
attrlist=['gidNumber'])
if len(r) > 0:
- return max(int(u[1]['gidNumber'][0]) for u in r) + 1
+ return max(int(u[1]['gidNumber'][0]) for u in r) + 1
raise ValueError("fail to find new gidNumber")
-
+
changed = False
try:
for group_name in self.ldap_membership_group.split(','):
@@ -145,7 +143,7 @@ class ProductTemplate(osv.osv):
attrs = {
'cn': group_name_b,
}
-
+
# Search group in LDAP.
search_filter = ldap.filter.filter_format('(&(objectClass=posixGroup)(cn=%s))', (group_name_b,))
r = l.search_s(
@@ -158,19 +156,18 @@ class ProductTemplate(osv.osv):
attrs['description'] = self.name.encode('utf-8')
attrs['gidNumber'] = str(_new_gid())
attrs['objectclass'] = ['posixGroup']
-
+
# User doesn't exists. Add it
dn = 'cn=%s,%s,%s' % (attrs['cn'], 'ou=Groups', conf['ldap_base'])
ldif = modlist.addModlist(attrs)
l.add_s(dn, ldif)
- self.message_post(body=_("LDAP group %s created") % group_name)
- changed = True
+ self.message_post(body=_("LDAP group %s created") % group_name)
+ changed = True
finally:
l.unbind_s()
-
+
return changed
-
-
+
@api.multi
def write(self, vals):
"""Override to create the group in LDAP."""
@@ -182,11 +179,11 @@ class ProductTemplate(osv.osv):
# TODO Should update all membership if ldap_membership_group change.
pass
return res
-
+
class ResPartner(models.Model):
_inherit = "res.partner"
-
+
# Declare new fields.
_columns = {
'ldap_membership_login': fields.char('Membership Login', size=64, required=False,
@@ -207,7 +204,7 @@ class ResPartner(models.Model):
if not ldap_obj.get_ldap_dicts():
_logger.warn('skip LDAP membership update - LDAP server not configured')
return
-
+
# Connect to LDAP server
for conf in ldap_obj.get_ldap_dicts():
try:
@@ -243,7 +240,7 @@ class ResPartner(models.Model):
username = re.sub('[ \-]', '.', username.lower())
# Remove invalid char
return re.sub('[^a-z0-9.]', '', username)
-
+
def _new_username():
"""Generate a unused ldap username."""
candidates = []
@@ -261,15 +258,15 @@ class ResPartner(models.Model):
attrsonly=1)
if len(r) == 0:
return c
- raise ValueError('cannot generate a unique username')
-
+ raise ValueError('cannot generate a unique username')
+
# Find a free user name.
login = None
try:
login = _new_username()
finally:
l.unbind_s()
-
+
# Update the user with this new user name.
if login:
self.write(vals={'ldap_membership_login': login})
@@ -286,13 +283,13 @@ class ResPartner(models.Model):
if not active and not self.ldap_membership_login:
# Update not required.
return
-
+
# Generate a new username.
if not self.ldap_membership_login:
self._pdsl_set_ldap_user()
_logger.info('updating user [%s] membership' % self.ldap_membership_login)
-
+
# Connect to LDAP server
l, ldap_conf = self._connect()
@@ -321,7 +318,7 @@ class ResPartner(models.Model):
'shadowExpire': str(int(expire_date // 86400)), # / 24 / 60 / 60
'description': groups_b,
}
-
+
# Search user in LDAP.
search_filter = ldap.filter.filter_format(ldap_conf['ldap_filter'], (ldap_membership_login_b,))
r = l.search_s(
@@ -333,7 +330,7 @@ class ResPartner(models.Model):
# Raise exception user should exists.
# Most likely user was deleted manually in LDAP.
raise Warning(_("Failed to update LDAP membership.\nLDAP user %s doesn't exists!") % self.ldap_membership_login)
-
+
# Update the record.
dn = r[0][0]
old = r[0][1]
@@ -360,9 +357,9 @@ class ResPartner(models.Model):
new['memberUid'].append(ldap_membership_login_b)
ldif = modlist.modifyModlist(old, new)
l.modify_s(dn, ldif)
-
+
# TODO Remove user from other groups ?
-
+
# Log this as an event.
self.message_post(
body=_("LDAP membership for user [%s] updated.
Member of: %s
Expired: %s") % (self.ldap_membership_login, ', '.join(groups), time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(expire_date))))
@@ -378,18 +375,18 @@ class ResPartner(models.Model):
@api.multi
def pdsl_update_ldap_user(self, force_reset_password=False):
"""Update or create the LDAP user."""
-
+
if not self.ldap_membership_login:
return
# Basic verification to make sure we have the right information.
if not self.name:
- raise Warning(_("Failed to update the LDAP membership.\nName field is required."))
+ raise Warning(_("Failed to update the LDAP membership.\nName field is required."))
if not self.email:
raise Warning(_("Failed to update the LDAP membership.\nEmail field is required."))
-
+
_logger.info('updating LDAP user %s' % self.ldap_membership_login)
-
+
# Connect to LDAP server
l, ldap_conf = self._connect()
@@ -402,14 +399,14 @@ class ResPartner(models.Model):
filterstr='(&(objectClass=posixAccount)(uidNumber=*))',
attrlist=['uidNumber'])
if len(r) > 0:
- return max(int(u[1]['uidNumber'][0]) for u in r) + 1
+ return max(int(u[1]['uidNumber'][0]) for u in r) + 1
raise Warning(_("fail to find new uidNumber"))
-
+
def _new_password(length=8):
"""Generate a new password."""
table = string.lowercase + string.digits
return ''.join([table[ord(c) % len(table)] for c in os.urandom(length)])
-
+
def _ssha(password):
"""Convert the password a SSHA (base64 SHA hash + salt)"""
salt = os.urandom(4)
@@ -417,7 +414,7 @@ class ResPartner(models.Model):
sha.update(salt)
digest_salt_b64 = '{}{}'.format(sha.digest(), salt).encode('base64').strip()
return '{{SSHA}}{}'.format(digest_salt_b64)
-
+
try:
# Build up expected user (should be bytes)
ldap_membership_login_b = self.ldap_membership_login.encode('utf-8')
@@ -429,7 +426,7 @@ class ResPartner(models.Model):
'sn': name_b.partition(' ')[2] or name_b.partition(' ')[0], # Lastname (required)
'mail': email_b,
}
-
+
# Search user in LDAP.
search_filter = ldap.filter.filter_format(ldap_conf['ldap_filter'], (ldap_membership_login_b,))
r = l.search_s(
@@ -448,22 +445,22 @@ class ResPartner(models.Model):
attrs['homeDirectory'] = '/home/%s' % (ldap_membership_login_b,)
attrs['objectclass'] = ['inetOrgPerson', 'posixAccount', 'organizationalPerson', 'person', 'shadowAccount']
attrs['userPassword'] = _ssha(password)
-
+
# User doesn't exists. Add it
dn = 'uid=%s,%s,%s' % (attrs['uid'], 'ou=People', ldap_conf['ldap_base'])
ldif = modlist.addModlist(attrs)
l.add_s(dn, ldif)
-
+
# Send username and password by mail.
ctx = dict(self._context, password=password)
template_id = self.env['ir.model.data'].xmlid_to_object('pdsl_ldap_membership.new_password_email_template')
template_id.with_context(ctx).send_mail(self.id)
-
+
self.message_post(body=_("LDAP user %s / %s created") % (self.ldap_membership_login, password))
-
+
# Also update the membership is a new user was created.
self.pdsl_update_ldap_membership()
-
+
else:
# Generate a new password if required.
if force_reset_password:
@@ -475,15 +472,15 @@ class ResPartner(models.Model):
old = r[0][1]
ldif = modlist.modifyModlist(old, attrs)
l.modify_s(dn, ldif)
-
+
# Send username and password by mail.
if force_reset_password:
ctx = dict(self._context, password=password)
template_id = self.env['ir.model.data'].xmlid_to_object('pdsl_ldap_membership.new_password_email_template')
template_id.with_context(ctx).send_mail(self.id)
-
+
self.message_post(body=_("LDAP user %s updated") % self.ldap_membership_login)
-
+
finally:
# Close connection
l.unbind_s()