新增空闲锁屏、修复401等问题,新增文件版本管理、共享库等占位符

This commit is contained in:
Cheng Zhou
2026-01-13 13:59:07 +08:00
parent b3cd8e03f2
commit 0c7c03069a
21 changed files with 829 additions and 40 deletions
+2
View File
@@ -12,6 +12,8 @@ class Settings(BaseSettings):
ENV: Literal["development", "production", "test"] = "development"
JWT_SECRET_KEY: str = "dev-secret"
JWT_EXPIRE_MINUTES: int = 60
JWT_EXTEND_GRACE_SECONDS: int = 120
ABSOLUTE_SESSION_MAX_HOURS: int = 8
@lru_cache
+7 -2
View File
@@ -33,12 +33,17 @@ async def get_current_user(
) from exc
user = await user_crud.get_by_id(db, uuid.UUID(str(token_data.sub)))
if not user or not user.is_active:
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="账号不存在或已停用",
detail="账号不存在",
headers={"WWW-Authenticate": "Bearer"},
)
if not user.is_active:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="账号已停用",
)
return user
+34 -5
View File
@@ -14,11 +14,23 @@ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login", scheme_name="Bearer")
def create_access_token(*, user_id: str, role: str, expires_minutes: Optional[int] = None) -> str:
expire = datetime.now(timezone.utc) + timedelta(
minutes=expires_minutes or settings.JWT_EXPIRE_MINUTES
)
to_encode: Dict[str, Any] = {"sub": user_id, "role": role, "exp": expire}
def create_access_token(
*,
user_id: str,
role: str,
expires_minutes: Optional[int] = None,
session_start: Optional[datetime] = None,
) -> str:
now = datetime.now(timezone.utc)
expire = now + timedelta(minutes=expires_minutes or settings.JWT_EXPIRE_MINUTES)
session_start_time = session_start or now
to_encode: Dict[str, Any] = {
"sub": user_id,
"role": role,
"exp": expire,
"iat": int(now.timestamp()),
"orig_iat": int(session_start_time.timestamp()),
}
return jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=ALGORITHM)
@@ -34,6 +46,23 @@ def decode_token(token: str) -> Dict[str, Any]:
return payload
def decode_token_allow_expired(token: str) -> Dict[str, Any]:
try:
payload = jwt.decode(
token,
settings.JWT_SECRET_KEY,
algorithms=[ALGORITHM],
options={"verify_exp": False},
)
except JWTError as exc:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="无法验证登录凭据",
headers={"WWW-Authenticate": "Bearer"},
) from exc
return payload
def hash_password(plain_password: str) -> str:
return pwd_context.hash(plain_password)