def _validate_image(http_request): request_files = http_request.files if "file" not in request_files: raise CustomValidationError("Debe enviar el archivo con la imagen del concurso") image_filename = validate_required_string(request_files["file"].filename, "Debe enviar el nombre del archivo de la imagen del concurso") if not files.allowed_image(image_filename): raise CustomValidationError(f"Archivo de imagen '{image_filename}' debe ser de tipo: f{files.get_supported_images()}") return request_files["file"]
def validate_media(http_request, allowed_media_validator, get_allowed_media, error_message): request_files = http_request.files if "file" not in request_files: raise CustomValidationError(error_message) media_filename = validate_required_string(request_files["file"].filename, error_message) if not allowed_media_validator(media_filename): raise CustomValidationError(f"Archivo '{media_filename}' debe ser de tipo: {get_allowed_media()}") return request_files["file"]
def validate_pay(self, key, value): error_message = f"El pago es requerido y debe ser un entero no negativo: '{value}'" try: pay = int(value) except ValueError: raise CustomValidationError(error_message) if pay < 0: raise CustomValidationError(error_message) return value
def _get_required_date(value, date_label): if isinstance(value, date): return value sanitized_value = value.strip() if len(sanitized_value) == 0: raise CustomValidationError(f"Debe proporcionar la {date_label}") try: parsed_date = datetime.strptime(sanitized_value, "%Y-%m-%d").date() except ValueError: raise CustomValidationError(f"El formato de {date_label} debe ser: 'YYYY-MM-DD'") return parsed_date
def create_contest_voice(email, contest_id): # Create the voice entity, which will validate the supplied attributes try: model_voice = Voice.from_api(request, contest_id, email) except OSError as ose: error_msg = str(ose) raise CustomValidationError(error_msg) voice_json = dict(model_voice.to_json_obj()) path = voice_json['source_path'] del voice_json['source_path'] voice_json['rel_source_path'] = path path = voice_json['target_path'] del voice_json['target_path'] voice_json['rel_target_path'] = path # TODO call "model_voice.remove_audio()" if dynamo operation fails voice_json.update({ 'pk': 'CONTEST#' + contest_id, 'sk': 'VOICE#' + model_voice.id, 'type': 'voice' }) table.put_item(Item=voice_json) # send message to the queue: queue.send_message(MessageBody=json.dumps(voice_json)) return model_voice.to_json_obj()
def delete_contest(email, contest_id): model_contest = Contest.find_by_id_and_email(contest_id, email) if model_contest is None: raise CustomValidationError("Concurso no existe", 404) model_contest = Contest( id=model_contest.get("id", ""), name=model_contest.get("name", ""), rel_image_path=model_contest.get("rel_image_path", ""), url=model_contest.get("url", ""), start_date=model_contest.get("start_date", ""), end_date=model_contest.get("end_date", ""), pay=model_contest.get("pay", ""), script=model_contest.get("script", ""), recommendations=model_contest.get("recommendations", ""), user_ref=model_contest.get("user_ref", "")) # delete contest (from user) table.delete_item(Key={ 'pk': 'USER#' + email, 'sk': 'CONTEST#' + contest_id }) # delete voices in contest (first query voices, then delete them) contest_voices = table.query( KeyConditionExpression=Key('pk').eq('CONTEST#' + contest_id))['Items'] for contest_voice in contest_voices: table.delete_item(Key={ 'pk': contest_voice['pk'], 'sk': contest_voice['sk'] }) model_contest.delete_media() # Only delete if commit succeeded return model_contest.to_json_obj()
def validate_names(self, name_type, value): sanitized_name = value.strip() if len(sanitized_name) == 0: field_name = "nombre" if name_type == "last_name": field_name = "apellido" raise CustomValidationError(f"Debe proporcionar su {field_name}") return sanitized_name
def validate_status(self, key, value): sanitized_status = value.strip() try: VoiceStatus(sanitized_status) except ValueError: accepted_statuses = VoiceStatus.get_possible_statuses() raise CustomValidationError(f"Debe proporcionar un estado válido: {accepted_statuses}") return sanitized_status
def login(email): secret = _get_secret( request.json) # Check secret was specified before going to the DB # Fetch user: model_user = table.get_item( Key={ 'pk': 'USER#' + email, 'sk': 'PROFILE' }, AttributesToGet=['email', 'secret', 'first_name', 'last_name']).get('Item') if model_user is None: raise CustomValidationError("Usuario no existe", 404) # Validate provided secret model_user = User.from_dict(model_user) authorized = model_user.check_secret(secret) if not authorized: raise CustomValidationError("Credenciales inválidas", 401) # Generate & return authorization token access_token = create_access_token(identity=str(model_user.email)) return {"access_token": access_token}
def get_contest(friendly_url): model_contests = Contest.find_by_url('/' + friendly_url) if len(model_contests) == 0: raise CustomValidationError("Concurso no existe", 404) model_contest = model_contests[0] model_contest = Contest( id=model_contest.get("id", ""), name=model_contest.get("name", ""), rel_image_path=model_contest.get("rel_image_path", ""), url=model_contest.get("url", ""), start_date=model_contest.get("start_date", ""), end_date=model_contest.get("end_date", ""), pay=model_contest.get("pay", ""), script=model_contest.get("script", ""), recommendations=model_contest.get("recommendations", ""), user_ref=model_contest.get("user_ref", "")) return model_contest.to_json_obj()
def create_contest(email): # Create the contest entity, which will first validate the supplied attributes try: model_contest = Contest.from_api(request, email) except OSError as ose: error_msg = str(ose) raise CustomValidationError(error_msg) # If we made it here, contest img is in DB. Try to store the entity # and delete the image from the filesystem if there was a DB error contest_to_return = model_contest.to_json_obj() contest_json = dict(contest_to_return) path = contest_json["image_path"] del contest_json["image_path"] contest_json["rel_image_path"] = path contest_json.update({ 'pk': 'USER#' + email, 'sk': 'CONTEST#' + model_contest.id, 'type': 'contest' }) table.put_item(Item=contest_json) return contest_to_return
def validate_secret(self, key, value): santized_secret = value.strip() if len(santized_secret) == 0: raise CustomValidationError("Debe proporcionar su contraseña") return santized_secret
def validate_email(self, key, value): sanitized_address = value.strip() if len(sanitized_address) == 0: raise CustomValidationError("Debe proporcionar su login") return sanitized_address
def _get_json_mapper(json_mapper): if json_mapper is None or not callable(json_mapper): raise CustomValidationError("El mapeador a json debe ser una función que se pueda ejecutar", 500) return json_mapper
def _get_pagination(pagination): if pagination is None: raise CustomValidationError("No se puede construir resultado paginado sin el objeto de paginación", 500) return pagination
def update_contest(email, contest_id): # Check if the contest we want to update exists and is owned by the calling admin model_contest = Contest.find_by_id_and_email(contest_id, email) if model_contest is None: raise CustomValidationError("Concurso no existe", 404) model_contest = Contest( id=model_contest.get("id", ""), name=model_contest.get("name", ""), rel_image_path=model_contest.get("rel_image_path", ""), url=model_contest.get("url", ""), start_date=model_contest.get("start_date", ""), end_date=model_contest.get("end_date", ""), pay=model_contest.get("pay", ""), script=model_contest.get("script", ""), recommendations=model_contest.get("recommendations", ""), user_ref=model_contest.get("user_ref", "")) # Let the entity validate & update its attributes from the request data old_image_path = model_contest.update_from_api(request) # Try to update the entity # and delete the previous image if successful # TODO if dynamo update fails, remove the new image from s3 table.update_item(Key={ 'pk': 'USER#' + email, 'sk': 'CONTEST#' + model_contest.id }, AttributeUpdates={ 'name': { 'Value': model_contest.name, 'Action': 'PUT' }, 'rel_image_path': { 'Value': model_contest.rel_image_path, 'Action': 'PUT' }, 'url': { 'Value': model_contest.url, 'Action': 'PUT' }, 'start_date': { 'Value': model_contest.start_date.strftime("%Y-%m-%d"), 'Action': 'PUT' }, 'end_date': { 'Value': model_contest.end_date.strftime("%Y-%m-%d"), 'Action': 'PUT' }, 'pay': { 'Value': model_contest.pay, 'Action': 'PUT' }, 'script': { 'Value': model_contest.script, 'Action': 'PUT' }, 'recommendations': { 'Value': model_contest.recommendations, 'Action': 'PUT' }, 'user_ref': { 'Value': model_contest.user_ref, 'Action': 'PUT' } }) if old_image_path is not None: # this means a new image was uploaded & stored model_contest.remove_image(old_image_path) return model_contest.to_json_obj()
def _validate_date_range(start_date, end_date): if start_date > end_date: raise CustomValidationError("Fecha de inicio no puede ser mayor o igual que la fecha final")
def validate_required_string(value, error_message): sanitized_value = value.strip() if len(sanitized_value) == 0: raise CustomValidationError(error_message) return sanitized_value
def _get_credential(request_payload, credential_type, error_message): credential = request_payload.get(credential_type, "").strip() if len(credential) == 0: raise CustomValidationError(error_message) return credential
def validate_url(self, key, value): sanitized_url = validate_required_string(value, "Debe enviar la url del concurso") if sanitized_url == "/": raise CustomValidationError("La url del evento no puede ser la raíz '/'") return sanitized_url