76 lines
2.7 KiB
Python
76 lines
2.7 KiB
Python
from typing import Annotated
|
||
|
||
from fastapi import Depends, Header, HTTPException, status
|
||
from sqlalchemy import select
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from models import Role, User, get_db
|
||
from security import decode_token
|
||
|
||
# Eski davranışla uyumluluk: bu hesaplar rol atanmasa da tam yetkili.
|
||
LEGACY_ADMIN_EMAILS = {"jts@jts.rocks", "afm@jts.rocks"}
|
||
|
||
# Panel izin kataloğu (kullanıcı yönetimi UI'ı buradan okur)
|
||
PERMISSIONS = {
|
||
"upload": "Dosya yükleme + Asset Takip",
|
||
"lore": "Lore notları (görme + ekleme + düzenleme)",
|
||
"map_view": "Harita editörünü görüntüleme (salt okunur)",
|
||
"npc": "NPC listesi (görme + ekleme + düzenleme)",
|
||
"map_edit": "Harita etiketi ekleme / düzenleme / silme",
|
||
"chars": "Karakterler (sınıf + skill tanımları)",
|
||
"users": "Kullanıcı ve rol yönetimi",
|
||
}
|
||
|
||
|
||
async def get_user_perms(user: User, db: AsyncSession) -> set[str]:
|
||
if user.email in LEGACY_ADMIN_EMAILS:
|
||
return {"*"}
|
||
if not user.role_id:
|
||
return set()
|
||
role = (await db.execute(select(Role).where(Role.id == user.role_id))).scalar_one_or_none()
|
||
return set(role.permissions or []) if role else set()
|
||
|
||
|
||
def has_perm(perms: set[str], perm: str) -> bool:
|
||
return "*" in perms or perm in perms
|
||
|
||
|
||
def require_perm(perm: str):
|
||
async def dep(
|
||
user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
) -> User:
|
||
perms = await get_user_perms(user, db)
|
||
if not has_perm(perms, perm):
|
||
raise HTTPException(status.HTTP_403_FORBIDDEN, "Yetkin yok")
|
||
return user
|
||
return dep
|
||
|
||
|
||
async def get_current_user(
|
||
authorization: Annotated[str | None, Header()] = None,
|
||
db: AsyncSession = Depends(get_db),
|
||
) -> User:
|
||
if not authorization or not authorization.lower().startswith("bearer "):
|
||
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Missing bearer token")
|
||
token = authorization.split(None, 1)[1].strip()
|
||
try:
|
||
payload = decode_token(token)
|
||
except Exception as e:
|
||
raise HTTPException(status.HTTP_401_UNAUTHORIZED, f"Invalid token: {e}")
|
||
user_id = int(payload["sub"])
|
||
user = (await db.execute(select(User).where(User.id == user_id))).scalar_one_or_none()
|
||
if not user or not user.is_active:
|
||
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "User not found or inactive")
|
||
return user
|
||
|
||
|
||
async def require_panel(
|
||
user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
) -> User:
|
||
"""Herhangi bir panel yetkisi olan (bir rolü/izni bulunan) her yetkili."""
|
||
perms = await get_user_perms(user, db)
|
||
if not perms:
|
||
raise HTTPException(status.HTTP_403_FORBIDDEN, "Panel yetkin yok")
|
||
return user
|