db-removed
This commit is contained in:
parent
e76f924b2d
commit
8b398fa589
|
@ -1,6 +1,4 @@
|
||||||
### `inbox`: Сервер для внутренних переписок
|
## `inbox`: Сервер для внутренних переписок
|
||||||
|
|
||||||
Для
|
|
||||||
|
|
||||||
### ENV
|
### ENV
|
||||||
- REDIS_URL
|
- REDIS_URL
|
||||||
|
|
|
@ -2,14 +2,9 @@ sentry-sdk
|
||||||
aioredis~=2.0.1
|
aioredis~=2.0.1
|
||||||
ariadne~=0.20.1
|
ariadne~=0.20.1
|
||||||
starlette~=0.31.1
|
starlette~=0.31.1
|
||||||
sqlalchemy~=2.0.21
|
|
||||||
graphql-core
|
|
||||||
gql
|
|
||||||
uvicorn~=0.23.2
|
uvicorn~=0.23.2
|
||||||
httpx
|
httpx
|
||||||
itsdangerous
|
itsdangerous
|
||||||
pydantic~=2.4.2
|
|
||||||
psycopg2-binary
|
|
||||||
######## development deps
|
######## development deps
|
||||||
isort
|
isort
|
||||||
brunette
|
brunette
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from services.core import get_author
|
from services.core import get_author
|
||||||
from services.db import local_session
|
|
||||||
from services.redis import redis
|
from services.redis import redis
|
||||||
from resolvers import query
|
from resolvers import query
|
||||||
from services.auth import login_required
|
from services.auth import login_required
|
||||||
|
@ -52,30 +51,29 @@ async def load_chats(_, info, limit: int = 50, offset: int = 0):
|
||||||
if len(cids) == 0:
|
if len(cids) == 0:
|
||||||
r = await create_chat(None, info, members=[1]) # member with id = 1 is discours
|
r = await create_chat(None, info, members=[1]) # member with id = 1 is discours
|
||||||
cids.append(r["chat"]["id"])
|
cids.append(r["chat"]["id"])
|
||||||
with local_session() as session:
|
for cid in cids:
|
||||||
for cid in cids:
|
cid = cid.decode("utf-8")
|
||||||
cid = cid.decode("utf-8")
|
c = await redis.execute("GET", "chats/" + cid)
|
||||||
c = await redis.execute("GET", "chats/" + cid)
|
if c:
|
||||||
if c:
|
c = dict(json.loads(c))
|
||||||
c = dict(json.loads(c))
|
c["messages"] = await load_messages(cid, 5, 0)
|
||||||
c["messages"] = await load_messages(cid, 5, 0)
|
c["unread"] = await get_unread_counter(cid, author_id)
|
||||||
c["unread"] = await get_unread_counter(cid, author_id)
|
member_ids = c["members"].copy()
|
||||||
member_ids = c["members"].copy()
|
c["members"] = []
|
||||||
c["members"] = []
|
for member_id in member_ids:
|
||||||
for member_id in member_ids:
|
a = await get_author(member_id)
|
||||||
a = await get_author(member_id)
|
if a:
|
||||||
if a:
|
c["members"].append(
|
||||||
c["members"].append(
|
{
|
||||||
{
|
"id": a.id,
|
||||||
"id": a.id,
|
"slug": a.slug,
|
||||||
"slug": a.slug,
|
"userpic": a.userpic,
|
||||||
"userpic": a.userpic,
|
"name": a.name,
|
||||||
"name": a.name,
|
"lastSeen": a.lastSeen,
|
||||||
"lastSeen": a.lastSeen,
|
"online": a.id in members_online,
|
||||||
"online": a.id in members_online,
|
}
|
||||||
}
|
)
|
||||||
)
|
chats.append(c)
|
||||||
chats.append(c)
|
|
||||||
return {"chats": chats, "error": None}
|
return {"chats": chats, "error": None}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,12 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from pydantic import BaseModel
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from starlette.authentication import AuthenticationBackend
|
|
||||||
from starlette.requests import HTTPConnection
|
|
||||||
from httpx import AsyncClient
|
from httpx import AsyncClient
|
||||||
from httpx._exceptions import HTTPError
|
from httpx._exceptions import HTTPError
|
||||||
from services.db import local_session
|
|
||||||
from settings import AUTH_URL
|
from settings import AUTH_URL
|
||||||
from orm.author import Author
|
|
||||||
|
|
||||||
|
|
||||||
INTERNAL_AUTH_SERVER = "v2.discours" in AUTH_URL
|
INTERNAL_AUTH_SERVER = "v2.discours" in AUTH_URL
|
||||||
|
|
||||||
|
|
||||||
class AuthCredentials(BaseModel):
|
|
||||||
user_id: Optional[int] = None
|
|
||||||
scopes: Optional[dict] = {}
|
|
||||||
logged_in: bool = False
|
|
||||||
error_message: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
class JWTAuthenticate(AuthenticationBackend):
|
|
||||||
async def authenticate(self, request: HTTPConnection):
|
|
||||||
logged_in, user_id = await check_auth(request)
|
|
||||||
return AuthCredentials(user_id=user_id, logged_in=logged_in), user_id
|
|
||||||
|
|
||||||
|
|
||||||
async def check_auth(req):
|
async def check_auth(req):
|
||||||
token = req.headers.get("Authorization")
|
token = req.headers.get("Authorization")
|
||||||
gql = (
|
gql = (
|
||||||
|
@ -45,12 +25,6 @@ async def check_auth(req):
|
||||||
return is_authenticated, user_id
|
return is_authenticated, user_id
|
||||||
|
|
||||||
|
|
||||||
async def author_id_by_user_id(user_id):
|
|
||||||
async with local_session() as session:
|
|
||||||
author = session(Author).where(Author.user == user_id).first()
|
|
||||||
return author.id
|
|
||||||
|
|
||||||
|
|
||||||
def login_required(f):
|
def login_required(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
async def decorated_function(*args, **kwargs):
|
async def decorated_function(*args, **kwargs):
|
||||||
|
@ -62,8 +36,7 @@ def login_required(f):
|
||||||
raise Exception("You are not logged in")
|
raise Exception("You are not logged in")
|
||||||
else:
|
else:
|
||||||
# Добавляем author_id в контекст
|
# Добавляем author_id в контекст
|
||||||
author_id = await author_id_by_user_id(user_id)
|
context["author_id"] = user_id
|
||||||
context["author_id"] = author_id
|
|
||||||
|
|
||||||
# Если пользователь аутентифицирован, выполняем резолвер
|
# Если пользователь аутентифицирован, выполняем резолвер
|
||||||
return await f(*args, **kwargs)
|
return await f(*args, **kwargs)
|
||||||
|
@ -79,9 +52,7 @@ def auth_request(f):
|
||||||
if not is_authenticated:
|
if not is_authenticated:
|
||||||
raise HTTPError("please, login first")
|
raise HTTPError("please, login first")
|
||||||
else:
|
else:
|
||||||
req["author_id"] = (
|
req["author_id"] = user_id
|
||||||
user_id if INTERNAL_AUTH_SERVER else await author_id_by_user_id(user_id)
|
|
||||||
)
|
|
||||||
return await f(*args, **kwargs)
|
return await f(*args, **kwargs)
|
||||||
|
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
from typing import TypeVar, Any, Dict, Generic, Callable
|
|
||||||
|
|
||||||
from sqlalchemy import create_engine, Column, Integer
|
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
from sqlalchemy.sql.schema import Table
|
|
||||||
|
|
||||||
from settings import DB_URL
|
|
||||||
|
|
||||||
engine = create_engine(DB_URL, echo=False, pool_size=10, max_overflow=20)
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
|
||||||
|
|
||||||
REGISTRY: Dict[str, type] = {}
|
|
||||||
|
|
||||||
|
|
||||||
def local_session():
|
|
||||||
return Session(bind=engine, expire_on_commit=False)
|
|
||||||
|
|
||||||
|
|
||||||
class Base(declarative_base()):
|
|
||||||
__table__: Table
|
|
||||||
__tablename__: str
|
|
||||||
__new__: Callable
|
|
||||||
__init__: Callable
|
|
||||||
__allow_unmapped__ = True
|
|
||||||
__abstract__ = True
|
|
||||||
__table_args__ = {"extend_existing": True}
|
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
|
||||||
|
|
||||||
def __init_subclass__(cls, **kwargs):
|
|
||||||
REGISTRY[cls.__name__] = cls
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(cls: Generic[T], **kwargs) -> Generic[T]:
|
|
||||||
instance = cls(**kwargs)
|
|
||||||
return instance.save()
|
|
||||||
|
|
||||||
def save(self) -> Generic[T]:
|
|
||||||
with local_session() as session:
|
|
||||||
session.add(self)
|
|
||||||
session.commit()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def update(self, input):
|
|
||||||
column_names = self.__table__.columns.keys()
|
|
||||||
for name, value in input.items():
|
|
||||||
if name in column_names:
|
|
||||||
setattr(self, name, value)
|
|
||||||
|
|
||||||
def dict(self) -> Dict[str, Any]:
|
|
||||||
column_names = self.__table__.columns.keys()
|
|
||||||
return {c: getattr(self, c) for c in column_names}
|
|
Loading…
Reference in New Issue
Block a user