summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Babinsky <mbabinsk@redhat.com>2015-06-23 13:39:35 +0200
committerJan Cholasta <jcholast@redhat.com>2015-07-02 14:43:44 +0000
commit93dab56ebfa6801e4f032af4a57b7b2179ba29ff (patch)
tree96db9e5d7cf4ac29e3b78d91156cd39ae1ff4685
parent8d30feb5391026a42a2f8da5df8d539311963b86 (diff)
downloadfreeipa-93dab56ebfa6801e4f032af4a57b7b2179ba29ff.zip
freeipa-93dab56ebfa6801e4f032af4a57b7b2179ba29ff.tar.gz
freeipa-93dab56ebfa6801e4f032af4a57b7b2179ba29ff.tar.xz
baseldap: add support for API commands managing only a single attribute
This patch extends the API framework with a set of classes which add/remove values to a single LDAPObject attribute. Reviewed-By: Jan Cholasta <jcholast@redhat.com>
-rw-r--r--ipalib/plugins/baseldap.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 2eab69f..2309bbc 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -2367,3 +2367,117 @@ class LDAPRemoveReverseMember(LDAPModReverseMember):
def interactive_prompt_callback(self, kw):
return
+
+
+class LDAPModAttribute(LDAPQuery):
+
+ attribute = None
+
+ has_output = output.standard_entry
+
+ def get_options(self):
+ for option in super(LDAPModAttribute, self).get_options():
+ yield option
+
+ option = self.obj.params[self.attribute]
+ attribute = 'virtual_attribute' not in option.flags
+ yield option.clone(attribute=attribute, alwaysask=True)
+
+ def _update_attrs(self, update, entry_attrs):
+ raise NotImplementedError("%s.update_attrs()", self.__class__.__name__)
+
+ def execute(self, *keys, **options):
+ ldap = self.obj.backend
+
+ dn = self.obj.get_dn(*keys, **options)
+ entry_attrs = ldap.make_entry(dn, self.args_options_2_entry(**options))
+
+ if options.get('all', False):
+ attrs_list = ['*', self.obj.primary_key.name]
+ else:
+ attrs_list = {self.obj.primary_key.name}
+ attrs_list.update(entry_attrs.keys())
+ attrs_list = list(attrs_list)
+
+ for callback in self.get_callbacks('pre'):
+ entry_attrs.dn = callback(
+ self, ldap, entry_attrs.dn, entry_attrs, attrs_list,
+ *keys, **options)
+
+ try:
+ update = self._exc_wrapper(keys, options, ldap.get_entry)(
+ entry_attrs.dn, entry_attrs.keys())
+ self._update_attrs(update, entry_attrs)
+
+ self._exc_wrapper(keys, options, ldap.update_entry)(update)
+ except errors.NotFound:
+ self.obj.handle_not_found(*keys)
+
+ try:
+ entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(
+ entry_attrs.dn, attrs_list)
+ except errors.NotFound:
+ raise errors.MidairCollision(
+ format=_('the entry was deleted while being modified')
+ )
+
+ for callback in self.get_callbacks('post'):
+ entry_attrs.dn = callback(
+ self, ldap, entry_attrs.dn, entry_attrs, *keys, **options)
+
+ entry_attrs = entry_to_dict(entry_attrs, **options)
+
+ if self.obj.primary_key:
+ pkey = keys[-1]
+ else:
+ pkey = None
+
+ return dict(result=entry_attrs, value=pkey_to_value(pkey, options))
+
+ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys,
+ **options):
+ assert isinstance(dn, DN)
+ return dn
+
+ def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+ assert isinstance(dn, DN)
+ return dn
+
+ def exc_callback(self, keys, options, exc, call_func, *call_args,
+ **call_kwargs):
+ raise exc
+
+ def interactive_prompt_callback(self, kw):
+ return
+
+
+class LDAPAddAttribute(LDAPModAttribute):
+ msg_summary = _('added attribute value to entry %(value)')
+
+ def _update_attrs(self, update, entry_attrs):
+ for name, value in entry_attrs.iteritems():
+ old_value = set(update.get(name, []))
+ value_to_add = set(value)
+
+ if not old_value.isdisjoint(value_to_add):
+ raise errors.ExecutionError(
+ message=_('\'%s\' already contains one or more values'
+ % name)
+ )
+
+ update[name] = list(old_value | value_to_add)
+
+
+class LDAPRemoveAttribute(LDAPModAttribute):
+ msg_summary = _('removed attribute values from entry %(value)')
+
+ def _update_attrs(self, update, entry_attrs):
+ for name, value in entry_attrs.iteritems():
+ old_value = set(update.get(name, []))
+ value_to_remove = set(value)
+
+ if not value_to_remove.issubset(old_value):
+ raise errors.AttrValueNotFound(
+ attr=name, value=_("one or more values to remove"))
+
+ update[name] = list(old_value - value_to_remove)