Skip to content

Commit

Permalink
Implements permissions per transition inveniosoftware#26
Browse files Browse the repository at this point in the history
Permissions factory per transition.

Rebased on master.

Loading permission factory from config for tests.

Clean up.
  • Loading branch information
topless committed Aug 2, 2018
1 parent 1a4f126 commit bcb5572
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 4 deletions.
4 changes: 4 additions & 0 deletions invenio_circulation/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

"""Invenio module for the circulation of bibliographic items."""

from invenio_records_rest.utils import allow_all

from .api import Loan
from .links import loan_links_factory
from .transitions.transitions import CreatedToItemOnLoan, CreatedToPending, \
Expand All @@ -33,6 +35,8 @@
_CIRCULATION_LOAN_LINKS_FACTORY = loan_links_factory
"""."""

CIRCULATION_PERMISSION_FACTORY = allow_all
"""."""

CIRCULATION_STATES_ITEM_AVAILABLE = ['ITEM_RETURNED']
"""."""
Expand Down
4 changes: 4 additions & 0 deletions invenio_circulation/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ class LoanActionError(CirculationException):
"""."""


class InvalidCirculationPermission(CirculationException):
"""Raised when permissions are not satisfied for transition."""


class TransitionConstraintsViolation(CirculationException):
"""Exception raised when constraints for the transition failed."""
7 changes: 6 additions & 1 deletion invenio_circulation/transitions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def __init__(self, src, dest, trigger='next', permission_factory=None,
self.src = src
self.dest = dest
self.trigger = trigger
self.permission_factory = permission_factory
self.permission_factory = permission_factory or \
current_app.config['CIRCULATION_PERMISSION_FACTORY']
# validate states
self.validate_transition_states()

Expand All @@ -110,6 +111,10 @@ def validate_transition_states(self):
@check_trigger
def before(self, loan, **kwargs):
"""Validate input, evaluate conditions and raise if failed."""
if self.permission_factory and not self.permission_factory(loan).can():
msg = 'Invalid circulation permission'
raise InvalidCirculationPermission(msg=msg)

kwargs.setdefault('transaction_date', datetime.now())
kwargs['transaction_date'] = parse_date(kwargs['transaction_date'])
loan.update(kwargs)
Expand Down
10 changes: 7 additions & 3 deletions invenio_circulation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
from invenio_rest import ContentNegotiatedMethodView
from invenio_rest.views import create_api_errorhandler

from invenio_circulation.errors import ItemNotAvailable, LoanActionError, \
NoValidTransitionAvailable
from invenio_circulation.errors import InvalidCirculationPermission, \
ItemNotAvailable, LoanActionError, NoValidTransitionAvailable
from invenio_circulation.proxies import current_circulation

HTTP_CODES = {
Expand Down Expand Up @@ -125,7 +125,11 @@ def post(self, pid, record, action, **kwargs):
record, **dict(params, trigger=action)
)
db.session.commit()
except (ItemNotAvailable, NoValidTransitionAvailable) as ex:
except (
ItemNotAvailable,
InvalidCirculationPermission,
NoValidTransitionAvailable
) as ex:
current_app.logger.exception(ex.msg)
raise LoanActionError(ex)

Expand Down
31 changes: 31 additions & 0 deletions tests/test_permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# This file is part of CDS.
# Copyright (C) 2015, 2016, 2018 CERN.
#
# CDS is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# CDS is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CDS; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, CERN does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""Test circulation permissions."""


def test_permission(app):
"""Test permission factories."""
factory = app.config['CIRCULATION_PERMISSION_FACTORY']
assert factory().can()

0 comments on commit bcb5572

Please sign in to comment.