*** Wartungsfenster jeden ersten Mittwoch vormittag im Monat ***

Skip to content
Snippets Groups Projects
Commit f2baa8aa authored by Moser, Maximilian's avatar Moser, Maximilian
Browse files

Fix file previewer

* Fix some bugs
* Check permissions before previewing files
* Refactor a little bit
parent 348c37c6
No related branches found
No related tags found
No related merge requests found
......@@ -202,6 +202,12 @@ try:
"route": "/records/<pid_value>/files/<path:filename>",
"view_imp": "invenio_config_tuw.views.file_download_ui",
}
recid_previewer = {
"pid_type": "recid",
"record_class": "invenio_rdm_records.records:BibliographicRecord",
"route": "/records/<pid_value>/preview/<path:filename>",
"view_imp": "invenio_config_tuw.views.preview",
}
try:
from invenio_theme_tuw.config import RECORDS_UI_ENDPOINTS
......@@ -209,6 +215,7 @@ try:
from invenio_rdm_records.config import RECORDS_UI_ENDPOINTS
RECORDS_UI_ENDPOINTS.get("recid_files", {}).update(recid_files)
RECORDS_UI_ENDPOINTS.get("recid_previewer", {}).update(recid_previewer)
except Exception as e:
print(e)
......
import logging
import arrow
from flask_principal import UserNeed
from invenio_access.permissions import any_user
from invenio_rdm_records.services import RDMRecordPermissionPolicy
......@@ -13,6 +12,8 @@ from invenio_records_permissions.generators import (
SuperUser,
)
from .utils import is_open
class RecordOwners(RecordOwners):
"""Allows record owners."""
......@@ -51,30 +52,9 @@ class RecordOwners(RecordOwners):
class AnyUserIfPublic(AnyUserIfPublic):
"""Allows anybody if the record is public."""
def is_open(self, record):
"""Check if the record is open or closed (or embargoed) access."""
if record is None:
return False
access = record.get("access", {})
embargo = access.get("embargo_date", None)
access_right = access.get("access_right", "closed")
# check if there's an embargo or the access isn't open
if embargo is None and access_right == "open":
return True
elif access_right != "open":
return False
# the access right is open, but we still have to check the embargo
if arrow.get(embargo).date() < arrow.utcnow().date():
return True
else:
return False
def needs(self, **kwargs):
"""Enabling Needs."""
if self.is_open(kwargs.get("record")):
if is_open(kwargs.get("record")):
return [any_user]
return []
......
"""Utility functions."""
import arrow
from flask_principal import Identity
from flask_security import current_user
from invenio_access import any_user
from invenio_access.utils import get_identity
from invenio_accounts import current_accounts
from invenio_rdm_records.services.services import BibliographicRecordFilesService
from invenio_records_resources.services.errors import PermissionDeniedError
def get_identity_for_user(user):
......@@ -23,3 +27,43 @@ def get_identity_for_user(user):
identity.provides.add(any_user)
return identity
def is_open(record):
"""Check if the record is open or closed (or embargoed) access."""
if record is None:
return False
access = record.get("access", {})
embargo = access.get("embargo_date", None)
access_right = access.get("access_right", "closed")
# check if there's an embargo or the access isn't open
if embargo is None and access_right == "open":
return True
elif access_right != "open":
return False
# the access right is open, but we still have to check the embargo
if arrow.get(embargo).date() < arrow.utcnow().date():
return True
else:
return False
def check_permission(
permission_str, record, service_cls=BibliographicRecordFilesService
):
"""Check if the current user has the specified permissions."""
service = service_cls()
try:
try:
identity = get_identity_for_user(current_user.id)
except AttributeError:
identity = get_identity_for_user(None)
service.require_permission(identity, permission_str, record=record)
return True
except PermissionDeniedError:
return False
from flask import abort, request
from flask_security import current_user
from flask import abort, current_app, request
from invenio_files_rest.views import ObjectResource
from invenio_rdm_records.services.services import BibliographicRecordFilesService
from invenio_previewer import current_previewer
from invenio_previewer.api import PreviewFile
from invenio_previewer.extensions import default
from invenio_rdm_records.utils import previewer_record_file_factory
from invenio_records_resources.services.errors import PermissionDeniedError
from .utils import get_identity_for_user
from .utils import check_permission
def file_download_ui(pid, record, _record_file_factory=None, **kwargs):
......@@ -27,15 +27,7 @@ def file_download_ui(pid, record, _record_file_factory=None, **kwargs):
obj = fileobj.obj
service = BibliographicRecordFilesService()
try:
try:
identity = get_identity_for_user(current_user.id)
except AttributeError:
identity = get_identity_for_user(None)
service.require_permission(identity, "read_files", record=record)
except PermissionDeniedError:
if not check_permission("read_files", record):
abort(403)
# Check permissions
......@@ -53,3 +45,56 @@ def file_download_ui(pid, record, _record_file_factory=None, **kwargs):
},
as_attachment=("download" in request.args),
)
def preview(pid, record, template=None, **kwargs):
"""Preview file for given record.
Plug this method into your ``RECORDS_UI_ENDPOINTS`` configuration:
.. code-block:: python
RECORDS_UI_ENDPOINTS = dict(
recid=dict(
# ...
route='/records/<pid_value/preview/<path:filename>',
view_imp='invenio_previewer.views.preview',
record_class='invenio_records_files.api:Record',
)
)
"""
# Get file from record
fileobj = current_previewer.record_file_factory(
pid,
record,
request.view_args.get("filename", request.args.get("filename", type=str)),
)
if fileobj is None: # actually check against None, not against bool(fileobj)
abort(404)
elif not check_permission("read_files", record):
return default.preview(fileobj)
# Try to see if specific previewer is set
file_previewer = fileobj.get("previewer")
# Find a suitable previewer
fileobj["size"] = fileobj.file.size # fixes the KeyError in plugin.can_preview()
fileobj = PreviewFile(pid, record, fileobj)
for plugin in current_previewer.iter_previewers(
previewers=[file_previewer] if file_previewer else None
):
if plugin.can_preview(fileobj):
try:
return plugin.preview(fileobj)
except Exception:
current_app.logger.warning(
(
"Preview failed for {key}, in {pid_type}:{pid_value}".format(
key=fileobj.file.key,
pid_type=fileobj.pid.pid_type,
pid_value=fileobj.pid.pid_value,
)
),
exc_info=True,
)
return default.preview(fileobj)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment