summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2010-08-09 16:40:51 -0400
committerRob Crittenden <rcritten@redhat.com>2010-08-10 16:41:47 -0400
commit5b894d1fb76f176b71aed6b8f6c2ea1ce4158af8 (patch)
tree61c0cb31c211500320d420c0b456ecaa4b4d16b9 /ipalib
parent719592a209a1d3d41565284ebfc79fc76e9f5164 (diff)
downloadfreeipa-5b894d1fb76f176b71aed6b8f6c2ea1ce4158af8.tar.gz
freeipa-5b894d1fb76f176b71aed6b8f6c2ea1ce4158af8.tar.xz
freeipa-5b894d1fb76f176b71aed6b8f6c2ea1ce4158af8.zip
Allow decoupling of user-private groups.
To do this we need to break the link manually on both sides, the user and the group. We also have to verify in advance that the user performing this is allowed to do both. Otherwise the user could be decoupled but not the group leaving it in a quasi broken state that only ldapmodify could fix. ticket 75
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/errors.py15
-rw-r--r--ipalib/plugins/group.py59
2 files changed, 74 insertions, 0 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py
index c35d424a7..efd0d640f 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -1070,6 +1070,21 @@ class DNSNotARecordError(ExecutionError):
errno = 4019
format = _('Host does not have corresponding DNS A record')
+class ManagedGroupError(ExecutionError):
+ """
+ **4020** Raised when a managed group is deleted
+
+ For example:
+
+ >>> raise ManagedGroupError()
+ Traceback (most recent call last):
+ ...
+ ManagedGroupError: Deleting a managed group is not allowed. It must be detached first.
+ """
+
+ errno = 4020
+ format = _('Deleting a managed group is not allowed. It must be detached first.')
+
class BuiltinError(ExecutionError):
"""
**4100** Base class for builtin execution errors (*4100 - 4199*).
diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py
index f0e9f7724..9bf5b1de8 100644
--- a/ipalib/plugins/group.py
+++ b/ipalib/plugins/group.py
@@ -158,6 +158,9 @@ class group_del(LDAPDelete):
def_primary_group_dn = group_dn = self.obj.get_dn(def_primary_group)
if dn == def_primary_group_dn:
raise errors.DefaultGroup()
+ (group_dn, group_attrs) = ldap.get_entry(dn)
+ if 'mepmanagedby' in group_attrs:
+ raise errors.ManagedGroupError()
return dn
def post_callback(self, ldap, dn, *keys, **options):
@@ -235,3 +238,59 @@ class group_remove_member(LDAPRemoveMember):
"""
api.register(group_remove_member)
+
+
+class group_detach(LDAPRemoveMember):
+ """
+ Detach a managed group from a user
+ """
+ has_output = output.standard_value
+ msg_summary = _('Detached group "%(value)s" from user "%(value)s"')
+
+ def execute(self, *keys, **options):
+ """
+ This requires updating both the user and the group. We first need to
+ verify that both the user and group can be updated, then we go
+ about our work. We don't want a situation where only the user or
+ group can be modified and we're left in a bad state.
+ """
+ ldap = self.obj.backend
+
+ group_dn = self.obj.get_dn(*keys, **options)
+ user_dn = self.api.Object['user'].get_dn(*keys)
+
+ if (not ldap.can_write(user_dn, "objectclass") or
+ not ldap.can_write(user_dn, "mepManagedEntry")):
+ raise errors.ACIError(info=_('not allowed to modify user entries'))
+
+ if (not ldap.can_write(group_dn, "objectclass") or
+ not ldap.can_write(group_dn, "mepManagedBy")):
+ raise errors.ACIError(info=_('not allowed to modify group entries'))
+
+ (user_dn, user_attrs) = ldap.get_entry(user_dn)
+ objectclasses = user_attrs['objectclass']
+ try:
+ i = objectclasses.index('mepOriginEntry')
+ except ValueError:
+ raise NotFound(reason=_('Not a managed group'))
+ del objectclasses[i]
+ update_attrs = {'objectclass': objectclasses, 'mepManagedEntry': None}
+ ldap.update_entry(user_dn, update_attrs)
+
+ (group_dn, group_attrs) = ldap.get_entry(group_dn)
+ objectclasses = group_attrs['objectclass']
+ try:
+ i = objectclasses.index('mepManagedEntry')
+ except ValueError:
+ # this should never happen
+ raise NotFound(reason=_('Not a managed group'))
+ del objectclasses[i]
+ update_attrs = {'objectclass': objectclasses, 'mepManagedBy': None}
+ ldap.update_entry(group_dn, update_attrs)
+
+ return dict(
+ result=True,
+ value=keys[0],
+ )
+
+api.register(group_detach)