fix 用户调整为使用名称做主键
add 插件API
This commit is contained in:
parent
df0ba221f9
commit
c7f897fdcd
@ -23,7 +23,7 @@ async def login_access_token(
|
|||||||
"""
|
"""
|
||||||
user = User.authenticate(
|
user = User.authenticate(
|
||||||
db=db,
|
db=db,
|
||||||
email=form_data.username,
|
name=form_data.username,
|
||||||
password=form_data.password
|
password=form_data.password
|
||||||
)
|
)
|
||||||
if not user:
|
if not user:
|
||||||
|
@ -1,28 +1,32 @@
|
|||||||
from typing import Any
|
from typing import Any, List
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends
|
||||||
|
|
||||||
from app import schemas
|
from app import schemas
|
||||||
from app.core.plugin import PluginManager
|
from app.core.plugin import PluginManager
|
||||||
from app.db.models.user import User
|
from app.db.models.user import User
|
||||||
|
from app.db.systemconfig_oper import SystemConfigOper
|
||||||
from app.db.userauth import get_current_active_user
|
from app.db.userauth import get_current_active_user
|
||||||
|
from app.schemas.types import SystemConfigKey
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", summary="运行插件方法", response_model=schemas.Response)
|
@router.get("/", summary="所有插件", response_model=List[schemas.Plugin])
|
||||||
@router.post("/", summary="运行插件方法", response_model=schemas.Response)
|
async def all_plugins(_: User = Depends(get_current_active_user)) -> Any:
|
||||||
async def run_plugin_method(plugin_id: str, method: str,
|
|
||||||
_: User = Depends(get_current_active_user),
|
|
||||||
*args,
|
|
||||||
**kwargs) -> Any:
|
|
||||||
"""
|
"""
|
||||||
运行插件方法
|
查询所有插件清单
|
||||||
"""
|
"""
|
||||||
return PluginManager().run_plugin_method(pid=plugin_id,
|
return PluginManager().get_plugin_apps()
|
||||||
method=method,
|
|
||||||
*args,
|
|
||||||
**kwargs)
|
@router.get("/installed", summary="已安装插件", response_model=List[str])
|
||||||
|
async def installed_plugins(_: User = Depends(get_current_active_user)) -> Any:
|
||||||
|
"""
|
||||||
|
查询用户已安装插件清单
|
||||||
|
"""
|
||||||
|
return SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
|
||||||
|
|
||||||
|
|
||||||
# 注册插件API
|
# 注册插件API
|
||||||
for api in PluginManager().get_plugin_apis():
|
for api in PluginManager().get_plugin_apis():
|
||||||
|
@ -34,7 +34,7 @@ async def create_user(
|
|||||||
"""
|
"""
|
||||||
新增用户
|
新增用户
|
||||||
"""
|
"""
|
||||||
user = current_user.get_by_email(db, email=user_in.email)
|
user = current_user.get_by_name(db, name=user_in.name)
|
||||||
if user:
|
if user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=400,
|
status_code=400,
|
||||||
@ -59,7 +59,7 @@ async def update_user(
|
|||||||
"""
|
"""
|
||||||
更新用户
|
更新用户
|
||||||
"""
|
"""
|
||||||
user = current_user.get_by_email(db, email=user_in.email)
|
user = current_user.get_by_name(db, name=user_in.name)
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404,
|
status_code=404,
|
||||||
@ -83,13 +83,13 @@ async def delete_user(
|
|||||||
"""
|
"""
|
||||||
删除用户
|
删除用户
|
||||||
"""
|
"""
|
||||||
user = current_user.get_by_email(db, email=user_in.email)
|
user = current_user.get_by_name(db, name=user_in.name)
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404,
|
status_code=404,
|
||||||
detail="用户不存在",
|
detail="用户不存在",
|
||||||
)
|
)
|
||||||
user.delete_by_email(db, user_in.email)
|
user.delete_by_name(db, user_in.name)
|
||||||
return schemas.Response(success=True)
|
return schemas.Response(success=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ from typing import List, Any, Dict
|
|||||||
from app.db.systemconfig_oper import SystemConfigOper
|
from app.db.systemconfig_oper import SystemConfigOper
|
||||||
from app.helper.module import ModuleHelper
|
from app.helper.module import ModuleHelper
|
||||||
from app.log import logger
|
from app.log import logger
|
||||||
|
from app.schemas.types import SystemConfigKey
|
||||||
from app.utils.object import ObjectUtils
|
from app.utils.object import ObjectUtils
|
||||||
from app.utils.singleton import Singleton
|
from app.utils.singleton import Singleton
|
||||||
|
|
||||||
@ -132,3 +133,46 @@ class PluginManager(metaclass=Singleton):
|
|||||||
if not hasattr(self._running_plugins[pid], method):
|
if not hasattr(self._running_plugins[pid], method):
|
||||||
return None
|
return None
|
||||||
return getattr(self._running_plugins[pid], method)(*args, **kwargs)
|
return getattr(self._running_plugins[pid], method)(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_plugin_apps(self) -> List[dict]:
|
||||||
|
"""
|
||||||
|
获取所有插件信息
|
||||||
|
"""
|
||||||
|
# 返回值
|
||||||
|
all_confs = []
|
||||||
|
# 已安装插件
|
||||||
|
installed_apps = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or []
|
||||||
|
for pid, plugin in self._plugins.items():
|
||||||
|
# 基本属性
|
||||||
|
conf = {}
|
||||||
|
# ID
|
||||||
|
conf.update({"id": pid})
|
||||||
|
# 安装状态
|
||||||
|
if pid in installed_apps:
|
||||||
|
conf.update({"installed": True})
|
||||||
|
else:
|
||||||
|
conf.update({"installed": False})
|
||||||
|
# 名称
|
||||||
|
if hasattr(plugin, "plugin_name"):
|
||||||
|
conf.update({"name": plugin.plugin_name})
|
||||||
|
# 描述
|
||||||
|
if hasattr(plugin, "plugin_desc"):
|
||||||
|
conf.update({"desc": plugin.plugin_desc})
|
||||||
|
# 版本
|
||||||
|
if hasattr(plugin, "plugin_version"):
|
||||||
|
conf.update({"version": plugin.plugin_version})
|
||||||
|
# 图标
|
||||||
|
if hasattr(plugin, "plugin_icon"):
|
||||||
|
conf.update({"icon": plugin.plugin_icon})
|
||||||
|
# 主题色
|
||||||
|
if hasattr(plugin, "plugin_color"):
|
||||||
|
conf.update({"color": plugin.plugin_color})
|
||||||
|
# 作者
|
||||||
|
if hasattr(plugin, "plugin_author"):
|
||||||
|
conf.update({"author": plugin.plugin_author})
|
||||||
|
# 作者链接
|
||||||
|
if hasattr(plugin, "author_url"):
|
||||||
|
conf.update({"author_url": plugin.author_url})
|
||||||
|
# 汇总
|
||||||
|
all_confs.append(conf)
|
||||||
|
return all_confs
|
||||||
|
@ -23,11 +23,10 @@ def init_db():
|
|||||||
Base.metadata.create_all(bind=Engine)
|
Base.metadata.create_all(bind=Engine)
|
||||||
# 初始化超级管理员
|
# 初始化超级管理员
|
||||||
_db = SessionLocal()
|
_db = SessionLocal()
|
||||||
user = User.get_by_email(db=_db, email=settings.SUPERUSER)
|
user = User.get_by_name(db=_db, name=settings.SUPERUSER)
|
||||||
if not user:
|
if not user:
|
||||||
user = User(
|
user = User(
|
||||||
full_name="Admin",
|
name=settings.SUPERUSER,
|
||||||
email=settings.SUPERUSER,
|
|
||||||
hashed_password=get_password_hash(settings.SUPERUSER_PASSWORD),
|
hashed_password=get_password_hash(settings.SUPERUSER_PASSWORD),
|
||||||
is_superuser=True,
|
is_superuser=True,
|
||||||
)
|
)
|
||||||
|
@ -10,15 +10,16 @@ class User(Base):
|
|||||||
用户表
|
用户表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
||||||
full_name = Column(String, index=True)
|
name = Column(String, index=True, nullable=False)
|
||||||
email = Column(String, unique=True, index=True, nullable=False)
|
email = Column(String, unique=True, index=True)
|
||||||
hashed_password = Column(String, nullable=False)
|
hashed_password = Column(String, nullable=False)
|
||||||
is_active = Column(Boolean(), default=True)
|
is_active = Column(Boolean(), default=True)
|
||||||
is_superuser = Column(Boolean(), default=False)
|
is_superuser = Column(Boolean(), default=False)
|
||||||
|
avatar = Column(String)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def authenticate(db: Session, email: str, password: str):
|
def authenticate(db: Session, name: str, password: str):
|
||||||
user = db.query(User).filter(User.email == email).first()
|
user = db.query(User).filter(User.name == name).first()
|
||||||
if not user:
|
if not user:
|
||||||
return None
|
return None
|
||||||
if not verify_password(password, str(user.hashed_password)):
|
if not verify_password(password, str(user.hashed_password)):
|
||||||
@ -26,9 +27,9 @@ class User(Base):
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_by_email(db: Session, email: str):
|
def get_by_name(db: Session, name: str):
|
||||||
return db.query(User).filter(User.email == email).first()
|
return db.query(User).filter(User.name == name).first()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_by_email(db: Session, email: str):
|
def delete_by_name(db: Session, name: str):
|
||||||
return db.query(User).filter(User.email == email).delete()
|
return db.query(User).filter(User.name == name).delete()
|
||||||
|
@ -29,7 +29,23 @@ class AutoSignIn(_PluginBase):
|
|||||||
# 插件名称
|
# 插件名称
|
||||||
plugin_name = "站点自动签到"
|
plugin_name = "站点自动签到"
|
||||||
# 插件描述
|
# 插件描述
|
||||||
plugin_desc = "站点每日自动模拟登录或签到,避免长期未登录封号。"
|
plugin_desc = "站点每日自动模拟登录或签到。"
|
||||||
|
# 插件图标
|
||||||
|
plugin_icon = ""
|
||||||
|
# 主题色
|
||||||
|
plugin_color = ""
|
||||||
|
# 插件版本
|
||||||
|
plugin_version = "1.0"
|
||||||
|
# 插件作者
|
||||||
|
plugin_author = "thsrite"
|
||||||
|
# 作者主页
|
||||||
|
author_url = "https://github.com/thsrite"
|
||||||
|
# 插件配置项ID前缀
|
||||||
|
plugin_config_prefix = "autosignin_"
|
||||||
|
# 加载顺序
|
||||||
|
plugin_order = 0
|
||||||
|
# 可使用的用户级别
|
||||||
|
auth_level = 2
|
||||||
|
|
||||||
# 私有属性
|
# 私有属性
|
||||||
sites: SitesHelper = None
|
sites: SitesHelper = None
|
||||||
|
@ -31,6 +31,29 @@ lock = Lock()
|
|||||||
|
|
||||||
|
|
||||||
class SiteStatistic(_PluginBase):
|
class SiteStatistic(_PluginBase):
|
||||||
|
|
||||||
|
# 插件名称
|
||||||
|
plugin_name = "站点数据统计"
|
||||||
|
# 插件描述
|
||||||
|
plugin_desc = "统计和展示站点数据。"
|
||||||
|
# 插件图标
|
||||||
|
module_icon = ""
|
||||||
|
# 主题色
|
||||||
|
module_color = ""
|
||||||
|
# 插件版本
|
||||||
|
module_version = "1.0"
|
||||||
|
# 插件作者
|
||||||
|
module_author = "lightolly"
|
||||||
|
# 作者主页
|
||||||
|
author_url = "https://github.com/lightolly"
|
||||||
|
# 插件配置项ID前缀
|
||||||
|
module_config_prefix = "sitestatistic_"
|
||||||
|
# 加载顺序
|
||||||
|
module_order = 1
|
||||||
|
# 可使用的用户级别
|
||||||
|
auth_level = 2
|
||||||
|
|
||||||
|
# 私有属性
|
||||||
sites = None
|
sites = None
|
||||||
_scheduler: BackgroundScheduler = None
|
_scheduler: BackgroundScheduler = None
|
||||||
_MAX_CONCURRENCY: int = 10
|
_MAX_CONCURRENCY: int = 10
|
||||||
|
@ -5,3 +5,4 @@ from .site import *
|
|||||||
from .subscribe import *
|
from .subscribe import *
|
||||||
from .context import *
|
from .context import *
|
||||||
from .servarr import *
|
from .servarr import *
|
||||||
|
from .plugin import *
|
||||||
|
28
app/schemas/plugin.py
Normal file
28
app/schemas/plugin.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(BaseModel):
|
||||||
|
"""
|
||||||
|
插件信息
|
||||||
|
"""
|
||||||
|
id: str = None
|
||||||
|
# 插件名称
|
||||||
|
plugin_name: str = None
|
||||||
|
# 插件描述
|
||||||
|
plugin_desc: str = None
|
||||||
|
# 插件图标
|
||||||
|
module_icon: str = None
|
||||||
|
# 主题色
|
||||||
|
module_color: str = None
|
||||||
|
# 插件版本
|
||||||
|
module_version: str = None
|
||||||
|
# 插件作者
|
||||||
|
module_author: str = None
|
||||||
|
# 作者主页
|
||||||
|
author_url: str = None
|
||||||
|
# 插件配置项ID前缀
|
||||||
|
module_config_prefix: str = None
|
||||||
|
# 加载顺序
|
||||||
|
module_order: int = 0
|
||||||
|
# 可使用的用户级别
|
||||||
|
auth_level: int = 0
|
@ -5,22 +5,23 @@ from pydantic import BaseModel
|
|||||||
|
|
||||||
# Shared properties
|
# Shared properties
|
||||||
class UserBase(BaseModel):
|
class UserBase(BaseModel):
|
||||||
|
name: str
|
||||||
email: Optional[str] = None
|
email: Optional[str] = None
|
||||||
is_active: Optional[bool] = True
|
is_active: Optional[bool] = True
|
||||||
is_superuser: bool = False
|
is_superuser: bool = False
|
||||||
full_name: Optional[str] = None
|
avatar: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
# Properties to receive via API on creation
|
# Properties to receive via API on creation
|
||||||
class UserCreate(UserBase):
|
class UserCreate(UserBase):
|
||||||
full_name: str
|
name: str
|
||||||
email: str
|
email: Optional[str] = None
|
||||||
password: str
|
password: str
|
||||||
|
|
||||||
|
|
||||||
# Properties to receive via API on update
|
# Properties to receive via API on update
|
||||||
class UserUpdate(UserBase):
|
class UserUpdate(UserBase):
|
||||||
full_name: str
|
name: str
|
||||||
password: Optional[str] = None
|
password: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
@ -33,8 +34,8 @@ class UserInDBBase(UserBase):
|
|||||||
|
|
||||||
# Additional properties to return via API
|
# Additional properties to return via API
|
||||||
class User(UserInDBBase):
|
class User(UserInDBBase):
|
||||||
full_name: str
|
name: str
|
||||||
email: str
|
email: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
# Additional properties stored in DB
|
# Additional properties stored in DB
|
||||||
|
Loading…
x
Reference in New Issue
Block a user