diff options
author | Kevin McCarthy <kmccarth@redhat.com> | 2007-09-14 15:20:09 -0700 |
---|---|---|
committer | Kevin McCarthy <kmccarth@redhat.com> | 2007-09-14 15:20:09 -0700 |
commit | 65e4d27e99cb939926f4e9e972a9c27d81c3b976 (patch) | |
tree | a93c80510ce704aade5f501d0d1feafc3089e31f /ipa-server/ipa-gui/ipagui | |
parent | a809d44429e5ce8f0b791f6f56a976f6c92b7c62 (diff) | |
download | freeipa-65e4d27e99cb939926f4e9e972a9c27d81c3b976.tar.gz freeipa-65e4d27e99cb939926f4e9e972a9c27d81c3b976.tar.xz freeipa-65e4d27e99cb939926f4e9e972a9c27d81c3b976.zip |
patch queue: groupmember.patch
Diffstat (limited to 'ipa-server/ipa-gui/ipagui')
-rw-r--r-- | ipa-server/ipa-gui/ipagui/controllers.py | 178 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/forms/group.py | 5 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/templates/groupedit.kid | 2 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/templates/groupeditform.kid | 150 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/templates/groupshow.kid | 12 | ||||
-rw-r--r-- | ipa-server/ipa-gui/ipagui/templates/userlistajax.kid | 14 |
6 files changed, 331 insertions, 30 deletions
diff --git a/ipa-server/ipa-gui/ipagui/controllers.py b/ipa-server/ipa-gui/ipagui/controllers.py index 5324578f..1cc99862 100644 --- a/ipa-server/ipa-gui/ipagui/controllers.py +++ b/ipa-server/ipa-gui/ipagui/controllers.py @@ -120,17 +120,21 @@ class Root(controllers.RootController): if tg_errors: turbogears.flash("There was a problem with the form!") - client.set_principal(identity.current.user_name) - user = client.get_user_by_uid(uid, user_fields) - user_dict = user.toDict() - # Edit shouldn't fill in the password field. - if user_dict.has_key('userpassword'): - del(user_dict['userpassword']) - - # store a copy of the original user for the update later - user_data = b64encode(dumps(user_dict)) - user_dict['user_orig'] = user_data - return dict(form=user_edit_form, user=user_dict) + try: + client.set_principal(identity.current.user_name) + user = client.get_user_by_uid(uid, user_fields) + user_dict = user.toDict() + # Edit shouldn't fill in the password field. + if user_dict.has_key('userpassword'): + del(user_dict['userpassword']) + + # store a copy of the original user for the update later + user_data = b64encode(dumps(user_dict)) + user_dict['user_orig'] = user_data + return dict(form=user_edit_form, user=user_dict) + except ipaerror.IPAError, e: + turbogears.flash("User edit failed: " + str(e)) + raise turbogears.redirect('/usershow', uid=kw.get('uid')) @expose() @identity.require(identity.not_anonymous()) @@ -204,6 +208,24 @@ class Root(controllers.RootController): return dict(users=users, uid=uid, fields=forms.user.UserFields()) + @expose("ipagui.templates.userlistajax") + @identity.require(identity.not_anonymous()) + def userlist_ajax(self, **kw): + """Searches for users and displays list of results in a table. + This method is used for ajax calls.""" + client.set_principal(identity.current.user_name) + users = [] + uid = kw.get('uid') + if uid != None and len(uid) > 0: + try: + users = client.find_users(uid.encode('utf-8')) + counter = users[0] + users = users[1:] + except ipaerror.IPAError, e: + turbogears.flash("User list failed: " + str(e)) + + return dict(users=users, uid=uid, fields=forms.user.UserFields()) + @expose("ipagui.templates.usershow") @identity.require(identity.not_anonymous()) @@ -371,8 +393,7 @@ class Root(controllers.RootController): rv = client.add_group(new_group) turbogears.flash("%s added!" % kw.get('cn')) - # raise turbogears.redirect('/groupedit', cn=kw['cn']) - raise turbogears.redirect('/') + raise turbogears.redirect('/groupshow', cn=kw.get('cn')) except ipaerror.exception_for(ipaerror.LDAP_DUPLICATE): turbogears.flash("Group with name '%s' already exists" % kw.get('cn')) @@ -390,13 +411,43 @@ class Root(controllers.RootController): turbogears.flash("There was a problem with the form!") client.set_principal(identity.current.user_name) - group = client.get_group_by_cn(cn, group_fields) - group_dict = group.toDict() + try: + group = client.get_group_by_cn(cn, group_fields) + + group_dict = group.toDict() - # store a copy of the original group for the update later - group_data = b64encode(dumps(group_dict)) - group_dict['group_orig'] = group_data - return dict(form=group_edit_form, group=group_dict) + # + # convert members to users, for easier manipulation on the page + # + member_dns = [] + if group_dict.has_key('uniquemember'): + member_dns = group_dict.get('uniquemember') + # remove from dict - it's not needed for update + # and we are storing the members in a different form + del group_dict['uniquemember'] + if not(isinstance(member_dns,list) or isinstance(member_dns,tuple)): + member_dns = [member_dns] + + # TODO: convert this into an efficient (single) function call + member_users = map( + lambda dn: client.get_user_by_dn(dn, ['givenname', 'sn', 'uid']), + member_dns) + + # Map users into an array of dicts, which can be serialized + # (so we don't have to do this on each round trip) + member_dicts = map(lambda user: user.toDict(), member_users) + + # store a copy of the original group for the update later + group_data = b64encode(dumps(group_dict)) + member_data = b64encode(dumps(member_dicts)) + group_dict['group_orig'] = group_data + group_dict['member_data'] = member_data + + return dict(form=group_edit_form, group=group_dict, members=member_dicts) + except ipaerror.IPAError, e: + turbogears.flash("User show failed: " + str(e)) + turbogears.flash("Group edit failed: " + str(e)) + raise turbogears.redirect('/groupshow', uid=kw.get('cn')) @expose() @identity.require(identity.not_anonymous()) @@ -408,27 +459,84 @@ class Root(controllers.RootController): turbogears.flash("Edit group cancelled") raise turbogears.redirect('/groupshow', cn=kw.get('cn')) + # Decode the member data, in case we need to round trip + member_dicts = loads(b64decode(kw.get('member_data'))) + + tg_errors, kw = self.groupupdatevalidate(**kw) if tg_errors: - return dict(form=group_edit_form, group=kw, + return dict(form=group_edit_form, group=kw, members=member_dicts, tg_template='ipagui.templates.groupedit') + group_modified = False + + # + # Update group itself + # try: orig_group_dict = loads(b64decode(kw.get('group_orig'))) new_group = ipa.group.Group(orig_group_dict) - new_group.setValue('description', kw.get('description')) + if new_group.description != kw.get('description'): + group_modified = True + new_group.setValue('description', kw.get('description')) if kw.get('gidnumber'): + group_modified = True new_group.setValue('gidnumber', str(kw.get('gidnumber'))) - rv = client.update_group(new_group) - turbogears.flash("%s updated!" % kw['cn']) - raise turbogears.redirect('/groupshow', cn=kw['cn']) + if group_modified: + rv = client.update_group(new_group) + # + # TODO - if the group update succeeds, but below operations fail, + # we needs to make sure a subsequent submit doesn't try to update + # the group again. Probably by overwriting the group_orig hidden + # field blob. + # except ipaerror.IPAError, e: turbogears.flash("User update failed: " + str(e)) - return dict(form=group_edit_form, group=kw, + return dict(form=group_edit_form, group=kw, members=member_dicts, tg_template='ipagui.templates.groupedit') + # + # Add members + # + try: + uidadds = kw.get('uidadd') + if uidadds != None: + if not(isinstance(uidadds,list) or isinstance(uidadds,tuple)): + uidadds = [uidadds] + failed = client.add_users_to_group(uidadds, kw.get('cn')) + # + # TODO - deal with failed adds + # + except ipaerror.IPAError, e: + turbogears.flash("User update failed: " + str(e)) + return dict(form=group_edit_form, group=kw, members=member_dicts, + tg_template='ipagui.templates.groupedit') + + # + # Remove members + # + try: + uiddels = kw.get('uiddel') + if uiddels != None: + if not(isinstance(uiddels,list) or isinstance(uiddels,tuple)): + uiddels = [uiddels] + failed = client.remove_users_from_group(uiddels, kw.get('cn')) + # + # TODO - deal with failed removals + # + except ipaerror.IPAError, e: + turbogears.flash("User update failed: " + str(e)) + return dict(form=group_edit_form, group=kw, members=member_dicts, + tg_template='ipagui.templates.groupedit') + + # TODO if not group_modified + + turbogears.flash("%s updated!" % kw['cn']) + raise turbogears.redirect('/groupshow', cn=kw['cn']) + + @expose("ipagui.templates.grouplist") @identity.require(identity.not_anonymous()) def grouplist(self, **kw): @@ -458,7 +566,25 @@ class Root(controllers.RootController): client.set_principal(identity.current.user_name) try: group = client.get_group_by_cn(cn, group_fields) - return dict(group=group.toDict(), fields=forms.group.GroupFields()) + group_dict = group.toDict() + + # + # convert members to users, for display on the page + # + member_dns = [] + if group_dict.has_key('uniquemember'): + member_dns = group_dict.get('uniquemember') + if not(isinstance(member_dns,list) or isinstance(member_dns,tuple)): + member_dns = [member_dns] + + # TODO: convert this into an efficient (single) function call + member_users = map( + lambda dn: client.get_user_by_dn(dn, ['givenname', 'sn', 'uid']), + member_dns) + member_dicts = map(lambda user: user.toDict(), member_users) + + return dict(group=group_dict, fields=forms.group.GroupFields(), + members = member_dicts) except ipaerror.IPAError, e: turbogears.flash("Group show failed: " + str(e)) raise turbogears.redirect("/") diff --git a/ipa-server/ipa-gui/ipagui/forms/group.py b/ipa-server/ipa-gui/ipagui/forms/group.py index fd915b2c..2a36d36e 100644 --- a/ipa-server/ipa-gui/ipagui/forms/group.py +++ b/ipa-server/ipa-gui/ipagui/forms/group.py @@ -9,6 +9,7 @@ class GroupFields(): cn_hidden = widgets.HiddenField(name="cn") group_orig = widgets.HiddenField(name="group_orig") + member_data = widgets.HiddenField(name="member_data") class GroupNewValidator(validators.Schema): cn = validators.PlainText(not_empty=True) @@ -36,11 +37,11 @@ class GroupEditValidator(validators.Schema): description = validators.String(not_empty=False) class GroupEditForm(widgets.Form): - params = ['group'] + params = ['members', 'group'] fields = [GroupFields.gidnumber, GroupFields.description, GroupFields.cn_hidden, - GroupFields.group_orig] + GroupFields.group_orig, GroupFields.member_data] validator = GroupEditValidator() diff --git a/ipa-server/ipa-gui/ipagui/templates/groupedit.kid b/ipa-server/ipa-gui/ipagui/templates/groupedit.kid index 14a81618..1017e400 100644 --- a/ipa-server/ipa-gui/ipagui/templates/groupedit.kid +++ b/ipa-server/ipa-gui/ipagui/templates/groupedit.kid @@ -16,6 +16,6 @@ <h2>Edit Group</h2> </div> - ${form.display(action="groupupdate", value=group)} + ${form.display(action="groupupdate", value=group, members=members)} </body> </html> diff --git a/ipa-server/ipa-gui/ipagui/templates/groupeditform.kid b/ipa-server/ipa-gui/ipagui/templates/groupeditform.kid index 34b8a008..dc7eb3dd 100644 --- a/ipa-server/ipa-gui/ipagui/templates/groupeditform.kid +++ b/ipa-server/ipa-gui/ipagui/templates/groupeditform.kid @@ -2,15 +2,113 @@ class="simpleroster"> <form action="${action}" name="${name}" method="${method}" class="tableform"> + + <?python searchurl = tg.url('/userlist_ajax') ?> + <script type="text/javascript"> function toggleProtectedFields(checkbox) { - gidnumberField = document.getElementById('form_gidnumber'); + gidnumberField = $('form_gidnumber'); if (checkbox.checked) { gidnumberField.disabled = false; } else { gidnumberField.disabled = true; } } + + /* + * Callback used for afterFinish in scriptaculous effect + */ + function removeElement(effect) { + Element.remove(effect.element); + } + + function adduser(uid, cn) { + newdiv = document.createElement('div'); + newdiv.appendChild(document.createTextNode( + cn.escapeHTML() + " (" + uid.escapeHTML() + ") ")); + + undolink = document.createElement('a'); + undolink.setAttribute('href', ''); + undolink.setAttribute('onclick', + 'new Effect.Fade(Element.up(this), {afterFinish: removeElement});' + + 'return false;'); + undolink.appendChild(document.createTextNode("undo")); + newdiv.appendChild(undolink); + + uidInfo = document.createElement('input'); + uidInfo.setAttribute('type', 'hidden'); + uidInfo.setAttribute('name', 'uidadd'); + uidInfo.setAttribute('value', uid); + newdiv.appendChild(uidInfo); + + newdiv.style.display = 'none'; + $('newmembers').appendChild(newdiv); + + return newdiv + } + + function adduserHandler(element, uid, cn) { + newdiv = adduser(uid, cn) + new Effect.Fade(Element.up(element)); + new Effect.Appear(newdiv); + /* Element.up(element).remove(); */ + } + + function removeuser(uid, cn) { + newdiv = document.createElement('div'); + newdiv.appendChild(document.createTextNode( + cn.escapeHTML() + " (" + uid.escapeHTML() + ") ")); + + undolink = document.createElement('a'); + undolink.setAttribute('href', ''); + undolink.setAttribute('onclick', + 'new Effect.Fade(Element.up(this), {afterFinish: removeElement});' + + "new Effect.Appear($('member-" + uid + "'));" + + 'return false;'); + undolink.appendChild(document.createTextNode("undo")); + newdiv.appendChild(undolink); + + uidInfo = document.createElement('input'); + uidInfo.setAttribute('type', 'hidden'); + uidInfo.setAttribute('name', 'uiddel'); + uidInfo.setAttribute('value', uid); + newdiv.appendChild(uidInfo); + + newdiv.style.display = 'none'; + $('delmembers').appendChild(newdiv); + + return newdiv + } + + function removeuserHandler(element, uid, cn) { + newdiv = removeuser(uid, cn); + new Effect.Fade(Element.up(element)); + new Effect.Appear(newdiv); + /* Element.up(element).remove(); */ + } + + function enterDoSearch(e) { + var keyPressed; + if (window.event) { + keyPressed = window.event.keyCode; + } else { + keyPressed = e.which; + } + + if (keyPressed == 13) { + return doSearch(); + } else { + return true; + } + } + + function doSearch() { + new Ajax.Updater('searchresults', + '${searchurl}', + { asynchronous:true, + parameters: { uid: $('uid').value } }); + return false; + } </script> <div py:for="field in hidden_fields" @@ -63,6 +161,56 @@ </tr> </table> + <div> + <div class="formsection">Group Members</div> + + <div style="float:right; width:50%"> + <div>To Remove:</div> + <div id="delmembers"> + </div> + </div> + + <div> + <div py:for="member in members" id="member-${member.get('uid')}"> + <?python + member_uid = member.get('uid') + member_name = "%s %s" % (member.get('givenname', ''), + member.get('sn', '')) + ?> + ${member_name} + <a href="" + onclick="removeuserHandler(this, '${member_uid}', '${member_name}'); + return false;" + >remove</a> + </div> + </div> + + </div> + + <div style="clear:both"> + <div class="formsection">Add Persons</div> + + <div style="float:right; width:50%"> + <div>To Add:</div> + <div id="newmembers"> + </div> + </div> + + <div> + <div id="search"> + <input id="uid" type="text" name="uid" + onkeypress="return enterDoSearch(event);" /> + <input type="button" value="Find Users" + onclick="return doSearch();" + /> + </div> + <div id="searchresults"> + </div> + </div> + </div> + + + <table class="formtable" cellpadding="2" cellspacing="0" border="0"> <tr> <th> diff --git a/ipa-server/ipa-gui/ipagui/templates/groupshow.kid b/ipa-server/ipa-gui/ipagui/templates/groupshow.kid index 73eab2de..48fd3663 100644 --- a/ipa-server/ipa-gui/ipagui/templates/groupshow.kid +++ b/ipa-server/ipa-gui/ipagui/templates/groupshow.kid @@ -32,6 +32,18 @@ </tr> </table> + <div class="formsection">Group Members</div> + <div py:for="member in members"> + <?python + member_name = "%s %s" % (member.get('givenname', ''), + member.get('sn', '')) + ?> + ${member_name} (${member.get('uid')}) + </div> + + <br/> + <br/> + <a href="${tg.url('/groupedit', cn=group.get('cn'))}">edit</a> </body> diff --git a/ipa-server/ipa-gui/ipagui/templates/userlistajax.kid b/ipa-server/ipa-gui/ipagui/templates/userlistajax.kid new file mode 100644 index 00000000..ebfb879b --- /dev/null +++ b/ipa-server/ipa-gui/ipagui/templates/userlistajax.kid @@ -0,0 +1,14 @@ +<div xmlns:py="http://purl.org/kid/ns#"> + <div py:if='(users != None) and (len(users) > 0)'> + <div>${len(users)} results returned:</div> + <div py:for="user in users"> + ${user.givenName} ${user.sn} (${user.uid}) + <a href="" + onclick="adduserHandler(this, '${user.uid}', '${user.cn}'); return false;" + >add</a> + </div> + </div> + <div py:if='(users != None) and (len(users) == 0)'> + No results found for "${uid}" + </div> +</div> |