This commit is contained in:
Tony Rewin 2023-10-04 20:14:06 +03:00
parent 34b7d0021d
commit 1360692b57
6 changed files with 42 additions and 38 deletions

View File

@ -4,6 +4,6 @@ WORKDIR /app
EXPOSE 8080
ADD nginx.conf.sigil ./
COPY requirements.txt .
RUN apt update && apt install -y gcc && pip install -r requirements.txt
RUN apt-get update && apt-get install -y gcc && pip install -r requirements.txt
COPY . .
CMD ["python", "server.py"]

View File

@ -1,14 +1,14 @@
sentry-sdk
aioredis
ariadne
starlette
sqlalchemy
aioredis~=2.0.1
ariadne~=0.20.1
starlette~=0.31.1
sqlalchemy~=2.0.21
graphql-core
gql
uvicorn
httpx
uvicorn~=0.23.2
aiohttp~=3.8.5
itsdangerous
pydantic
pydantic~=2.4.2
psycopg2-binary
######## development deps
isort

View File

@ -1,6 +1,7 @@
import json
from datetime import datetime, timezone
from services.auth import login_required
from services.presence import notify_message
from services.redis import redis
from resolvers import mutation
@ -53,11 +54,7 @@ async def create_message(_, info, chat: str, body: str, reply_to=None):
# await FollowingManager.push("chat", result)
# subscribe on updates
channel_name = (
f"chat:{chat['id']}" if not chat["title"] else f"group:{chat['id']}"
)
new_message["kind"] = "new_message"
await redis.execute_pubsub("PUBLISH", channel_name, json.dumps(new_message))
await notify_message(new_message, chat["id"])
return {"message": new_message, "error": None}

View File

@ -2,12 +2,6 @@ import sys
import uvicorn
from settings import PORT
def exception_handler(exception_type, exception, traceback, debug_hook=sys.excepthook):
print(vars(traceback))
print("%s: %s" % (exception_type.__name__, exception))
log_settings = {
"version": 1,
"disable_existing_loggers": True,
@ -53,6 +47,11 @@ local_headers = [
]
def exception_handler(exception_type, exception, traceback, debug_hook=sys.excepthook):
traceback.print_exc()
print("%s: %s" % (exception_type.__name__, exception))
if __name__ == "__main__":
sys.excepthook = exception_handler
uvicorn.run(

View File

@ -1,10 +1,11 @@
from typing import Optional
from aiohttp.web import HTTPUnauthorized
from aiohttp.client import ClientSession
from pydantic import BaseModel
from functools import wraps
from starlette.authentication import AuthenticationBackend
from starlette.requests import HTTPConnection
from graphql.error import GraphQLError
from httpx import AsyncClient
from services.db import local_session
from settings import AUTH_URL
from orm.author import Author
@ -24,19 +25,13 @@ class AuthCredentials(BaseModel):
class JWTAuthenticate(AuthenticationBackend):
async def authenticate(self, request: HTTPConnection):
scopes = {} # TODO: integrate await user.get_permission
logged_in, user_id = await check_auth(request)
return (
AuthCredentials(user_id=user_id, scopes=scopes, logged_in=logged_in),
AuthUser(user_id=user_id, username=""),
AuthCredentials(user_id=user_id, logged_in=logged_in),
AuthUser(user_id=user_id),
)
class Unauthorized(GraphQLError):
code = 401
message = "401 Unauthorized"
async def check_auth(req):
token = req.headers.get("Authorization")
gql = (
@ -45,12 +40,14 @@ async def check_auth(req):
else {"query": "{ session { user { id } } }"}
)
headers = {"Authorization": token, "Content-Type": "application/json"}
async with AsyncClient() as client:
response = await client.post(AUTH_URL, headers=headers, data=gql)
if response.status_code != 200:
async with ClientSession(headers=headers) as session:
async with session.post(AUTH_URL, data=gql) as response:
if response.status != 200:
return False, None
r = response.json()
user_id = r.get("data", {}).get("session", {}).get("user", {}).get("id", None)
r = await response.json()
user_id = (
r.get("data", {}).get("session", {}).get("user", {}).get("id", None)
)
is_authenticated = user_id is not None
return is_authenticated, user_id
@ -87,7 +84,7 @@ def auth_request(f):
req = args[0]
is_authenticated, user_id = await check_auth(req)
if not is_authenticated:
raise Unauthorized("You are not logged in")
raise HTTPUnauthorized()
else:
author_id = await author_id_by_user_id(user_id)
req["author_id"] = author_id

11
services/presence.py Normal file
View File

@ -0,0 +1,11 @@
import json
from redis import redis
async def notify_message(message, chat_id: str):
channel_name = f"chat:{chat_id}"
data = {**message, "kind": "new_message"}
try:
await redis.execute_pubsub("PUBLISH", channel_name, json.dumps(data))
except Exception as e:
print(f"Failed to publish to channel {channel_name}: {e}")