Skip to content
Snippets Groups Projects
Commit f7b06717 authored by Julian's avatar Julian
Browse files

Simplified defaults mechanism and added attribute aliases

parent 467bf2a3
Branches
No related tags found
No related merge requests found
...@@ -40,7 +40,7 @@ class UffdTestCase(unittest.TestCase): ...@@ -40,7 +40,7 @@ class UffdTestCase(unittest.TestCase):
os.system("ldapdelete -c -D 'cn=uffd,ou=system,dc=example,dc=com' -w 'uffd-ldap-password' -H 'ldap://localhost' -f ldap_server_entries_cleanup.ldif > /dev/null 2>&1") os.system("ldapdelete -c -D 'cn=uffd,ou=system,dc=example,dc=com' -w 'uffd-ldap-password' -H 'ldap://localhost' -f ldap_server_entries_cleanup.ldif > /dev/null 2>&1")
os.system("ldapadd -c -D 'cn=uffd,ou=system,dc=example,dc=com' -w 'uffd-ldap-password' -H 'ldap://localhost' -f ldap_server_entries_add.ldif") os.system("ldapadd -c -D 'cn=uffd,ou=system,dc=example,dc=com' -w 'uffd-ldap-password' -H 'ldap://localhost' -f ldap_server_entries_add.ldif")
os.system("ldapmodify -c -D 'cn=uffd,ou=system,dc=example,dc=com' -w 'uffd-ldap-password' -H 'ldap://localhost' -f ldap_server_entries_modify.ldif") os.system("ldapmodify -c -D 'cn=uffd,ou=system,dc=example,dc=com' -w 'uffd-ldap-password' -H 'ldap://localhost' -f ldap_server_entries_modify.ldif")
os.system("/usr/sbin/slapcat -n 1 -l /dev/stdout") #os.system("/usr/sbin/slapcat -n 1 -l /dev/stdout")
self.app = create_app(config) self.app = create_app(config)
self.setUpApp() self.setUpApp()
self.client = self.app.test_client() self.client = self.app.test_client()
......
...@@ -149,24 +149,27 @@ class LDAPSet(MutableSet): ...@@ -149,24 +149,27 @@ class LDAPSet(MutableSet):
self.__delitem(self.__encode(value)) self.__delitem(self.__encode(value))
class LDAPAttribute: class LDAPAttribute:
def __init__(self, name, multi=False, default=None, encode=None, decode=None): def __init__(self, name, multi=False, default=None, encode=None, decode=None, aliases=None):
self.name = name self.name = name
self.multi = multi self.multi = multi
self.encode = encode or (lambda x: x) self.encode = encode or (lambda x: x)
self.decode = decode or (lambda x: x) self.decode = decode or (lambda x: x)
def default_wrapper(): self.default_values = default
values = default() if callable(default) else default self.aliases = aliases or []
if not isinstance(values, list):
values = [values] def default(self, obj):
return [self.encode(value) for value in values] if obj.ldap_getattr(self.name) == []:
self.default = default_wrapper values = self.default_values
if callable(values):
values = values()
self.__set__(obj, values)
for name in self.aliases:
obj.ldap_setattr(name, obj.ldap_getattr(self.name))
def __set_name__(self, cls, name): def __set_name__(self, cls, name):
if self.default is None: if self.default is None:
return return
if not cls.ldap_defaults: cls.ldap_defaults = cls.ldap_defaults + [self.default]
cls.ldap_defaults = {}
cls.ldap_defaults[self.name] = self.default
def __get__(self, obj, objtype=None): def __get__(self, obj, objtype=None):
if obj is None: if obj is None:
...@@ -187,9 +190,7 @@ class LDAPBackref: ...@@ -187,9 +190,7 @@ class LDAPBackref:
def __init__(self, srccls, srcattr): def __init__(self, srccls, srcattr):
self.srccls = srccls self.srccls = srccls
self.srcattr = srcattr self.srcattr = srcattr
if srccls.ldap_relations is None: srccls.ldap_relations = srccls.ldap_relations + [srcattr]
srccls.ldap_relations = set()
srccls.ldap_relations.add(srcattr)
def init(self, obj): def init(self, obj):
if self.srcattr not in obj.ldap_relation_data and obj.ldap_created: if self.srcattr not in obj.ldap_relation_data and obj.ldap_created:
...@@ -229,8 +230,9 @@ class LDAPModel: ...@@ -229,8 +230,9 @@ class LDAPModel:
ldap_base = None ldap_base = None
ldap_object_classes = None ldap_object_classes = None
ldap_filter = None ldap_filter = None
ldap_defaults = None # Populated by LDAPAttribute # Caution: Never mutate ldap_defaults and ldap_relations, always reassign!
ldap_relations = None # Populated by LDAPBackref ldap_defaults = []
ldap_relations = []
def __init__(self, _ldap_dn=None, _ldap_attributes=None, **kwargs): def __init__(self, _ldap_dn=None, _ldap_attributes=None, **kwargs):
self.ldap_relation_data = set() self.ldap_relation_data = set()
...@@ -247,11 +249,11 @@ class LDAPModel: ...@@ -247,11 +249,11 @@ class LDAPModel:
if not hasattr(self, key): if not hasattr(self, key):
raise Exception() raise Exception()
setattr(self, key, value) setattr(self, key, value)
for name in (self.ldap_relations or []): for name in self.ldap_relations:
self.__update_relations(name, add_dns=self.__attributes.get(name, [])) self.__update_relations(name, add_dns=self.__attributes.get(name, []))
def __update_relations(self, name, delete_dns=None, add_dns=None): def __update_relations(self, name, delete_dns=None, add_dns=None):
if name in (self.ldap_relations or []): if name in self.ldap_relations:
ldap.session.update_relations(self, name, delete_dns, add_dns) ldap.session.update_relations(self, name, delete_dns, add_dns)
def ldap_getattr(self, name): def ldap_getattr(self, name):
...@@ -344,11 +346,11 @@ class LDAPModel: ...@@ -344,11 +346,11 @@ class LDAPModel:
return cls.ldap_filter_by_raw(**_kwargs) return cls.ldap_filter_by_raw(**_kwargs)
def ldap_reset(self): def ldap_reset(self):
for name in (self.ldap_relations or []): for name in self.ldap_relations:
self.__update_relations(name, delete_dns=self.__attributes.get(name, [])) self.__update_relations(name, delete_dns=self.__attributes.get(name, []))
self.__changes = {} self.__changes = {}
self.__attributes = deepcopy(self.__ldap_attributes) self.__attributes = deepcopy(self.__ldap_attributes)
for name in (self.ldap_relations or {}): for name in self.ldap_relations:
self.__update_relations(name, add_dns=self.__attributes.get(name, [])) self.__update_relations(name, add_dns=self.__attributes.get(name, []))
@property @property
...@@ -375,13 +377,11 @@ class LDAPModel: ...@@ -375,13 +377,11 @@ class LDAPModel:
if self.ldap_created: if self.ldap_created:
raise Exception() raise Exception()
conn = get_conn() conn = get_conn()
for key, func in (self.ldap_defaults or {}).items(): for func in self.ldap_defaults:
if key not in self.__attributes: func(self)
values = func()
self.__attributes[key] = values
self.__changes[key] = [(MODIFY_REPLACE, values)]
success = conn.add(self.dn, self.ldap_object_classes, self.__attributes) success = conn.add(self.dn, self.ldap_object_classes, self.__attributes)
if not success: if not success:
print('commit error', success, conn.result)
raise LDAPCommitError() raise LDAPCommitError()
self.__changes = {} self.__changes = {}
self.__ldap_attributes = deepcopy(self.__attributes) self.__ldap_attributes = deepcopy(self.__attributes)
......
...@@ -25,10 +25,20 @@ class User(LDAPModel): ...@@ -25,10 +25,20 @@ class User(LDAPModel):
uid = LDAPAttribute('uidNumber', default=get_next_uid) uid = LDAPAttribute('uidNumber', default=get_next_uid)
loginname = LDAPAttribute('uid') loginname = LDAPAttribute('uid')
displayname = LDAPAttribute('cn') displayname = LDAPAttribute('cn', aliases=['givenName', 'displayName'])
mail = LDAPAttribute('mail') mail = LDAPAttribute('mail')
pwhash = LDAPAttribute('userPassword', default=lambda: hashed(HASHED_SALTED_SHA512, secrets.token_hex(128))) pwhash = LDAPAttribute('userPassword', default=lambda: hashed(HASHED_SALTED_SHA512, secrets.token_hex(128)))
def dummy_attribute_defaults(self):
if self.ldap_getattr('sn') == []:
self.ldap_setattr('sn', [' '])
if self.ldap_getattr('homeDirectory') == []:
self.ldap_setattr('homeDirectory', ['/home/%s'%self.loginname])
if self.ldap_getattr('gidNumber') == []:
self.ldap_setattr('gidNumber', [current_app.config['LDAP_USER_GID']])
ldap_defaults = LDAPModel.ldap_defaults + [dummy_attribute_defaults]
# Write-only property # Write-only property
def password(self, value): def password(self, value):
self.pwhash = hashed(HASHED_SALTED_SHA512, value) self.pwhash = hashed(HASHED_SALTED_SHA512, value)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment