summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'ipalib/plugins')
-rw-r--r--ipalib/plugins/range.py81
1 files changed, 81 insertions, 0 deletions
diff --git a/ipalib/plugins/range.py b/ipalib/plugins/range.py
index 95b00b39..cc0c1275 100644
--- a/ipalib/plugins/range.py
+++ b/ipalib/plugins/range.py
@@ -91,6 +91,58 @@ class range(LDAPObject):
if not options.get('all', False) or options.get('pkey_only', False):
entry_attrs.pop('objectclass', None)
+ def check_ids_in_modified_range(self, old_base, old_size, new_base, new_size):
+ if new_base is None and new_size is None:
+ # nothing to check
+ return
+ if new_base is None:
+ new_base = old_base
+ if new_size is None:
+ new_size = old_size
+ old_interval = (old_base, old_base + old_size - 1)
+ new_interval = (new_base, new_base + new_size - 1)
+ checked_intervals = []
+ low_diff = new_interval[0] - old_interval[0]
+ if low_diff > 0:
+ checked_intervals.append(
+ (old_interval[0], min(old_interval[1], new_interval[0] - 1)))
+ high_diff = old_interval[1] - new_interval[1]
+ if high_diff > 0:
+ checked_intervals.append(
+ (max(old_interval[0], new_interval[1] + 1), old_interval[1]))
+
+ if not checked_intervals:
+ # range is equal or covers the entire old range, nothing to check
+ return
+
+ ldap = self.backend
+ id_filter_base = ["(objectclass=posixAccount)",
+ "(objectclass=posixGroup)",
+ "(objectclass=ipaIDObject)"]
+ id_filter_ids = []
+
+ for id_low, id_high in checked_intervals:
+ id_filter_ids.append("(&(uidNumber>=%(low)d)(uidNumber<=%(high)d))"
+ % dict(low=id_low, high=id_high))
+ id_filter_ids.append("(&(gidNumber>=%(low)d)(gidNumber<=%(high)d))"
+ % dict(low=id_low, high=id_high))
+ id_filter = ldap.combine_filters(
+ [ldap.combine_filters(id_filter_base, "|"),
+ ldap.combine_filters(id_filter_ids, "|")],
+ "&")
+
+ try:
+ (objects, truncated) = ldap.find_entries(filter=id_filter,
+ attrs_list=['uid', 'cn'],
+ base_dn=DN(api.env.container_accounts, api.env.basedn))
+ except errors.NotFound:
+ # no objects in this range found, allow the command
+ pass
+ else:
+ raise errors.ValidationError(name="ipabaseid,ipaidrangesize",
+ error=_('range modification leaving objects with ID out '
+ 'of the defined range is not allowed'))
+
class range_add(LDAPCreate):
__doc__ = _('Add new ID range.')
@@ -121,6 +173,18 @@ class range_del(LDAPDelete):
msg_summary = _('Deleted ID range "%(value)s"')
+ def pre_callback(self, ldap, dn, *keys, **options):
+ try:
+ (old_dn, old_attrs) = ldap.get_entry(dn, ['ipabaseid', 'ipaidrangesize'])
+ except errors.NotFound:
+ self.obj.handle_not_found(*keys)
+
+ old_base_id = int(old_attrs.get('ipabaseid', [0])[0])
+ old_range_size = int(old_attrs.get('ipaidrangesize', [0])[0])
+ self.obj.check_ids_in_modified_range(
+ old_base_id, old_range_size, 0, 0)
+ return dn
+
class range_find(LDAPSearch):
__doc__ = _('Search for ranges.')
@@ -161,6 +225,23 @@ class range_mod(LDAPUpdate):
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
attrs_list.append('objectclass')
+
+ try:
+ (old_dn, old_attrs) = ldap.get_entry(dn, ['ipabaseid', 'ipaidrangesize'])
+ except errors.NotFound:
+ self.obj.handle_not_found(*keys)
+
+ old_base_id = int(old_attrs.get('ipabaseid', [0])[0])
+ old_range_size = int(old_attrs.get('ipaidrangesize', [0])[0])
+ new_base_id = entry_attrs.get('ipabaseid')
+ if new_base_id is not None:
+ new_base_id = int(new_base_id)
+ new_range_size = entry_attrs.get('ipaidrangesize')
+ if new_range_size is not None:
+ new_range_size = int(new_range_size)
+ self.obj.check_ids_in_modified_range(old_base_id, old_range_size,
+ new_base_id, new_range_size)
+
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):