Spaces:
Running
Running
from fastapi import FastAPI, Depends, HTTPException, Security, status | |
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm | |
from fastapi.middleware.cors import CORSMiddleware | |
from jose import JWTError, jwt | |
from passlib.context import CryptContext | |
from datetime import datetime, timedelta | |
from typing import Optional, Dict, Any | |
import os | |
from pydantic import BaseModel | |
from routes import router | |
from config import settings | |
# Güvenlik yapılandırması | |
SECRET_KEY = os.environ.get("SECRET_KEY", "güvenli_bir_anahtar_oluşturun") | |
ALGORITHM = "HS256" | |
ACCESS_TOKEN_EXPIRE_MINUTES = 30 | |
# Şifre hashleme | |
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") | |
# Token doğrulama | |
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") | |
# Kullanıcı modeli | |
class User(BaseModel): | |
username: str | |
full_name: str | |
email: str | |
role: str # "admin", "doctor", "specialist" | |
disabled: bool = False | |
# Token modeli | |
class Token(BaseModel): | |
access_token: str | |
token_type: str | |
# Örnek kullanıcı veritabanı (gerçek uygulamada güvenli bir veritabanı kullanın) | |
fake_users_db = { | |
"doktor": { | |
"username": "doktor", | |
"full_name": "Doktor Kullanıcı", | |
"email": "doktor@example.com", | |
"hashed_password": pwd_context.hash("gizlisifre"), | |
"role": "doctor", | |
"disabled": False | |
}, | |
"bölüm_başkanı": { | |
"username": "bölüm_başkanı", | |
"full_name": "Bölüm Başkanı", | |
"email": "bolum@example.com", | |
"hashed_password": pwd_context.hash("gizlisifre2"), | |
"role": "specialist", | |
"disabled": False | |
} | |
} | |
# Uygulama | |
app = FastAPI( | |
title="Tıbbi Konuşma Transkripsiyon Servisi", | |
description="Doktor viziteleri sırasında konuşmaları transkribe eden ve diyarize eden API", | |
version="0.1.0" | |
) | |
# CORS ayarları - sadece güvenilir kaynaklar | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=["https://sizin-guvenli-web-siteniz.com"], # Üretimde belirli bir domain listesi kullanın | |
allow_credentials=True, | |
allow_methods=["GET", "POST"], | |
allow_headers=["Authorization", "Content-Type"], | |
) | |
# Yetkilendirme fonksiyonları | |
def verify_password(plain_password, hashed_password): | |
return pwd_context.verify(plain_password, hashed_password) | |
def get_user(db, username: str): | |
if username in db: | |
user_dict = db[username] | |
return User(**user_dict) | |
def authenticate_user(db, username: str, password: str): | |
user = get_user(db, username) | |
if not user: | |
return False | |
if not verify_password(password, db[username]["hashed_password"]): | |
return False | |
return user | |
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): | |
to_encode = data.copy() | |
if expires_delta: | |
expire = datetime.utcnow() + expires_delta | |
else: | |
expire = datetime.utcnow() + timedelta(minutes=15) | |
to_encode.update({"exp": expire}) | |
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) | |
return encoded_jwt | |
async def get_current_user(token: str = Depends(oauth2_scheme)): | |
credentials_exception = HTTPException( | |
status_code=status.HTTP_401_UNAUTHORIZED, | |
detail="Geçersiz kimlik bilgileri", | |
headers={"WWW-Authenticate": "Bearer"}, | |
) | |
try: | |
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) | |
username: str = payload.get("sub") | |
if username is None: | |
raise credentials_exception | |
except JWTError: | |
raise credentials_exception | |
user = get_user(fake_users_db, username) | |
if user is None: | |
raise credentials_exception | |
return user | |
async def get_current_active_user(current_user: User = Depends(get_current_user)): | |
if current_user.disabled: | |
raise HTTPException(status_code=400, detail="Inactive user") | |
return current_user | |
# Doktor yetkisi kontrolü | |
def doctor_required(current_user: User = Depends(get_current_active_user)): | |
if current_user.role not in ["doctor", "specialist"]: | |
raise HTTPException( | |
status_code=status.HTTP_403_FORBIDDEN, | |
detail="Bu işlem için doktor yetkisi gereklidir" | |
) | |
return current_user | |
# Token endpoint | |
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()): | |
user = authenticate_user(fake_users_db, form_data.username, form_data.password) | |
if not user: | |
raise HTTPException( | |
status_code=status.HTTP_401_UNAUTHORIZED, | |
detail="Kullanıcı adı veya şifre hatalı", | |
headers={"WWW-Authenticate": "Bearer"}, | |
) | |
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) | |
access_token = create_access_token( | |
data={"sub": user.username}, expires_delta=access_token_expires | |
) | |
return {"access_token": access_token, "token_type": "bearer"} | |
# Türkçe dil desteği yapılandırması | |
app.state.asr_config = { | |
"language": "tr", | |
"model": "whisper-large-v3", | |
"domain": "medical", | |
# Güvenlik ayarları | |
"anonymize_data": True # Varsayılan olarak veri anonimleştirme aktif | |
} | |
# Router'ı ekle - doktor yetkisi gerektir | |
app.include_router(router, prefix="/api", dependencies=[Depends(doctor_required)]) | |