Initial commit: SenSu Alpha 0.2.0

- 13-service async plugin framework
- Textual TUI with CLI fallback
- Plugin hot-reload + permission system
- Web management panel (aiohttp)
- Bridge-based inter-module communication
- 10 regression tests

Fixes applied:
- PBKDF2-SHA256 auth (was plain SHA256)
- Auth bypass removed (was allow-all on fail)
- Bare excepts replaced with logged errors
- CatFramework/DreamSu -> SenSu naming unified
- ServiceManager: health checks + startup_order
- Env var credentials (SENSU_ADMIN_PASSWORD etc)
This commit is contained in:
2026-06-10 12:27:14 +08:00
commit e6875f0b4b
78 changed files with 14843 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
from aiohttp import web
from ..utils.auth import panel_auth
logger = logging.getLogger(__name__)
def setup_routes(app, prefix=''):
app.router.add_get(f'{prefix}/api/plugins', panel_auth(list_plugins))
app.router.add_post(f'{prefix}/api/plugins/{{name}}/{{action}}', panel_auth(manage_plugin))
app.router.add_get(f'{prefix}/api/plugins/{{name}}/perms', panel_auth(get_perms))
app.router.add_post(f'{prefix}/api/plugins/{{name}}/perms', panel_auth(set_perms))
async def list_plugins(req):
sm = req.app.get('service_manager')
if not sm:
return web.json_response({"error": "Service Manager 未初始化"}, status=503)
ps = sm.get_service("plugin")
if not ps:
return web.json_response({"plugins": []})
data = []
for name, info in ps.plugin_info.items():
data.append({
"name": name,
"version": getattr(info, 'version', '?'),
"running": name in ps.plugins,
"enabled": True
})
return web.json_response({"plugins": data})
async def manage_plugin(req):
sm = req.app.get('service_manager')
if not sm: return web.json_response({"error": "SM Missing"}, 503)
name = req.match_info['name']
action = req.match_info['action']
ps = sm.get_service("plugin")
if not ps: return web.json_response({"error": "Plugin Service Missing"}, 503)
try:
if action in ('disable', 'unload'):
await ps.unload_plugin(name)
elif action == 'enable':
await ps.load_plugin(name)
elif action == 'reload':
await ps.unload_plugin(name)
await ps.load_plugin(name)
return web.json_response({"success": True, "msg": "操作成功"})
except Exception as e:
logger.error(f"插件操作失败: {e}")
return web.json_response({"success": False, "error": str(e)})
async def get_perms(req):
return web.json_response({"plugin": req.match_info['name'], "permissions": ["read", "write"]})
async def set_perms(req):
return web.json_response({"success": True})