diff --git a/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py b/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py index aac8355..7eacbc5 100644 --- a/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py +++ b/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py @@ -527,6 +527,46 @@ def _ldap_pre_remove(self): def _ldap_post_remove(self): pass + def remove_value(self, key, value=None): + """Removes a specific value from the specified property. + If this value is currently not set univention.admin.uexceptions.valueNotSet is raised. + if value is None the whole values of this property gets removed. + """ + if not self.has_key(key): + raise univention.admin.uexceptions.noProperty(key) + + if value is None: + # remove all currently set values + self[key] = [] if self.descriptions[key].multivalue else None + return + + if not self.contains_value(key, value): + raise univention.admin.uexceptions.valueNotSet(key, value) + + if not self.descriptions[key].multivalue: + self[key] = value + return + + current_values = list(self[key]) + for val in current_values[:]: + if self.compare_value(key, value, val): + current_values.remove(val) + self[key] = current_values + + def contains_value(self, key, value): + if self.descriptions[key].multivalue and any(self.compare_value(key, value, val) for val in self[key]): + return True + if not self.descriptions[key].multivalue and self.compare_value(key, value, self[key]): + return True + return False + + def compare_value(self, key, a, b): + return self.descriptions[key].syntax.compare(a, b) + + def append_value(self, key, value): + if not self.has_key(key): + raise univention.admin.uexceptions.noProperty(key) + def _not_implemented_method(attr): def _not_implemented_error(self, *args, **kwargs): diff --git a/management/univention-directory-manager-modules/modules/univention/admin/syntax.py b/management/univention-directory-manager-modules/modules/univention/admin/syntax.py index 3a04a1e..5605c9b 100644 --- a/management/univention-directory-manager-modules/modules/univention/admin/syntax.py +++ b/management/univention-directory-manager-modules/modules/univention/admin/syntax.py @@ -138,6 +138,10 @@ def type(cls): def tostring(self, text): return text + @classmethod + def compare(cls, a, b): + return a == b + class simple(ISyntax): regex = None @@ -2055,17 +2059,23 @@ class soundModule(select): ] -class GroupDN(UDM_Objects): +class _DNCompare(UDM_Objects): + @classmethod + def compare(cls, a, b): + return univention.admin.uldap.DN(a) == univention.admin.uldap.DN(b) + + +class GroupDN(_DNCompare): udm_modules = ('groups/group', ) use_objects = False -class UserDN(UDM_Objects): +class UserDN(_DNCompare): udm_modules = ('users/user', ) use_objects = False -class HostDN(UDM_Objects): +class HostDN(_DNCompare): udm_modules = ('computers/computer', ) udm_filter = '!(univentionObjectFlag=docker)' diff --git a/management/univention-directory-manager-modules/modules/univention/admin/uexceptions.py b/management/univention-directory-manager-modules/modules/univention/admin/uexceptions.py index 1f7e72a..b279ab1 100644 --- a/management/univention-directory-manager-modules/modules/univention/admin/uexceptions.py +++ b/management/univention-directory-manager-modules/modules/univention/admin/uexceptions.py @@ -97,6 +97,10 @@ class valueMismatch(valueError): message = _('Values do not match.') +class valueNotSet(valueError): + message = _('The value is not set.') + + class noLock(base): message = _('Could not acquire lock.') diff --git a/management/univention-directory-manager-modules/modules/univention/admincli/admin.py b/management/univention-directory-manager-modules/modules/univention/admincli/admin.py index 2f5701c..8965800 100755 --- a/management/univention-directory-manager-modules/modules/univention/admincli/admin.py +++ b/management/univention-directory-manager-modules/modules/univention/admincli/admin.py @@ -299,48 +299,25 @@ def object_input(module, object, input, append=None, remove=None): except univention.admin.uexceptions.valueInvalidSyntax, errmsg: out.append('E: Invalid Syntax: %s' % str(errmsg)) if remove: - for key, value in remove.items(): - if univention.admin.syntax.is_syntax(module.property_descriptions[key].syntax, univention.admin.syntax.complex): - if value: - for i in range(0, len(value)): - test_val = value[i].split('"') - if test_val[0] and test_val[0] == value[i]: - val = value[i].split(' ') - else: - val = [] - out.append('test_val=%s' % test_val) - for j in test_val: - if j and j.rstrip().lstrip(): - val.append(j.rstrip().lstrip()) - - for j in range(0, len(val)): - val[j] = '"%s"' % val[j] - - if val and val in object[key]: - object[key].remove(val) - else: - out.append("WARNING: cannot remove %s from %s, value does not exist" % (val, key)) - else: - object[key] = [] + for key, values in remove.items(): + if not values: + values = [None] # remove the whole property - else: - current_values = [object[key]] if isinstance(object[key], basestring) else list(object[key]) - if value is None: - current_values = [] - else: - vallist = [value] if isinstance(value, basestring) else value + if univention.admin.syntax.is_syntax(module.property_descriptions[key].syntax, univention.admin.syntax.complex): + parsed_values = [] + for value in values: + if '"' not in value: + value = value.split(' ') + else: + value = ['"%s"' % (x.strip(),) for x in value.split('"') if x.strip()] + parsed_values.append(value) + values = parsed_values - for val in vallist: - if val in current_values: - current_values.remove(val) - else: - out.append("WARNING: cannot remove %s from %s, value does not exist" % (val, key)) - if not module.property_descriptions[key].multivalue: - try: - current_values = current_values[0] - except IndexError: - current_values = None - object[key] = current_values + for value in values: + try: + object.remove_value(key, value) + except univention.admin.uexceptions.valueNotSet as exc: + out.append("WARNING: cannot remove %s from %s: %s" % (value, key, exc)) if input: for key, value in input.items(): if module.property_descriptions[key].syntax.name == 'binaryfile': @@ -669,28 +646,29 @@ def _doit(arglist): out.append("WARNING: No attribute with name %s in this module, value not appended." % name) elif opt == '--remove': - pos = val.find('=') - if pos == -1: + try: + name, value = val.split('=', 1) + except ValueError: name = val - value = None + remove[name] = None else: - name = val[:pos] - value = _2utf8(val[pos + 1:]) - was_set = False - for mod, (properties, options) in information.items(): - if properties.has_key(name): - was_set = True - if properties[name].multivalue: - if value is None: - remove[name] = value - elif value: - remove.setdefault(name, []) - if remove[name] is not None: - remove[name].append(value) - else: - remove[name] = value - if not was_set: - out.append("WARNING: No attribute with name %s in this module, value not removed." % name) + value = _2utf8(value) + remove.setdefault(name, []).append(value) +# was_set = False +# for mod, (properties, options) in information.items(): +# if properties.has_key(name): +# was_set = True +# if properties[name].multivalue: +# if value is None: +# remove[name] = value +# elif value: +# remove.setdefault(name, []) +# if remove[name] is not None: +# remove[name].append(value) +# else: +# remove[name] = value +# if not was_set: +# out.append("WARNING: No attribute with name %s in this module, value not removed." % name) elif opt == '--remove_referring': remove_referring = 1 elif opt == '--recursive':