From 988b7e964ec594039f0b57a213555f08e6c19c48 Mon Sep 17 00:00:00 2001 From: rasmus Date: Thu, 7 Aug 2025 23:18:45 +0300 Subject: [PATCH] refactor slack logger --- .gitignore | 1 + app/doorboy-proxy.py | 49 ++++++++++++++++++++++++++++++++++---------- app/slack.py | 43 ++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 3 ++- requirements.txt | 7 +++++++ 5 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 app/slack.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 8c75193..b00221b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env .overnodebundle +.venv diff --git a/app/doorboy-proxy.py b/app/doorboy-proxy.py index 91b6de6..69969a2 100755 --- a/app/doorboy-proxy.py +++ b/app/doorboy-proxy.py @@ -3,12 +3,14 @@ from datetime import date, datetime from sanic import Sanic from sanic.response import text, json from sanic_prometheus import monitor -from motor.motor_asyncio import AsyncIOMotorClient import httpx -import pymongo +from motor.motor_asyncio import AsyncIOMotorClient +from pymongo.errors import PyMongoError import os +from .slack import add_slack_routes app = Sanic(__name__) +add_slack_routes(app) monitor(app).expose_endpoint() DOORBOY_SECRET_FLOOR = os.environ["DOORBOY_SECRET_FLOOR"] # API key for godoor controllers authenticating for k-space:floor @@ -148,16 +150,41 @@ async def forward_swipe(request): print("Door", repr(data.get("door")), "not in", doors) return text("Not allowed", 403) - async with httpx.AsyncClient() as client: - r = await client.post(SWIPE_URI, json=data, headers={ - "Content-Type": "application/json", - "Authorization": f"Basic {INVENTORY_API_KEY}" - }) - if r.status_code == 200: - return text("ok") - else: - return text("Failed", 500) +def slack_post(msg): + if SLACK_DOORLOG_CALLBACK == "DEV": + print(f"[DEV SLACK]: {msg}") + return + try: + requests.post(SLACK_DOORLOG_CALLBACK, json={"text": msg }).raise_for_status() + except requests.exceptions.RequestException as e: + print(f"[SLACK]: {e}") + +def approvedStr(approved: bool) -> str: + if approved: + return "Permitted" + + return "Denied" + +# consumes SLACK_DOORLOG_CALLBACK and app.ctx.db +@app.listener("after_server_start") +async def slack_log(app, loop): + pipeline = [{ + "$match": { + "operationType": "insert", + } + }] + while True: + try: + async with app.ctx.db.eventlog.watch(pipeline) as stream: + async for event in stream: + ev = event["fullDocument"] + + msg = "%s %s access for %s via %s" % (approvedStr(ev["approved"]), ev["door"], ev["user"]["name"], ev("method")) + slack_post(msg) + + except PyMongoError as e: + print(e) if __name__ == "__main__": app.run(debug=False, host="0.0.0.0", port=5000, single_process=True, access_log=True) diff --git a/app/slack.py b/app/slack.py new file mode 100644 index 0000000..51cc083 --- /dev/null +++ b/app/slack.py @@ -0,0 +1,43 @@ +from pymongo.errors import PyMongoError +from requests.exceptions import RequestException +import os +import requests + +SLACK_DOORLOG_CALLBACK = os.environ["SLACK_DOORLOG_CALLBACK"] # webhook logs to private channel or "DEV" to print to console. + +def add_slack_routes(app): + app.app.register_listener(slack_log, "after_server_start") # consumes SLACK_DOORLOG_CALLBACK and app.ctx.db + +def slack_post(msg): + if SLACK_DOORLOG_CALLBACK == "DEV": + print(f"[DEV SLACK]: {msg}") + return + + try: + requests.post(SLACK_DOORLOG_CALLBACK, json={"text": msg }).raise_for_status() + except RequestException as e: + print(f"[SLACK]: {e}") + +def approvedStr(approved: bool) -> str: + if approved: + return "Permitted" + + return "Denied" + +async def slack_log(app, loop): + pipeline = [{ + "$match": { + "operationType": "insert", + } + }] + while True: + try: + async with app.ctx.db.eventlog.watch(pipeline) as stream: + async for event in stream: + ev = event["fullDocument"] + + msg = "%s %s access for %s via %s" % (approvedStr(ev["approved"]), ev["door"], ev["user"]["name"], ev("method")) + slack_post(msg) + + except PyMongoError as e: + print(e) diff --git a/docker-compose.yml b/docker-compose.yml index c216584..9efa962 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,6 +30,7 @@ services: FLOOR_ACCESS_GROUP: "k-space:floor" WORKSHOP_ACCESS_GROUP: "k-space:workshop" CARD_URI: "https://inventory-app-72zn4.codemowers.ee/cards" - SWIPE_URI: "https://inventory-app-72zn4.codemowers.ee/m/doorboy/swipe" + SLACK_DOORLOG_CALLBACK: DEV + env_file: .env build: context: . diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..88b4c3b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +httpx==0.28.1 +motor==3.7.1 +pymongo==4.14.0 +python_dateutil==2.9.0 +Requests==2.32.4 +sanic==25.3.0 +sanic_prometheus==0.2.1