|
1 | 1 | # -*- coding: utf-8 -*-
|
2 | 2 | #
|
3 |
| -# Copyright (C) 2019-2024 CERN. |
| 3 | +# Copyright (C) 2019-2025 CERN. |
4 | 4 | # Copyright (C) 2019-2021 Northwestern University.
|
5 | 5 | # Copyright (C) 2021 TU Wien.
|
6 | 6 | #
|
|
11 | 11 |
|
12 | 12 | from functools import wraps
|
13 | 13 |
|
14 |
| -from flask import g, make_response, redirect, request, session, url_for |
| 14 | +from flask import current_app, g, make_response, redirect, request, session, url_for |
15 | 15 | from flask_login import login_required
|
16 | 16 | from invenio_communities.communities.resources.serializer import (
|
17 | 17 | UICommunityJSONSerializer,
|
18 | 18 | )
|
19 | 19 | from invenio_communities.proxies import current_communities
|
20 | 20 | from invenio_pidstore.errors import PIDDoesNotExistError
|
21 | 21 | from invenio_rdm_records.proxies import current_rdm_records
|
| 22 | +from invenio_rdm_records.resources.serializers.signposting import ( |
| 23 | + FAIRSignpostingProfileLvl1Serializer, |
| 24 | +) |
22 | 25 | from invenio_records_resources.services.errors import PermissionDeniedError
|
23 | 26 | from sqlalchemy.orm.exc import NoResultFound
|
24 | 27 |
|
@@ -365,20 +368,100 @@ def view(**kwargs):
|
365 | 368 | return view
|
366 | 369 |
|
367 | 370 |
|
368 |
| -def add_signposting(f): |
369 |
| - """Add signposting link to view's response headers.""" |
| 371 | +def _get_header(rel, value, link_type=None): |
| 372 | + header = f'<{value}> ; rel="{rel}"' |
| 373 | + if link_type: |
| 374 | + header += f' ; type="{link_type}"' |
| 375 | + return header |
| 376 | + |
| 377 | + |
| 378 | +def _get_signposting_collection(pid_value): |
| 379 | + ui_url = record_url_for(pid_value=pid_value) |
| 380 | + return _get_header("collection", ui_url, "text/html") |
| 381 | + |
| 382 | + |
| 383 | +def _get_signposting_describes(pid_value): |
| 384 | + ui_url = record_url_for(pid_value=pid_value) |
| 385 | + return _get_header("describes", ui_url, "text/html") |
| 386 | + |
| 387 | + |
| 388 | +def _get_signposting_linkset(pid_value): |
| 389 | + api_url = record_url_for(_app="api", pid_value=pid_value) |
| 390 | + return _get_header("linkset", api_url, "application/linkset+json") |
| 391 | + |
| 392 | + |
| 393 | +def add_signposting_landing_page(f): |
| 394 | + """Add signposting links to the landing page view's response headers.""" |
| 395 | + |
| 396 | + @wraps(f) |
| 397 | + def view(*args, **kwargs): |
| 398 | + response = make_response(f(*args, **kwargs)) |
| 399 | + |
| 400 | + # Relies on other decorators having operated before it |
| 401 | + if current_app.config[ |
| 402 | + "APP_RDM_RECORD_LANDING_PAGE_FAIR_SIGNPOSTING_LEVEL_1_ENABLED" |
| 403 | + ]: |
| 404 | + record = kwargs["record"] |
| 405 | + |
| 406 | + signposting_headers = ( |
| 407 | + FAIRSignpostingProfileLvl1Serializer().serialize_object( |
| 408 | + record.to_dict() |
| 409 | + ) |
| 410 | + ) |
| 411 | + |
| 412 | + response.headers["Link"] = signposting_headers |
| 413 | + else: |
| 414 | + pid_value = kwargs["pid_value"] |
| 415 | + signposting_link = record_url_for(_app="api", pid_value=pid_value) |
| 416 | + |
| 417 | + response.headers["Link"] = ( |
| 418 | + f'<{signposting_link}> ; rel="linkset" ; type="application/linkset+json"' # fmt: skip |
| 419 | + ) |
| 420 | + |
| 421 | + return response |
| 422 | + |
| 423 | + return view |
| 424 | + |
| 425 | + |
| 426 | +def add_signposting_content_resources(f): |
| 427 | + """Add signposting links to the content resources view's response headers.""" |
370 | 428 |
|
371 | 429 | @wraps(f)
|
372 | 430 | def view(*args, **kwargs):
|
373 | 431 | response = make_response(f(*args, **kwargs))
|
374 | 432 |
|
375 | 433 | # Relies on other decorators having operated before it
|
376 | 434 | pid_value = kwargs["pid_value"]
|
377 |
| - signposting_link = record_url_for(_app="api", pid_value=pid_value) |
378 | 435 |
|
379 |
| - response.headers["Link"] = ( |
380 |
| - f'<{signposting_link}> ; rel="linkset" ; type="application/linkset+json"' # fmt: skip |
381 |
| - ) |
| 436 | + signposting_headers = [ |
| 437 | + _get_signposting_collection(pid_value), |
| 438 | + _get_signposting_linkset(pid_value), |
| 439 | + ] |
| 440 | + |
| 441 | + response.headers["Link"] = " , ".join(signposting_headers) |
| 442 | + |
| 443 | + return response |
| 444 | + |
| 445 | + return view |
| 446 | + |
| 447 | + |
| 448 | +def add_signposting_metadata_resources(f): |
| 449 | + """Add signposting links to the metadata resources view's response headers.""" |
| 450 | + |
| 451 | + @wraps(f) |
| 452 | + def view(*args, **kwargs): |
| 453 | + response = make_response(f(*args, **kwargs)) |
| 454 | + |
| 455 | + # Relies on other decorators having operated before it |
| 456 | + pid_value = kwargs["pid_value"] |
| 457 | + |
| 458 | + signposting_headers = [ |
| 459 | + _get_signposting_describes(pid_value), |
| 460 | + _get_signposting_linkset(pid_value), |
| 461 | + ] |
| 462 | + |
| 463 | + response.headers["Link"] = " , ".join(signposting_headers) |
| 464 | + |
382 | 465 | return response
|
383 | 466 |
|
384 | 467 | return view
|
|
0 commit comments