Changeset View
Changeset View
Standalone View
Standalone View
swh/deposit/api/deposit_update.py
# Copyright (C) 2017-2020 The Software Heritage developers | # Copyright (C) 2017-2020 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
from typing import Any, Dict, Optional, Tuple | from typing import Any, Dict, Optional, Tuple | ||||
from rest_framework import status | from rest_framework import status | ||||
from rest_framework.request import Request | from rest_framework.request import Request | ||||
from swh.deposit.api.checks import check_metadata | |||||
from swh.deposit.api.converters import convert_status_detail | |||||
from swh.deposit.models import Deposit | from swh.deposit.models import Deposit | ||||
from swh.model.identifiers import parse_swhid | from swh.model.identifiers import parse_swhid | ||||
from swh.model.model import ( | |||||
MetadataAuthority, | |||||
MetadataAuthorityType, | |||||
MetadataFetcher, | |||||
MetadataTargetType, | |||||
RawExtrinsicMetadata, | |||||
) | |||||
from swh.storage import get_storage | |||||
from swh.storage.interface import StorageInterface | |||||
from ..config import ( | from ..config import CONT_FILE_IRI, DEPOSIT_STATUS_LOAD_SUCCESS, EDIT_SE_IRI, EM_IRI | ||||
CONT_FILE_IRI, | |||||
DEPOSIT_STATUS_LOAD_SUCCESS, | |||||
EDIT_SE_IRI, | |||||
EM_IRI, | |||||
METADATA_KEY, | |||||
RAW_METADATA_KEY, | |||||
) | |||||
from ..errors import BAD_REQUEST, ParserError, make_error_dict | from ..errors import BAD_REQUEST, ParserError, make_error_dict | ||||
from ..parsers import ( | from ..parsers import ( | ||||
SWHAtomEntryParser, | SWHAtomEntryParser, | ||||
SWHFileUploadTarParser, | SWHFileUploadTarParser, | ||||
SWHFileUploadZipParser, | SWHFileUploadZipParser, | ||||
SWHMultiPartParser, | SWHMultiPartParser, | ||||
) | ) | ||||
from .common import ACCEPT_ARCHIVE_CONTENT_TYPES, APIDelete, APIPost, APIPut | from .common import ACCEPT_ARCHIVE_CONTENT_TYPES, APIDelete, APIPost, APIPut | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | """Deposit request class defining api endpoints for sword deposit. | ||||
What's known as 'Edit IRI' (and SE IRI) in the sword specification. | What's known as 'Edit IRI' (and SE IRI) in the sword specification. | ||||
HTTP verbs supported: POST (SE IRI), PUT (Edit IRI), DELETE | HTTP verbs supported: POST (SE IRI), PUT (Edit IRI), DELETE | ||||
""" | """ | ||||
parser_classes = (SWHMultiPartParser, SWHAtomEntryParser) | parser_classes = (SWHMultiPartParser, SWHAtomEntryParser) | ||||
def __init__(self): | |||||
super().__init__() | |||||
self.storage_metadata: StorageInterface = get_storage( | |||||
**self.config["storage_metadata"] | |||||
) | |||||
def restrict_access( | def restrict_access( | ||||
self, request: Request, headers: Dict, deposit: Deposit | self, request: Request, headers: Dict, deposit: Deposit | ||||
) -> Dict[str, Any]: | ) -> Dict[str, Any]: | ||||
"""Relax restriction access to allow metadata update on deposit with status "done" when | """Relax restriction access to allow metadata update on deposit with status "done" when | ||||
a swhid is provided. | a swhid is provided. | ||||
""" | """ | ||||
if ( | if ( | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | ) -> Dict[str, Any]: | ||||
except ParserError: | except ParserError: | ||||
return make_error_dict( | return make_error_dict( | ||||
BAD_REQUEST, | BAD_REQUEST, | ||||
"Malformed xml metadata", | "Malformed xml metadata", | ||||
"The xml received is malformed. " | "The xml received is malformed. " | ||||
"Please ensure your metadata file is correctly formatted.", | "Please ensure your metadata file is correctly formatted.", | ||||
) | ) | ||||
if not metadata: | return self._store_metadata_deposit( | ||||
return make_error_dict( | deposit, | ||||
BAD_REQUEST, | parse_swhid(swhid), | ||||
"Empty body request is not supported", | metadata, | ||||
"Atom entry deposit is supposed to send for metadata. " | raw_metadata, | ||||
"If the body is empty, there is no metadata.", | with_deposit_origin=True, | ||||
) | |||||
metadata_ok, error_details = check_metadata(metadata) | |||||
if not metadata_ok: | |||||
assert error_details, "Details should be set when a failure occurs" | |||||
return make_error_dict( | |||||
BAD_REQUEST, | |||||
"Functional metadata checks failure", | |||||
convert_status_detail(error_details), | |||||
) | ) | ||||
metadata_authority = MetadataAuthority( | |||||
type=MetadataAuthorityType.DEPOSIT_CLIENT, | |||||
url=deposit.client.provider_url, | |||||
metadata={"name": deposit.client.last_name}, | |||||
) | |||||
metadata_fetcher = MetadataFetcher( | |||||
name=self.tool["name"], | |||||
version=self.tool["version"], | |||||
metadata=self.tool["configuration"], | |||||
) | |||||
deposit_swhid = parse_swhid(swhid) | |||||
# replace metadata within the deposit backend | |||||
deposit_request_data = { | |||||
METADATA_KEY: metadata, | |||||
RAW_METADATA_KEY: raw_metadata, | |||||
} | |||||
# actually add the metadata to the completed deposit | |||||
deposit_request = self._deposit_request_put(deposit, deposit_request_data) | |||||
# store that metadata to the metadata storage | |||||
metadata_object = RawExtrinsicMetadata( | |||||
type=MetadataTargetType.DIRECTORY, | |||||
target=deposit_swhid, | |||||
discovery_date=deposit_request.date, | |||||
authority=metadata_authority, | |||||
fetcher=metadata_fetcher, | |||||
format="sword-v2-atom-codemeta", | |||||
metadata=raw_metadata, | |||||
origin=deposit.origin_url, | |||||
) | |||||
# write to metadata storage | |||||
self.storage_metadata.metadata_authority_add([metadata_authority]) | |||||
self.storage_metadata.metadata_fetcher_add([metadata_fetcher]) | |||||
self.storage_metadata.raw_extrinsic_metadata_add([metadata_object]) | |||||
return { | |||||
"deposit_id": deposit_id, | |||||
"deposit_date": deposit_request.date, | |||||
"status": deposit.status, | |||||
"archive": None, | |||||
} | |||||
def process_post( | def process_post( | ||||
self, | self, | ||||
request, | request, | ||||
headers: Dict, | headers: Dict, | ||||
collection_name: str, | collection_name: str, | ||||
deposit_id: Optional[int] = None, | deposit_id: Optional[int] = None, | ||||
) -> Tuple[int, str, Dict]: | ) -> Tuple[int, str, Dict]: | ||||
"""Add new metadata/archive to existing deposit. | """Add new metadata/archive to existing deposit. | ||||
▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines |