From b0bd293f8f28c895eb22058d030f95ec9ebc67a8 Mon Sep 17 00:00:00 2001 From: Super User Date: Tue, 2 Jul 2024 13:06:13 +0300 Subject: [PATCH] added service endpoint --- .../endpoints/__init__.py | 0 .../endpoints/service.py | 125 ++++++++++++++++++ webhook_to_fedora_messaging/endpoints/util.py | 29 ++++ 3 files changed, 154 insertions(+) create mode 100644 webhook_to_fedora_messaging/endpoints/__init__.py create mode 100644 webhook_to_fedora_messaging/endpoints/service.py create mode 100644 webhook_to_fedora_messaging/endpoints/util.py diff --git a/webhook_to_fedora_messaging/endpoints/__init__.py b/webhook_to_fedora_messaging/endpoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/webhook_to_fedora_messaging/endpoints/service.py b/webhook_to_fedora_messaging/endpoints/service.py new file mode 100644 index 0000000..190efa5 --- /dev/null +++ b/webhook_to_fedora_messaging/endpoints/service.py @@ -0,0 +1,125 @@ +from flask import Blueprint, Flask, request, Response, Request +from ..database import db +from ..models.service import Service +from ..models.user import User +from sqlalchemy_helpers import get_or_create +from .util import not_found, success, bad_request, created, conflict, validate_request, exclude_from_val, unprocessable_entity + + +app = Flask(__name__) +service_endpoint = Blueprint("service_endpoint", __name__) + + +@service_endpoint.route("/service", methods=["POST"]) +def create_service(): + """ + Used for creating a new service by sending a post request to /service/ path. + """ + if not validate_request(request.json, fields=['username', 'type', 'desc', 'name']): + return unprocessable_entity() + + session = db.Session() + body = request.json + + + user = session.query(User).filter(User.username == body['username']).first() + if user is None: + return not_found() + + service, is_created = get_or_create(session, Service, name=body['name'], type=body['type'], desc=body['desc'], user_id=user.id) + + if not is_created: + return conflict({'message': 'Service Already Exists'}) + else: + return created({'message': 'Created', 'uuid': service.id}) + + +@service_endpoint.route("/service/search", methods=["GET"]) +def list_services(): + """ + Used for listing all services belong to a user by sending a get request to /service/search path + """ + if not validate_request(request): + return unprocessable_entity() + + session = db.Session() + user = session.query(User).filter(User.username.like(request.json['username'])).first() + if user is None: + return not_found() + + services = session.query(Service).filter(Service.user_id == user.id).all() + + return success({'service_list': services}) + + +@service_endpoint.route("/service", methods=["GET"]) +def lookup_service(): + """ + Used for retrieving a service by it's uuid by sending a get request + to the /service path. + + Request Body: + service_uuid: Service UUID + """ + if not validate_request(request, ['service_uuid']): + return unprocessable_entity() + + session = db.Session() + service = session.query(Service).filter(Service.id == request.json['service_uuid']).first() + + if service is None: + return not_found() + else: + return success({'uuid': service.id, 'name': service.name, 'type': service.type, 'desc': service.desc}) + + +@service_endpoint.route("/service/revoke", methods=["PUT"]) +def revoke_service(): + """ + Used for revoking a service by sending a PUT request to /service/revoke path. + + Request Body: + service_uuid: Service UUID + username: Username of the user that servicce belongs to. + """ + if not validate_request(request, fields=['username', 'service_uuid']): + return unprocessable_entity() + + session = db.Session() + user = session.query(User).filter(User.username == request.json['username']).first() + if user is None: + return not_found() + + service = session.query(Service).filter(Service.user_id == user.id).filter(Service.id == request.json['service_uuid']).first() + if service is None: + return not_found() + + service.disabled = True + session.commit() + + return success({'uuid': service.id, 'is_valid': not service.disabled}) + + +@service_endpoint.route("/service", methods=["PUT"]) +def update_service(): + """ + Used for updating a service by sending a PUT request to /service path. + + Request Body: + uuid: UUID of the service + name: Updated name (optional) + mesg_body: Updated message body (optional) + + """ + if not validate_request(request, fields=['uuid', 'name', 'mesg_body']): + return unprocessable_entity() + + session = db.Session() + service = session.query(Service).filter(Service.id == request.json['uuid']).first() + if service is None: + return not_found() + + service.name = request.json['name'] if request.json['name'] is not None and request.json['name'] != "" else service.name + service.desc = request.json['mesg_body'] if request.json['mesg_body'] is not None and request.json['mesg_body'] != "" else service.desc + session.commit() + return success({'uuid': service.id, 'name': service.name, 'mesg_body': service.desc, 'is_valid': not service.disabled}) diff --git a/webhook_to_fedora_messaging/endpoints/util.py b/webhook_to_fedora_messaging/endpoints/util.py new file mode 100644 index 0000000..0c0f8c3 --- /dev/null +++ b/webhook_to_fedora_messaging/endpoints/util.py @@ -0,0 +1,29 @@ +from flask import Response, Request + + +def not_found() -> Response: + return Response({'message': 'Not Found'}, status=404, mimetype='application/json') + + +def success(data: dict) ->Response: + return Response(data, status=200, mimetype='application/json') + + +def bad_request() -> Response: + return Response("{'message': 'Bad Request'}", status=400, mimetype='application/json') + + +def created(data: dict) -> Response: + return Response(data, status=201, mimetype='application/json') + + +def conflict(data: dict) -> Response: + return Response(data, status=409, mimetype='application/json') + + +def unprocessable_entity() -> Response: + return Response("{'message: 'Unprocessable Entity'}", status=429, mimetype="application/json") + + +def validate_request(request: dict, fields=['username']) -> bool: + return all(field in request for field in fields)