feat(admin): Complete tenant management and module access control system
Major Features: - Tenant management CRUD (list, create, edit, delete, module configuration) - Dynamic module management system (modules table with 8 modules) - Multi-tenant module permission merging (ModuleService) - Module access control middleware (requireModule) - User module permission API (GET /api/v1/auth/me/modules) - Frontend module permission filtering (HomePage + TopNavigation) Module Integration: - RVW module integrated with PromptService (editorial + methodology) - All modules (RVW/PKB/ASL/DC) added authenticate + requireModule middleware - Fixed ReviewTask foreign key constraint (cross-schema issue) - Removed all MOCK_USER_ID, unified to request.user?.userId Prompt Management Enhancements: - Module names displayed in Chinese (RVW -> 智能审稿) - Enhanced version history with view content and rollback features - List page shows both activeVersion and draftVersion columns Database Changes: - Added platform_schema.modules table - Modified tenant_modules table (added index and UUID) - Removed ReviewTask foreign key to public.users (cross-schema fix) - Seeded 8 modules: RVW, PKB, ASL, DC, IIT, AIA, SSA, ST Documentation Updates: - Updated ADMIN module development status - Updated TODO checklist (89% progress) - Updated Prompt management plan (Phase 3.5.5 completed) - Added module authentication specification Files Changed: 80+ Status: All features tested and verified locally Next: User management module development
This commit is contained in:
@@ -56,21 +56,43 @@ export async function listPrompts(
|
||||
|
||||
const templates = await promptService.listTemplates(module);
|
||||
|
||||
// 转换为 API 响应格式
|
||||
const result = templates.map(t => ({
|
||||
id: t.id,
|
||||
code: t.code,
|
||||
name: t.name,
|
||||
module: t.module,
|
||||
description: t.description,
|
||||
variables: t.variables,
|
||||
latestVersion: t.versions[0] ? {
|
||||
version: t.versions[0].version,
|
||||
status: t.versions[0].status,
|
||||
createdAt: t.versions[0].created_at,
|
||||
} : null,
|
||||
updatedAt: t.updated_at,
|
||||
}));
|
||||
// 转换为 API 响应格式,分别返回 ACTIVE 和 DRAFT 版本
|
||||
const result = templates.map(t => {
|
||||
const activeVersion = t.versions.find(v => v.status === 'ACTIVE');
|
||||
const draftVersion = t.versions.find(v => v.status === 'DRAFT');
|
||||
|
||||
// 调试日志
|
||||
console.log(`[PromptController] ${t.code} 版本数量: ${t.versions.length}`);
|
||||
console.log(` - ACTIVE: ${activeVersion ? 'v' + activeVersion.version : '无'}`);
|
||||
console.log(` - DRAFT: ${draftVersion ? 'v' + draftVersion.version : '无'}`);
|
||||
|
||||
return {
|
||||
id: t.id,
|
||||
code: t.code,
|
||||
name: t.name,
|
||||
module: t.module,
|
||||
description: t.description,
|
||||
variables: t.variables,
|
||||
activeVersion: activeVersion ? {
|
||||
version: activeVersion.version,
|
||||
status: activeVersion.status,
|
||||
createdAt: activeVersion.created_at,
|
||||
} : null,
|
||||
draftVersion: draftVersion ? {
|
||||
version: draftVersion.version,
|
||||
status: draftVersion.status,
|
||||
createdAt: draftVersion.created_at,
|
||||
} : null,
|
||||
latestVersion: t.versions[0] ? {
|
||||
version: t.versions[0].version,
|
||||
status: t.versions[0].status,
|
||||
createdAt: t.versions[0].created_at,
|
||||
} : null,
|
||||
updatedAt: t.updated_at,
|
||||
};
|
||||
});
|
||||
|
||||
console.log('[PromptController] 返回数据示例:', JSON.stringify(result[0], null, 2));
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
@@ -155,7 +177,7 @@ export async function saveDraft(
|
||||
try {
|
||||
const { code } = request.params;
|
||||
const { content, modelConfig, changelog } = request.body;
|
||||
const userId = (request as any).user?.id;
|
||||
const userId = (request as any).user?.userId;
|
||||
|
||||
const promptService = getPromptService(prisma);
|
||||
|
||||
@@ -202,7 +224,7 @@ export async function publishPrompt(
|
||||
) {
|
||||
try {
|
||||
const { code } = request.params;
|
||||
const userId = (request as any).user?.id;
|
||||
const userId = (request as any).user?.userId;
|
||||
|
||||
const promptService = getPromptService(prisma);
|
||||
|
||||
@@ -238,7 +260,7 @@ export async function rollbackPrompt(
|
||||
try {
|
||||
const { code } = request.params;
|
||||
const { version } = request.body;
|
||||
const userId = (request as any).user?.id;
|
||||
const userId = (request as any).user?.userId;
|
||||
|
||||
const promptService = getPromptService(prisma);
|
||||
|
||||
@@ -273,7 +295,7 @@ export async function setDebugMode(
|
||||
) {
|
||||
try {
|
||||
const { modules, enabled } = request.body;
|
||||
const userId = (request as any).user?.id;
|
||||
const userId = (request as any).user?.userId;
|
||||
|
||||
if (!userId) {
|
||||
return reply.status(401).send({
|
||||
@@ -317,7 +339,7 @@ export async function getDebugStatus(
|
||||
reply: FastifyReply
|
||||
) {
|
||||
try {
|
||||
const userId = (request as any).user?.id;
|
||||
const userId = (request as any).user?.userId;
|
||||
|
||||
if (!userId) {
|
||||
return reply.status(401).send({
|
||||
@@ -416,3 +438,4 @@ export async function invalidateCache(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user