diff --git a/invenio_rdm_records/resources/config.py b/invenio_rdm_records/resources/config.py index c34623f4e..e7a8d431d 100644 --- a/invenio_rdm_records/resources/config.py +++ b/invenio_rdm_records/resources/config.py @@ -237,6 +237,7 @@ class RDMRecordResourceConfig(RecordResourceConfig, ConfiguratorMixin): routes["restore-record"] = "//restore" routes["set-record-quota"] = "//quota" routes["set-user-quota"] = "/users//quota" + routes["item-revision-list"] = "//revisions" request_view_args = { "pid_value": ma.fields.Str(), diff --git a/invenio_rdm_records/resources/resources.py b/invenio_rdm_records/resources/resources.py index 2afe6fe07..196acfeac 100644 --- a/invenio_rdm_records/resources/resources.py +++ b/invenio_rdm_records/resources/resources.py @@ -94,10 +94,22 @@ def p(route): route("POST", p(routes["set-record-quota"]), self.set_record_quota), # TODO: move to users? route("POST", routes["set-user-quota"], self.set_user_quota), + route("GET", p(routes["item-revision-list"]), self.search_revisions), ] return url_rules + @request_headers + @request_extra_args + @request_view_args + def search_revisions(self): + """Discard a previously reserved PID.""" + item = self.service.search_revisions( + identity=g.identity, id_=resource_requestctx.view_args["pid_value"] + ) + + return item.to_dict(), 200 + @request_extra_args @request_read_args @request_view_args diff --git a/invenio_rdm_records/services/config.py b/invenio_rdm_records/services/config.py index 95865b6ac..40e5ca41d 100644 --- a/invenio_rdm_records/services/config.py +++ b/invenio_rdm_records/services/config.py @@ -83,7 +83,7 @@ ) from .permissions import RDMRecordPermissionPolicy from .result_items import GrantItem, GrantList, SecretLinkItem, SecretLinkList -from .results import RDMRecordList +from .results import RDMRecordList, RDMRecordRevisionsList from .schemas import RDMParentSchema, RDMRecordSchema from .schemas.community_records import CommunityRecordsSchema from .schemas.parent.access import AccessSettingsSchema @@ -422,6 +422,7 @@ class RDMRecordServiceConfig(RecordServiceConfig, ConfiguratorMixin): grant_result_item_cls = GrantItem grant_result_list_cls = GrantList result_list_cls = RDMRecordList + revision_result_list_cls = RDMRecordRevisionsList default_files_enabled = FromConfig("RDM_DEFAULT_FILES_ENABLED", default=True) diff --git a/invenio_rdm_records/services/permissions.py b/invenio_rdm_records/services/permissions.py index 6c89de5e2..edc7efa49 100644 --- a/invenio_rdm_records/services/permissions.py +++ b/invenio_rdm_records/services/permissions.py @@ -136,6 +136,8 @@ class RDMRecordPermissionPolicy(RecordPermissionPolicy): # Allow submitting new record can_create = can_authenticated + can_search_revisions = [Administration()] + # # Drafts # diff --git a/invenio_rdm_records/services/results.py b/invenio_rdm_records/services/results.py index 12b10287d..ae1964202 100644 --- a/invenio_rdm_records/services/results.py +++ b/invenio_rdm_records/services/results.py @@ -12,6 +12,10 @@ from invenio_communities.communities.entity_resolvers import pick_fields from invenio_communities.communities.schema import CommunityGhostSchema from invenio_communities.proxies import current_communities +from invenio_records_resources.services.base.results import ( + ServiceItemResult, + ServiceListResult, +) from invenio_records_resources.services.records.results import ( ExpandableField, RecordList, @@ -105,3 +109,32 @@ def hits(self): ) yield projection + + +class RDMRecordRevisionsList(ServiceListResult): + """Record revisions list. + + We need a custom result class to handle the record revisions list as they are stored only in DB. + """ + + def __init__(self, identity, revisions): + """Instantiate a Collection tree list item.""" + self._identity = identity + self._revisions = revisions + + def to_dict(self): + """Serialize the collection tree list to a dictionary.""" + res = map( + lambda revision: { + "updated": revision.updated, + "created": revision.created, + "revision_id": revision.transaction_id, + "json": revision.json, + }, + self._revisions, + ) + return list(res) + + def __iter__(self): + """Iterate over the collection revisions.""" + return iter(self._revisions) diff --git a/invenio_rdm_records/services/services.py b/invenio_rdm_records/services/services.py index e99d0761a..8b0aa476f 100644 --- a/invenio_rdm_records/services/services.py +++ b/invenio_rdm_records/services/services.py @@ -731,3 +731,15 @@ def set_user_quota( db.session.add(user_quota) return True + + def search_revisions(self, identity, id_): + """Return a list of record revisions.""" + record = self.record_cls.pid.resolve(id_) + # Check permissions + self.require_permission(identity, "search_revisions", record=record) + revisions = list(reversed(record.model.versions.all())) + + return self.config.revision_result_list_cls( + identity, + revisions, + )