diff --git a/Pipfile b/Pipfile index c3380be7ec881ca1b942f39363ad73d4f93a3a78..830c70e828ea94de913153e67d7e8b437d5688f8 100644 --- a/Pipfile +++ b/Pipfile @@ -10,6 +10,7 @@ pyrabbit = "*" flask = "*" flask-restful = "*" marshmallow = "*" +bson = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 3cd34d20a17d9f6dc7710a03cfa563ac973834bb..6bfa164eac8b2c1023b1195ad342d66842e4f891 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b71ec6300f7c04a8d222991089770e4384941bf5553cfa12031330227ad043cb" + "sha256": "6197445b839f98b90944ea771c7c0f63db31f0e455b325be3435fa2d17a89517" }, "pipfile-spec": 6, "requires": { @@ -31,6 +31,13 @@ ], "version": "==9.0.1" }, + "bson": { + "hashes": [ + "sha256:d6511b2ab051139a9123c184de1a04227262173ad593429d21e443d6462d6590" + ], + "index": "pypi", + "version": "==0.5.10" + }, "click": { "hashes": [ "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", @@ -70,6 +77,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.21.0" }, + "importlib-metadata": { + "hashes": [ + "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab", + "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43" + ], + "markers": "python_version < '3.10'", + "version": "==5.0.0" + }, "itsdangerous": { "hashes": [ "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", @@ -142,11 +157,11 @@ }, "marshmallow": { "hashes": [ - "sha256:35e02a3a06899c9119b785c12a22f4cda361745d66a71ab691fd7610202ae104", - "sha256:6804c16114f7fce1f5b4dadc31f4674af23317fcc7f075da21e35c1a35d781f7" + "sha256:90032c0fd650ce94b6ec6dc8dfeb0e3ff50c144586462c389b81a07205bedb78", + "sha256:93f0958568da045b0021ec6aeb7ac37c81bfcccbb9a0e7ed8559885070b3a19b" ], "index": "pypi", - "version": "==3.18.0" + "version": "==3.19.0" }, "packaging": { "hashes": [ @@ -187,6 +202,14 @@ "index": "pypi", "version": "==1.1.0" }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.2" + }, "pytz": { "hashes": [ "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", @@ -217,6 +240,14 @@ ], "markers": "python_version >= '3.7'", "version": "==2.2.2" + }, + "zipp": { + "hashes": [ + "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1", + "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8" + ], + "markers": "python_version >= '3.7'", + "version": "==3.10.0" } }, "develop": {} diff --git a/api.py b/api.py index 41e02f074cdc3fb9e7ae850a3c306c00770dc308..825c204f582d2371c6ac5487f587976f411bfea7 100644 --- a/api.py +++ b/api.py @@ -3,6 +3,8 @@ from flask_restful import Api from endpoints.hello import HelloWorld from endpoints.clients import Client, ClientList from endpoints.receive import Receive +from endpoints.send import Send +from endpoints.notify import Notify app = Flask(__name__) api = Api(app) @@ -11,6 +13,8 @@ api.add_resource(HelloWorld, "/") api.add_resource(ClientList, "/client") api.add_resource(Client, "/client/<client_id>") api.add_resource(Receive, "/receive") +api.add_resource(Send, "/send") +api.add_resource(Notify, "/notify") if __name__ == "__main__": app.run(debug=True) diff --git a/endpoints/notify.py b/endpoints/notify.py index c5f420630ef357d4afa3c276bbc50bd06b8d3e3b..8c683859c6ee75bc112b7bb95d035a5450bee1d2 100644 --- a/endpoints/notify.py +++ b/endpoints/notify.py @@ -1,28 +1,39 @@ from flask_restful import Resource, reqparse, abort, fields, marshal_with +from marshmallow import Schema, field import json +class NotifySchema(Schema): + client_id = fields.Str(required=True) + secret = fields.Str(required=True) + body = fields.Str(required=True) class Notify(Resource): - def setup_request_parser(self): - parser = reqparse.RequestParser() - parser.add_argument( - "client_id", type=str, help="A unique name to identify the client" - ) - parser.add_argument( - "secret", type=str, help="A human friendly name to identify the client" - ) - parser.add_argument("content", type=str, help="The message") - self.parser = parser + clients = None + schema = None - def parse(self): - return self.parser.parse_args() + def __init__(self): + self.schema = ReceiveSchema() + with open("clients.json", "r") as clients_file: + self.clients = json.load(clients_file) - def put(self, client_id): - args = clients_file.parse() + def post(self): + errors = self.schema.validate(request.args) + if errors: + abort(400, str(errors)) - client = clients_file.find(client_id) - if not client: - abort(404, message="No client with id: {}".format(client_id)) - else: - client = clients_file.update(args) - return client, 201 + messages = [] + allow = False + body = request.args.get("body") + client_id = request.args.get("client_id") + notify_queue = client_id + "-notify" + if client_id in self.clients: + client = self.clients.get(client_id) + if request.args.get("secret") == client.get("secret"): + allow = True + + if allow: + connection = pika.BlockingConnection(pika.ConnectionParameters(host="localhost")) + channel = connection.channel() + channel.queue_declare(queue=notify_queue, durable=True) + channel.basic_publish(exchange="", routing_key=notify_queue, body=body) + deliver_connection.close() diff --git a/endpoints/receive.py b/endpoints/receive.py index 75e027606c3817b22d8526722feeac08cb734daf..6567b0d1eb8cdca6a2faf7fcc605d43d1a3219ec 100644 --- a/endpoints/receive.py +++ b/endpoints/receive.py @@ -4,7 +4,7 @@ import pika import json -class ReceiveSchema(Schema): +class ReceiveQuerySchema(Schema): client_id = fields.Str(required=True) secret = fields.Str(required=True) max_messages = fields.Int(required=False) @@ -15,7 +15,7 @@ class Receive(Resource): schema = None def __init__(self): - self.schema = ReceiveSchema() + self.schema = ReceiveQuerySchema() with open("clients.json", "r") as clients_file: self.clients = json.load(clients_file) diff --git a/endpoints/send.py b/endpoints/send.py index 70353c9f4fc8a193afb504907e83a1f4a45e2be5..31e38d96548d45fa8190846d6f2505233f80556d 100644 --- a/endpoints/send.py +++ b/endpoints/send.py @@ -1,29 +1,45 @@ from flask_restful import Resource, reqparse, abort, fields, marshal_with +from marshmallow import Schema, field import json +class SendSchema(Schema): + client_id = fields.Str(required=True) + secret = fields.Str(required=True) + body = fields.Str(required=True) + topic = fields.Str(required=True) class Send(Resource): - def setup_request_parser(self): - parser = reqparse.RequestParser() - parser.add_argument( - "client_id", type=str, help="A unique name to identify the client" - ) - parser.add_argument( - "secret", type=str, help="A human friendly name to identify the client" - ) - parser.add_argument("topic", type=str, help="Publisher topic") - parser.add_argument("content", type=str, help="The message") - self.parser = parser + clients = None + schema = None - def parse(self): - return self.parser.parse_args() + def __init__(self): + self.schema = ReceiveSchema() + with open("clients.json", "r") as clients_file: + self.clients = json.load(clients_file) - def put(self, client_id): - args = clients_file.parse() + def post(self): + errors = self.schema.validate(request.args) + if errors: + abort(400, str(errors)) - client = clients_file.find(client_id) - if not client: - abort(404, message="No client with id: {}".format(client_id)) - else: - client = clients_file.update(args) - return client, 201 + messages = [] + allow = False + body = request.args.get("body") + topic = request.args.get("topic") + client_id = request.args.get("client_id") + outbox_queue = client_id + "-outbox" + if client_id in self.clients: + client = self.clients.get(client_id) + if request.args.get("secret") == client.get("secret"): + allow = True + + if allow: + connection = pika.BlockingConnection(pika.ConnectionParameters(host="localhost")) + channel = connection.channel() + channel.queue_declare(queue=notify_queue, durable=True) + message = { + 'topic': topic, + 'message': body, + } + channel.basic_publish(exchange="", routing_key=notify_queue, body=message) + deliver_connection.close()