Merge pull request #1920 from hotlcc/develop-20240417-用户配置

新增用户配置相关能力和接口
This commit is contained in:
jxxghp 2024-04-23 09:57:55 +08:00 committed by GitHub
commit 0cbe8f5cdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 163 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(username=current_user.name, key=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(username=current_user.name, key=key, value=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)
# 用户名
username = Column(String, index=True)
# 配置键
key = Column(String)
# 值
value = Column(String, nullable=True)
__table_args__ = (
# 用户名和配置键联合唯一
UniqueConstraint('username', 'key'),
Index('ix_userconfig_username_key', 'username', 'key'),
)
@staticmethod
@db_query
def get_by_key(db: Session, username: str, key: str):
return db.query(UserConfig) \
.filter(UserConfig.username == username) \
.filter(UserConfig.key == key) \
.first()
@db_update
def delete_by_key(self, db: Session, username: str, key: str):
userconfig = self.get_by_key(db=db, username=username, key=key)
if userconfig:
userconfig.delete(db=db, rid=userconfig.id)
return True

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

@ -0,0 +1,96 @@
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[str, Dict[str, Any]] = {}
def __init__(self):
"""
加载配置到内存
"""
super().__init__()
for item in UserConfig.list(self._db):
value = json.loads(item.value) if ObjectUtils.is_obj(item.value) else item.value
self.__set_config_cache(username=item.username, key=item.key, value=value)
def set(self, username: str, key: Union[str, UserConfigKey], value: Any):
"""
设置用户配置
"""
if isinstance(key, UserConfigKey):
key = key.value
# 更新内存
self.__set_config_cache(username=username, key=key, value=value)
# 写入数据库
if ObjectUtils.is_obj(value):
value = json.dumps(value)
elif value is None:
value = ''
conf = UserConfig.get_by_key(db=self._db, username=username, key=key)
if conf:
if value:
conf.update(self._db, {"value": value})
else:
conf.delete(self._db, conf.id)
else:
conf = UserConfig(username=username, key=key, value=value)
conf.create(self._db)
def get(self, username: str, key: Union[str, UserConfigKey] = None) -> Any:
"""
获取用户配置
"""
if not username:
return self.__USERCONF
if isinstance(key, UserConfigKey):
key = key.value
if not key:
return self.__get_config_caches(username=username)
return self.__get_config_cache(username=username, key=key)
def __del__(self):
if self._db:
self._db.close()
def __set_config_cache(self, username: str, key: str, value: Any):
"""
设置配置缓存
"""
if not username or not key:
return
cache = self.__USERCONF
if not cache:
cache = {}
user_cache = cache.get(username)
if not user_cache:
user_cache = {}
cache[username] = user_cache
user_cache[key] = value
self.__USERCONF = cache
def __get_config_caches(self, username: str) -> Dict[str, Any]:
"""
获取配置缓存
"""
if not username or not self.__USERCONF:
return None
return self.__USERCONF.get(username)
def __get_config_cache(self, username: str, key: str) -> Any:
"""
获取配置缓存
"""
if not username or not key or not self.__USERCONF:
return None
user_cache = self.__get_config_caches(username)
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"