diff --git a/middleware/app_be/views/rest_api.py b/middleware/app_be/views/rest_api.py index d07023d..e66b37f 100644 --- a/middleware/app_be/views/rest_api.py +++ b/middleware/app_be/views/rest_api.py @@ -51,27 +51,54 @@ class ImageEndpoint: # get stored SHA512 hash stored_hash = metadata.get('sha512', '') logger.debug('Sorted SHA512: {}'.format(stored_hash)) - service_image_bytes = None + # recovery code + recovery_has_image = {} + recovery_hash_matches = {} + valid_image_bytes = None + # check image existence and correctness for each service + retrieve valid image if possible for service in ImageEndpoint.storageServiceList: - logger.debug('Checking hash for ' + service.name) - # get image bytes from Dropbox + logger.debug('Checking recovery for service ' + service.name) + print('Checking recovery for service ' + service.name) service_image_bytes = service.read_file(metadata['filename']) - if service_image_bytes is None: - return JsonResponse({'Result': 'Error - could not find image in ' + service.name, 'id': identifier}, - status=404, safe=False) + if service_image_bytes is not None: + recovery_has_image[service.name] = True + actual_service_hash = create_sha512(service_image_bytes) + if stored_hash == actual_service_hash: + recovery_hash_matches[service.name] = True + if valid_image_bytes is None: + valid_image_bytes = service_image_bytes + else: + recovery_hash_matches[service.name] = False + else: + recovery_has_image[service.name] = False + recovery_hash_matches[service.name] = False - # calc dropbox image hash - actual_service_hash = create_sha512(service_image_bytes) - logger.debug('Actual '+service.name+' SHA512: {}'.format(actual_service_hash)) - if stored_hash != actual_service_hash: - return JsonResponse('Stored hash in service "'+service.name+'"does not match generated one! ' - 'stored: {} actual: {}'.format(stored_hash, actual_service_hash), - status=400, safe=False) + # TODO: after talking with tobias about updating => replace with older version if hash is wrong + + # check if any service has the image saved + if not ImageEndpoint.combine_boolean_dict_or(recovery_has_image): + logger.debug('None of the storage services has the requested image saved') + MongoDBService.deleteSingle(identifier) + return JsonResponse({'Result': 'Error - image is not available on any storage service and was deleted', + 'id': identifier}, status=404, safe=False) + + # check if any service has a valid version of the image saved + if not ImageEndpoint.combine_boolean_dict_or(recovery_hash_matches) and valid_image_bytes is None: + logger.debug('None of the storage services has a valid image saved') + MongoDBService.deleteSingle(identifier) + return JsonResponse({'Result': 'Error - image is not available on any storage service and was deleted', + 'id': identifier}, status=404, safe=False) + + # at this point we know at least one valid image is available + for service in ImageEndpoint.storageServiceList: + if not recovery_has_image[service.name] or not recovery_hash_matches[service.name]: + if not service.create_file(metadata['filename'], valid_image_bytes): + logger.error('Error duplicating file in service ' + service.name) payload = { 'id': identifier, 'metadata': metadata, - 'image_data': WrapperService.wrap_file(service_image_bytes) + 'image_data': WrapperService.wrap_file(valid_image_bytes) } return JsonResponse(payload, safe=False) @@ -175,6 +202,20 @@ class ImageEndpoint: return JsonResponse({'id': identifier, 'filename': filename}, safe=False) + @staticmethod + def combine_boolean_dict_and(d: dict) -> bool: + result = True + for entry in d: + result = (result and d[entry]) + return result + + @staticmethod + def combine_boolean_dict_or(d: dict) -> bool: + result = False + for entry in d: + result = (result or d[entry]) + return result + class HealthEndpoint: