feat(admin): add user-level direct permission system and enhance activity tracking

Features:
- Add user_permissions table for direct user-to-permission grants (ops:user-ops)
- Merge role_permissions + user_permissions in auth chain (login, middleware, getCurrentUser)
- Add getUserQueryScope support for USER role with ops:user-ops (cross-tenant access)
- Unify cross-tenant operation checks via getUserQueryScope (remove hardcoded SUPER_ADMIN checks)
- Add 3 new API endpoints: GET/PUT /:id/permissions, GET /options/permissions
- Support ops:user-ops as alternative permission on all user/tenant management routes
- Frontend: add user-ops permission toggle on UserFormPage and UserDetailPage
- Enhance DC module activity tracking (StreamAIController, SessionController, QuickActionController)
- Fix DC AIController user ID extraction and feature name consistency
- Add verify-activity-tracking.ts validation script
- Update deployment checklist and admin module documentation

DB Migration: 20260309_add_user_permissions_table

Made-with: Cursor
This commit is contained in:
2026-03-10 09:02:35 +08:00
parent 971e903acf
commit 097e7920ab
19 changed files with 693 additions and 87 deletions

View File

@@ -19,6 +19,7 @@ import { sessionService } from '../services/SessionService.js';
import { dataProcessService } from '../services/DataProcessService.js';
import { jobQueue } from '../../../../common/jobs/index.js';
import * as xlsx from 'xlsx';
import { activityService } from '../../../../common/services/activity.service.js';
/**
* 获取用户ID从JWT Token中获取
@@ -92,6 +93,23 @@ export class SessionController {
logger.info(`[SessionController] Session创建成功: ${sessionResult.id}, jobId: ${sessionResult.jobId}`);
// 埋点DC 上传数据文件
try {
const user = (request as any).user;
if (user) {
activityService.log(
user.tenantId,
user.tenantName || null,
user.userId || user.id,
user.name || null,
'DC',
'智能数据清洗',
'USE',
`upload:${fileName}, session:${sessionResult.id}`,
);
}
} catch { /* 埋点失败不影响主业务 */ }
// 6. 返回Session信息 + jobId用于前端轮询
return reply.code(201).send({
success: true,