From adea625b1346cfd57b9f5341e44175453b6c3ab0 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Tue, 21 Oct 2008 16:33:34 -0400 Subject: [PATCH] Implement group member add/remove Add gidNumber to the group command-line --- ipa_server/plugins/b_ldap.py | 18 +++++ ipa_server/servercore.py | 46 ++++++----- ipalib/plugins/f_group.py | 151 ++++++++++++++++++++++++++++++++++- 3 files changed, 193 insertions(+), 22 deletions(-) diff --git a/ipa_server/plugins/b_ldap.py b/ipa_server/plugins/b_ldap.py index e63865bbf..a07e8e710 100644 --- a/ipa_server/plugins/b_ldap.py +++ b/ipa_server/plugins/b_ldap.py @@ -146,6 +146,24 @@ class ldap(CrudBackend): def modify_password(self, dn, **kw): return servercore.modify_password(dn, kw.get('oldpass'), kw.get('newpass')) + def add_member_to_group(self, memberdn, groupdn): + """ + Add a new member to a group. + + :param memberdn: the DN of the member to add + :param groupdn: the DN of the group to add a member to + """ + return servercore.add_member_to_group(memberdn, groupdn) + + def remove_member_from_group(self, memberdn, groupdn): + """ + Remove a new member from a group. + + :param memberdn: the DN of the member to remove + :param groupdn: the DN of the group to remove a member from + """ + return servercore.remove_member_from_group(memberdn, groupdn) + # The CRUD operations def create(self, **kw): diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py index 1f41d410f..e69967a90 100644 --- a/ipa_server/servercore.py +++ b/ipa_server/servercore.py @@ -389,7 +389,9 @@ def mark_entry_inactive (dn): return res def add_member_to_group(member_dn, group_dn): - """Add a member to an existing group.""" + """ + Add a member to an existing group. + """ # logging.info("IPA: add_member_to_group '%s' to '%s'" % (member_dn, group_dn)) if member_dn.lower() == group_dn.lower(): # You can't add a group to itself @@ -404,12 +406,12 @@ def add_member_to_group(member_dn, group_dn): if not member_entry: raise errors.NotFound - if group.get('member') is not None: - if isinstance(group.get('member'),basestring): - group['member'] = [group['member']] - group['member'].append(member_dn) - else: - group['member'] = member_dn + # Add the new member to the group member attribute + members = group.get('member', []) + if isinstance(members, basestring): + members = [members] + members.append(member_dn) + group['member'] = members try: return update_entry(group) @@ -430,21 +432,25 @@ def remove_member_from_group(member_dn, group_dn=None): """ # logging.info("IPA: remove_member_from_group '%s' from '%s'" % (member_dn, group_dn)) - if group.get('member') is not None: - if isinstance(group.get('member'),basestring): - group['member'] = [group['member']] - for i in range(len(group['member'])): - group['member'][i] = ipaldap.IPAdmin.normalizeDN(group['member'][i]) - try: - group['member'].remove(member_dn) - except ValueError: - # member is not in the group - # FIXME: raise more specific error? - raise errors.NotGroupMember - else: - # Nothing to do if the group has no members + members = group.get('member', False) + if not members: raise errors.NotGroupMember + if isinstance(members,basestring): + members = [members] + for i in range(len(members)): + members[i] = ipaldap.IPAdmin.normalizeDN(members[i]) + try: + members.remove(member_dn) + except ValueError: + # member is not in the group + # FIXME: raise more specific error? + raise errors.NotGroupMember + except Exception, e: + raise e + + group['member'] = members + try: return update_entry(group) except errors.EmptyModlist: diff --git a/ipalib/plugins/f_group.py b/ipalib/plugins/f_group.py index e83c870e9..b5f80f93c 100644 --- a/ipalib/plugins/f_group.py +++ b/ipalib/plugins/f_group.py @@ -25,7 +25,8 @@ from ipalib import frontend from ipalib import crud from ipalib.frontend import Param from ipalib import api -from ipa_server import ipautil +from ipalib import errors +from ipalib import ipa_types class group(frontend.Object): @@ -33,7 +34,14 @@ class group(frontend.Object): Group object. """ takes_params = ( - 'description', + Param('description', + doc='A description of this group', + ), + Param('gidnumber?', + cli_name='gid', + type=ipa_types.Int(), + doc='The gid to use for this group. If not included one is automatically set.', + ), Param('cn', cli_name='name', primary_key=True, @@ -210,4 +218,143 @@ class group_show(crud.Get): # FIXME: should kw contain the list of attributes to display? return ldap.retrieve(dn) + def output_for_cli(self, group): + if not group: + return + + for a in group.keys(): + print "%s: %s" % (a, group[a]) + api.register(group_show) + + +class group_add_member(frontend.Command): + 'Add a member to a group.' + takes_args = ( + Param('group', primary_key=True), + ) + takes_options = ( + Param('users?', doc='comma-separated list of users to add'), + Param('groups?', doc='comma-separated list of groups to add'), + ) + def execute(self, cn, **kw): + """ + Execute the group-add-member operation. + + Returns the updated group entry + + :param cn: The group name to add new members to. + :param kw: groups is a comma-separated list of groups to add + :parem kw: users is a comma-separated list of users to add + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn) + add_failed = [] + to_add = [] + completed = 0 + + members = kw.get('groups', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m) + to_add.append(member_dn) + except errors.NotFound: + add_failed.append(m) + continue + + members = kw.get('users', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("uid", m) + to_add.append(member_dn) + except errors.NotFound: + add_failed.append(m) + continue + + for member_dn in to_add: + try: + ldap.add_member_to_group(member_dn, dn) + completed+=1 + except: + add_failed.append(member_dn) + + return add_failed + + def output_for_cli(self, add_failed): + """ + Output result of this command to command line interface. + """ + if add_failed: + print "These entries failed to add to the group:" + for a in add_failed: + print "\t'%s'" % a + + +api.register(group_add_member) + + +class group_remove_member(frontend.Command): + 'Remove a member from a group.' + takes_args = ( + Param('group', primary_key=True), + ) + takes_options = ( + Param('users?', doc='comma-separated list of users to remove'), + Param('groups?', doc='comma-separated list of groups to remove'), + ) + def execute(self, cn, **kw): + """ + Execute the group-remove-member operation. + + Returns the members that could not be added + + :param cn: The group name to add new members to. + :param kw: groups is a comma-separated list of groups to remove + :parem kw: users is a comma-separated list of users to remove + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn) + to_remove = [] + remove_failed = [] + completed = 0 + + members = kw.get('groups', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m) + to_remove.append(member_dn) + except errors.NotFound: + remove_failed.append(m) + continue + + members = kw.get('users', '').split(',') + for m in members: + try: + member_dn = ldap.find_entry_dn("uid", m,) + to_remove.append(member_dn) + except errors.NotFound: + remove_failed.append(m) + continue + + for member_dn in to_remove: + try: + ldap.remove_member_from_group(member_dn, dn) + completed+=1 + except: + remove_failed.append(member_dn) + + return remove_failed + + def output_for_cli(self, remove_failed): + """ + Output result of this command to command line interface. + """ + if remove_failed: + print "These entries failed to be removed from the group:" + for a in remove_failed: + print "\t'%s'" % a + +api.register(group_remove_member)