From ed25f0ba2b01cebb72f3b37d98f81b77eabdca84 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Mon, 17 Feb 2025 12:16:28 +0100 Subject: [PATCH] Synchronization is now operated from dolibarr data --- main.py | 146 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 55 deletions(-) mode change 100644 => 100755 main.py diff --git a/main.py b/main.py old mode 100644 new mode 100755 index 782bfd2..160cb1d --- a/main.py +++ b/main.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dolibarrpy import Dolibarrpy -from ldap3 import ALL, Connection, ObjectDef, Reader, Server, Writer +from ldap3 import ALL, Connection, ObjectDef, Reader, Server, WritableEntry, Writer import config @@ -20,71 +20,107 @@ def main(): def manage_users_extra_fields(ldap_conn: Connection, dolibarr_client: Dolibarrpy): dolibarr_users = dolibarr_client.find_all_users() + for dolibarr_user in dolibarr_users: + manage_user_extra_fields(ldap_conn, dolibarr_user) - obj_inetorgperson = ObjectDef(['inetOrgPerson'] + config.LDAP_USERS_EXTRA_OBJECT_CLASSES, ldap_conn) - users_reader = Reader(ldap_conn, obj_inetorgperson, config.LDAP_USERS_OU) + +def manage_user_extra_fields(ldap_conn: Connection, dolibarr_user: dict): + login = dolibarr_user['login'] + obj_inetorgperson = ObjectDef(['top', 'inetOrgPerson', 'posixAccount'], ldap_conn) + obj_user = ObjectDef(['top', 'inetOrgPerson', 'posixAccount'] + config.LDAP_GROUPS_EXTRA_OBJECT_CLASSES, ldap_conn) + users_reader = Reader(ldap_conn, obj_inetorgperson, config.LDAP_USERS_OU, f"uid:={login}") users_reader.search() - users_writer = Writer.from_cursor(users_reader) - for ldap_user in users_writer: - uid = ldap_user.uid - for dolibarr_user in dolibarr_users: - if dolibarr_user['login'] == uid: - break - else: - continue - - for extra_object_class in config.LDAP_USERS_EXTRA_OBJECT_CLASSES: - if extra_object_class not in ldap_user.objectClass: - ldap_user.objectClass.append(extra_object_class) - - for extra_field in config.LDAP_USERS_EXTRA_FIELDS: - dolibarr_attr, ldap_attr = extra_field.split(':') - if dolibarr_attr.endswith('[]'): - dolibarr_attr = dolibarr_attr[:-2] - value = dolibarr_user['array_options'][f'options_{dolibarr_attr}'] - value = value.split() if value else [] - setattr(ldap_user, ldap_attr, value) - else: - value = dolibarr_user['array_options'][f'options_{dolibarr_attr}'] or "" - setattr(ldap_user, ldap_attr, value) + users_writer = Writer.from_cursor(users_reader, object_def=obj_user) + if users_writer.entries: + ldap_user = users_writer[0] + else: + attrs = { + 'cn': f"{dolibarr_user['firstname']} {dolibarr_user['lastname']}".strip(), + 'givenName': dolibarr_user['firstname'], + 'sn': dolibarr_user['lastname'], + 'mail': dolibarr_user['email'], + 'street': dolibarr_user['address'], + 'postalCode': dolibarr_user['zip'], + 'l': dolibarr_user['town'], + 'mobile': dolibarr_user['user_mobile'], + 'uidNumber': dolibarr_user['id'], + 'gidNumber': dolibarr_user['id'], + 'homeDirectory': f"/home/{login}", + } + for key, value in list(attrs.items()): + if not value: + del attrs[key] + ldap_conn.add(f"uid={login},{config.LDAP_USERS_OU}", ["top", "inetOrgPerson", "posixAccount", "shadowAccount"], attrs) + users_reader.search() + users_writer = Writer.from_cursor(users_reader, object_def=obj_user) + ldap_user = users_writer[0] + append_extra_fields_to_ldap_user(ldap_user, dolibarr_user) users_writer.commit() +def append_extra_fields_to_ldap_user(ldap_user: WritableEntry, dolibarr_user: dict): + for extra_object_class in config.LDAP_USERS_EXTRA_OBJECT_CLASSES: + if extra_object_class not in ldap_user.objectClass: + ldap_user.objectClass += extra_object_class + + for extra_field in config.LDAP_USERS_EXTRA_FIELDS: + dolibarr_attr, ldap_attr = extra_field.split(':') + if dolibarr_attr.endswith('[]'): + dolibarr_attr = dolibarr_attr[:-2] + value = dolibarr_user['array_options'][f'options_{dolibarr_attr}'] + value = value.split() if value else [] + setattr(ldap_user, ldap_attr, value) + else: + value = dolibarr_user['array_options'][f'options_{dolibarr_attr}'] or "" + setattr(ldap_user, ldap_attr, value) + + def manage_groups_extra_fields(ldap_conn: Connection, dolibarr_client: Dolibarrpy): dolibarr_groups = dolibarr_client.call_list_api('users/groups') + for dolibarr_group in dolibarr_groups: + manage_group_extra_fields(ldap_conn, dolibarr_group) - obj_posixgroup = ObjectDef(['posixGroup'] + config.LDAP_GROUPS_EXTRA_OBJECT_CLASSES, ldap_conn) - groups_reader = Reader(ldap_conn, obj_posixgroup, config.LDAP_GROUPS_OU) + +def manage_group_extra_fields(ldap_conn: Connection, dolibarr_group: dict): + name = dolibarr_group['name'] + obj_posixgroup = ObjectDef(['posixGroup'], ldap_conn) + obj_group = ObjectDef(['posixGroup'] + config.LDAP_GROUPS_EXTRA_OBJECT_CLASSES, ldap_conn) + groups_reader = Reader(ldap_conn, obj_posixgroup, config.LDAP_GROUPS_OU, f"cn:={name}") groups_reader.search() - groups_writer = Writer.from_cursor(groups_reader) - for ldap_group in groups_writer: - print(ldap_group) - name = ldap_group.cn - for dolibarr_group in dolibarr_groups: - if dolibarr_group['nom'] == name: - break - else: - continue - - for extra_object_class in config.LDAP_GROUPS_EXTRA_OBJECT_CLASSES: - if extra_object_class not in ldap_group.objectClass: - ldap_group.objectClass.append(extra_object_class) - - for extra_field in config.LDAP_GROUPS_EXTRA_FIELDS: - dolibarr_attr, ldap_attr = extra_field.split(':') - if dolibarr_attr.endswith('[]'): - dolibarr_attr = dolibarr_attr[:-2] - print(dolibarr_group) - value = dolibarr_group['array_options'][f'options_{dolibarr_attr}'] - value = value.split() if value else [] - print(ldap_attr, value) - setattr(ldap_group, ldap_attr, value) - else: - value = dolibarr_group['array_options'][f'options_{dolibarr_attr}'] or "" - print(ldap_attr, value) - setattr(ldap_group, ldap_attr, value) + groups_writer = Writer.from_cursor(groups_reader, object_def=obj_group) + if groups_writer.entries: + ldap_group = groups_writer[0] + else: + attrs = { + 'cn': name, + 'gidNumber': dolibarr_group['id'], + } + for key, value in list(attrs.items()): + if not value: + del attrs[key] + ldap_conn.add(f"cn={name},{config.LDAP_GROUPS_OU}", ["top", "posixGroup"], attrs) + groups_reader.search() + groups_writer = Writer.from_cursor(groups_reader, object_def=obj_group) + ldap_group = groups_writer[0] + append_extra_fields_to_ldap_group(ldap_group, dolibarr_group) groups_writer.commit() +def append_extra_fields_to_ldap_group(ldap_group: WritableEntry, dolibarr_group: dict): + for extra_object_class in config.LDAP_GROUPS_EXTRA_OBJECT_CLASSES: + if extra_object_class not in ldap_group.objectClass: + ldap_group.objectClass += extra_object_class + + for extra_field in config.LDAP_GROUPS_EXTRA_FIELDS: + dolibarr_attr, ldap_attr = extra_field.split(':') + if dolibarr_attr.endswith('[]'): + dolibarr_attr = dolibarr_attr[:-2] + value = dolibarr_group['array_options'][f'options_{dolibarr_attr}'] + value = value.split() if value else [] + setattr(ldap_group, ldap_attr, value) + else: + value = dolibarr_group['array_options'][f'options_{dolibarr_attr}'] or "" + setattr(ldap_group, ldap_attr, value) + if __name__ == '__main__': main()