新增用户配置相关能力和接口

This commit is contained in:
Allen 2024-04-18 12:33:35 +08:00
parent 73a3a8cf94
commit 666d6eb048
5 changed files with 169 additions and 1 deletions

View File

@ -1,6 +1,6 @@
import base64
import re
from typing import Any, List
from typing import Any, List, Union
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
from sqlalchemy.orm import Session
@ -10,6 +10,7 @@ from app.core.security import get_password_hash
from app.db import get_db
from app.db.models.user import User
from app.db.userauth import get_current_active_superuser, get_current_active_user
from app.db.userconfig_oper import UserConfigOper
from app.utils.otp import OtpUtils
router = APIRouter()
@ -182,3 +183,23 @@ def read_user_by_id(
detail="用户权限不足"
)
return user
@router.get("/config/{key}", summary="查询用户配置", response_model=schemas.Response)
def get_config(key: str,
current_user: User = Depends(get_current_active_user)):
"""
查询用户配置
"""
value = UserConfigOper().get(current_user.id, key)
return schemas.Response(success=True, data={
"value": value
})
@router.post("/config/{key}", summary="更新用户配置", response_model=schemas.Response)
def set_config(key: str, value: Union[list, dict, bool, int, str] = None,
current_user: User = Depends(get_current_active_user)):
"""
更新用户配置
"""
UserConfigOper().set(current_user.id, key, value)
return schemas.Response(success=True)

View File

@ -7,3 +7,4 @@ from .subscribe import Subscribe
from .systemconfig import SystemConfig
from .transferhistory import TransferHistory
from .user import User
from .userconfig import UserConfig

View File

@ -0,0 +1,38 @@
from sqlalchemy import Column, Integer, String, Sequence, UniqueConstraint, Index
from sqlalchemy.orm import Session
from app.db import db_query, db_update, Base
class UserConfig(Base):
"""
用户配置表
"""
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
# 用户ID
user_id = Column(Integer, index=True)
# 配置键
key = Column(String)
# 值
value = Column(String, nullable=True)
__table_args__ = (
# 用户ID和配置键联合唯一
UniqueConstraint('user_id', 'key'),
Index('ix_userconfig_userid_key', 'user_id', 'key'),
)
@staticmethod
@db_query
def get_by_key(db: Session, user_id: int, key: str):
return db.query(UserConfig) \
.filter(UserConfig.user_id == user_id) \
.filter(UserConfig.key == key) \
.first()
@db_update
def delete_by_key(self, db: Session, user_id: int, key: str):
userconfig = self.get_by_key(db, user_id, key)
if userconfig:
userconfig.delete(db, userconfig.id)
return True

102
app/db/userconfig_oper.py Normal file
View File

@ -0,0 +1,102 @@
import json
from typing import Any, Union, Dict
from app.db import DbOper
from app.db.models.userconfig import UserConfig
from app.schemas.types import UserConfigKey
from app.utils.object import ObjectUtils
from app.utils.singleton import Singleton
class UserConfigOper(DbOper, metaclass=Singleton):
# 配置缓存
__USERCONF: Dict[int, Dict[str, Any]] = {}
def __init__(self):
"""
加载配置到内存
"""
super().__init__()
for item in UserConfig.list(self._db):
self.__set_config_cache(user_id=item.user_id, key=item.key, value=item.value)
def set(self, user_id: int, key: Union[str, UserConfigKey], value: Any):
"""
设置用户配置
"""
if isinstance(key, UserConfigKey):
key = key.value
# 更新内存
self.__set_config_cache(user_id=user_id, key=key, value=value)
# 写入数据库
if ObjectUtils.is_obj(value):
value = json.dumps(value)
elif value is None:
value = ''
conf = UserConfig.get_by_key(self._db, user_id, key)
if conf:
if value:
conf.update(self._db, {"value": value})
else:
conf.delete(self._db, conf.id)
else:
conf = UserConfig(user_id=user_id, key=key, value=value)
conf.create(self._db)
def get(self, user_id: int, key: Union[str, UserConfigKey] = None) -> Any:
"""
获取用户配置
"""
if not user_id:
return self.__USERCONF
if isinstance(key, UserConfigKey):
key = key.value
if not key:
return self.__get_config_caches(user_id=user_id)
return self.__get_config_cache(user_id=user_id, key=key)
def __del__(self):
if self._db:
self._db.close()
def __set_config_cache(self, user_id: int, key: str, value: Any):
"""
设置配置缓存
"""
if not user_id or not key:
return
cache = self.__USERCONF
if not cache:
cache = {}
user_cache = cache.get(user_id)
if not user_cache:
user_cache = {}
cache[user_id] = user_cache
if ObjectUtils.is_obj(value):
user_cache[key] = json.loads(value)
else:
user_cache[key] = value
self.__USERCONF = cache
def __get_config_caches(self, user_id: int) -> Dict[str, Any]:
"""
获取配置缓存
"""
if not user_id:
return None
if not self.__USERCONF:
return None
return self.__USERCONF.get(user_id)
def __get_config_cache(self, user_id: int, key: str) -> Any:
"""
获取配置缓存
"""
if not user_id or not key:
return None
if not self.__USERCONF:
return None
user_cache = self.__USERCONF.get(user_id)
if not user_cache:
return None
return user_cache.get(key)

View File

@ -124,3 +124,9 @@ class MessageChannel(Enum):
SynologyChat = "SynologyChat"
VoceChat = "VoceChat"
Web = "Web"
# 用户配置Key字典
class UserConfigKey(Enum):
# 监控面板
Dashboard = "Dashboard"