Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
0.2 (unreleased)
------------------------
* Highlight deactivated roles: set role status to "Terminated" on
deactivation, sort roles listing by active/inactive, visually mark
inactive roles [valipod]
* Show "Export all members" button also on top-level role;
* hide "All members" button when already on that page [valipod]
* Switch Excel export library from xlwt to xlsxwriter [valipod]
* Sort users inside role listings by name [valipod]
* Role membership type: store, edit, filter, and export membership type
per user in roles (stored on destinationIndicator attribute)
[batranud, valipod]
* Role activate/deactivate support with status tracking and export [batranud]
* Role description stored in postalAddress and included in export [batranud]
* Merge role name and description cells in export [batranud]
* Group "All members" export by role [batranud]
* Include role information in export regardless of subroles option [batranud]
* Link to role details instead of just displaying the role id [valipod]

0.1 (2021-04-03)
------------------------
Expand Down
32 changes: 22 additions & 10 deletions be/ldapadmin/db_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ def role_infos_in_role(self, role_id):
query_dn, ldap.SCOPE_ONELEVEL,
filterstr='(objectClass=role)',
attrlist=('description', 'owner', 'permittedSender',
'permittedPerson', 'leaderMember', 'alternateLeader')
'permittedPerson', 'leaderMember', 'alternateLeader',
'l', 'postalAddress', 'postOfficeBox', 'businessCategory')
)

out = {}
Expand Down Expand Up @@ -1740,20 +1741,31 @@ def set_role_status(self, role_id, role_status):
"""
Sets role postOfficeBox (or name) to `role_status`
`role_status` must be unicode or ascii bytes
If role_status is empty, deletes the attribute

"""
assert self._bound, "call `perform_bind` before `set_role_status`"
log.info("Set postOfficeBox %r for role %r", role_status, role_id)
role_dn = self._role_dn(role_id)
role_status_bytes = role_status.encode(self._encoding)
try:
self.conn.modify_s(role_dn, (
(ldap.MOD_REPLACE, 'postOfficeBox', [role_status_bytes]),
))
except ldap.NO_SUCH_ATTRIBUTE:
self.conn.modify_s(role_dn, (
(ldap.MOD_ADD, 'postOfficeBox', [role_status_bytes]),
))

if role_status == '' or role_status == u'':
# Delete the attribute when empty (corresponds to "-" option in UI)
try:
self.conn.modify_s(role_dn, (
(ldap.MOD_DELETE, 'postOfficeBox', []),
))
except ldap.NO_SUCH_ATTRIBUTE:
pass # Attribute already doesn't exist
else:
role_status_bytes = role_status.encode(self._encoding)
try:
self.conn.modify_s(role_dn, (
(ldap.MOD_REPLACE, 'postOfficeBox', [role_status_bytes]),
))
except ldap.NO_SUCH_ATTRIBUTE:
self.conn.modify_s(role_dn, (
(ldap.MOD_ADD, 'postOfficeBox', [role_status_bytes]),
))

@log_ldap_exceptions
def set_role_address(self, role_id, address):
Expand Down
6 changes: 6 additions & 0 deletions be/ldapadmin/roles_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,13 +393,17 @@ def get_user_info(user_dn):
for role in roles:
if role not in user_roles:
del(role_infos[role])
# Sort role IDs: active roles first (alphabetically), then deactivated (alphabetically)
sorted_role_ids = sorted(role_infos.keys(),
key=lambda x: (role_infos[x].get('isDeactivated', False), x))
options = {
'roles_domain': ROLES_DOMAIN,
'roles_status': OPTIONS_ROLES_STATUS,
'role_id': role_id,
'role_name': get_role_name(agent, role_id),
'role_info': role_info,
'role_infos': role_infos,
'sorted_role_ids': sorted_role_ids,
'role_members': role_members(agent, role_id),
'role_owners': role_owners,
'permitted_persons': persons,
Expand Down Expand Up @@ -863,6 +867,7 @@ def activate_role(self, REQUEST):
agent = self._get_ldap_agent(bind=True)
with agent.new_action():
agent.activate_role(role_id)
agent.set_role_status(role_id, u'')
_set_session_message(REQUEST, 'info', "Activated role %s" % role_id)

log.info("%s ACTIVATED ROLE %s", logged_in, role_id)
Expand All @@ -881,6 +886,7 @@ def deactivate_role(self, REQUEST):
agent = self._get_ldap_agent(bind=True)
with agent.new_action():
agent.deactivate_role(role_id)
agent.set_role_status(role_id, u'Terminated')
_set_session_message(REQUEST, 'info', "Deactivated role %s" % role_id)

log.info("%s DEACTIVATED ROLE %s", logged_in, role_id)
Expand Down
13 changes: 13 additions & 0 deletions be/ldapadmin/www/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ div#operations ul li a, a.button, .account-links a.current {
box-shadow: none;
text-shadow: none;
padding: 6px 12px;
white-space: nowrap;
}

div#operations ul li a:hover, a.button:hover {
Expand Down Expand Up @@ -793,6 +794,9 @@ div#role-status {
display: inline-block;
margin: 0.5em;
}
div#role-status.terminated {
background-color: #bf5900;
}
div#role-status:empty {
display: none;
}
Expand Down Expand Up @@ -853,6 +857,15 @@ a#activate-role {
margin: 0 1em;
}

tr.deactivated-role,
tr.deactivated-role a {
color: #999;
}

tr.deactivated-role {
opacity: 0.7;
}

#senders_tokens span.info{
/*font-style: italic;*/
}
Expand Down
9 changes: 5 additions & 4 deletions be/ldapadmin/zpt/roles_browse.zpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
<h1 tal:define="name python:(options['role_info']['description'].strip()
or 'Role %s' % options['role_id'])"
tal:content="name" class="left-position" />
<div id="role-status" title="Status" tal:content="role_status"></div>
<div id="role-status" title="Status" tal:content="role_status"
tal:attributes="class python:'terminated' if options['role_info'].get('isDeactivated', False) else ''"></div>
<img tal:condition="python:options.get('role_id') and options['role_info']['isActivated'] and options['can_edit_members']"
src="/++resource++be.ldapadmin-www/edit.gif" id="edit-role-description-arrow" />
<div id="role-description" tal:content="options/role_info/postalAddress|nothing"></div>
Expand Down Expand Up @@ -110,8 +111,8 @@
</thead>

<tbody>
<tr tal:repeat="sub_role_id python:sorted(role_infos)"
tal:attributes="class python:'odd' if path('repeat/sub_role_id/odd') else 'even'">
<tr tal:repeat="sub_role_id options/sorted_role_ids"
tal:attributes="class python:('deactivated-role ' if role_infos[sub_role_id].get('isDeactivated', False) else '') + ('odd' if path('repeat/sub_role_id/odd') else 'even')">
<td>
<a tal:attributes="href string:?role_id=${sub_role_id};
class python: 'has-children' if options['agent'].role_names_in_role(sub_role_id) else '';"
Expand All @@ -131,7 +132,7 @@
</tal:rep>
</td>
<!--<td>
<div tal:repeat="sender python:role_infos[sub_role_id]['permittedSender']"
<div tal:repeat="sender python:role_infos[sub_role_id]['permittedSender']"
tal:content="sender" />
</td>-->
</tal:cond>
Expand Down
6 changes: 6 additions & 0 deletions be/ldapadmin/zpt/roles_buttons.zpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
$('.button.no-members').click(function(){
return window.confirm("This role has no explicit members. Attempting instead to export members in all subroles?");
});
$('#deactivate-role').click(function(){
return window.confirm("Are you sure you want to deactivate this role?");
});
$('#activate-role').click(function(){
return window.confirm("Are you sure you want to activate this role?");
});
});
})(jQuery);
</script>
Expand Down