Changeset View
Changeset View
Standalone View
Standalone View
swh/deposit/api/common.py
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | from ..errors import ( | ||||
FORBIDDEN, | FORBIDDEN, | ||||
MAX_UPLOAD_SIZE_EXCEEDED, | MAX_UPLOAD_SIZE_EXCEEDED, | ||||
MEDIATION_NOT_ALLOWED, | MEDIATION_NOT_ALLOWED, | ||||
METHOD_NOT_ALLOWED, | METHOD_NOT_ALLOWED, | ||||
NOT_FOUND, | NOT_FOUND, | ||||
PARSING_ERROR, | PARSING_ERROR, | ||||
DepositError, | DepositError, | ||||
ParserError, | ParserError, | ||||
make_error_dict, | raise_missing_slug_error, | ||||
make_error_response, | |||||
make_error_response_from_dict, | |||||
make_missing_slug_error, | |||||
) | ) | ||||
from ..models import DepositClient, DepositCollection, DepositRequest | from ..models import DepositClient, DepositCollection, DepositRequest | ||||
from ..parsers import parse_swh_reference, parse_xml | from ..parsers import parse_swh_reference, parse_xml | ||||
ACCEPT_PACKAGINGS = ["http://purl.org/net/sword/package/SimpleZip"] | ACCEPT_PACKAGINGS = ["http://purl.org/net/sword/package/SimpleZip"] | ||||
ACCEPT_ARCHIVE_CONTENT_TYPES = ["application/zip", "application/x-tar"] | ACCEPT_ARCHIVE_CONTENT_TYPES = ["application/zip", "application/x-tar"] | ||||
▲ Show 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | class APIBase(APIConfig, AuthenticatedAPIView, metaclass=ABCMeta): | ||||
def _delete_archives(self, collection_name: str, deposit_id: int) -> Dict: | def _delete_archives(self, collection_name: str, deposit_id: int) -> Dict: | ||||
"""Delete archive references from the deposit id. | """Delete archive references from the deposit id. | ||||
""" | """ | ||||
try: | try: | ||||
deposit = Deposit.objects.get(pk=deposit_id) | deposit = Deposit.objects.get(pk=deposit_id) | ||||
except Deposit.DoesNotExist: | except Deposit.DoesNotExist: | ||||
return make_error_dict( | raise DepositError(NOT_FOUND, f"The deposit {deposit_id} does not exist") | ||||
NOT_FOUND, f"The deposit {deposit_id} does not exist" | |||||
) | |||||
DepositRequest.objects.filter(deposit=deposit, type=ARCHIVE_TYPE).delete() | DepositRequest.objects.filter(deposit=deposit, type=ARCHIVE_TYPE).delete() | ||||
return {} | return {} | ||||
def _delete_deposit(self, collection_name: str, deposit_id: int) -> Dict: | def _delete_deposit(self, collection_name: str, deposit_id: int) -> Dict: | ||||
"""Delete deposit reference. | """Delete deposit reference. | ||||
Args: | Args: | ||||
collection_name: Client's collection | collection_name: Client's collection | ||||
deposit_id: The deposit to delete | deposit_id: The deposit to delete | ||||
Returns | Returns | ||||
Empty dict when ok. | Empty dict when ok. | ||||
Dict with error key to describe the failure. | Dict with error key to describe the failure. | ||||
""" | """ | ||||
try: | try: | ||||
deposit = Deposit.objects.get(pk=deposit_id) | deposit = Deposit.objects.get(pk=deposit_id) | ||||
except Deposit.DoesNotExist: | except Deposit.DoesNotExist: | ||||
return make_error_dict( | raise DepositError(NOT_FOUND, f"The deposit {deposit_id} does not exist") | ||||
NOT_FOUND, f"The deposit {deposit_id} does not exist" | |||||
) | |||||
if deposit.collection.name != collection_name: | if deposit.collection.name != collection_name: | ||||
summary = "Cannot delete a deposit from another collection" | summary = "Cannot delete a deposit from another collection" | ||||
description = "Deposit %s does not belong to the collection %s" % ( | description = "Deposit %s does not belong to the collection %s" % ( | ||||
deposit_id, | deposit_id, | ||||
collection_name, | collection_name, | ||||
) | ) | ||||
return make_error_dict( | raise DepositError( | ||||
BAD_REQUEST, summary=summary, verbose_description=description | BAD_REQUEST, summary=summary, verbose_description=description | ||||
) | ) | ||||
DepositRequest.objects.filter(deposit=deposit).delete() | DepositRequest.objects.filter(deposit=deposit).delete() | ||||
deposit.delete() | deposit.delete() | ||||
return {} | return {} | ||||
Show All 11 Lines | ) -> Optional[Dict]: | ||||
Returns: | Returns: | ||||
Either none if no error or a dictionary with a key error | Either none if no error or a dictionary with a key error | ||||
detailing the problem. | detailing the problem. | ||||
""" | """ | ||||
max_upload_size = self.config["max_upload_size"] | max_upload_size = self.config["max_upload_size"] | ||||
if content_length: | if content_length: | ||||
if content_length > max_upload_size: | if content_length > max_upload_size: | ||||
return make_error_dict( | raise DepositError( | ||||
MAX_UPLOAD_SIZE_EXCEEDED, | MAX_UPLOAD_SIZE_EXCEEDED, | ||||
f"Upload size limit exceeded (max {max_upload_size} bytes)." | f"Upload size limit exceeded (max {max_upload_size} bytes)." | ||||
"Please consider sending the archive in multiple steps.", | "Please consider sending the archive in multiple steps.", | ||||
) | ) | ||||
length = filehandler.size | length = filehandler.size | ||||
if length != content_length: | if length != content_length: | ||||
return make_error_dict( | raise DepositError(status.HTTP_412_PRECONDITION_FAILED, "Wrong length") | ||||
status.HTTP_412_PRECONDITION_FAILED, "Wrong length" | |||||
) | |||||
if md5sum: | if md5sum: | ||||
_md5sum = _compute_md5(filehandler) | _md5sum = _compute_md5(filehandler) | ||||
if _md5sum != md5sum: | if _md5sum != md5sum: | ||||
return make_error_dict( | raise DepositError( | ||||
CHECKSUM_MISMATCH, | CHECKSUM_MISMATCH, | ||||
"Wrong md5 hash", | "Wrong md5 hash", | ||||
f"The checksum sent {hashutil.hash_to_hex(md5sum)} and the actual " | f"The checksum sent {hashutil.hash_to_hex(md5sum)} and the actual " | ||||
f"checksum {hashutil.hash_to_hex(_md5sum)} does not match.", | f"checksum {hashutil.hash_to_hex(_md5sum)} does not match.", | ||||
) | ) | ||||
return None | return None | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | ) -> Dict[str, Any]: | ||||
archive exceeds the max size configured | archive exceeds the max size configured | ||||
- 412 (precondition failed) if the length or md5 hash provided | - 412 (precondition failed) if the length or md5 hash provided | ||||
mismatch the reality of the archive | mismatch the reality of the archive | ||||
- 415 (unsupported media type) if a wrong media type is provided | - 415 (unsupported media type) if a wrong media type is provided | ||||
""" | """ | ||||
content_length = headers.content_length | content_length = headers.content_length | ||||
if not content_length: | if not content_length: | ||||
return make_error_dict( | raise DepositError( | ||||
BAD_REQUEST, | BAD_REQUEST, | ||||
"CONTENT_LENGTH header is mandatory", | "CONTENT_LENGTH header is mandatory", | ||||
"For archive deposit, the CONTENT_LENGTH header must be sent.", | "For archive deposit, the CONTENT_LENGTH header must be sent.", | ||||
) | ) | ||||
content_disposition = headers.content_disposition | content_disposition = headers.content_disposition | ||||
if not content_disposition: | if not content_disposition: | ||||
return make_error_dict( | raise DepositError( | ||||
BAD_REQUEST, | BAD_REQUEST, | ||||
"CONTENT_DISPOSITION header is mandatory", | "CONTENT_DISPOSITION header is mandatory", | ||||
"For archive deposit, the CONTENT_DISPOSITION header must be sent.", | "For archive deposit, the CONTENT_DISPOSITION header must be sent.", | ||||
) | ) | ||||
packaging = headers.packaging | packaging = headers.packaging | ||||
if packaging and packaging not in ACCEPT_PACKAGINGS: | if packaging and packaging not in ACCEPT_PACKAGINGS: | ||||
return make_error_dict( | raise DepositError( | ||||
BAD_REQUEST, | BAD_REQUEST, | ||||
f"Only packaging {ACCEPT_PACKAGINGS} is supported", | f"Only packaging {ACCEPT_PACKAGINGS} is supported", | ||||
f"The packaging provided {packaging} is not supported", | f"The packaging provided {packaging} is not supported", | ||||
) | ) | ||||
filehandler = request.FILES["file"] | filehandler = request.FILES["file"] | ||||
precondition_status_response = self._check_preconditions_on( | precondition_status_response = self._check_preconditions_on( | ||||
filehandler, headers.content_md5sum, content_length | filehandler, headers.content_md5sum, content_length | ||||
) | ) | ||||
if precondition_status_response: | if precondition_status_response: | ||||
return precondition_status_response | return precondition_status_response | ||||
slug = headers.slug | slug = headers.slug | ||||
if check_slug_is_present and not slug: | if check_slug_is_present and not slug: | ||||
return make_missing_slug_error() | raise_missing_slug_error() | ||||
# actual storage of data | # actual storage of data | ||||
archive_metadata = filehandler | archive_metadata = filehandler | ||||
deposit = self._deposit_put( | deposit = self._deposit_put( | ||||
request, | request, | ||||
deposit_id=deposit_id, | deposit_id=deposit_id, | ||||
in_progress=headers.in_progress, | in_progress=headers.in_progress, | ||||
external_id=slug, | external_id=slug, | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | ) -> Dict: | ||||
mismatch the reality of the archive | mismatch the reality of the archive | ||||
- 413 (request entity too large) if the length of the | - 413 (request entity too large) if the length of the | ||||
archive exceeds the max size configured | archive exceeds the max size configured | ||||
- 415 (unsupported media type) if a wrong media type is provided | - 415 (unsupported media type) if a wrong media type is provided | ||||
""" | """ | ||||
slug = headers.slug | slug = headers.slug | ||||
if check_slug_is_present and not slug: | if check_slug_is_present and not slug: | ||||
return make_missing_slug_error() | raise_missing_slug_error() | ||||
content_types_present = set() | content_types_present = set() | ||||
data: Dict[str, Optional[Any]] = { | data: Dict[str, Optional[Any]] = { | ||||
"application/zip": None, # expected either zip | "application/zip": None, # expected either zip | ||||
"application/x-tar": None, # or x-tar | "application/x-tar": None, # or x-tar | ||||
"application/atom+xml": None, | "application/atom+xml": None, | ||||
} | } | ||||
for key, value in request.FILES.items(): | for key, value in request.FILES.items(): | ||||
fh = value | fh = value | ||||
content_type = fh.content_type | content_type = fh.content_type | ||||
if content_type in content_types_present: | if content_type in content_types_present: | ||||
return make_error_dict( | raise DepositError( | ||||
ERROR_CONTENT, | ERROR_CONTENT, | ||||
"Only 1 application/zip (or application/x-tar) archive " | "Only 1 application/zip (or application/x-tar) archive " | ||||
"and 1 atom+xml entry is supported (as per sword2.0 " | "and 1 atom+xml entry is supported (as per sword2.0 " | ||||
"specification)", | "specification)", | ||||
"You provided more than 1 application/(zip|x-tar) " | "You provided more than 1 application/(zip|x-tar) " | ||||
"or more than 1 application/atom+xml content-disposition " | "or more than 1 application/atom+xml content-disposition " | ||||
"header in the multipart deposit", | "header in the multipart deposit", | ||||
) | ) | ||||
content_types_present.add(content_type) | content_types_present.add(content_type) | ||||
assert content_type is not None | assert content_type is not None | ||||
data[content_type] = fh | data[content_type] = fh | ||||
if len(content_types_present) != 2: | if len(content_types_present) != 2: | ||||
return make_error_dict( | raise DepositError( | ||||
ERROR_CONTENT, | ERROR_CONTENT, | ||||
"You must provide both 1 application/zip (or " | "You must provide both 1 application/zip (or " | ||||
"application/x-tar) and 1 atom+xml entry for multipart " | "application/x-tar) and 1 atom+xml entry for multipart " | ||||
"deposit", | "deposit", | ||||
"You need to provide only 1 application/(zip|x-tar) " | "You need to provide only 1 application/(zip|x-tar) " | ||||
"and 1 application/atom+xml content-disposition header " | "and 1 application/atom+xml content-disposition header " | ||||
"in the multipart deposit", | "in the multipart deposit", | ||||
) | ) | ||||
filehandler = data["application/zip"] | filehandler = data["application/zip"] | ||||
if not filehandler: | if not filehandler: | ||||
filehandler = data["application/x-tar"] | filehandler = data["application/x-tar"] | ||||
precondition_status_response = self._check_preconditions_on( | precondition_status_response = self._check_preconditions_on( | ||||
filehandler, headers.content_md5sum | filehandler, headers.content_md5sum | ||||
) | ) | ||||
if precondition_status_response: | if precondition_status_response: | ||||
return precondition_status_response | return precondition_status_response | ||||
try: | try: | ||||
raw_metadata, metadata = self._read_metadata(data["application/atom+xml"]) | raw_metadata, metadata = self._read_metadata(data["application/atom+xml"]) | ||||
except ParserError: | except ParserError: | ||||
return make_error_dict( | raise DepositError( | ||||
PARSING_ERROR, | PARSING_ERROR, | ||||
"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.", | ||||
) | ) | ||||
# actual storage of data | # actual storage of data | ||||
deposit = self._deposit_put( | deposit = self._deposit_put( | ||||
▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | ) -> Dict[str, Any]: | ||||
identifier | identifier | ||||
- 400 (bad request) if the request's body is empty | - 400 (bad request) if the request's body is empty | ||||
- 415 (unsupported media type) if a wrong media type is provided | - 415 (unsupported media type) if a wrong media type is provided | ||||
""" | """ | ||||
try: | try: | ||||
raw_metadata, metadata = self._read_metadata(request.data) | raw_metadata, metadata = self._read_metadata(request.data) | ||||
except ParserError: | except ParserError: | ||||
return make_error_dict( | raise DepositError( | ||||
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: | if not metadata: | ||||
return make_error_dict( | raise DepositError( | ||||
BAD_REQUEST, | BAD_REQUEST, | ||||
"Empty body request is not supported", | "Empty body request is not supported", | ||||
"Atom entry deposit is supposed to send for metadata. " | "Atom entry deposit is supposed to send for metadata. " | ||||
"If the body is empty, there is no metadata.", | "If the body is empty, there is no metadata.", | ||||
) | ) | ||||
# Determine if we are in the metadata-only deposit case | # Determine if we are in the metadata-only deposit case | ||||
try: | try: | ||||
swhid = parse_swh_reference(metadata) | swhid = parse_swh_reference(metadata) | ||||
except ValidationError as e: | except ValidationError as e: | ||||
return make_error_dict(PARSING_ERROR, "Invalid SWHID reference", str(e),) | raise DepositError( | ||||
PARSING_ERROR, "Invalid SWHID reference", str(e), | |||||
) | |||||
if swhid is not None: | if swhid is not None: | ||||
external_id = metadata.get("external_identifier", headers.slug) | external_id = metadata.get("external_identifier", headers.slug) | ||||
else: | else: | ||||
slug = headers.slug | slug = headers.slug | ||||
if check_slug_is_present and not slug: | if check_slug_is_present and not slug: | ||||
return make_missing_slug_error() | raise_missing_slug_error() | ||||
external_id = metadata.get("external_identifier", slug) | external_id = metadata.get("external_identifier", slug) | ||||
deposit = self._deposit_put( | deposit = self._deposit_put( | ||||
request, | request, | ||||
deposit_id=deposit_id, | deposit_id=deposit_id, | ||||
in_progress=headers.in_progress, | in_progress=headers.in_progress, | ||||
external_id=external_id, | external_id=external_id, | ||||
) | ) | ||||
if swhid is not None: | if swhid is not None: | ||||
try: | |||||
swhid, swhid_ref, depo, depo_request = self._store_metadata_deposit( | swhid, swhid_ref, depo, depo_request = self._store_metadata_deposit( | ||||
deposit, swhid, metadata, raw_metadata | deposit, swhid, metadata, raw_metadata | ||||
) | ) | ||||
except DepositError as deposit_error: | |||||
return deposit_error.to_dict() | |||||
deposit.status = DEPOSIT_STATUS_LOAD_SUCCESS | deposit.status = DEPOSIT_STATUS_LOAD_SUCCESS | ||||
if isinstance(swhid_ref, SWHID): | if isinstance(swhid_ref, SWHID): | ||||
deposit.swhid = str(swhid) | deposit.swhid = str(swhid) | ||||
deposit.swhid_context = str(swhid_ref) | deposit.swhid_context = str(swhid_ref) | ||||
deposit.complete_date = depo_request.date | deposit.complete_date = depo_request.date | ||||
deposit.reception_date = depo_request.date | deposit.reception_date = depo_request.date | ||||
deposit.save() | deposit.save() | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | ) -> Dict[str, Any]: | ||||
return {} | return {} | ||||
def checks( | def checks( | ||||
self, request: Request, collection_name: str, deposit_id: Optional[int] = None | self, request: Request, collection_name: str, deposit_id: Optional[int] = None | ||||
) -> Dict[str, Any]: | ) -> Dict[str, Any]: | ||||
try: | try: | ||||
self._collection = DepositCollection.objects.get(name=collection_name) | self._collection = DepositCollection.objects.get(name=collection_name) | ||||
except DepositCollection.DoesNotExist: | except DepositCollection.DoesNotExist: | ||||
return make_error_dict( | raise DepositError(NOT_FOUND, f"Unknown collection name {collection_name}") | ||||
NOT_FOUND, f"Unknown collection name {collection_name}" | |||||
) | |||||
assert self._collection is not None | assert self._collection is not None | ||||
username = request.user.username | username = request.user.username | ||||
if username: # unauthenticated request can have the username empty | if username: # unauthenticated request can have the username empty | ||||
try: | try: | ||||
self._client: DepositClient = DepositClient.objects.get( # type: ignore | self._client: DepositClient = DepositClient.objects.get( # type: ignore | ||||
username=username | username=username | ||||
) | ) | ||||
except DepositClient.DoesNotExist: | except DepositClient.DoesNotExist: | ||||
return make_error_dict(NOT_FOUND, f"Unknown client name {username}") | raise DepositError(NOT_FOUND, f"Unknown client name {username}") | ||||
collection_id = self._collection.id | collection_id = self._collection.id | ||||
collections = self._client.collections | collections = self._client.collections | ||||
assert collections is not None | assert collections is not None | ||||
if collection_id not in collections: | if collection_id not in collections: | ||||
return make_error_dict( | raise DepositError( | ||||
FORBIDDEN, | FORBIDDEN, | ||||
f"Client {username} cannot access collection {collection_name}", | f"Client {username} cannot access collection {collection_name}", | ||||
) | ) | ||||
headers = self._read_headers(request) | headers = self._read_headers(request) | ||||
if deposit_id: | if deposit_id: | ||||
try: | try: | ||||
deposit = Deposit.objects.get(pk=deposit_id) | deposit = Deposit.objects.get(pk=deposit_id) | ||||
except Deposit.DoesNotExist: | except Deposit.DoesNotExist: | ||||
return make_error_dict( | raise DepositError( | ||||
NOT_FOUND, f"Deposit with id {deposit_id} does not exist" | NOT_FOUND, f"Deposit with id {deposit_id} does not exist" | ||||
) | ) | ||||
assert deposit is not None | assert deposit is not None | ||||
checks = self.restrict_access(request, headers, deposit) | self.restrict_access(request, headers, deposit) | ||||
if checks: | |||||
return checks | |||||
if headers.on_behalf_of: | if headers.on_behalf_of: | ||||
return make_error_dict(MEDIATION_NOT_ALLOWED, "Mediation is not supported.") | raise DepositError(MEDIATION_NOT_ALLOWED, "Mediation is not supported.") | ||||
checks = self.additional_checks(request, headers, collection_name, deposit_id) | self.additional_checks(request, headers, collection_name, deposit_id) | ||||
if "error" in checks: | |||||
return checks | |||||
return {"headers": headers} | return {"headers": headers} | ||||
def restrict_access( | def restrict_access( | ||||
self, request: Request, headers: ParsedRequestHeaders, deposit: Deposit | self, request: Request, headers: ParsedRequestHeaders, deposit: Deposit | ||||
) -> Dict[str, Any]: | ) -> None: | ||||
"""Allow modifications on deposit with status 'partial' only, reject the rest. | """Allow modifications on deposit with status 'partial' only, reject the rest. | ||||
""" | """ | ||||
if request.method != "GET" and deposit.status != DEPOSIT_STATUS_PARTIAL: | if request.method != "GET" and deposit.status != DEPOSIT_STATUS_PARTIAL: | ||||
summary = "You can only act on deposit with status '%s'" % ( | summary = "You can only act on deposit with status '%s'" % ( | ||||
DEPOSIT_STATUS_PARTIAL, | DEPOSIT_STATUS_PARTIAL, | ||||
) | ) | ||||
description = f"This deposit has status '{deposit.status}'" | description = f"This deposit has status '{deposit.status}'" | ||||
return make_error_dict( | raise DepositError( | ||||
BAD_REQUEST, summary=summary, verbose_description=description | BAD_REQUEST, summary=summary, verbose_description=description | ||||
) | ) | ||||
return {} | |||||
def _basic_not_allowed_method(self, request: Request, method: str): | def _basic_not_allowed_method(self, request: Request, method: str): | ||||
return make_error_response( | raise DepositError( | ||||
request, | |||||
METHOD_NOT_ALLOWED, | METHOD_NOT_ALLOWED, | ||||
f"{method} method is not supported on this endpoint", | f"{method} method is not supported on this endpoint", | ||||
) | ) | ||||
def get( | def get( | ||||
self, request: Request, collection_name: str, deposit_id: int | self, request: Request, collection_name: str, deposit_id: int | ||||
) -> Union[HttpResponse, FileResponse]: | ) -> Union[HttpResponse, FileResponse]: | ||||
return self._basic_not_allowed_method(request, "GET") | return self._basic_not_allowed_method(request, "GET") | ||||
Show All 25 Lines | ) -> Union[HttpResponse, FileResponse]: | ||||
"""Endpoint to create/add resources to deposit. | """Endpoint to create/add resources to deposit. | ||||
Returns: | Returns: | ||||
200 response when no error during routine occurred | 200 response when no error during routine occurred | ||||
400 if the deposit does not belong to the collection | 400 if the deposit does not belong to the collection | ||||
404 if the deposit or the collection does not exist | 404 if the deposit or the collection does not exist | ||||
""" | """ | ||||
checks = self.checks(request, collection_name, deposit_id) | self.checks(request, collection_name, deposit_id) | ||||
if "error" in checks: | |||||
return make_error_response_from_dict(request, checks["error"]) | |||||
r = self.process_get(request, collection_name, deposit_id) | r = self.process_get(request, collection_name, deposit_id) | ||||
status, content, content_type = r | status, content, content_type = r | ||||
if content_type == "swh/generator": | if content_type == "swh/generator": | ||||
with content as path: | with content as path: | ||||
return FileResponse( | return FileResponse( | ||||
open(path, "rb"), status=status, content_type="application/zip" | open(path, "rb"), status=status, content_type="application/zip" | ||||
Show All 29 Lines | ) -> HttpResponse: | ||||
Returns: | Returns: | ||||
204 response when no error during routine occurred. | 204 response when no error during routine occurred. | ||||
400 if the deposit does not belong to the collection | 400 if the deposit does not belong to the collection | ||||
404 if the deposit or the collection does not exist | 404 if the deposit or the collection does not exist | ||||
""" | """ | ||||
checks = self.checks(request, collection_name, deposit_id) | checks = self.checks(request, collection_name, deposit_id) | ||||
if "error" in checks: | |||||
return make_error_response_from_dict(request, checks["error"]) | |||||
headers = checks["headers"] | headers = checks["headers"] | ||||
status, iri_key, data = self.process_post( | status, iri_key, data = self.process_post( | ||||
request, headers, collection_name, deposit_id | request, headers, collection_name, deposit_id | ||||
) | ) | ||||
error = data.get("error") | |||||
if error: | |||||
return make_error_response_from_dict(request, error) | |||||
return self._make_deposit_receipt( | return self._make_deposit_receipt( | ||||
request, collection_name, status, iri_key, data, | request, collection_name, status, iri_key, data, | ||||
) | ) | ||||
def _make_deposit_receipt( | def _make_deposit_receipt( | ||||
self, | self, | ||||
request, | request, | ||||
collection_name: str, | collection_name: str, | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | ) -> HttpResponse: | ||||
Returns: | Returns: | ||||
204 response when no error during routine occurred. | 204 response when no error during routine occurred. | ||||
400 if the deposit does not belong to the collection | 400 if the deposit does not belong to the collection | ||||
404 if the deposit or the collection does not exist | 404 if the deposit or the collection does not exist | ||||
""" | """ | ||||
checks = self.checks(request, collection_name, deposit_id) | checks = self.checks(request, collection_name, deposit_id) | ||||
if "error" in checks: | |||||
return make_error_response_from_dict(request, checks["error"]) | |||||
headers = checks["headers"] | headers = checks["headers"] | ||||
data = self.process_put(request, headers, collection_name, deposit_id) | self.process_put(request, headers, collection_name, deposit_id) | ||||
error = data.get("error") | |||||
if error: | |||||
return make_error_response_from_dict(request, error) | |||||
return HttpResponse(status=status.HTTP_204_NO_CONTENT) | return HttpResponse(status=status.HTTP_204_NO_CONTENT) | ||||
@abstractmethod | @abstractmethod | ||||
def process_put( | def process_put( | ||||
self, | self, | ||||
request: Request, | request: Request, | ||||
headers: ParsedRequestHeaders, | headers: ParsedRequestHeaders, | ||||
Show All 20 Lines | ) -> HttpResponse: | ||||
"""Endpoint to delete some deposit's resources (archives, deposit). | """Endpoint to delete some deposit's resources (archives, deposit). | ||||
Returns: | Returns: | ||||
204 response when no error during routine occurred. | 204 response when no error during routine occurred. | ||||
400 if the deposit does not belong to the collection | 400 if the deposit does not belong to the collection | ||||
404 if the deposit or the collection does not exist | 404 if the deposit or the collection does not exist | ||||
""" | """ | ||||
checks = self.checks(request, collection_name, deposit_id) | self.checks(request, collection_name, deposit_id) | ||||
if "error" in checks: | |||||
return make_error_response_from_dict(request, checks["error"]) | |||||
assert deposit_id is not None | assert deposit_id is not None | ||||
data = self.process_delete(request, collection_name, deposit_id) | self.process_delete(request, collection_name, deposit_id) | ||||
error = data.get("error") | |||||
if error: | |||||
return make_error_response_from_dict(request, error) | |||||
return HttpResponse(status=status.HTTP_204_NO_CONTENT) | return HttpResponse(status=status.HTTP_204_NO_CONTENT) | ||||
@abstractmethod | @abstractmethod | ||||
def process_delete( | def process_delete( | ||||
self, request: Request, collection_name: str, deposit_id: int | self, request: Request, collection_name: str, deposit_id: int | ||||
) -> Dict: | ) -> Dict: | ||||
"""Routine to delete a resource. | """Routine to delete a resource. | ||||
This is mostly not allowed except for the | This is mostly not allowed except for the | ||||
EM_IRI (cf. .api.deposit_update.APIUpdateArchive) | EM_IRI (cf. .api.deposit_update.APIUpdateArchive) | ||||
""" | """ | ||||
return {} | return {} |