diff --git a/app/dao/service_inbound_api_dao.py b/app/dao/service_inbound_api_dao.py index db694b653..53691f56d 100644 --- a/app/dao/service_inbound_api_dao.py +++ b/app/dao/service_inbound_api_dao.py @@ -23,4 +23,4 @@ def reset_service_inbound_api(service_inbound_api): def get_service_inbound_api(service_inbound_api_id, service_id): return ServiceInboundApi.query.filter_by(id=service_inbound_api_id, - service_id=service_id).one() + service_id=service_id).first() diff --git a/app/models.py b/app/models.py index ae057f6e6..baa03dc42 100644 --- a/app/models.py +++ b/app/models.py @@ -298,8 +298,8 @@ class ServiceWhitelist(db.Model): class ServiceInboundApi(db.Model, Versioned): __tablename__ = 'service_inbound_api' id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) - service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), index=True, nullable=False) - service = db.relationship('Service') + service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), index=True, nullable=False, unique=True) + service = db.relationship('Service', backref='inbound_api') url = db.Column(db.String(255), nullable=False) bearer_token = db.Column(db.String(255), nullable=False) created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow, nullable=False) @@ -313,11 +313,11 @@ class ServiceInboundApi(db.Model, Versioned): def serialize(self): return { - "id": self.id, - "service_id": self.service_id, + "id": str(self.id), + "service_id": str(self.service_id), "url": self.url, "bearer_token": self.bearer_token, - "updated_by_id": self.updated_by_id, + "updated_by_id": str(self.updated_by_id), "created_at": self.created_at.strftime(DATETIME_FORMAT), "updated_at": self.updated_at.strftime(DATETIME_FORMAT) if self.updated_at else None } diff --git a/app/service/rest.py b/app/service/rest.py index 4f4da5371..5fe831f35 100644 --- a/app/service/rest.py +++ b/app/service/rest.py @@ -8,6 +8,7 @@ from flask import ( current_app, Blueprint ) +from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm.exc import NoResultFound from app import redis_store @@ -547,17 +548,28 @@ def create_service_inbound_api(service_id): validate(data, service_inbound_api) data["service_id"] = service_id inbound_api = ServiceInboundApi(**data) - save_service_inbound_api(inbound_api) + try: + save_service_inbound_api(inbound_api) + except SQLAlchemyError as e: + if hasattr(e, 'orig') and hasattr(e.orig, 'pgerror')and e.orig.pgerror\ + and ('duplicate key value violates unique constraint "ix_service_inbound_api_service_id"' + in e.orig.pgerror): + return jsonify( + result='error', + message={'name': ["You can only have one URL and bearer token for your service."]} + ), 400 + else: + raise e return jsonify(data=inbound_api.serialize()), 201 -@service_blueprint.route('//inbound-api/', methods=['POST']) -def update_service_inbound_api(service_id, id): +@service_blueprint.route('//inbound-api/', methods=['POST']) +def update_service_inbound_api(service_id, inbound_api_id): data = request.get_json() validate(data, update_service_inbound_api_schema) - to_update = get_service_inbound_api(id, service_id) + to_update = get_service_inbound_api(inbound_api_id, service_id) if data.get("url", None): to_update.url = data["url"] @@ -568,3 +580,10 @@ def update_service_inbound_api(service_id, id): reset_service_inbound_api(to_update) return jsonify(data=to_update.serialize()), 200 + + +@service_blueprint.route('//inbound-api/', methods=["GET"]) +def fetch_service_inbound_api(service_id, inbound_api_id): + inbound_api = get_service_inbound_api(inbound_api_id, service_id) + + return jsonify(data=inbound_api.serialize()), 200 diff --git a/migrations/versions/0098_service_inbound_api.py b/migrations/versions/0098_service_inbound_api.py index 3dd84b64b..1d0a54b6d 100644 --- a/migrations/versions/0098_service_inbound_api.py +++ b/migrations/versions/0098_service_inbound_api.py @@ -25,8 +25,10 @@ def upgrade(): sa.Column('version', sa.Integer(), autoincrement=False, nullable=False), sa.PrimaryKeyConstraint('id', 'version') ) - op.create_index(op.f('ix_service_inbound_api_history_service_id'), 'service_inbound_api_history', ['service_id'], unique=False) - op.create_index(op.f('ix_service_inbound_api_history_updated_by_id'), 'service_inbound_api_history', ['updated_by_id'], unique=False) + op.create_index(op.f('ix_service_inbound_api_history_service_id'), 'service_inbound_api_history', ['service_id'], + unique=False) + op.create_index(op.f('ix_service_inbound_api_history_updated_by_id'), 'service_inbound_api_history', + ['updated_by_id'], unique=False) op.create_table('service_inbound_api', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('service_id', postgresql.UUID(as_uuid=True), nullable=False), @@ -35,13 +37,14 @@ def upgrade(): sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=True), sa.Column('updated_by_id', postgresql.UUID(as_uuid=True), nullable=False), - sa.Column('version', sa.Integer(), nullable=False), + sa.Column('version', sa.Integer(), nullable=False),\ sa.ForeignKeyConstraint(['service_id'], ['services.id'], ), sa.ForeignKeyConstraint(['updated_by_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) - op.create_index(op.f('ix_service_inbound_api_service_id'), 'service_inbound_api', ['service_id'], unique=False) - op.create_index(op.f('ix_service_inbound_api_updated_by_id'), 'service_inbound_api', ['updated_by_id'], unique=False) + op.create_index(op.f('ix_service_inbound_api_service_id'), 'service_inbound_api', ['service_id'], unique=True) + op.create_index(op.f('ix_service_inbound_api_updated_by_id'), 'service_inbound_api', ['updated_by_id'], + unique=False) def downgrade(): diff --git a/tests/app/service/test_rest.py b/tests/app/service/test_rest.py index 678745e42..17bedcc77 100644 --- a/tests/app/service/test_rest.py +++ b/tests/app/service/test_rest.py @@ -2219,3 +2219,13 @@ def test_update_service_inbound_api_updates_bearer_token(client, sample_service) resp_json = json.loads(response.get_data(as_text=True))["data"] assert get_secret(resp_json["bearer_token"]) == "different_token" assert service_inbound_api.unsigned_bearer_token == "different_token" + + +def test_fetch_service_inbound_api(client, sample_service): + service_inbound_api = create_service_inbound_api(service=sample_service) + + response = client.get("/service/{}/inbound-api/{}".format(sample_service.id, service_inbound_api.id), + headers=[create_authorization_header()]) + + assert response.status_code == 200 + assert json.loads(response.get_data(as_text=True))["data"] == service_inbound_api.serialize()