0001-admin-turn-permissions-panel-into-a-matrix-of-roles-.patch
tests/test_admin_pages.py | ||
---|---|---|
2285 | 2285 |
assert resp.location == 'http://example.net/backoffice/settings/data-sources/' |
2286 | 2286 |
resp = resp.follow() |
2287 | 2287 |
assert NamedDataSource.count() == 0 |
2288 | ||
2289 |
def test_settings_permissions(): |
|
2290 |
create_superuser() |
|
2291 |
role1 = create_role() |
|
2292 |
role1.name = 'foobar1' |
|
2293 |
role1.store() |
|
2294 |
role2 = Role(name='foobar2') |
|
2295 |
role2.store() |
|
2296 |
role3 = Role(name='foobar3') |
|
2297 |
role3.store() |
|
2298 | ||
2299 |
app = login(get_app(pub)) |
|
2300 |
resp = app.get('/backoffice/settings/admin-permissions') |
|
2301 |
# assert all first checkboxes are checked |
|
2302 |
assert resp.forms[0]['permissions$c-0-0'].checked |
|
2303 |
assert resp.forms[0]['permissions$c-1-0'].checked |
|
2304 |
assert resp.forms[0]['permissions$c-2-0'].checked |
|
2305 | ||
2306 |
role2.allows_backoffice_access = False |
|
2307 |
role2.store() |
|
2308 |
resp = app.get('/backoffice/settings/admin-permissions') |
|
2309 |
assert resp.forms[0]['permissions$c-0-0'].checked |
|
2310 |
assert not resp.forms[0]['permissions$c-1-0'].checked |
|
2311 |
assert resp.forms[0]['permissions$c-2-0'].checked |
|
2312 | ||
2313 |
resp.forms[0]['permissions$c-0-0'].checked = False |
|
2314 |
resp.forms[0]['permissions$c-1-0'].checked = True |
|
2315 |
resp = resp.forms[0].submit() |
|
2316 |
assert Role.get(role1.id).allows_backoffice_access is False |
|
2317 |
assert Role.get(role2.id).allows_backoffice_access is True |
|
2318 | ||
2319 |
# give some roles access to the forms workshop (2nd checkbox) and to the |
|
2320 |
# workflows workshop (3rd) |
|
2321 |
resp = app.get('/backoffice/settings/admin-permissions') |
|
2322 |
resp.forms[0]['permissions$c-1-1'].checked = True |
|
2323 |
resp.forms[0]['permissions$c-2-1'].checked = True |
|
2324 |
resp.forms[0]['permissions$c-2-2'].checked = True |
|
2325 |
resp = resp.forms[0].submit() |
|
2326 |
pub.reload_cfg() |
|
2327 |
assert set(pub.cfg['admin-permissions']['forms']) == set([role2.id, role3.id]) |
|
2328 |
assert set(pub.cfg['admin-permissions']['workflows']) == set([role3.id]) |
|
2329 | ||
2330 |
# remove accesses |
|
2331 |
resp = app.get('/backoffice/settings/admin-permissions') |
|
2332 |
resp.forms[0]['permissions$c-1-1'].checked = False |
|
2333 |
resp.forms[0]['permissions$c-2-1'].checked = False |
|
2334 |
resp.forms[0]['permissions$c-2-2'].checked = False |
|
2335 |
resp = resp.forms[0].submit() |
|
2336 |
pub.reload_cfg() |
|
2337 |
assert pub.cfg['admin-permissions']['forms'] == [] |
|
2338 |
assert pub.cfg['admin-permissions']['workflows'] == [] |
wcs/admin/settings.py | ||
---|---|---|
16 | 16 | |
17 | 17 |
import copy |
18 | 18 |
import cStringIO |
19 |
import hashlib |
|
19 | 20 |
import mimetypes |
20 | 21 |
import random |
21 | 22 |
import os |
... | ... | |
503 | 504 |
r += htmltext('</div>') |
504 | 505 |
return r.getvalue() |
505 | 506 | |
506 |
def add_roles_widget(self, form, permissions_cfg, key, label): |
|
507 |
roles = list(Role.select()) |
|
508 |
form.add(WidgetList, key, title=label, element_type=SingleSelectWidget, |
|
509 |
value=permissions_cfg.get(key, None), |
|
510 |
add_element_label=_('Add Role'), |
|
511 |
element_kwargs = { |
|
512 |
'render_br': False, |
|
513 |
'options': [(None, str('---'))] + [(x.id, x.name) for x in roles]}) |
|
514 | ||
515 | 507 |
def admin_permissions(self): |
516 | 508 |
permissions_cfg = get_cfg('admin-permissions', {}) |
517 | 509 |
form = Form(enctype='multipart/form-data') |
518 | 510 | |
519 |
keys = [] |
|
511 |
permissions = [_('Backoffice')] |
|
512 | ||
513 |
permission_keys = [] |
|
520 | 514 |
for k, v in get_publisher().get_admin_root().menu_items: |
521 | 515 |
if not k.endswith(str('/')): |
522 | 516 |
continue |
523 | 517 |
k = k.strip(str('/')) |
524 | 518 |
if not k: |
525 | 519 |
continue |
526 |
self.add_roles_widget(form, permissions_cfg, k, _(v)) |
|
527 |
keys.append(k) |
|
520 |
permissions.append(_(v)) |
|
521 |
permission_keys.append(k) |
|
522 | ||
523 |
rows = [] |
|
524 |
value = [] |
|
525 |
roles = list(Role.select(order_by='name')) |
|
526 |
for role in roles: |
|
527 |
rows.append(role.name) |
|
528 |
value.append([role.allows_backoffice_access]) |
|
529 |
for k in permission_keys: |
|
530 |
authorised_roles = [str(x) for x in permissions_cfg.get(k) or []] |
|
531 |
value[-1].append(bool(str(role.id) in authorised_roles)) |
|
532 |
colrows_hash = hashlib.md5('%r-%r' % (rows, permissions)).hexdigest() |
|
533 | ||
534 |
form.add_hidden('hash', colrows_hash) |
|
535 |
form.add(CheckboxesTableWidget, 'permissions', rows=rows, columns=permissions) |
|
536 |
form.get_widget('permissions').set_value(value) |
|
528 | 537 | |
529 | 538 |
form.add_submit('submit', _('Submit')) |
530 | 539 |
form.add_submit('cancel', _('Cancel')) |
... | ... | |
532 | 541 |
if form.get_widget('cancel').parse(): |
533 | 542 |
return redirect('.') |
534 | 543 | |
544 |
if form.get_widget('hash').parse() != colrows_hash: |
|
545 |
# The columns and rows are made of indices; permissions could be |
|
546 |
# wrongly assigned if there were some changes to the columns and |
|
547 |
# rows between the form being displayed and submitted. |
|
548 |
form.get_widget('permissions').set_error( |
|
549 |
_('Changes were made to roles or permissions while the table was displayed.')) |
|
550 | ||
535 | 551 |
if not form.is_submitted() or form.has_errors(): |
536 | 552 |
get_response().breadcrumb.append(('admin-permissions', _('Admin Permissions'))) |
537 | 553 |
html_top('settings', title = _('Admin Permissions')) |
538 | 554 |
r = TemplateIO(html=True) |
555 |
r += htmltext('<div class="admin-permissions">') |
|
539 | 556 |
r += htmltext('<h2>%s</h2>') % _('Admin Permissions') |
540 | 557 |
r += form.render() |
558 |
r += htmltext('</div>') |
|
541 | 559 |
return r.getvalue() |
542 | 560 |
else: |
543 |
cfg_submit(form, 'admin-permissions', keys) |
|
561 |
value = form.get_widget('permissions').parse() |
|
562 |
permissions = {} |
|
563 |
for key in permission_keys: |
|
564 |
permissions[key] = [] |
|
565 |
for i, role in enumerate(roles): |
|
566 |
permission_row = value[i] |
|
567 |
if role.allows_backoffice_access != permission_row[0]: |
|
568 |
role.allows_backoffice_access = permission_row[0] |
|
569 |
role.store() |
|
570 |
for j, key in enumerate(permission_keys): |
|
571 |
if permission_row[j+1]: |
|
572 |
permissions[key].append(role.id) |
|
573 |
get_publisher().cfg['admin-permissions'] = permissions |
|
574 |
get_publisher().write_cfg() |
|
544 | 575 |
return redirect('.') |
545 | 576 | |
546 | 577 |
def themes(self): |
wcs/qommon/form.py | ||
---|---|---|
1266 | 1266 |
r = TemplateIO(html=True) |
1267 | 1267 |
r += htmltext('<table><thead><tr><td></td>') |
1268 | 1268 |
for column in self.columns: |
1269 |
r += htmltext('<th>%s</th>') % column
|
|
1269 |
r += htmltext('<th><span>%s</span></th>') % column
|
|
1270 | 1270 |
r += htmltext('</tr></thead><tbody>') |
1271 | 1271 |
for i, row in enumerate(self.rows): |
1272 | 1272 |
r += htmltext('<tr><th>%s</th>') % row |
... | ... | |
1328 | 1328 |
return self.add(SingleSelectWidget, 'c-%s-%s' % (i, j), **widget_kwargs) |
1329 | 1329 | |
1330 | 1330 | |
1331 |
class CheckboxesTableWidget(TableWidget): |
|
1332 |
def add_widget(self, kwargs, i, j): |
|
1333 |
widget_kwargs = {'options': kwargs.get('options')} |
|
1334 |
if kwargs.has_key('readonly') and kwargs.get('readonly'): |
|
1335 |
widget_kwargs['readonly'] = 'readonly' |
|
1336 |
return self.add(CheckboxWidget, 'c-%s-%s' % (i, j), **widget_kwargs) |
|
1337 | ||
1338 | ||
1331 | 1339 |
class SingleSelectHintWidget(SingleSelectWidget): |
1332 | 1340 | |
1333 | 1341 |
def separate_hint(self): |
wcs/qommon/static/css/dc2/admin.css | ||
---|---|---|
1049 | 1049 |
width: calc(100% - 1em); |
1050 | 1050 |
} |
1051 | 1051 | |
1052 |
div.admin-permissions thead th { |
|
1053 |
transform: rotate(-45deg); |
|
1054 |
transform-origin: 10% 0; |
|
1055 |
} |
|
1056 | ||
1057 |
div.admin-permissions thead th span { |
|
1058 |
width: 3em; |
|
1059 |
display: inline-block; |
|
1060 |
white-space: nowrap; |
|
1061 |
} |
|
1062 | ||
1063 |
div.admin-permissions tbody th { |
|
1064 |
text-align: left; |
|
1065 |
padding-right: 1ex; |
|
1066 |
} |
|
1067 | ||
1068 |
div.admin-permissions tbody tr:nth-child(even) { |
|
1069 |
background: #eee; |
|
1070 |
} |
|
1052 | 1071 | |
1053 | 1072 |
@media print { |
1054 | 1073 |
div#sidebar { |
1055 |
- |