summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/errors.py32
-rw-r--r--ipalib/plugins/group.py16
-rw-r--r--ipalib/plugins/user.py9
-rw-r--r--tests/test_xmlrpc/test_group_plugin.py55
-rw-r--r--tests/test_xmlrpc/test_user_plugin.py41
5 files changed, 150 insertions, 3 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py
index df4ab4167..407d9f7db 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -1575,6 +1575,38 @@ class DependentEntry(ExecutionError):
format = _('%(key)s cannot be deleted because %(label)s %(dependent)s requires it')
+class LastMemberError(ExecutionError):
+ """
+ **4308** Raised when an entry being deleted is last member of a protected group
+
+ For example:
+ >>> raise LastMemberError(key=u'admin', label=u'group', container=u'admins')
+ Traceback (most recent call last):
+ ...
+ LastMemberError: admin cannot be deleted because it is the last member of group admins
+
+ """
+
+ errno = 4308
+ format = _('%(key)s cannot be deleted because it is the last member of %(label)s %(container)s')
+
+
+class ProtectedEntryError(ExecutionError):
+ """
+ **4309** Raised when an entry being deleted is protected
+
+ For example:
+ >>> raise ProtectedEntryError(label=u'group', key=u'admins', reason=u'privileged group')
+ Traceback (most recent call last):
+ ...
+ ProtectedEntryError: group admins cannot be deleted: privileged group
+
+ """
+
+ errno = 4309
+ format = _('%(label)s %(key)s cannot be deleted: %(reason)s')
+
+
##############################################################################
# 5000 - 5999: Generic errors
diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py
index 13208542c..65657363a 100644
--- a/ipalib/plugins/group.py
+++ b/ipalib/plugins/group.py
@@ -72,6 +72,8 @@ EXAMPLES:
ipa group-show localadmins
""")
+protected_group_name = u'admins'
+
class group(LDAPObject):
"""
Group object.
@@ -164,7 +166,9 @@ class group_del(LDAPDelete):
group_attrs = self.obj.methods.show(
self.obj.get_primary_key_from_dn(dn), all=True
)['result']
-
+ if keys[0] == protected_group_name:
+ raise errors.ProtectedEntryError(label=_(u'group'), key=keys[0],
+ reason=_(u'privileged group'))
if 'mepmanagedby' in group_attrs:
raise errors.ManagedGroupError()
return dn
@@ -276,6 +280,16 @@ api.register(group_add_member)
class group_remove_member(LDAPRemoveMember):
__doc__ = _('Remove members from a group.')
+ def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
+ if keys[0] == protected_group_name:
+ result = api.Command.group_show(protected_group_name)
+ users_left = set(result['result'].get('member_user', []))
+ users_deleted = set(options['user'])
+ if users_left.issubset(users_deleted):
+ raise errors.LastMemberError(key=sorted(users_deleted)[0],
+ label=_(u'group'), container=protected_group_name)
+ return dn
+
api.register(group_remove_member)
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index b48e68022..7e98bba4c 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -544,8 +544,13 @@ class user_del(LDAPDelete):
msg_summary = _('Deleted user "%(value)s"')
- def post_callback(self, ldap, dn, *keys, **options):
- return True
+ def pre_callback(self, ldap, dn, *keys, **options):
+ protected_group_name = u'admins'
+ result = api.Command.group_show(protected_group_name)
+ if result['result'].get('member_user', []) == [keys[-1]]:
+ raise errors.LastMemberError(key=keys[-1], label=_(u'group'),
+ container=protected_group_name)
+ return dn
api.register(user_del)
diff --git a/tests/test_xmlrpc/test_group_plugin.py b/tests/test_xmlrpc/test_group_plugin.py
index c0abcb955..abee7bac7 100644
--- a/tests/test_xmlrpc/test_group_plugin.py
+++ b/tests/test_xmlrpc/test_group_plugin.py
@@ -797,4 +797,59 @@ class test_group(Declarative):
expected=errors.NotFound(reason=u'%s: group not found' % user1),
),
+ dict(
+ desc='Try to remove the admin user from the admins group',
+ command=('group_remove_member', [u'admins'], dict(user=[u'admin'])),
+ expected=errors.LastMemberError(key=u'admin', label=u'group',
+ container='admins'),
+ ),
+
+ dict(
+ desc='Add %r to the admins group' % user1,
+ command=('group_add_member', [u'admins'], dict(user=user1)),
+ expected=dict(
+ completed=1,
+ failed=dict(
+ member=dict(
+ group=tuple(),
+ user=tuple(),
+ ),
+ ),
+ result={
+ 'dn': lambda x: DN(x) == \
+ DN(('cn', 'admins'), ('cn', 'groups'),
+ ('cn', 'accounts'), api.env.basedn),
+ 'member_user': [u'admin', user1],
+ 'gidnumber': [fuzzy_digits],
+ 'cn': [u'admins'],
+ 'description': [u'Account administrators group'],
+ },
+ ),
+ ),
+
+ dict(
+ desc='Try to remove admin and %r from the admins group' % user1,
+ command=('group_remove_member', [u'admins'],
+ dict(user=[u'admin', user1])),
+ expected=errors.LastMemberError(key=u'admin', label=u'group',
+ container='admins'),
+ ),
+
+ dict(
+ desc='Try to delete the admins group',
+ command=('group_del', [u'admins'], {}),
+ expected=errors.ProtectedEntryError(label=u'group',
+ key='admins', reason='privileged group'),
+ ),
+
+ dict(
+ desc='Delete %r' % user1,
+ command=('user_del', [user1], {}),
+ expected=dict(
+ result=dict(failed=u''),
+ summary=u'Deleted user "%s"' % user1,
+ value=user1,
+ ),
+ ),
+
]
diff --git a/tests/test_xmlrpc/test_user_plugin.py b/tests/test_xmlrpc/test_user_plugin.py
index 4b2be5c32..355a4cbbb 100644
--- a/tests/test_xmlrpc/test_user_plugin.py
+++ b/tests/test_xmlrpc/test_user_plugin.py
@@ -1330,4 +1330,45 @@ class test_user(Declarative):
),
expected=lambda x: True,
),
+
+ dict(
+ desc='Try to remove the admin user',
+ command=('user_del', [u'admin'], {}),
+ expected=errors.LastMemberError(key=u'admin', label=u'group',
+ container='admins'),
+ ),
+
+ dict(
+ desc='Add %r to the admins group' % user2,
+ command=('group_add_member', [u'admins'], dict(user=user2)),
+ expected=dict(
+ completed=1,
+ failed=dict(
+ member=dict(
+ group=tuple(),
+ user=tuple(),
+ ),
+ ),
+ result={
+ 'dn': lambda x: DN(x) == \
+ DN(('cn', 'admins'), ('cn', 'groups'),
+ ('cn', 'accounts'), api.env.basedn),
+ 'member_user': [u'admin', user2],
+ 'gidnumber': [fuzzy_digits],
+ 'cn': [u'admins'],
+ 'description': [u'Account administrators group'],
+ },
+ ),
+ ),
+
+ dict(
+ desc='Delete %r' % user2,
+ command=('user_del', [user2], {}),
+ expected=dict(
+ result=dict(failed=u''),
+ summary=u'Deleted user "%s"' % user2,
+ value=user2,
+ ),
+ ),
+
]