mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-02 17:31:14 -05:00
Merge pull request #424 from alphagov/more-error-logging
Make errors return via error handlers in errors.py
This commit is contained in:
@@ -10,7 +10,11 @@ from notifications_utils.url_safe_token import check_token
|
||||
|
||||
from app.dao.invited_user_dao import get_invited_user_by_id
|
||||
|
||||
from app.errors import register_errors
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
from app.schemas import invited_user_schema
|
||||
|
||||
|
||||
@@ -30,7 +34,8 @@ def get_invited_user_by_token(token):
|
||||
max_age_seconds)
|
||||
except SignatureExpired:
|
||||
message = 'Invitation with id {} expired'.format(invited_user_id)
|
||||
return jsonify(result='error', message=message), 400
|
||||
errors = {'invitation': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
invited_user = get_invited_user_by_id(invited_user_id)
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@ from flask import (
|
||||
)
|
||||
from sqlalchemy.exc import SQLAlchemyError, DataError
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
from marshmallow import ValidationError
|
||||
|
||||
|
||||
class InvalidData(Exception):
|
||||
class InvalidRequest(Exception):
|
||||
|
||||
def __init__(self, message, status_code):
|
||||
super().__init__()
|
||||
@@ -22,7 +23,12 @@ class InvalidData(Exception):
|
||||
|
||||
def register_errors(blueprint):
|
||||
|
||||
@blueprint.app_errorhandler(InvalidData)
|
||||
@blueprint.app_errorhandler(ValidationError)
|
||||
def validation_error(error):
|
||||
current_app.logger.error(error)
|
||||
return jsonify(result='error', message=error.messages), 400
|
||||
|
||||
@blueprint.app_errorhandler(InvalidRequest)
|
||||
def invalid_data(error):
|
||||
response = jsonify(error.to_dict())
|
||||
response.status_code = error.status_code
|
||||
|
||||
@@ -5,6 +5,7 @@ from flask import (
|
||||
)
|
||||
|
||||
from app.errors import register_errors
|
||||
|
||||
from app.schemas import event_schema
|
||||
from app.dao.events_dao import dao_create_event
|
||||
|
||||
@@ -15,8 +16,6 @@ register_errors(events)
|
||||
@events.route('', methods=['POST'])
|
||||
def create_event():
|
||||
data = request.get_json()
|
||||
event, errors = event_schema.load(data)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
event = event_schema.load(data).data
|
||||
dao_create_event(event)
|
||||
return jsonify(data=event_schema.dump(event).data), 201
|
||||
|
||||
@@ -19,14 +19,13 @@ from app.celery.tasks import (email_invited_user)
|
||||
invite = Blueprint('invite', __name__, url_prefix='/service/<service_id>/invite')
|
||||
|
||||
from app.errors import register_errors
|
||||
|
||||
register_errors(invite)
|
||||
|
||||
|
||||
@invite.route('', methods=['POST'])
|
||||
def create_invited_user(service_id):
|
||||
invited_user, errors = invited_user_schema.load(request.get_json())
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
save_invited_user(invited_user)
|
||||
invitation = _create_invitation(invited_user)
|
||||
encrypted_invitation = encryption.encrypt(invitation)
|
||||
@@ -53,9 +52,7 @@ def update_invited_user(service_id, invited_user_id):
|
||||
|
||||
current_data = dict(invited_user_schema.dump(fetched).data.items())
|
||||
current_data.update(request.get_json())
|
||||
update_dict, errors = invited_user_schema.load(current_data)
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
update_dict = invited_user_schema.load(current_data).data
|
||||
save_invited_user(update_dict)
|
||||
return jsonify(data=invited_user_schema.dump(fetched).data), 200
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from flask import (
|
||||
Blueprint,
|
||||
jsonify,
|
||||
request,
|
||||
current_app)
|
||||
request
|
||||
)
|
||||
|
||||
from app.dao.jobs_dao import (
|
||||
dao_create_job,
|
||||
@@ -22,7 +22,10 @@ from app.celery.tasks import process_job
|
||||
|
||||
job = Blueprint('job', __name__, url_prefix='/service/<uuid:service_id>/job')
|
||||
|
||||
from app.errors import register_errors
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
register_errors(job)
|
||||
|
||||
@@ -30,7 +33,7 @@ register_errors(job)
|
||||
@job.route('/<job_id>', methods=['GET'])
|
||||
def get_job_by_service_and_job_id(service_id, job_id):
|
||||
job = dao_get_job_by_service_id_and_job_id(service_id, job_id)
|
||||
data, errors = job_schema.dump(job)
|
||||
data = job_schema.dump(job).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@@ -40,16 +43,13 @@ def get_jobs_by_service(service_id):
|
||||
try:
|
||||
limit_days = int(request.args['limit_days'])
|
||||
except ValueError as e:
|
||||
error = '{} is not an integer'.format(request.args['limit_days'])
|
||||
current_app.logger.error(error)
|
||||
return jsonify(result="error", message={'limit_days': [error]}), 400
|
||||
errors = {'limit_days': ['{} is not an integer'.format(request.args['limit_days'])]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
else:
|
||||
limit_days = None
|
||||
|
||||
jobs = dao_get_jobs_by_service_id(service_id, limit_days)
|
||||
data, errors = job_schema.dump(jobs, many=True)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
data = job_schema.dump(jobs, many=True).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@@ -66,13 +66,10 @@ def create_job(service_id):
|
||||
errors = unarchived_template_schema.validate({'archived': template.archived})
|
||||
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
data.update({"template_version": template.version})
|
||||
job, errors = job_schema.load(data)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
job = job_schema.load(data).data
|
||||
dao_create_job(job)
|
||||
process_job.apply_async([str(job.id)], queue="process-job")
|
||||
return jsonify(data=job_schema.dump(job).data), 201
|
||||
|
||||
@@ -35,7 +35,10 @@ from app.celery.tasks import send_sms, send_email
|
||||
|
||||
notifications = Blueprint('notifications', __name__)
|
||||
|
||||
from app.errors import register_errors
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
register_errors(notifications)
|
||||
|
||||
@@ -47,16 +50,12 @@ def process_ses_response():
|
||||
ses_request = json.loads(request.data)
|
||||
errors = validate_callback_data(data=ses_request, fields=['Message'], client_name=client_name)
|
||||
if errors:
|
||||
return jsonify(
|
||||
result="error", message=errors
|
||||
), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
ses_message = json.loads(ses_request['Message'])
|
||||
errors = validate_callback_data(data=ses_message, fields=['notificationType'], client_name=client_name)
|
||||
if errors:
|
||||
return jsonify(
|
||||
result="error", message=errors
|
||||
), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
notification_type = ses_message['notificationType']
|
||||
if notification_type == 'Bounce':
|
||||
@@ -67,12 +66,8 @@ def process_ses_response():
|
||||
try:
|
||||
aws_response_dict = get_aws_responses(notification_type)
|
||||
except KeyError:
|
||||
message = "{} callback failed: status {} not found".format(client_name, notification_type)
|
||||
current_app.logger.info(message)
|
||||
return jsonify(
|
||||
result="error",
|
||||
message=message
|
||||
), 400
|
||||
error = "{} callback failed: status {} not found".format(client_name, notification_type)
|
||||
raise InvalidRequest(error, status_code=400)
|
||||
|
||||
notification_status = aws_response_dict['notification_status']
|
||||
notification_statistics_status = aws_response_dict['notification_statistics_status']
|
||||
@@ -93,15 +88,9 @@ def process_ses_response():
|
||||
notification_status,
|
||||
notification_statistics_status
|
||||
):
|
||||
message = "SES callback failed: notification either not found or already updated " \
|
||||
"from sending. Status {}".format(notification_status)
|
||||
current_app.logger.info(
|
||||
message
|
||||
)
|
||||
return jsonify(
|
||||
result="error",
|
||||
message=message
|
||||
), 404
|
||||
error = "SES callback failed: notification either not found or already updated " \
|
||||
"from sending. Status {}".format(notification_status)
|
||||
raise InvalidRequest(error, status_code=404)
|
||||
|
||||
if not aws_response_dict['success']:
|
||||
current_app.logger.info(
|
||||
@@ -117,20 +106,12 @@ def process_ses_response():
|
||||
), 200
|
||||
|
||||
except KeyError:
|
||||
current_app.logger.error(
|
||||
"SES callback failed: messageId missing"
|
||||
)
|
||||
return jsonify(
|
||||
result="error", message="SES callback failed: messageId missing"
|
||||
), 400
|
||||
message = "SES callback failed: messageId missing"
|
||||
raise InvalidRequest(message, status_code=400)
|
||||
|
||||
except ValueError as ex:
|
||||
current_app.logger.exception(
|
||||
"{} callback failed: invalid json {}".format(client_name, ex)
|
||||
)
|
||||
return jsonify(
|
||||
result="error", message="{} callback failed: invalid json".format(client_name)
|
||||
), 400
|
||||
error = "{} callback failed: invalid json".format(client_name)
|
||||
raise InvalidRequest(error, status_code=400)
|
||||
|
||||
|
||||
def is_not_a_notification(source):
|
||||
@@ -149,19 +130,17 @@ def is_not_a_notification(source):
|
||||
def process_mmg_response():
|
||||
client_name = 'MMG'
|
||||
data = json.loads(request.data)
|
||||
validation_errors = validate_callback_data(data=data,
|
||||
fields=['status', 'CID'],
|
||||
client_name=client_name)
|
||||
if validation_errors:
|
||||
[current_app.logger.info(e) for e in validation_errors]
|
||||
return jsonify(result='error', message=validation_errors), 400
|
||||
errors = validate_callback_data(data=data,
|
||||
fields=['status', 'CID'],
|
||||
client_name=client_name)
|
||||
if errors:
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
success, errors = process_sms_client_response(status=str(data.get('status')),
|
||||
reference=data.get('CID'),
|
||||
client_name=client_name)
|
||||
if errors:
|
||||
[current_app.logger.info(e) for e in errors]
|
||||
return jsonify(result='error', message=errors), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
else:
|
||||
return jsonify(result='success', message=success), 200
|
||||
|
||||
@@ -169,12 +148,11 @@ def process_mmg_response():
|
||||
@notifications.route('/notifications/sms/firetext', methods=['POST'])
|
||||
def process_firetext_response():
|
||||
client_name = 'Firetext'
|
||||
validation_errors = validate_callback_data(data=request.form,
|
||||
fields=['status', 'reference'],
|
||||
client_name=client_name)
|
||||
if validation_errors:
|
||||
current_app.logger.info(validation_errors)
|
||||
return jsonify(result='error', message=validation_errors), 400
|
||||
errors = validate_callback_data(data=request.form,
|
||||
fields=['status', 'reference'],
|
||||
client_name=client_name)
|
||||
if errors:
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
response_code = request.form.get('code')
|
||||
status = request.form.get('status')
|
||||
@@ -185,8 +163,7 @@ def process_firetext_response():
|
||||
reference=request.form.get('reference'),
|
||||
client_name=client_name)
|
||||
if errors:
|
||||
[current_app.logger.info(e) for e in errors]
|
||||
return jsonify(result='error', message=errors), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
else:
|
||||
return jsonify(result='success', message=success), 200
|
||||
|
||||
@@ -199,10 +176,7 @@ def get_notifications(notification_id):
|
||||
|
||||
@notifications.route('/notifications', methods=['GET'])
|
||||
def get_all_notifications():
|
||||
data, errors = notifications_filter_schema.load(request.args)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
data = notifications_filter_schema.load(request.args).data
|
||||
page = data['page'] if 'page' in data else 1
|
||||
page_size = data['page_size'] if 'page_size' in data else current_app.config.get('PAGE_SIZE')
|
||||
limit_days = data.get('limit_days')
|
||||
@@ -228,10 +202,7 @@ def get_all_notifications():
|
||||
@notifications.route('/service/<service_id>/notifications', methods=['GET'])
|
||||
@require_admin()
|
||||
def get_all_notifications_for_service(service_id):
|
||||
data, errors = notifications_filter_schema.load(request.args)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
data = notifications_filter_schema.load(request.args).data
|
||||
page = data['page'] if 'page' in data else 1
|
||||
page_size = data['page_size'] if 'page_size' in data else current_app.config.get('PAGE_SIZE')
|
||||
limit_days = data.get('limit_days')
|
||||
@@ -259,10 +230,7 @@ def get_all_notifications_for_service(service_id):
|
||||
@notifications.route('/service/<service_id>/job/<job_id>/notifications', methods=['GET'])
|
||||
@require_admin()
|
||||
def get_all_notifications_for_service_job(service_id, job_id):
|
||||
data, errors = notifications_filter_schema.load(request.args)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
data = notifications_filter_schema.load(request.args).data
|
||||
page = data['page'] if 'page' in data else 1
|
||||
page_size = data['page_size'] if 'page_size' in data else current_app.config.get('PAGE_SIZE')
|
||||
|
||||
@@ -317,15 +285,15 @@ def send_notification(notification_type):
|
||||
total_email_count = service_stats.emails_requested
|
||||
|
||||
if (total_email_count + total_sms_count >= service.message_limit) and service.restricted:
|
||||
return jsonify(result="error", message='Exceeded send limits ({}) for today'.format(
|
||||
service.message_limit)), 429
|
||||
error = 'Exceeded send limits ({}) for today'.format(service.message_limit)
|
||||
raise InvalidRequest(error, status_code=429)
|
||||
|
||||
notification, errors = (
|
||||
sms_template_notification_schema if notification_type == 'sms' else email_notification_schema
|
||||
).load(request.get_json())
|
||||
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
template = templates_dao.dao_get_template_by_id_and_service_id(
|
||||
template_id=notification['template'],
|
||||
@@ -334,33 +302,24 @@ def send_notification(notification_type):
|
||||
|
||||
errors = unarchived_template_schema.validate({'archived': template.archived})
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
template_object = Template(template.__dict__, notification.get('personalisation', {}))
|
||||
if template_object.missing_data:
|
||||
return jsonify(
|
||||
result="error",
|
||||
message={
|
||||
'template': ['Missing personalisation: {}'.format(
|
||||
", ".join(template_object.missing_data)
|
||||
)]
|
||||
}
|
||||
), 400
|
||||
message = 'Missing personalisation: {}'.format(", ".join(template_object.missing_data))
|
||||
errors = {'template': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
if template_object.additional_data:
|
||||
return jsonify(
|
||||
result="error",
|
||||
message={
|
||||
'template': ['Personalisation not needed for template: {}'.format(
|
||||
", ".join(template_object.additional_data)
|
||||
)]
|
||||
}
|
||||
), 400
|
||||
message = 'Personalisation not needed for template: {}'.format(", ".join(template_object.additional_data))
|
||||
errors = {'template': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
if template_object.replaced_content_count > current_app.config.get('SMS_CHAR_COUNT_LIMIT'):
|
||||
return jsonify(
|
||||
result="error",
|
||||
message={'content': ['Content has a character count greater than the limit of {}'.format(
|
||||
current_app.config.get('SMS_CHAR_COUNT_LIMIT'))]}), 400
|
||||
char_count = current_app.config.get('SMS_CHAR_COUNT_LIMIT')
|
||||
message = 'Content has a character count greater than the limit of {}'.format(char_count)
|
||||
errors = {'content': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
if service.restricted and not allowed_to_send_to(
|
||||
notification['to'],
|
||||
@@ -368,11 +327,9 @@ def send_notification(notification_type):
|
||||
[user.mobile_number, user.email_address] for user in service.users
|
||||
)
|
||||
):
|
||||
return jsonify(
|
||||
result="error", message={
|
||||
'to': ['Invalid {} for restricted service'.format(first_column_heading[notification_type])]
|
||||
}
|
||||
), 400
|
||||
message = 'Invalid {} for restricted service'.format(first_column_heading[notification_type])
|
||||
errors = {'to': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
notification_id = create_uuid()
|
||||
notification.update({"template_version": template.version})
|
||||
@@ -397,13 +354,9 @@ def send_notification(notification_type):
|
||||
|
||||
@notifications.route('/notifications/statistics')
|
||||
def get_notification_statistics_for_day():
|
||||
data, errors = day_schema.load(request.args)
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
|
||||
data = day_schema.load(request.args).data
|
||||
statistics = notifications_dao.dao_get_potential_notification_statistics_for_day(
|
||||
day=data['day']
|
||||
)
|
||||
|
||||
data, errors = notifications_statistics_schema.dump(statistics, many=True)
|
||||
return jsonify(data=data), 200
|
||||
|
||||
@@ -19,7 +19,10 @@ notifications_statistics = Blueprint(
|
||||
__name__, url_prefix='/service/<service_id>/notifications-statistics'
|
||||
)
|
||||
|
||||
from app.errors import register_errors
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
register_errors(notifications_statistics)
|
||||
|
||||
@@ -34,9 +37,9 @@ def get_all_notification_statistics_for_service(service_id):
|
||||
limit_days=int(request.args['limit_days'])
|
||||
)
|
||||
except ValueError as e:
|
||||
error = '{} is not an integer'.format(request.args['limit_days'])
|
||||
current_app.logger.error(error)
|
||||
return jsonify(result="error", message={'limit_days': [error]}), 400
|
||||
message = '{} is not an integer'.format(request.args['limit_days'])
|
||||
errors = {'limit_days': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
else:
|
||||
statistics = dao_get_notification_statistics_for_service(service_id=service_id)
|
||||
|
||||
@@ -46,9 +49,7 @@ def get_all_notification_statistics_for_service(service_id):
|
||||
|
||||
@notifications_statistics.route('/seven_day_aggregate')
|
||||
def get_notification_statistics_for_service_seven_day_aggregate(service_id):
|
||||
data, errors = week_aggregate_notification_statistics_schema.load(request.args)
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
data = week_aggregate_notification_statistics_schema.load(request.args).data
|
||||
date_from = data['date_from'] if 'date_from' in data else date(date.today().year, 4, 1)
|
||||
week_count = data['week_count'] if 'week_count' in data else 52
|
||||
stats = dao_get_7_day_agg_notification_statistics_for_service(
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
from flask import (
|
||||
jsonify,
|
||||
request,
|
||||
Blueprint
|
||||
)
|
||||
|
||||
from flask import (jsonify, request, abort, Blueprint, current_app)
|
||||
from app.schemas import permission_schema
|
||||
from app.errors import register_errors
|
||||
from app.dao.permissions_dao import permission_dao
|
||||
@@ -10,17 +14,12 @@ register_errors(permission)
|
||||
|
||||
@permission.route('', methods=['GET'])
|
||||
def get_permissions():
|
||||
data, errors = permission_schema.dump(
|
||||
permission_dao.get_query(filter_by_dict=request.args), many=True)
|
||||
if errors:
|
||||
abort(500, errors)
|
||||
data = permission_schema.dump(permission_dao.get_query(filter_by_dict=request.args), many=True).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@permission.route('/<permission_id>', methods=['GET'])
|
||||
def get_permission(permission_id):
|
||||
inst = permission_dao.get_query(filter_by_dict={'id': permission_id}).one()
|
||||
data, errors = permission_schema.dump(inst)
|
||||
if errors:
|
||||
abort(500, errors)
|
||||
data = permission_schema.dump(inst).data
|
||||
return jsonify(data=data)
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from app.schemas import provider_details_schema
|
||||
|
||||
from app.dao.provider_details_dao import (
|
||||
get_provider_details,
|
||||
get_provider_details_by_id,
|
||||
get_provider_details_by_id,
|
||||
dao_update_provider_details
|
||||
)
|
||||
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
provider_details = Blueprint('provider_details', __name__)
|
||||
register_errors(provider_details)
|
||||
|
||||
|
||||
@provider_details.route('', methods=['GET'])
|
||||
def get_providers():
|
||||
data, errors = provider_details_schema.dump(get_provider_details(), many=True)
|
||||
data = provider_details_schema.dump(get_provider_details(), many=True).data
|
||||
return jsonify(provider_details=data)
|
||||
|
||||
|
||||
@provider_details.route('/<uuid:provider_details_id>', methods=['GET'])
|
||||
def get_provider_by_id(provider_details_id):
|
||||
data, errors = provider_details_schema.dump(get_provider_details_by_id(provider_details_id))
|
||||
data = provider_details_schema.dump(get_provider_details_by_id(provider_details_id)).data
|
||||
return jsonify(provider_details=data)
|
||||
|
||||
|
||||
@@ -29,14 +35,12 @@ def update_provider_details(provider_details_id):
|
||||
|
||||
current_data = dict(provider_details_schema.dump(fetched_provider_details).data.items())
|
||||
current_data.update(request.get_json())
|
||||
update_dict, errors = provider_details_schema.load(current_data)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
update_dict = provider_details_schema.load(current_data).data
|
||||
|
||||
if "identifier" in request.get_json().keys():
|
||||
return jsonify(message={
|
||||
"identifier": ["Not permitted to be updated"]
|
||||
}, result='error'), 400
|
||||
message = "Not permitted to be updated"
|
||||
errors = {'identifier': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
dao_update_provider_details(update_dict)
|
||||
return jsonify(provider_details=provider_details_schema.dump(fetched_provider_details).data), 200
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
from datetime import date
|
||||
from datetime import (
|
||||
datetime,
|
||||
date
|
||||
)
|
||||
from flask_marshmallow.fields import fields
|
||||
from sqlalchemy.orm import load_only
|
||||
|
||||
from marshmallow import (
|
||||
post_load,
|
||||
ValidationError,
|
||||
validates,
|
||||
validates_schema,
|
||||
pre_load
|
||||
pre_load,
|
||||
pre_dump
|
||||
)
|
||||
from marshmallow_sqlalchemy import field_for
|
||||
|
||||
@@ -46,6 +49,7 @@ def _validate_not_in_future(dte, msg="Date cannot be in the future"):
|
||||
|
||||
|
||||
class BaseSchema(ma.ModelSchema):
|
||||
|
||||
def __init__(self, load_json=False, *args, **kwargs):
|
||||
self.load_json = load_json
|
||||
super(BaseSchema, self).__init__(*args, **kwargs)
|
||||
@@ -82,12 +86,14 @@ class UserSchema(BaseSchema):
|
||||
exclude = (
|
||||
"updated_at", "created_at", "user_to_service",
|
||||
"_password", "verify_codes")
|
||||
strict = True
|
||||
|
||||
|
||||
class ProviderDetailsSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.ProviderDetails
|
||||
exclude = ("provider_rates", "provider_stats")
|
||||
strict = True
|
||||
|
||||
|
||||
class ServiceSchema(BaseSchema):
|
||||
@@ -97,11 +103,13 @@ class ServiceSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.Service
|
||||
exclude = ("updated_at", "created_at", "api_keys", "templates", "jobs", 'old_id')
|
||||
strict = True
|
||||
|
||||
|
||||
class NotificationModelSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.Notification
|
||||
strict = True
|
||||
|
||||
|
||||
class BaseTemplateSchema(BaseSchema):
|
||||
@@ -109,6 +117,7 @@ class BaseTemplateSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.Template
|
||||
exclude = ("service_id", "jobs")
|
||||
strict = True
|
||||
|
||||
|
||||
class TemplateSchema(BaseTemplateSchema):
|
||||
@@ -142,6 +151,13 @@ class TemplateHistorySchema(BaseSchema):
|
||||
class NotificationsStatisticsSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.NotificationStatistics
|
||||
strict = True
|
||||
|
||||
@pre_dump
|
||||
def handle_date_str(self, in_data):
|
||||
if isinstance(in_data, dict) and 'day' in in_data:
|
||||
in_data['day'] = datetime.strptime(in_data['day'], '%Y-%m-%d').date()
|
||||
return in_data
|
||||
|
||||
|
||||
class ApiKeySchema(BaseSchema):
|
||||
@@ -151,6 +167,7 @@ class ApiKeySchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.ApiKey
|
||||
exclude = ("service", "secret")
|
||||
strict = True
|
||||
|
||||
|
||||
class JobSchema(BaseSchema):
|
||||
@@ -161,13 +178,22 @@ class JobSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.Job
|
||||
exclude = ('notifications',)
|
||||
strict = True
|
||||
|
||||
|
||||
class RequestVerifyCodeSchema(ma.Schema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
to = fields.Str(required=False)
|
||||
|
||||
|
||||
class NotificationSchema(ma.Schema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
personalisation = fields.Dict(required=False)
|
||||
|
||||
|
||||
@@ -225,12 +251,14 @@ class NotificationStatusSchema(BaseSchema):
|
||||
|
||||
class Meta:
|
||||
model = models.Notification
|
||||
strict = True
|
||||
|
||||
|
||||
class InvitedUserSchema(BaseSchema):
|
||||
|
||||
class Meta:
|
||||
model = models.InvitedUser
|
||||
strict = True
|
||||
|
||||
@validates('email_address')
|
||||
def validate_to(self, value):
|
||||
@@ -255,9 +283,14 @@ class PermissionSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.Permission
|
||||
exclude = ("created_at",)
|
||||
strict = True
|
||||
|
||||
|
||||
class EmailDataSchema(ma.Schema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
email = fields.Str(required=False)
|
||||
|
||||
@validates('email')
|
||||
@@ -269,6 +302,10 @@ class EmailDataSchema(ma.Schema):
|
||||
|
||||
|
||||
class NotificationsFilterSchema(ma.Schema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
template_type = fields.Nested(BaseTemplateSchema, only=['template_type'], many=True)
|
||||
status = fields.Nested(NotificationModelSchema, only=['status'], many=True)
|
||||
page = fields.Int(required=False)
|
||||
@@ -309,6 +346,7 @@ class TemplateStatisticsSchema(BaseSchema):
|
||||
|
||||
class Meta:
|
||||
model = models.TemplateStatistics
|
||||
strict = True
|
||||
|
||||
|
||||
class ServiceHistorySchema(ma.Schema):
|
||||
@@ -337,10 +375,14 @@ class ApiKeyHistorySchema(ma.Schema):
|
||||
class EventSchema(BaseSchema):
|
||||
class Meta:
|
||||
model = models.Event
|
||||
strict = True
|
||||
|
||||
|
||||
class FromToDateSchema(ma.Schema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
date_from = fields.Date()
|
||||
date_to = fields.Date()
|
||||
|
||||
@@ -361,6 +403,10 @@ class FromToDateSchema(ma.Schema):
|
||||
|
||||
|
||||
class DaySchema(ma.Schema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
day = fields.Date(required=True)
|
||||
|
||||
@validates('day')
|
||||
@@ -370,6 +416,9 @@ class DaySchema(ma.Schema):
|
||||
|
||||
class WeekAggregateNotificationStatisticsSchema(ma.Schema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
date_from = fields.Date()
|
||||
week_count = fields.Int()
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ from datetime import (
|
||||
from flask import (
|
||||
jsonify,
|
||||
request,
|
||||
abort,
|
||||
Blueprint
|
||||
)
|
||||
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from app.dao.api_key_dao import (
|
||||
@@ -39,11 +39,12 @@ from app.schemas import (
|
||||
permission_schema
|
||||
)
|
||||
|
||||
from app.errors import register_errors
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
service = Blueprint('service', __name__)
|
||||
|
||||
|
||||
register_errors(service)
|
||||
|
||||
|
||||
@@ -54,7 +55,7 @@ def get_services():
|
||||
services = dao_fetch_all_services_by_user(user_id)
|
||||
else:
|
||||
services = dao_fetch_all_services()
|
||||
data, errors = service_schema.dump(services, many=True)
|
||||
data = service_schema.dump(services, many=True).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@@ -66,7 +67,7 @@ def get_service_by_id(service_id):
|
||||
else:
|
||||
fetched = dao_fetch_service_by_id(service_id)
|
||||
|
||||
data, errors = service_schema.dump(fetched)
|
||||
data = service_schema.dump(fetched).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@@ -74,16 +75,12 @@ def get_service_by_id(service_id):
|
||||
def create_service():
|
||||
data = request.get_json()
|
||||
if not data.get('user_id', None):
|
||||
return jsonify(result="error", message={'user_id': ['Missing data for required field.']}), 400
|
||||
errors = {'user_id': ['Missing data for required field.']}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
user = get_model_users(data['user_id'])
|
||||
|
||||
data.pop('user_id', None)
|
||||
valid_service, errors = service_schema.load(request.get_json())
|
||||
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
valid_service = service_schema.load(request.get_json()).data
|
||||
dao_create_service(valid_service, user)
|
||||
return jsonify(data=service_schema.dump(valid_service).data), 201
|
||||
|
||||
@@ -93,9 +90,7 @@ def update_service(service_id):
|
||||
fetched_service = dao_fetch_service_by_id(service_id)
|
||||
current_data = dict(service_schema.dump(fetched_service).data.items())
|
||||
current_data.update(request.get_json())
|
||||
update_dict, errors = service_schema.load(current_data)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
update_dict = service_schema.load(current_data).data
|
||||
dao_update_service(update_dict)
|
||||
return jsonify(data=service_schema.dump(fetched_service).data), 200
|
||||
|
||||
@@ -103,14 +98,9 @@ def update_service(service_id):
|
||||
@service.route('/<uuid:service_id>/api-key', methods=['POST'])
|
||||
def renew_api_key(service_id=None):
|
||||
fetched_service = dao_fetch_service_by_id(service_id=service_id)
|
||||
|
||||
valid_api_key, errors = api_key_schema.load(request.get_json())
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
valid_api_key = api_key_schema.load(request.get_json()).data
|
||||
valid_api_key.service = fetched_service
|
||||
|
||||
save_model_api_key(valid_api_key)
|
||||
|
||||
unsigned_api_key = get_unsigned_secret(valid_api_key.id)
|
||||
return jsonify(data=unsigned_api_key), 201
|
||||
|
||||
@@ -133,7 +123,8 @@ def get_api_keys(service_id, key_id=None):
|
||||
else:
|
||||
api_keys = get_model_api_keys(service_id=service_id)
|
||||
except NoResultFound:
|
||||
return jsonify(result="error", message="API key not found for id: {}".format(service_id)), 404
|
||||
error = "API key not found for id: {}".format(service_id)
|
||||
raise InvalidRequest(error, status_code=404)
|
||||
|
||||
return jsonify(apiKeys=api_key_schema.dump(api_keys, many=True).data), 200
|
||||
|
||||
@@ -141,7 +132,6 @@ def get_api_keys(service_id, key_id=None):
|
||||
@service.route('/<uuid:service_id>/users', methods=['GET'])
|
||||
def get_users_for_service(service_id):
|
||||
fetched = dao_fetch_service_by_id(service_id)
|
||||
|
||||
result = user_schema.dump(fetched.users, many=True)
|
||||
return jsonify(data=result.data)
|
||||
|
||||
@@ -152,15 +142,12 @@ def add_user_to_service(service_id, user_id):
|
||||
user = get_model_users(user_id=user_id)
|
||||
|
||||
if user in service.users:
|
||||
return jsonify(result='error',
|
||||
message='User id: {} already part of service id: {}'.format(user_id, service_id)), 400
|
||||
|
||||
permissions, errors = permission_schema.load(request.get_json(), many=True)
|
||||
if errors:
|
||||
abort(400, errors)
|
||||
error = 'User id: {} already part of service id: {}'.format(user_id, service_id)
|
||||
raise InvalidRequest(error, status_code=400)
|
||||
|
||||
permissions = permission_schema.load(request.get_json(), many=True).data
|
||||
dao_add_user_to_service(service, user, permissions)
|
||||
data, errors = service_schema.dump(service)
|
||||
data = service_schema.dump(service).data
|
||||
return jsonify(data=data), 201
|
||||
|
||||
|
||||
@@ -169,13 +156,13 @@ def remove_user_from_service(service_id, user_id):
|
||||
service = dao_fetch_service_by_id(service_id)
|
||||
user = get_model_users(user_id=user_id)
|
||||
if user not in service.users:
|
||||
return jsonify(
|
||||
result='error',
|
||||
message='User not found'), 404
|
||||
error = 'User not found'
|
||||
raise InvalidRequest(error, status_code=404)
|
||||
|
||||
elif len(service.users) == 1:
|
||||
return jsonify(
|
||||
result='error',
|
||||
message='You cannot remove the only user for a service'), 400
|
||||
error = 'You cannot remove the only user for a service'
|
||||
raise InvalidRequest(error, status_code=400)
|
||||
|
||||
dao_remove_user_from_service(service, user)
|
||||
return jsonify({}), 204
|
||||
|
||||
@@ -183,10 +170,7 @@ def remove_user_from_service(service_id, user_id):
|
||||
@service.route('/<uuid:service_id>/fragment/aggregate_statistics')
|
||||
def get_service_provider_aggregate_statistics(service_id):
|
||||
service = dao_fetch_service_by_id(service_id)
|
||||
data, errors = from_to_date_schema.load(request.args)
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
|
||||
data = from_to_date_schema.load(request.args).data
|
||||
return jsonify(data=get_fragment_count(
|
||||
service,
|
||||
date_from=(data.pop('date_from') if 'date_from' in data else date.today()),
|
||||
@@ -208,21 +192,15 @@ def get_service_history(service_id):
|
||||
)
|
||||
|
||||
service_history = Service.get_history_model().query.filter_by(id=service_id).all()
|
||||
service_data, errors = service_history_schema.dump(service_history, many=True)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
service_data = service_history_schema.dump(service_history, many=True).data
|
||||
api_key_history = ApiKey.get_history_model().query.filter_by(service_id=service_id).all()
|
||||
|
||||
api_keys_data, errors = api_key_history_schema.dump(api_key_history, many=True)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
api_keys_data = api_key_history_schema.dump(api_key_history, many=True).data
|
||||
|
||||
template_history = Template.get_history_model().query.filter_by(service_id=service_id).all()
|
||||
template_data, errors = template_history_schema.dump(template_history, many=True)
|
||||
|
||||
events = Event.query.all()
|
||||
events_data, errors = event_schema.dump(events, many=True)
|
||||
events_data = event_schema.dump(events, many=True).data
|
||||
|
||||
data = {
|
||||
'service_history': service_data,
|
||||
|
||||
@@ -19,36 +19,32 @@ from app.schemas import (template_schema, template_history_schema)
|
||||
|
||||
template = Blueprint('template', __name__, url_prefix='/service/<uuid:service_id>/template')
|
||||
|
||||
from app.errors import register_errors
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
register_errors(template)
|
||||
|
||||
|
||||
def _content_count_greater_than_limit(content, template_type):
|
||||
template = Template({'content': content, 'template_type': template_type})
|
||||
if template_type == 'sms' and \
|
||||
template.content_count > current_app.config.get('SMS_CHAR_COUNT_LIMIT'):
|
||||
return True, jsonify(
|
||||
result="error",
|
||||
message={'content': ['Content has a character count greater than the limit of {}'.format(
|
||||
current_app.config.get('SMS_CHAR_COUNT_LIMIT'))]}
|
||||
)
|
||||
return False, ''
|
||||
return template_type == 'sms' and template.content_count > current_app.config.get('SMS_CHAR_COUNT_LIMIT')
|
||||
|
||||
|
||||
@template.route('', methods=['POST'])
|
||||
def create_template(service_id):
|
||||
fetched_service = dao_fetch_service_by_id(service_id=service_id)
|
||||
new_template, errors = template_schema.load(request.get_json())
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
new_template = template_schema.load(request.get_json()).data
|
||||
new_template.service = fetched_service
|
||||
new_template.content = _strip_html(new_template.content)
|
||||
over_limit, json_resp = _content_count_greater_than_limit(
|
||||
new_template.content,
|
||||
new_template.template_type)
|
||||
over_limit = _content_count_greater_than_limit(new_template.content, new_template.template_type)
|
||||
if over_limit:
|
||||
return json_resp, 400
|
||||
char_count_limit = current_app.config.get('SMS_CHAR_COUNT_LIMIT')
|
||||
message = 'Content has a character count greater than the limit of {}'.format(char_count_limit)
|
||||
errors = {'content': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
dao_create_template(new_template)
|
||||
return jsonify(data=template_schema.dump(new_template).data), 201
|
||||
|
||||
@@ -65,14 +61,13 @@ def update_template(service_id, template_id):
|
||||
if _template_has_not_changed(current_data, updated_template):
|
||||
return jsonify(data=updated_template), 200
|
||||
|
||||
update_dict, errors = template_schema.load(updated_template)
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
over_limit, json_resp = _content_count_greater_than_limit(
|
||||
updated_template['content'],
|
||||
fetched_template.template_type)
|
||||
update_dict = template_schema.load(updated_template).data
|
||||
over_limit = _content_count_greater_than_limit(updated_template['content'], fetched_template.template_type)
|
||||
if over_limit:
|
||||
return json_resp, 400
|
||||
char_count_limit = current_app.config.get('SMS_CHAR_COUNT_LIMIT')
|
||||
message = 'Content has a character count greater than the limit of {}'.format(char_count_limit)
|
||||
errors = {'content': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
dao_update_template(update_dict)
|
||||
return jsonify(data=template_schema.dump(update_dict).data), 200
|
||||
|
||||
@@ -80,39 +75,35 @@ def update_template(service_id, template_id):
|
||||
@template.route('', methods=['GET'])
|
||||
def get_all_templates_for_service(service_id):
|
||||
templates = dao_get_all_templates_for_service(service_id=service_id)
|
||||
data, errors = template_schema.dump(templates, many=True)
|
||||
data = template_schema.dump(templates, many=True).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@template.route('/<uuid:template_id>', methods=['GET'])
|
||||
def get_template_by_id_and_service_id(service_id, template_id):
|
||||
fetched_template = dao_get_template_by_id_and_service_id(template_id=template_id, service_id=service_id)
|
||||
data, errors = template_schema.dump(fetched_template)
|
||||
data = template_schema.dump(fetched_template).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@template.route('/<uuid:template_id>/version/<int:version>')
|
||||
def get_template_version(service_id, template_id, version):
|
||||
data, errors = template_history_schema.dump(
|
||||
data = template_history_schema.dump(
|
||||
dao_get_template_by_id_and_service_id(
|
||||
template_id=template_id,
|
||||
service_id=service_id,
|
||||
version=version
|
||||
)
|
||||
)
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@template.route('/<uuid:template_id>/versions')
|
||||
def get_template_versions(service_id, template_id):
|
||||
data, errors = template_history_schema.dump(
|
||||
data = template_history_schema.dump(
|
||||
dao_get_template_versions(service_id=service_id, template_id=template_id),
|
||||
many=True
|
||||
)
|
||||
if errors:
|
||||
return jsonify(result='error', message=errors), 400
|
||||
).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ template_statistics = Blueprint('template-statistics',
|
||||
__name__,
|
||||
url_prefix='/service/<service_id>/template-statistics')
|
||||
|
||||
from app.errors import register_errors, InvalidData
|
||||
from app.errors import register_errors, InvalidRequest
|
||||
|
||||
register_errors(template_statistics)
|
||||
|
||||
@@ -28,20 +28,16 @@ def get_template_statistics_for_service(service_id):
|
||||
except ValueError as e:
|
||||
error = '{} is not an integer'.format(request.args['limit_days'])
|
||||
message = {'limit_days': [error]}
|
||||
raise InvalidData(message, status_code=400)
|
||||
raise InvalidRequest(message, status_code=400)
|
||||
else:
|
||||
limit_days = None
|
||||
stats = dao_get_template_statistics_for_service(service_id, limit_days=limit_days)
|
||||
data, errors = template_statistics_schema.dump(stats, many=True)
|
||||
if errors:
|
||||
raise InvalidData(errors, status_code=400)
|
||||
data = template_statistics_schema.dump(stats, many=True).data
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@template_statistics.route('/<template_id>')
|
||||
def get_template_statistics_for_template_id(service_id, template_id):
|
||||
stats = dao_get_template_statistics_for_template(template_id)
|
||||
data, errors = template_statistics_schema.dump(stats, many=True)
|
||||
if errors:
|
||||
raise InvalidData(errors, status_code=400)
|
||||
data = template_statistics_schema.dump(stats, many=True).data
|
||||
return jsonify(data=data)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import json
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from flask import (jsonify, request, abort, Blueprint, current_app)
|
||||
from flask import (jsonify, request, Blueprint, current_app)
|
||||
from app import encryption, DATETIME_FORMAT
|
||||
from app.dao.users_dao import (
|
||||
get_model_users,
|
||||
@@ -28,9 +28,13 @@ from app.schemas import (
|
||||
from app.celery.tasks import (
|
||||
send_sms,
|
||||
email_reset_password,
|
||||
send_email)
|
||||
send_email
|
||||
)
|
||||
|
||||
from app.errors import register_errors
|
||||
from app.errors import (
|
||||
register_errors,
|
||||
InvalidRequest
|
||||
)
|
||||
|
||||
user = Blueprint('user', __name__)
|
||||
register_errors(user)
|
||||
@@ -43,9 +47,7 @@ def create_user():
|
||||
# TODO password policy, what is valid password
|
||||
if not req_json.get('password', None):
|
||||
errors.update({'password': ['Missing data for required field.']})
|
||||
return jsonify(result="error", message=errors), 400
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
save_model_user(user_to_create, pwd=req_json.get('password'))
|
||||
return jsonify(data=user_schema.dump(user_to_create).data), 201
|
||||
|
||||
@@ -60,11 +62,9 @@ def update_user(user_id):
|
||||
# but would be good to have the same validation here.
|
||||
if pwd is not None and not pwd:
|
||||
errors.update({'password': ['Invalid data for field']})
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
status_code = 200
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
save_model_user(user_to_update, update_dict=update_dct, pwd=pwd)
|
||||
return jsonify(data=user_schema.dump(user_to_update).data), status_code
|
||||
return jsonify(data=user_schema.dump(user_to_update).data), 200
|
||||
|
||||
|
||||
@user.route('/<uuid:user_id>/verify/password', methods=['POST'])
|
||||
@@ -75,9 +75,10 @@ def verify_user_password(user_id):
|
||||
try:
|
||||
txt_pwd = request.get_json()['password']
|
||||
except KeyError:
|
||||
return jsonify(
|
||||
result="error",
|
||||
message={'password': ['Required field missing data']}), 400
|
||||
message = 'Required field missing data'
|
||||
errors = {'password': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
if user_to_verify.check_password(txt_pwd):
|
||||
user_to_verify.logged_in_at = datetime.utcnow()
|
||||
save_model_user(user_to_verify)
|
||||
@@ -85,7 +86,9 @@ def verify_user_password(user_id):
|
||||
return jsonify({}), 204
|
||||
else:
|
||||
increment_failed_login_count(user_to_verify)
|
||||
return jsonify(result='error', message={'password': ['Incorrect password']}), 400
|
||||
message = 'Incorrect password'
|
||||
errors = {'password': [message]}
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
|
||||
@user.route('/<uuid:user_id>/verify/code', methods=['POST'])
|
||||
@@ -105,12 +108,13 @@ def verify_user_code(user_id):
|
||||
except KeyError:
|
||||
errors.update({'code_type': ['Required field missing data']})
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
raise InvalidRequest(errors, status_code=400)
|
||||
|
||||
code = get_user_code(user_to_verify, txt_code, txt_type)
|
||||
if not code:
|
||||
return jsonify(result="error", message="Code not found"), 404
|
||||
raise InvalidRequest("Code not found", status_code=404)
|
||||
if datetime.utcnow() > code.expiry_datetime or code.code_used:
|
||||
return jsonify(result="error", message="Code has expired"), 400
|
||||
raise InvalidRequest("Code has expired", status_code=400)
|
||||
use_user_code(code.id)
|
||||
return jsonify({}), 204
|
||||
|
||||
@@ -119,8 +123,6 @@ def verify_user_code(user_id):
|
||||
def send_user_sms_code(user_id):
|
||||
user_to_send_to = get_model_users(user_id=user_id)
|
||||
verify_code, errors = request_verify_code_schema.load(request.get_json())
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
secret_code = create_secret_code()
|
||||
create_user_code(user_to_send_to, secret_code, 'sms')
|
||||
@@ -150,8 +152,6 @@ def send_user_sms_code(user_id):
|
||||
def send_user_email_verification(user_id):
|
||||
user_to_send_to = get_model_users(user_id=user_id)
|
||||
verify_code, errors = request_verify_code_schema.load(request.get_json())
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
secret_code = create_secret_code()
|
||||
create_user_code(user_to_send_to, secret_code, 'email')
|
||||
@@ -191,8 +191,7 @@ def set_permissions(user_id, service_id):
|
||||
user = get_model_users(user_id=user_id)
|
||||
service = dao_fetch_service_by_id(service_id=service_id)
|
||||
permissions, errors = permission_schema.load(request.get_json(), many=True)
|
||||
if errors:
|
||||
abort(400, errors)
|
||||
|
||||
for p in permissions:
|
||||
p.user = user
|
||||
p.service = service
|
||||
@@ -204,7 +203,8 @@ def set_permissions(user_id, service_id):
|
||||
def get_by_email():
|
||||
email = request.args.get('email')
|
||||
if not email:
|
||||
return jsonify(result="error", message="invalid request"), 400
|
||||
error = 'Invalid request. Email query string param required'
|
||||
raise InvalidRequest(error, status_code=400)
|
||||
fetched_user = get_user_by_email(email)
|
||||
result = user_schema.dump(fetched_user)
|
||||
|
||||
@@ -214,8 +214,6 @@ def get_by_email():
|
||||
@user.route('/reset-password', methods=['POST'])
|
||||
def send_user_reset_password():
|
||||
email, errors = email_data_request_schema.load(request.get_json())
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
|
||||
user_to_send_to = get_user_by_email(email['email'])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user