Skip to content

Commit 06d9448

Browse files
committed
authentication: add read permission for records
1 parent 4089fd3 commit 06d9448

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

cernopendata/config.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,54 +341,65 @@
341341
),
342342
)
343343

344+
_RECORD_PERMISSION_FACTORY = (
345+
"cernopendata.modules.records.permissions:record_read_permission_factory"
346+
)
347+
344348
RECORDS_UI_ENDPOINTS = dict(
345349
recid=dict(
346350
pid_type="recid",
347351
route="/record/<pid_value>",
348-
permission_factory_imp=None,
352+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
349353
record_class="cernopendata.api:RecordFilesWithIndex",
350354
view_imp="cernopendata.modules.records.utils:record_metadata_view",
351355
),
352356
recid_files=dict(
353357
pid_type="recid",
354358
route="/record/<pid_value>/files/<path:filename>",
359+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
355360
view_imp="cernopendata.modules.records.utils:file_download_ui",
356361
record_class="cernopendata.api:RecordFilesWithIndex",
357362
),
358363
recid_file_index=dict(
359364
pid_type="recid",
360365
route="/record/<pid_value>/file_index/<path:file_index>",
366+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
361367
view_imp="cernopendata.modules.records.utils:get_file_index",
362368
record_class="cernopendata.api:RecordFilesWithIndex",
363369
),
364370
recid_files_assets=dict(
365371
pid_type="recid",
366372
route="/record/<pid_value>/files/assets/<path:filepath>",
373+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
367374
view_imp="cernopendata.modules.records.utils:eos_file_download_ui",
368375
record_class="cernopendata.api:RecordFilesWithIndex",
369376
),
370377
recid_files_page=dict(
371378
pid_type="recid",
372379
route="/record/<pid_value>/filepage/<int:page>",
380+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
373381
view_imp="cernopendata.modules.records.utils:record_file_page",
374382
record_class="cernopendata.api:RecordFilesWithIndex",
375383
),
376384
recid_export=dict(
377385
pid_type="recid",
378386
route="/record/<pid_value>/export/<format>",
387+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
379388
view_imp="cernopendata.modules.records.utils:export_json_view",
380389
record_class="cernopendata.api:RecordFilesWithIndex",
381390
),
382391
recid_stage=dict(
383392
pid_type="recid",
384393
route="/record/<pid_value>/stage",
394+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
385395
view_imp="cernopendata.modules.records.utils:stage",
386396
methods=["POST"],
387397
record_class="cernopendata.api:RecordFilesWithIndex",
388398
),
389399
recid_subscribe=dict(
390400
pid_type="recid",
391401
route="/record/<pid_value>/subscribe",
402+
permission_factory_imp=_RECORD_PERMISSION_FACTORY,
392403
view_imp="cernopendata.modules.records.utils:subscribe",
393404
methods=["POST"],
394405
record_class="cernopendata.api:RecordFilesWithIndex",
@@ -460,6 +471,7 @@ def _query_parser_and(qstr=None):
460471
),
461472
},
462473
"search_factory_imp": "cernopendata.modules.records.queries:search_factory",
474+
"read_permission_factory_imp": _RECORD_PERMISSION_FACTORY,
463475
}
464476
)
465477

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""CERN Open Data record permissions."""
2+
3+
from flask_login import current_user
4+
5+
from cernopendata.modules.releases.models import ReleaseMetadata, ReleaseStatus
6+
from cernopendata.modules.releases.utils import curator_experiments
7+
8+
9+
def record_read_permission_factory(record, *args, **kwargs):
10+
"""Return a read permission for a record.
11+
12+
By default, records are publicly accessible. If the record appears
13+
in a release that has not yet been published, access is restricted
14+
to curators of the corresponding experiment.
15+
"""
16+
17+
def can(self):
18+
prerelease = record.get("prerelease")
19+
if not prerelease:
20+
return True
21+
22+
try:
23+
experiment, release_id = prerelease.split("/", 1)
24+
release_id = int(release_id)
25+
except (ValueError, AttributeError):
26+
return True
27+
28+
release = ReleaseMetadata.query.filter_by(
29+
id=release_id, experiment=experiment
30+
).first()
31+
32+
if release is None or release.status == ReleaseStatus.PUBLISHED.value:
33+
return True
34+
35+
if not current_user.is_authenticated:
36+
return False
37+
38+
return experiment in curator_experiments()["curator_experiments"]
39+
40+
return type("RecordReadPermission", (), {"can": can})()

0 commit comments

Comments
 (0)