added RAG, Multiuser, TG bot
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
from app.auth.deps import get_current_user
|
||||
from app.auth.service import create_user, find_user_by_token
|
||||
from app.auth.tokens import hash_token, verify_token
|
||||
|
||||
__all__ = ["get_current_user", "hash_token", "verify_token"]
|
||||
@@ -0,0 +1,34 @@
|
||||
from fastapi import Depends, HTTPException, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth.tokens import hash_token
|
||||
from app.db.base import get_db
|
||||
from app.db.models import User
|
||||
|
||||
|
||||
def _extract_token(request: Request) -> str | None:
|
||||
auth = request.headers.get("Authorization", "")
|
||||
if auth.lower().startswith("bearer "):
|
||||
token = auth[7:].strip()
|
||||
if token:
|
||||
return token
|
||||
header = request.headers.get("X-API-Token", "").strip()
|
||||
return header or None
|
||||
|
||||
|
||||
def get_current_user(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
) -> User:
|
||||
token = _extract_token(request)
|
||||
if not token:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing API token")
|
||||
|
||||
token_hash = hash_token(token)
|
||||
user = db.scalar(
|
||||
select(User).where(User.api_token_hash == token_hash, User.is_active.is_(True))
|
||||
)
|
||||
if not user:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API token")
|
||||
return user
|
||||
@@ -0,0 +1,61 @@
|
||||
import secrets
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth.tokens import hash_token
|
||||
from app.db.models import CharacterCard, User
|
||||
from app.character.card import DEFAULT_CARD, normalize_card
|
||||
import json
|
||||
|
||||
|
||||
def find_user_by_token(db: Session, token: str) -> User | None:
|
||||
token_hash = hash_token(token.strip())
|
||||
return db.scalar(
|
||||
select(User).where(User.api_token_hash == token_hash, User.is_active.is_(True))
|
||||
)
|
||||
|
||||
|
||||
def user_to_dict(user: User) -> dict[str, Any]:
|
||||
return {
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"display_name": user.display_name or user.username,
|
||||
}
|
||||
|
||||
|
||||
def create_user(
|
||||
db: Session,
|
||||
*,
|
||||
username: str,
|
||||
display_name: str = "",
|
||||
api_token: str | None = None,
|
||||
) -> tuple[User, str]:
|
||||
clean = username.strip().lower()
|
||||
if not clean:
|
||||
raise ValueError("username не может быть пустым")
|
||||
existing = db.scalar(select(User).where(User.username == clean))
|
||||
if existing:
|
||||
raise ValueError(f"Пользователь «{clean}» уже существует")
|
||||
|
||||
plain_token = (api_token or "").strip() or secrets.token_urlsafe(32)
|
||||
user = User(
|
||||
username=clean,
|
||||
display_name=(display_name or clean).strip(),
|
||||
api_token_hash=hash_token(plain_token),
|
||||
is_active=True,
|
||||
)
|
||||
db.add(user)
|
||||
db.flush()
|
||||
|
||||
card = normalize_card(DEFAULT_CARD)
|
||||
db.add(
|
||||
CharacterCard(
|
||||
user_id=user.id,
|
||||
card_json=json.dumps(card, ensure_ascii=False),
|
||||
)
|
||||
)
|
||||
db.commit()
|
||||
db.refresh(user)
|
||||
return user, plain_token
|
||||
@@ -0,0 +1,9 @@
|
||||
import hashlib
|
||||
|
||||
|
||||
def hash_token(token: str) -> str:
|
||||
return hashlib.sha256(token.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def verify_token(plain: str, token_hash: str) -> bool:
|
||||
return hash_token(plain) == token_hash
|
||||
Reference in New Issue
Block a user