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 31, 2022
1 parent 2422b85 commit 7647014
Show file tree
Hide file tree
Showing 26 changed files with 1,615 additions and 99 deletions.
17 changes: 13 additions & 4 deletions sonar/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,9 @@ def _(x):
},
'doc_files': {
'pid_type': 'doc',
'record_class': 'sonar.modules.documents.api:DocumentRecord',
'route': '/documents/<pid_value>/files/<filename>',
'view_imp': 'invenio_records_files.utils:file_download_ui',
'view_imp': 'sonar.modules.utils:file_download_ui',
'record_class': 'invenio_records_files.api:Record'
},
'depo_previewer': {
Expand All @@ -301,7 +302,7 @@ def _(x):
'depo_files': {
'pid_type': 'depo',
'route': '/deposits/<pid_value>/files/<filename>',
'view_imp': 'invenio_records_files.utils:file_download_ui',
'view_imp': 'sonar.modules.utils:file_download_ui',
'record_class': 'invenio_records_files.api:Record'
},
'org_previewer': {
Expand All @@ -313,7 +314,7 @@ def _(x):
'org_files': {
'pid_type': 'org',
'route': '/organisations/<pid_value>/files/<filename>',
'view_imp': 'invenio_records_files.utils:file_download_ui',
'view_imp': 'sonar.modules.utils:file_download_ui',
'record_class': 'invenio_records_files.api:Record'
},
'proj': {
Expand All @@ -339,7 +340,7 @@ def _(x):
'coll_files': {
'pid_type': 'coll',
'route': '/collections/<pid_value>/files/<filename>',
'view_imp': 'invenio_records_files.utils:file_download_ui',
'view_imp': 'sonar.modules.utils:file_download_ui',
'record_class': 'invenio_records_files.api:Record'
},
}
Expand Down Expand Up @@ -801,6 +802,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:FilesPermission',
'depo': 'sonar.modules.deposits.permissions:DepositFilesPermission'
}
"""FilesPermission class to make the invenio files permission more flexible"""

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

"""Record permissions."""


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

from .api import Record
Expand Down Expand Up @@ -104,3 +106,61 @@ 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.
"""

@classmethod
def get_collection(cls, parent_record):
"""Get the collection record from the parent record."""
return Record.get_record_by_pid(parent_record['pid'])

@classmethod
def read(cls, user, record, pid, parent_record):
"""Read permission check.
:param user: Current user record.
:param record: Record to check.
:param pid: The :class:`invenio_pidstore.models.PersistentIdentifier`
instance.
:param parent_record: the record related to the bucket.
:returns: True is action can be done.
"""
# allowed for anyone
return True

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

@classmethod
def delete(cls, user, record, pid, parent_record):
"""Delete permission check.
:param user: Current user record.
:param record: Record to check.
:param pid: The :class:`invenio_pidstore.models.PersistentIdentifier`
instance.
:param parent_record: the record related to the bucket.
:returns: True is action can be done.
"""
return cls.update(user, record, pid, parent_record)
74 changes: 68 additions & 6 deletions sonar/modules/deposits/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

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 +30,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 +44,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 +58,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 +103,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 +114,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 +123,65 @@ 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.
"""

@classmethod
def get_deposit(cls, parent_record):
"""Get the deposit from the parent record."""
return DepositRecord.get_record_by_pid(parent_record.get('pid'))

@classmethod
def read(cls, user, record, pid, parent_record):
"""Read permission check.
:param user: Current user record.
:param record: Record to check.
:param pid: The :class:`invenio_pidstore.models.PersistentIdentifier`
instance.
:param parent_record: the record related to the bucket.
:returns: True is action can be done.
"""
# Superuser is allowed.
if user and user.is_superuser:
return True
deposit = cls.get_deposit(parent_record)
return deposit and DepositPermission.read(user, deposit)

@classmethod
def update(cls, user, record, pid, parent_record):
"""Update permission check.
:param user: Current user record.
:param record: Record to check.
:param pid: The :class:`invenio_pidstore.models.PersistentIdentifier`
instance.
:param parent_record: the record related to the bucket.
:returns: True is action can be done.
"""
# Superuser is allowed.
if user and user.is_superuser:
return True
deposit = cls.get_deposit(parent_record)
return deposit and DepositPermission.update(user, deposit)

@classmethod
def delete(cls, user, record, pid, parent_record):
"""Delete permission check.
:param user: Current user record.
:param record: Record to check.
:param pid: The :class:`invenio_pidstore.models.PersistentIdentifier`
instance.
:param parent_record: the record related to the bucket.
:returns: True is action can be done.
"""
# Superuser is allowed.
if user and user.is_superuser:
return True
deposit = cls.get_deposit(parent_record)
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 7647014

Please sign in to comment.