diff --git a/app/dao/__init__.py b/app/dao/__init__.py index e69de29bb..ce0df4421 100644 --- a/app/dao/__init__.py +++ b/app/dao/__init__.py @@ -0,0 +1,6 @@ +from sqlalchemy.exc import SQLAlchemyError + + +# Should I use SQLAlchemyError? +class DAOException(SQLAlchemyError): + pass diff --git a/app/dao/services_dao.py b/app/dao/services_dao.py index d9bc4e5d7..403b28579 100644 --- a/app/dao/services_dao.py +++ b/app/dao/services_dao.py @@ -1,24 +1,22 @@ import json from datetime import datetime - from sqlalchemy.orm import load_only -from sqlalchemy.exc import SQLAlchemyError - +from . import DAOException from app import db from app.models import Service -# Should I use SQLAlchemyError? -class DAOException(SQLAlchemyError): - pass - - -def create_model_service(service): - users_list = getattr(service, 'users', []) +def save_model_service(service, update_dict=None): + users_list = update_dict.get('users', []) if update_dict else getattr(service, 'users', []) if not users_list: error_msg = {'users': 'Missing data for required attribute'} raise DAOException(json.dumps(error_msg)) - db.session.add(service) + if update_dict: + del update_dict['id'] + del update_dict['users'] + db.session.query(Service).filter_by(id=service.id).update(update_dict) + else: + db.session.add(service) db.session.commit() diff --git a/app/dao/users_dao.py b/app/dao/users_dao.py index da4577fd3..ca4264cca 100644 --- a/app/dao/users_dao.py +++ b/app/dao/users_dao.py @@ -1,13 +1,17 @@ from datetime import datetime - +from . import DAOException from sqlalchemy.orm import load_only from app import db from app.models import User -def create_model_user(usr): - db.session.add(usr) +def save_model_user(usr, update_dict={}): + if update_dict: + del update_dict['id'] + db.session.query(User).filter_by(id=usr.id).update(update_dict) + else: + db.session.add(usr) db.session.commit() diff --git a/app/schemas.py b/app/schemas.py index 912259a90..0d2e14d06 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -13,17 +13,6 @@ class UserSchema(ma.ModelSchema): model = models.User exclude = ("updated_at", "created_at", "user_to_service") - def make_object(self, data): - # TODO possibly override to handle instance creation - return super(UserSchema, self).make_object(data) - - # def dump(self, obj, many=None, update_fields=True, **kwargs): - # retval = super(UserSchema, self).dump( - # obj, many=many, update_fields=update_fields, **kwargs) - # if not many and 'email_address' not in retval.data: - # retval.data['email_address'] = obj.email_address - # return retval - # TODO process users list, to return a list of user.id # Should that list be restricted by the auth parsed?? @@ -32,10 +21,6 @@ class ServiceSchema(ma.ModelSchema): model = models.Service exclude = ("updated_at", "created_at") - def make_object(self, data): - # TODO possibly override to handle instance creation - return super(ServiceSchema, self).make_object(data) - user_schema = UserSchema() users_schema = UserSchema(many=True) diff --git a/app/service/views/rest.py b/app/service/views/rest.py index 75054a336..18a14ba3f 100644 --- a/app/service/views/rest.py +++ b/app/service/views/rest.py @@ -1,9 +1,10 @@ from flask import (jsonify, request) from sqlalchemy.exc import DataError from sqlalchemy.orm.exc import NoResultFound -from app.dao.services_dao import (create_model_service, get_model_services) +from app.dao.services_dao import (save_model_service, get_model_services) from app.dao.users_dao import get_model_users from .. import service +from app import db from app.schemas import (services_schema, service_schema) @@ -11,17 +12,29 @@ from app.schemas import (services_schema, service_schema) @service.route('/', methods=['POST']) def create_service(): # TODO what exceptions get passed from schema parsing? - service = service_schema.load(request.get_json()).data - print(service_schema.dump(service).data) - # Some magic here, it automatically creates the service object. - # Cool but need to understand how this works. + service, errors = service_schema.load(request.get_json()) + # I believe service is already added to the session but just needs a + # db.session.commit + save_model_service(service) return jsonify(data=service_schema.dump(service).data), 201 # TODO auth to be added @service.route('/', methods=['PUT']) def update_service(service_id): - service = get_services(service_id=service_id) + try: + service = get_model_services(service_id=service_id) + except DataError: + return jsonify(result="error", message="Invalid service id"), 400 + except NoResultFound: + return jsonify(result="error", message="Service not found"), 404 + # TODO there has got to be a better way to do the next three lines + update_service, errors = service_schema.load(request.get_json()) + update_dict, errors = service_schema.dump(update_service) + # TODO FIX ME + # Remove update_service model which is added to db.session + db.session.rollback() + save_model_service(service, update_dict=update_dict) return jsonify(data=service_schema.dump(service).data) @@ -34,6 +47,6 @@ def get_service(service_id=None): except DataError: return jsonify(result="error", message="Invalid service id"), 400 except NoResultFound: - return jsonify(result="error", message="Service doesn't exist"), 404 - result = services_schema.dump(services) if isinstance(services, list) else service_schema.dump(services) - return jsonify(data=result.data) + return jsonify(result="error", message="Service not found"), 404 + data, errors = services_schema.dump(services) if isinstance(services, list) else service_schema.dump(services) + return jsonify(data=data) diff --git a/app/user/views/rest.py b/app/user/views/rest.py index 615f6b7f6..dc0dcfd1f 100644 --- a/app/user/views/rest.py +++ b/app/user/views/rest.py @@ -2,24 +2,37 @@ from flask import (jsonify, request) from sqlalchemy.exc import DataError from sqlalchemy.orm.exc import NoResultFound from app.dao.services_dao import get_model_services -from app.dao.users_dao import (get_model_users, create_model_user) +from app.dao.users_dao import (get_model_users, save_model_user) from app.schemas import ( user_schema, users_schema, service_schema, services_schema) from .. import user +from app import db # TODO auth to be added @user.route('/', methods=['POST']) def create_user(): user = user_schema.load(request.get_json()).data - create_model_user(user) + save_model_user(user) return jsonify(data=user_schema.dump(user).data), 201 # TODO auth to be added @user.route('/', methods=['PUT']) def update_user(user_id): - user = get_model_users(user_id=user_id) + try: + user = get_model_users(user_id=user_id) + except DataError: + return jsonify(result="error", message="Invalid user id"), 400 + except NoResultFound: + return jsonify(result="error", message="User not found"), 404 + # TODO there has got to be a better way to do the next three lines + update_user, errors = user_schema.load(request.get_json()) + update_dict, errors = user_schema.dump(update_user) + # TODO FIX ME + # Remove update_service model which is added to db.session + db.session.rollback() + save_model_user(user, update_dict=update_dict) return jsonify(data=user_schema.dump(user).data) diff --git a/tests/app/conftest.py b/tests/app/conftest.py index 19d706573..5f3b5ead4 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -1,7 +1,7 @@ import pytest from app.models import (User, Service) -from app.dao.users_dao import (create_model_user, get_model_users) -from app.dao.services_dao import create_model_service +from app.dao.users_dao import (save_model_user, get_model_users) +from app.dao.services_dao import save_model_service @pytest.fixture(scope='function') @@ -9,7 +9,7 @@ def sample_user(notify_db, notify_db_session, email="notify@digital.cabinet-office.gov.uk"): user = User(**{'email_address': email}) - create_model_user(user) + save_model_user(user) return user @@ -27,5 +27,5 @@ def sample_service(notify_db, 'active': False, 'restricted': False} service = Service(**data) - create_model_service(service) + save_model_service(service) return service diff --git a/tests/app/dao/test_services_dao.py b/tests/app/dao/test_services_dao.py index 146a2cd44..a6b4abe68 100644 --- a/tests/app/dao/test_services_dao.py +++ b/tests/app/dao/test_services_dao.py @@ -1,6 +1,6 @@ import pytest from app.dao.services_dao import ( - create_model_service, get_model_services, DAOException) + save_model_service, get_model_services, DAOException) from tests.app.conftest import sample_service as create_sample_service from app.models import Service @@ -15,7 +15,7 @@ def test_create_service(notify_api, notify_db, notify_db_session, sample_user): 'active': False, 'restricted': False} service = Service(**data) - create_model_service(service) + save_model_service(service) assert Service.query.count() == 1 assert Service.query.first().name == service_name assert Service.query.first().id == service.id @@ -58,7 +58,7 @@ def test_missing_user_attribute(notify_api, notify_db, notify_db_session): 'restricted': False} service = Service(**data) - create_model_service(service) + save_model_service(service) pytest.fail("DAOException not thrown") except DAOException as e: assert "Missing data for required attribute" in str(e) diff --git a/tests/app/dao/test_users_dao.py b/tests/app/dao/test_users_dao.py index dd342e668..443a1cf22 100644 --- a/tests/app/dao/test_users_dao.py +++ b/tests/app/dao/test_users_dao.py @@ -1,6 +1,6 @@ from sqlalchemy.exc import DataError from sqlalchemy.orm.exc import NoResultFound -from app.dao.users_dao import (create_model_user, get_model_users) +from app.dao.users_dao import (save_model_user, get_model_users) from tests.app.conftest import sample_user as create_sample_user from app.models import User @@ -8,7 +8,7 @@ from app.models import User def test_create_user(notify_api, notify_db, notify_db_session): email = 'notify@digital.cabinet-office.gov.uk' user = User(**{'email_address': email}) - create_model_user(user) + save_model_user(user) assert User.query.count() == 1 assert User.query.first().email_address == email assert User.query.first().id == user.id diff --git a/tests/app/service/views/test_rest.py b/tests/app/service/views/test_rest.py index 01e687284..4251e0508 100644 --- a/tests/app/service/views/test_rest.py +++ b/tests/app/service/views/test_rest.py @@ -1,5 +1,5 @@ import json -from app.models import Service +from app.models import (Service, User) from flask import url_for @@ -58,4 +58,30 @@ def test_post_service(notify_api, notify_db, notify_db_session, sample_user): def test_put_service(notify_api, notify_db, notify_db_session, sample_service): - pass + """ + Tests Put endpoint '/