From cec0d40e5bc9a81e6e53a84baee52d3ea57e231d Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 1 Feb 2016 10:48:33 +0000 Subject: [PATCH] Create schema for RequestVerifyCodeSchema Previously we were using a schema that mapped onto db.Model. However, the json in the request did not reflect the VerfiyCode db Model. I did not add validation on the to field, we did not have that previously. --- app/schemas.py | 23 +++++++++++------------ app/user/rest.py | 18 ++++++++---------- tests/app/user/test_rest_verify.py | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/app/schemas.py b/app/schemas.py index 9557f63eb..a394b2f67 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -1,6 +1,8 @@ +from flask_marshmallow.fields import fields from . import ma from . import models -from marshmallow import post_load +from marshmallow import post_load, ValidationError + # TODO I think marshmallow provides a better integration and error handling. # Would be better to replace functionality in dao with the marshmallow supported @@ -9,7 +11,6 @@ from marshmallow import post_load class BaseSchema(ma.ModelSchema): - def __init__(self, *args, load_json=False, **kwargs): self.load_json = load_json super(BaseSchema, self).__init__(*args, **kwargs) @@ -27,7 +28,6 @@ class BaseSchema(ma.ModelSchema): class UserSchema(BaseSchema): - class Meta: model = models.User exclude = ( @@ -36,36 +36,35 @@ class UserSchema(BaseSchema): class ServiceSchema(BaseSchema): - class Meta: model = models.Service exclude = ("updated_at", "created_at", "api_keys", "templates", "jobs", "queue_name") class TemplateSchema(BaseSchema): - class Meta: model = models.Template exclude = ("updated_at", "created_at", "service_id", "jobs") class ApiKeySchema(BaseSchema): - class Meta: model = models.ApiKey exclude = ("service", "secret") class JobSchema(BaseSchema): - class Meta: model = models.Job -class VerifyCodeSchema(BaseSchema): - class Meta: - model = models.VerifyCode - exclude = ('user', "_code", "expiry_datetime", "code_used", "created_at") +class RequestVerifyCodeSchema(ma.Schema): + def verify_code_type(self): + if self not in ['sms', 'email']: + raise ValidationError('Invalid code type') + + code_type = fields.Str(required=True, validate=verify_code_type) + to = fields.Str(required=False) user_schema = UserSchema() @@ -83,4 +82,4 @@ api_keys_schema = ApiKeySchema(many=True) job_schema = JobSchema() job_schema_load_json = JobSchema(load_json=True) jobs_schema = JobSchema(many=True) -verify_code_schema = VerifyCodeSchema() +request_verify_code_schema = RequestVerifyCodeSchema() diff --git a/app/user/rest.py b/app/user/rest.py index 2af6cbc53..9c1262298 100644 --- a/app/user/rest.py +++ b/app/user/rest.py @@ -15,8 +15,8 @@ from app.dao.users_dao import ( ) from app.schemas import ( user_schema, users_schema, service_schema, services_schema, - verify_code_schema, user_schema_load_json) -from app import db, notify_alpha_client + request_verify_code_schema, user_schema_load_json) +from app import notify_alpha_client from flask import Blueprint @@ -126,24 +126,22 @@ def send_user_code(user_id): except NoResultFound: return jsonify(result="error", message="User not found"), 404 - request_json = request.get_json() - - verify_code, errors = verify_code_schema.load(request_json) + verify_code, errors = request_verify_code_schema.load(request.get_json()) if errors: return jsonify(result="error", message=errors), 400 from app.dao.users_dao import create_secret_code secret_code = create_secret_code() - create_user_code(user, secret_code, verify_code.code_type) + create_user_code(user, secret_code, verify_code.get('code_type')) # TODO this will need to fixed up when we stop using # notify_alpha_client - if verify_code.code_type == 'sms': - mobile = user.mobile_number if 'to' not in request_json else request_json['to'] + if verify_code.get('code_type') == 'sms': + mobile = user.mobile_number if verify_code.get('to', None) is None else verify_code.get('to') notify_alpha_client.send_sms( mobile_number=mobile, message=secret_code) - elif verify_code.code_type == 'email': - email = user.email_address if 'to' not in request_json else request_json['to'] + elif verify_code.get('code_type') == 'email': + email = user.email_address if verify_code.get('to', None) is None else verify_code.get('to') notify_alpha_client.send_email( email, secret_code, diff --git a/tests/app/user/test_rest_verify.py b/tests/app/user/test_rest_verify.py index ab4f2a66c..a2228d44b 100644 --- a/tests/app/user/test_rest_verify.py +++ b/tests/app/user/test_rest_verify.py @@ -348,3 +348,21 @@ def test_send_user_code_for_email_uses_optional_to_field(notify_api, '11111', 'notify@digital.cabinet-office.gov.uk', 'Verification code') + + +def test_request_verify_code_schema_invalid_code_type(notify_api, notify_db, notify_db_session, sample_user): + import json + from app.schemas import request_verify_code_schema + data = json.dumps({'code_type': 'not_sms'}) + code, error = request_verify_code_schema.loads(data) + assert code == {} + assert error == {'code_type': ['Invalid code type']} + + +def test_request_verify_code_schema_with_to(notify_api, notify_db, notify_db_session, sample_user): + import json + from app.schemas import request_verify_code_schema + data = json.dumps({'code_type': 'sms', 'to': 'some@one.gov.uk'}) + code, error = request_verify_code_schema.loads(data) + assert code == {'code_type': 'sms', 'to': 'some@one.gov.uk'} + assert error == {}