Skip to content

Commit

Permalink
files: fix files permissions
Browse files Browse the repository at this point in the history
* Adds files restriction for documents.
* Adds files restriction for deposits.
* Adds files restriction for organisations.
* Adds files restriction for collections.
* Fixes document restrictions.
* Closes #746.

Co-Authored-by: Johnny Mariéthoz <[email protected]>
  • Loading branch information
jma committed Jan 26, 2022
1 parent 2422b85 commit 68ff0fd
Show file tree
Hide file tree
Showing 21 changed files with 1,311 additions and 90 deletions.
8 changes: 8 additions & 0 deletions sonar/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,14 @@ def _(x):
FILES_REST_PERMISSION_FACTORY = \
'sonar.modules.permissions.files_permission_factory'

SONAR_APP_FILES_REST_PERMISSION = {
'doc': 'sonar.modules.documents.permissions:DocumentFilesPermission',
'org': 'sonar.modules.organisations.permissions:OrganisationFilesPermission',
'coll': 'sonar.modules.collections.permissions:CollectionFilesPermission',
'depo': 'sonar.modules.deposits.permissions:DepositFilesPermission'
}
"""FilesPermission class to make the invenio files permission more flexible"""

# Database
# =========================
DB_VERSIONING = False
Expand Down
61 changes: 60 additions & 1 deletion sonar/modules/collections/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

"""Record permissions."""

from flask import request

from sonar.modules.documents.api import DocumentSearch
from sonar.modules.organisations.api import current_organisation
from sonar.modules.permissions import RecordPermission as BaseRecordPermission

from sonar.modules.permissions import FilesPermission as BaseFilesPermission
from .api import Record


Expand Down Expand Up @@ -104,3 +106,60 @@ def delete(cls, user, record):
return False

return cls.read(user, record)

class FilesPermission(BaseFilesPermission):
"""Collection files permissions.
Follows the same rules than the corresponding collection except for read
which is always accessible.
"""

def __init__(self, record, func, user):
"""Constructor."""
super().__init__(record, func, user)

@classmethod
def get_collection(cls):
"""Get the collection record from the URL path."""
pid_value_args = request.view_args.get('pid_value')
record = None
if pid_value_args:
(pid, record) = pid_value_args.data
return Record.get_record_by_pid(record['pid'])

@classmethod
def read(cls, user, record):
"""Read permission check.
:param user: Current user record.
:param record: Record to check.
:returns: True is action can be done.
"""
# allowed for anyone
return True

@classmethod
def update(cls, user, record):
"""Update permission check.
Mainly the same behavior than the corresponding collection record.
:param user: Current user record.
:param record: Record to check.
:returns: True is action can be done.
"""
# Superuser is allowed.
if user and user.is_superuser:
return True
collection = cls.get_collection()
return collection and RecordPermission.update(user, collection)

@classmethod
def delete(cls, user, record):
"""Delete permission check.
:param user: Current user record.
:param record: Record to check.
:returns: True is action can be done.
"""
return cls.update(user, record)
74 changes: 68 additions & 6 deletions sonar/modules/deposits/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Permissions for deposits."""
from flask import request

from sonar.modules.deposits.api import DepositRecord
from sonar.modules.organisations.api import current_organisation
from sonar.modules.permissions import RecordPermission
from sonar.modules.permissions import FilesPermission, RecordPermission


class DepositPermission(RecordPermission):
Expand All @@ -30,7 +31,7 @@ def list(cls, user, record=None):
"""List permission check.
:param user: Current user record.
:param recor: Record to check.
:param record: Record to check.
:returns: True is action can be done.
"""
# At least for submitters logged users.
Expand All @@ -44,7 +45,7 @@ def create(cls, user, record=None):
"""Create permission check.
:param user: Current user record.
:param recor: Record to check.
:param record: Record to check.
:returns: True is action can be done.
"""
# No logged user.
Expand All @@ -58,7 +59,7 @@ def read(cls, user, record):
"""Read permission check.
:param user: Current user record.
:param recor: Record to check.
:param record: Record to check.
:returns: True is action can be done.
"""
# At least for submitters logged users.
Expand Down Expand Up @@ -103,7 +104,7 @@ def update(cls, user, record):
"""Update permission check.
:param user: Current user record.
:param recor: Record to check.
:param record: Record to check.
:returns: True is action can be done.
"""
# Same rules as read.
Expand All @@ -114,7 +115,7 @@ def delete(cls, user, record):
"""Delete permission check.
:param user: Current user record.
:param recor: Record to check.
:param record: Record to check.
:returns: True is action can be done.
"""
# Cannot delete a validated deposit.
Expand All @@ -123,3 +124,64 @@ def delete(cls, user, record):

# Same rules as read.
return cls.read(user, record)

class DepositFilesPermission(FilesPermission):
"""Deposits files permissions.
Follows the same rules than the corresponding deposit.
"""

def __init__(self, record, func, user):
"""Constructor."""
super().__init__(record, func, user)

@classmethod
def get_deposit(cls):
"""Get the document from the URL path."""
pid_value_args = request.view_args.get('pid_value')
record = None
if pid_value_args:
(pid, record) = pid_value_args.data
return DepositRecord.get_record_by_pid(record['pid'])

@classmethod
def read(cls, user, record):
"""Read permission check.
:param user: Current user record.
:param record: Record to check.
:returns: True is action can be done.
"""
# Superuser is allowed.
if user and user.is_superuser:
return True
deposit = cls.get_deposit()
return deposit and DepositPermission.read(user, deposit)

@classmethod
def update(cls, user, record):
"""Update permission check.
:param user: Current user record.
:param record: Record to check.
:returns: True is action can be done.
"""
# Superuser is allowed.
if user and user.is_superuser:
return True
deposit = cls.get_deposit()
return deposit and DepositPermission.update(user, deposit)

@classmethod
def delete(cls, user, record):
"""Delete permission check.
:param user: Current user record.
:param record: Record to check.
:returns: True is action can be done.
"""
# Superuser is allowed.
if user and user.is_superuser:
return True
deposit = cls.get_deposit()
return deposit and DepositPermission.delete(user, deposit)
23 changes: 22 additions & 1 deletion sonar/modules/documents/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from sonar.modules.documents.minters import id_minter
from sonar.modules.pdf_extractor.utils import extract_text_from_content
from sonar.modules.utils import change_filename_extension, \
create_thumbnail_from_file
create_thumbnail_from_file, get_current_ip, is_ip_in_list

from ..api import SonarIndexer, SonarRecord, SonarSearch
from ..ark.api import current_ark
Expand Down Expand Up @@ -359,6 +359,27 @@ def is_open_access(self):

return True

@property
def is_masked(self):
"""Check if record is masked.
:returns: True if record is masked
:rtype: boolean
"""
if not self.get('masked'):
return False

if self['masked'] == 'masked_for_all':
return True

if self['masked'] == 'masked_for_external_ips' and self.get(
'organisation') and not is_ip_in_list(
get_current_ip(), self['organisation'][0].get(
'allowedIps', '').split('\n')):
return True

return False

def get_ark_resolver_url(self):
"""Get the ark resolver url.
Expand Down
Loading

0 comments on commit 68ff0fd

Please sign in to comment.