diff --git a/app/api/endpoints/login.py b/app/api/endpoints/login.py index ce4f5525..cd5188f0 100644 --- a/app/api/endpoints/login.py +++ b/app/api/endpoints/login.py @@ -23,7 +23,7 @@ async def login_access_token( """ user = User.authenticate( db=db, - email=form_data.username, + name=form_data.username, password=form_data.password ) if not user: diff --git a/app/api/endpoints/plugin.py b/app/api/endpoints/plugin.py index d83707f4..8b8eae5b 100644 --- a/app/api/endpoints/plugin.py +++ b/app/api/endpoints/plugin.py @@ -1,28 +1,32 @@ -from typing import Any +from typing import Any, List from fastapi import APIRouter, Depends from app import schemas from app.core.plugin import PluginManager 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.schemas.types import SystemConfigKey router = APIRouter() -@router.get("/", summary="运行插件方法", response_model=schemas.Response) -@router.post("/", summary="运行插件方法", response_model=schemas.Response) -async def run_plugin_method(plugin_id: str, method: str, - _: User = Depends(get_current_active_user), - *args, - **kwargs) -> Any: +@router.get("/", summary="所有插件", response_model=List[schemas.Plugin]) +async def all_plugins(_: User = Depends(get_current_active_user)) -> Any: """ - 运行插件方法 + 查询所有插件清单 """ - return PluginManager().run_plugin_method(pid=plugin_id, - method=method, - *args, - **kwargs) + return PluginManager().get_plugin_apps() + + +@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 for api in PluginManager().get_plugin_apis(): diff --git a/app/api/endpoints/user.py b/app/api/endpoints/user.py index fca30e7f..92b0fe80 100644 --- a/app/api/endpoints/user.py +++ b/app/api/endpoints/user.py @@ -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: raise HTTPException( 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: raise HTTPException( 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: raise HTTPException( status_code=404, detail="用户不存在", ) - user.delete_by_email(db, user_in.email) + user.delete_by_name(db, user_in.name) return schemas.Response(success=True) diff --git a/app/core/plugin.py b/app/core/plugin.py index 775a570d..cafc1a80 100644 --- a/app/core/plugin.py +++ b/app/core/plugin.py @@ -4,6 +4,7 @@ from typing import List, Any, Dict from app.db.systemconfig_oper import SystemConfigOper from app.helper.module import ModuleHelper from app.log import logger +from app.schemas.types import SystemConfigKey from app.utils.object import ObjectUtils from app.utils.singleton import Singleton @@ -132,3 +133,46 @@ class PluginManager(metaclass=Singleton): if not hasattr(self._running_plugins[pid], method): return None 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 diff --git a/app/db/init.py b/app/db/init.py index 2823847a..bea477b4 100644 --- a/app/db/init.py +++ b/app/db/init.py @@ -23,11 +23,10 @@ def init_db(): Base.metadata.create_all(bind=Engine) # 初始化超级管理员 _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: user = User( - full_name="Admin", - email=settings.SUPERUSER, + name=settings.SUPERUSER, hashed_password=get_password_hash(settings.SUPERUSER_PASSWORD), is_superuser=True, ) diff --git a/app/db/models/user.py b/app/db/models/user.py index 686e55c5..f2d40683 100644 --- a/app/db/models/user.py +++ b/app/db/models/user.py @@ -10,15 +10,16 @@ class User(Base): 用户表 """ id = Column(Integer, Sequence('id'), primary_key=True, index=True) - full_name = Column(String, index=True) - email = Column(String, unique=True, index=True, nullable=False) + name = Column(String, index=True, nullable=False) + email = Column(String, unique=True, index=True) hashed_password = Column(String, nullable=False) is_active = Column(Boolean(), default=True) is_superuser = Column(Boolean(), default=False) + avatar = Column(String) @staticmethod - def authenticate(db: Session, email: str, password: str): - user = db.query(User).filter(User.email == email).first() + def authenticate(db: Session, name: str, password: str): + user = db.query(User).filter(User.name == name).first() if not user: return None if not verify_password(password, str(user.hashed_password)): @@ -26,9 +27,9 @@ class User(Base): return user @staticmethod - def get_by_email(db: Session, email: str): - return db.query(User).filter(User.email == email).first() + def get_by_name(db: Session, name: str): + return db.query(User).filter(User.name == name).first() @staticmethod - def delete_by_email(db: Session, email: str): - return db.query(User).filter(User.email == email).delete() + def delete_by_name(db: Session, name: str): + return db.query(User).filter(User.name == name).delete() diff --git a/app/plugins/autosignin/__init__.py b/app/plugins/autosignin/__init__.py index 3a268ac4..cd21a182 100644 --- a/app/plugins/autosignin/__init__.py +++ b/app/plugins/autosignin/__init__.py @@ -29,7 +29,23 @@ class AutoSignIn(_PluginBase): # 插件名称 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 diff --git a/app/plugins/sitestatistic/__init__.py b/app/plugins/sitestatistic/__init__.py index ef84b72c..96e223ea 100644 --- a/app/plugins/sitestatistic/__init__.py +++ b/app/plugins/sitestatistic/__init__.py @@ -31,6 +31,29 @@ lock = Lock() 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 _scheduler: BackgroundScheduler = None _MAX_CONCURRENCY: int = 10 diff --git a/app/schemas/__init__.py b/app/schemas/__init__.py index 4417369a..86058a17 100644 --- a/app/schemas/__init__.py +++ b/app/schemas/__init__.py @@ -5,3 +5,4 @@ from .site import * from .subscribe import * from .context import * from .servarr import * +from .plugin import * diff --git a/app/schemas/plugin.py b/app/schemas/plugin.py new file mode 100644 index 00000000..cf23d66e --- /dev/null +++ b/app/schemas/plugin.py @@ -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 diff --git a/app/schemas/user.py b/app/schemas/user.py index 8815d3da..26b43540 100644 --- a/app/schemas/user.py +++ b/app/schemas/user.py @@ -5,22 +5,23 @@ from pydantic import BaseModel # Shared properties class UserBase(BaseModel): + name: str email: Optional[str] = None is_active: Optional[bool] = True is_superuser: bool = False - full_name: Optional[str] = None + avatar: Optional[str] = None # Properties to receive via API on creation class UserCreate(UserBase): - full_name: str - email: str + name: str + email: Optional[str] = None password: str # Properties to receive via API on update class UserUpdate(UserBase): - full_name: str + name: str password: Optional[str] = None @@ -33,8 +34,8 @@ class UserInDBBase(UserBase): # Additional properties to return via API class User(UserInDBBase): - full_name: str - email: str + name: str + email: Optional[str] = None # Additional properties stored in DB