merged-isolated-core
Some checks failed
deploy / deploy (push) Failing after 1m46s

This commit is contained in:
2023-10-23 17:47:11 +03:00
parent b675188013
commit bf241a8fbd
56 changed files with 1683 additions and 2784 deletions

69
services/auth.py Normal file
View File

@@ -0,0 +1,69 @@
from functools import wraps
from httpx import AsyncClient, HTTPError
from settings import AUTH_URL
async def check_auth(req):
token = req.headers.get("Authorization")
print(f"[services.auth] checking auth token: {token}")
query_name = "session"
query_type = "query"
operation = "GetUserId"
headers = {"Authorization": "Bearer " + token, "Content-Type": "application/json"}
gql = {
"query": query_type + " " + operation + " { " + query_name + " { user { id } } " + " }",
"operationName": operation,
"variables": None,
}
async with AsyncClient(timeout=30.0) as client:
response = await client.post(AUTH_URL, headers=headers, json=gql)
print(f"[services.auth] response: {response.status_code} {response.text}")
if response.status_code != 200:
return False, None
r = response.json()
try:
user_id = (
r.get("data", {}).get(query_name, {}).get("user", {}).get("id", None)
)
is_authenticated = user_id is not None
return is_authenticated, user_id
except Exception as e:
print(f"{e}: {r}")
return False, None
def login_required(f):
@wraps(f)
async def decorated_function(*args, **kwargs):
info = args[1]
context = info.context
req = context.get("request")
is_authenticated, user_id = await check_auth(req)
if not is_authenticated:
raise Exception("You are not logged in")
else:
# Добавляем author_id в контекст
context["author_id"] = user_id
# Если пользователь аутентифицирован, выполняем резолвер
return await f(*args, **kwargs)
return decorated_function
def auth_request(f):
@wraps(f)
async def decorated_function(*args, **kwargs):
req = args[0]
is_authenticated, user_id = await check_auth(req)
if not is_authenticated:
raise HTTPError("please, login first")
else:
req["author_id"] = user_id
return await f(*args, **kwargs)
return decorated_function

View File

@@ -1,12 +1,12 @@
import json
from services.redis import redis
from services.rediscache import redis
async def notify_reaction(reaction):
async def notify_reaction(reaction, action: str = "create"):
channel_name = "reaction"
data = {
"payload": reaction,
"action": "create"
"action": action
}
try:
await redis.publish(channel_name, json.dumps(data))
@@ -14,11 +14,11 @@ async def notify_reaction(reaction):
print(f"Failed to publish to channel {channel_name}: {e}")
async def notify_shout(shout):
async def notify_shout(shout, action: str = "create"):
channel_name = "shout"
data = {
"payload": shout,
"action": "create"
"action": action
}
try:
await redis.publish(channel_name, json.dumps(data))
@@ -26,7 +26,7 @@ async def notify_shout(shout):
print(f"Failed to publish to channel {channel_name}: {e}")
async def notify_follower(follower: dict, author_id: int):
async def notify_follower(follower: dict, author_id: int, action: str = "follow"):
fields = follower.keys()
for k in fields:
if k not in ["id", "name", "slug", "userpic"]:
@@ -34,7 +34,7 @@ async def notify_follower(follower: dict, author_id: int):
channel_name = f"follower:{author_id}"
data = {
"payload": follower,
"action": "follow",
"action": action
}
try:
await redis.publish(channel_name, json.dumps(data))

View File

@@ -1,6 +1,6 @@
import asyncio
import json
from services.redis import redis
from services.rediscache import redis
from orm.shout import Shout
from resolvers.load import load_shouts_by

67
services/server.py Normal file
View File

@@ -0,0 +1,67 @@
import sys
import uvicorn
from uvicorn.main import logger
from settings import PORT
log_settings = {
"version": 1,
"disable_existing_loggers": True,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(levelprefix)s %(message)s",
"use_colors": None,
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": '%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s',
},
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr",
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
},
"loggers": {
"uvicorn": {"handlers": ["default"], "level": "INFO"},
"uvicorn.error": {"level": "INFO", "handlers": ["default"], "propagate": True},
"uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False},
},
}
local_headers = [
("Access-Control-Allow-Methods", "GET, POST, OPTIONS, HEAD"),
("Access-Control-Allow-Origin", "https://localhost:3000"),
(
"Access-Control-Allow-Headers",
"DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization",
),
("Access-Control-Expose-Headers", "Content-Length,Content-Range"),
("Access-Control-Allow-Credentials", "true"),
]
def exception_handler(_et, exc, _tb):
logger.error(..., exc_info=(type(exc), exc, exc.__traceback__))
if __name__ == "__main__":
sys.excepthook = exception_handler
if "dev" in sys.argv:
import os
os.environ.set("MODE", "development")
uvicorn.run(
"main:app",
host="0.0.0.0",
port=PORT,
proxy_headers=True,
server_header=True
)

14
services/settings.py Normal file
View File

@@ -0,0 +1,14 @@
from os import environ
PORT = 8080
DB_URL = (
environ.get("DATABASE_URL")
or environ.get("DB_URL")
or "postgresql://postgres@localhost:5432/discoursio"
)
REDIS_URL = environ.get("REDIS_URL") or "redis://127.0.0.1"
API_BASE = environ.get("API_BASE") or ""
AUTH_URL = environ.get("AUTH_URL") or ""
MODE = environ.get("MODE") or "production"
SENTRY_DSN = environ.get("SENTRY_DSN")
DEV_SERVER_PID_FILE_NAME = "dev-server.pid"

View File

@@ -1,6 +1,4 @@
import json
from services.redis import redis
from services.rediscache import redis
async def get_unread_counter(chat_id: str, author_id: int) -> int: