Skip to content

Commit

Permalink
fix(templates): allow private delete for syslib
Browse files Browse the repository at this point in the history
* Closes #3449.
* This also allows full_permissions librarians to edit and change
visibility of private templates.

Co-Authored-by: Pascal Repond <pascal.repond@rero.ch>
  • Loading branch information
PascalRepond committed Apr 2, 2024
1 parent df629e2 commit 4ea0a09
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 30 deletions.
36 changes: 16 additions & 20 deletions rero_ils/modules/templates/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"""Templates permissions."""

from flask import g
from flask_principal import RoleNeed
from invenio_access import action_factory

from rero_ils.modules.patrons.api import current_librarian
Expand Down Expand Up @@ -106,28 +107,23 @@ def needs(self, record, **kwargs):
if not record:
return required_needs

# if current logged user isn't a staff member then protect the template
# by only its owner. If permission matrix is correctly build, it should
# never happen.
owner_need = OwnerNeed(record.creator_pid)
if not current_librarian and owner_need not in g.identity.provides:
return [] # empty array == disable operation
# If user is 'full_permissions', allow write to
# any template (private or public) in their own organisation.
needs = {
OrganisationNeed(record.organisation_pid),
RoleNeed(UserRole.FULL_PERMISSIONS)
}
if needs.issubset(g.identity.provides):
return required_needs

# * If template is public, only 'full_permission' user can perform
# create/update/delete operations on such record for record of its
# own organisation.
# * If template is private, only owner can perform create/update/delete
# operations on such record.
user_roles = current_librarian.get('roles', [])
if record.is_public:
org_need = OrganisationNeed(record.organisation_pid)
if UserRole.FULL_PERMISSIONS not in user_roles or \
org_need not in g.identity.provides:
return [] # empty array == disable operation
elif record.is_private and owner_need not in g.identity.provides:
return [] # empty array == disable operation
# If the template is private and it belongs to the user,
# allow write according to required_needs
owner_need = OwnerNeed(record.creator_pid)
if record.is_private and owner_need in g.identity.provides:
return required_needs

return required_needs
# Any other case, disallow operation
return []


class TemplatePermissionPolicy(RecordPermissionPolicy):
Expand Down
13 changes: 5 additions & 8 deletions tests/api/templates/test_templates_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,8 @@ def test_template_permissions(
}, templ_doc_private_sion)

# Librarian with classic 'full-permissions' role:
# * public template:
# - all operations about templates for its own organisation
# * private templates :
# - read: all templates linked to its own organisation
# - other operations available only for its own templates.
# * public and private templates:
# - all operations for templates in their own organisation
librarian_martigny['roles'] = ['pro_full_permissions']
librarian_martigny.update(librarian_martigny, dbcommit=True, reindex=True)
flush_index(PatronsSearch.Meta.index)
Expand Down Expand Up @@ -260,9 +257,9 @@ def test_template_permissions(
check_permission(TemplatePermissionPolicy, {
'search': True,
'read': True,
'create': False,
'update': False,
'delete': False
'create': True,
'update': True,
'delete': True
}, templ_doc_private_saxon)
check_permission(TemplatePermissionPolicy, {
'search': True,
Expand Down
7 changes: 5 additions & 2 deletions tests/api/templates/test_templates_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def test_template_secure_api_update(
data = templ_doc_private_martigny_data
data['name'] = 'Test Name'
res = client.put(record_url, data=json.dumps(data), headers=json_header)
assert res.status_code == 403
assert res.status_code == 200

login_user_via_session(client, librarian_martigny.user)
data = templ_doc_private_martigny_data
Expand All @@ -296,7 +296,10 @@ def test_template_secure_api_update(
data = templ_doc_private_martigny_data
data['visibility'] = TemplateVisibility.PUBLIC
res = client.put(record_url, data=json.dumps(data), headers=json_header)
assert res.status_code == 403
assert res.status_code == 200
data['visibility'] = TemplateVisibility.PRIVATE
# reverse visibility
data.update(data, dbcommit=True, reindex=True)

login_user_via_session(client, librarian_saxon.user)
data = templ_doc_private_martigny_data
Expand Down

0 comments on commit 4ea0a09

Please sign in to comment.