Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
{% if record_deletion %}
<input type="hidden" name="deposits-record-deletion" value='{{ record_deletion | tojson }}'>
{% endif %}
{% if file_modification %}
<input type="hidden" name="deposits-file-modification" value='{{ file_modification | tojson }}'>
{% endif %}
<input type="hidden" name="config-groups-enabled"
value='{{ config.USERS_RESOURCES_GROUPS_ENABLED | tojson }}'>
<input type="hidden" name="records-resources-allow-empty-files"
Expand Down
65 changes: 64 additions & 1 deletion invenio_app_rdm/records_ui/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@

from itertools import chain

from flask import current_app
from flask import current_app, g
from invenio_access.permissions import system_identity
from invenio_rdm_records.records.api import RDMRecord
from invenio_rdm_records.requests.record_deletion import RecordDeletion
from invenio_rdm_records.services.config import (
FileModificationPolicyEvaluator,
RDMRecordDeletionPolicy,
)
from invenio_records.dictutils import dict_set
from invenio_records.errors import MissingModelError
from invenio_records_files.api import FileObject
Expand Down Expand Up @@ -109,3 +114,61 @@ def get_existing_deletion_request(record_id):
)
if existing_requests.total > 0:
return list(existing_requests)[0]


def evaluate_record_deletion(record: RDMRecord):
"""Evaluate whether a given record can be deleted by an identity."""
rec_del = RDMRecordDeletionPolicy().evaluate(g.identity, record._record)

immediate, request = rec_del["immediate_deletion"], rec_del["request_deletion"]
rd_enabled = immediate.enabled or request.enabled
rd_valid_user = immediate.valid_user or request.valid_user
rd_allowed = immediate.allowed or request.allowed
existing_request = get_existing_deletion_request(record.id)

if rd_allowed:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't the feature behind a flag? should we return all this information if f.e. we in CDS do not allow any record deletions?

record_deletion = {
"enabled": rd_enabled,
"valid_user": rd_valid_user,
"allowed": rd_allowed,
"recordDeletion": rec_del,
"checklist": (
current_app.config["RDM_IMMEDIATE_RECORD_DELETION_CHECKLIST"]
if immediate.allowed
else current_app.config["RDM_REQUEST_RECORD_DELETION_CHECKLIST"]
),
"context": {
"files": record["files"]["count"],
"internalDoi": record["pids"]["doi"]["provider"] != "external",
},
}
else:
record_deletion = {
"enabled": rd_enabled,
"valid_user": rd_valid_user,
"allowed": rd_allowed,
}
record_deletion["existing_request"] = (
existing_request["links"]["self_html"] if existing_request else None
)

return record_deletion


def evaluate_file_modification(record):
"""Evaluate whether a given record file's can be edited by an identity."""
file_mod = FileModificationPolicyEvaluator().evaluate(g.identity, record._record)

file_mod = file_mod["immediate_file_modification"]
fm_allowed = file_mod.allowed

file_modification = {
"enabled": file_mod.enabled,
"valid_user": file_mod.valid_user,
"allowed": fm_allowed,
}
if fm_allowed:
file_modification["fileModification"] = file_mod
file_modification["context"] = {}

return file_modification
6 changes: 1 addition & 5 deletions invenio_app_rdm/records_ui/views/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,7 @@ def view(**kwargs):
expand=expand,
)
kwargs["draft"] = draft
kwargs["files_locked"] = (
record_service.config.lock_edit_published_files(
record_service, g.identity, draft=draft, record=draft._record
)
)
kwargs["files_locked"] = draft._record.files.bucket.locked
return f(**kwargs)
except PIDDoesNotExistError:
# Redirect to /records/:id because users are interchangeably
Expand Down
48 changes: 9 additions & 39 deletions invenio_app_rdm/records_ui/views/deposits.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from invenio_rdm_records.proxies import current_rdm_records
from invenio_rdm_records.records.api import get_files_quota
from invenio_rdm_records.resources.serializers import UIJSONSerializer
from invenio_rdm_records.services.config import RDMRecordDeletionPolicy
from invenio_rdm_records.services.schemas import RDMRecordSchema
from invenio_rdm_records.services.schemas.utils import dump_empty
from invenio_rdm_records.views import file_transfer_type
Expand All @@ -38,7 +37,11 @@
from marshmallow_utils.fields.babel import gettext_from_dict
from sqlalchemy.orm import load_only

from ..utils import get_existing_deletion_request, set_default_value
from ..utils import (
evaluate_file_modification,
evaluate_record_deletion,
set_default_value,
)
from .decorators import (
no_cache_response,
pass_draft,
Expand Down Expand Up @@ -542,45 +545,11 @@ def deposit_edit(pid_value, draft=None, draft_files=None, files_locked=True):
)
published_record = ui_serializer.dump_obj(published_record_result.to_dict())

rec_del = RDMRecordDeletionPolicy().evaluate(
g.identity, published_record_result._record
)
immediate, request = rec_del["immediate_deletion"], rec_del["request_deletion"]
rd_enabled = immediate.enabled or request.enabled
rd_valid_user = (
rec_del["immediate_deletion"].valid_user
or rec_del["request_deletion"].valid_user
)
rd_allowed = immediate.allowed or request.allowed
existing_request = get_existing_deletion_request(record.get("id"))

if rd_allowed:
record_deletion = {
"enabled": rd_enabled,
"valid_user": rd_valid_user,
"allowed": rd_allowed,
"recordDeletion": rec_del,
"checklist": (
current_app.config["RDM_IMMEDIATE_RECORD_DELETION_CHECKLIST"]
if immediate.allowed
else current_app.config["RDM_REQUEST_RECORD_DELETION_CHECKLIST"]
),
"context": {
"files": draft._record.files.count,
"internalDoi": draft._record.pids["doi"]["provider"] != "external",
},
}
else:
record_deletion = {
"enabled": rd_enabled,
"valid_user": rd_valid_user,
"allowed": rd_allowed,
}
record_deletion["existing_request"] = (
existing_request["links"]["self_html"] if existing_request else None
)
record_deletion = evaluate_record_deletion(published_record_result)
file_modification = evaluate_file_modification(published_record_result)
else:
record_deletion = {}
file_modification = {}

community_ui = None
community_theme = None
Expand Down Expand Up @@ -656,6 +625,7 @@ def deposit_edit(pid_value, draft=None, draft_files=None, files_locked=True):
]
),
record_deletion=record_deletion,
file_modification=file_modification,
)


Expand Down
40 changes: 2 additions & 38 deletions invenio_app_rdm/records_ui/views/records.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
AccessSettings,
)
from invenio_rdm_records.resources.serializers import UIJSONSerializer
from invenio_rdm_records.services.config import RDMRecordDeletionPolicy
from invenio_stats.proxies import current_stats
from invenio_users_resources.proxies import current_user_resources
from marshmallow import ValidationError
Expand All @@ -38,7 +37,7 @@
previewable_extensions as image_extensions,
)

from ..utils import get_existing_deletion_request, get_external_resources
from ..utils import evaluate_record_deletion, get_external_resources
from .decorators import (
add_signposting_content_resources,
add_signposting_landing_page,
Expand Down Expand Up @@ -158,42 +157,7 @@ def record_detail(

record_ui = UIJSONSerializer().dump_obj(record.to_dict())

rec_del = RDMRecordDeletionPolicy().evaluate(g.identity, record._record)

immediate, request = rec_del["immediate_deletion"], rec_del["request_deletion"]
rd_enabled = immediate.enabled or request.enabled
rd_valid_user = (
rec_del["immediate_deletion"].valid_user
or rec_del["request_deletion"].valid_user
)
rd_allowed = immediate.allowed or request.allowed
existing_request = get_existing_deletion_request(record.id)

if rd_allowed:
record_deletion = {
"enabled": rd_enabled,
"valid_user": rd_valid_user,
"allowed": rd_allowed,
"recordDeletion": rec_del,
"checklist": (
current_app.config["RDM_IMMEDIATE_RECORD_DELETION_CHECKLIST"]
if immediate.allowed
else current_app.config["RDM_REQUEST_RECORD_DELETION_CHECKLIST"]
),
"context": {
"files": record._record.files.count,
"internalDoi": record._record.pids["doi"]["provider"] != "external",
},
}
else:
record_deletion = {
"enabled": rd_enabled,
"valid_user": rd_valid_user,
"allowed": rd_allowed,
}
record_deletion["existing_request"] = (
existing_request["links"]["self_html"] if existing_request else None
)
record_deletion = evaluate_record_deletion(record)

is_draft = record_ui["is_draft"]
custom_fields = load_custom_fields()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{# -*- coding: utf-8 -*-

This file is part of Invenio.
Copyright (C) 2016-2025 CERN.

Invenio is free software; you can redistribute it and/or modify it
under the terms of the MIT License; see LICENSE file for more details.
#}

{% extends "invenio_requests/details/index.html" %}

{% set active_dashboard_menu_item = 'requests' %}
{% set active_community_header_menu_item = 'requests' %}

{%- block request_header %}
{% set back_button_url = url_for("invenio_app_rdm_users.requests") %}
{% from "invenio_requests/macros/request_header.html" import inclusion_request_header %}
{{ inclusion_request_header(
request=invenio_request,
record=record,
accepted=request_is_accepted,
back_button_url=back_button_url,
back_button_text=_("Back to requests")
) }}
{%- endblock request_header %}

{% block request_timeline %}
<div
class="ui container rdm-tab-container fluid rel-pt-2 ml-0-mobile mr-0-mobile"
id="request-request-deletion-tab-container"
>
<div
class="ui secondary pointing menu rdm-tab-menu"
id="request-deletion-request-tab"
>
<a
class="active item"
data-tab="conversation"
role="tab"
aria-selected="true"
aria-controls="conversation-tab-panel"
id="conversation-tab"
>
{{ _("Conversation") }}
</a>

{% if record_ui %}
<a
role="tab"
class="item"
data-tab="record"
aria-selected="false"
aria-controls="record-tab-panel"
id="record-tab"
>
{{ _("Record") }}
</a>
{% endif %}
</div>

<div
class="ui bottom attached tab segment active borderless p-0"
data-tab="conversation"
role="tabpanel"
aria-labelledby="conversation-tab"
id="conversation-tab-panel"
>
{{ super() }}
</div>

{# The record tab content needs to be last since the HTML structure is complex and breaks following tab contents #}
{% if record_ui %}
<div
class="ui bottom attached tab segment borderless"
data-tab="record"
role="tabpanel"
aria-labelledby="record-tab"
id="record-tab-panel"
hidden="hidden"
>
{% set use_theme_basic_template = false %}
{% set preview_submission_request = true %}
{% include config.APP_RDM_RECORD_LANDING_PAGE_TEMPLATE %}
</div>
{% endif %}

</div>
{% endblock request_timeline %}
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,11 @@ RecordDeletion.propTypes = {
disabled: PropTypes.bool,
record: PropTypes.object.isRequired,
permissions: PropTypes.object.isRequired,
recordDeletion: PropTypes.object.isRequired,
recordDeletion: PropTypes.object,
options: PropTypes.array.isRequired,
};

RecordDeletion.defaultProps = {
disabled: false,
recordDeletion: {},
};
Loading
Loading