diff --git a/branches/ucs-4.1/ucs-4.1-2/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py b/branches/ucs-4.1/ucs-4.1-2/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py index 1c82abb..b2e903a 100644 --- a/branches/ucs-4.1/ucs-4.1-2/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py +++ b/branches/ucs-4.1/ucs-4.1-2/management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py @@ -815,42 +815,50 @@ class simpleLdap(base): ocs -= set(chain.from_iterable(m.options[option].objectClasses for option in removed_options)) ocs |= set(chain.from_iterable(m.options[option].objectClasses for option in added_options)) if set(self.oldattr.get('objectClass', [])) != ocs: - ml = [x for x in ml if x[0].lower() != 'objectClass'.lower()] + ml = [x for x in ml if x[0].lower() != 'objectclass'] ml.append(('objectClass', self.oldattr.get('objectClass', []), list(ocs))) + elif not object_classes_to_remove: + return ml + + # parse LDAP schema + schema = self.lo.get_schema() + newattr = ldap.cidict.cidict(_MergedAttributes(self, ml).get_attributes()) + ocs_afterwards = ocs - object_classes_to_remove + + # make sure we still have a structural object class + if not schema.get_structural_oc(ocs_afterwards): + structural_ocs = schema.get_structural_oc(object_classes_to_remove) + if structural_ocs: + univention.debug.debug(univention.debug.ADMIN, univention.debug.WARN, 'Preventing to remove last structural object class %r' % (structural_ocs,)) + object_classes_to_remove -= set(schema.get_obj(ldap.schema.models.ObjectClass, structural_ocs).names) + ocs_afterwards = ocs - object_classes_to_remove + else: + univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'missing structural object class. Modify will fail.') + return ml - if object_classes_to_remove or set(self.oldattr.get('objectClass', [])) != ocs: - # parse LDAP schema - schema = self.lo.get_schema() - newattr = ldap.cidict.cidict(_MergedAttributes(self, ml).get_attributes()) - ocs_afterwards = set(newattr.get('objectClass', [])) - object_classes_to_remove - - # make sure we still have a structural object class - if not schema.get_structural_oc(ocs_afterwards): - structural_ocs = schema.get_structural_oc(object_classes_to_remove) - if structural_ocs: - univention.debug.debug(univention.debug.ADMIN, univention.debug.WARN, 'Preventing to remove last structural object class %r' % (structural_ocs,)) - object_classes_to_remove -= set(schema.get_obj(ldap.schema.models.ObjectClass, structural_ocs).names) - ocs_afterwards = set(newattr.get('objectClass', [])) - object_classes_to_remove - else: - univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'missing structural object class. Modify will fail.') - - # validate removal of object classes - must, may = schema.attribute_types(ocs_afterwards) - must = ldap.cidict.cidict(dict((x, x) for x in list(chain.from_iterable(x.names for x in must.values())))) - may = ldap.cidict.cidict(dict((x, x) for x in list(chain.from_iterable(x.names for x in may.values())))) - for attr in must.keys(): - if not newattr.get(attr): - univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'The attribute %r is required by the current object classes.' % (attr,)) + # validate removal of object classes + must, may = schema.attribute_types(ocs_afterwards) + allowed = set(name.lower() for attr in may.values() for name in attr.names) | set(name.lower() for attr in must.values() for name in attr.names) + + for attr, val in newattr.items(): + if not val: + continue + if attr.lower() not in allowed: + univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'The attribute %r is not allowed by any object class.' % (attr,)) + # ml.append((attr, val, [])) # TODO: Remove the now invalid attribute instead + return ml + + for attr in must.values(): + for name in attr.names: + if newattr.get(name): break else: - for attr, val in newattr.items(): - if val and not must.get(attr) and not may.get(attr): - univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'The attribute %r is not allowed by any object class.' % (attr,)) - # ml.append((attr, val, [])) # TODO: Remove the now invalid attribute instead - break - else: - ml = [x for x in ml if x[0].lower() != 'objectclass'] - ml.append(('objectClass', self.oldattr.get('objectClass', []), list(ocs - object_classes_to_remove))) + univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'The attribute %r is required by the current object classes.' % (attr.names,)) + return ml + + ml = [x for x in ml if x[0].lower() != 'objectclass'] + ml.append(('objectClass', self.oldattr.get('objectClass', []), list(ocs_afterwards))) + return ml def _move_in_subordinates(self, olddn):