fix: 全面优化安全、性能和代码质量

P0: 环境变量校验/事务保护/RBAC权限
P1: 花名册分页/密码重置验证码/ErrorBoundary/N+1查询优化
P2: 导出限制/自定义错误类/body大小限制/代码去重
P3: 自定义确认弹窗替换window.confirm
This commit is contained in:
freedakgmail
2026-07-24 22:28:58 +08:00
parent 9ec21fedea
commit 5c12f28ac7
23 changed files with 634 additions and 366 deletions
+7 -6
View File
@@ -2,6 +2,7 @@ import { Router } from 'express'
import bcrypt from 'bcryptjs'
import prisma from '../lib/prisma'
import { authMiddleware, AuthRequest } from '../middleware/auth'
import { requireAdmin } from '../middleware/rbac'
import { z } from 'zod'
const router = Router()
@@ -35,7 +36,7 @@ router.get('/org', async (req: AuthRequest, res, next) => {
})
// 更新企业信息
router.put('/org', async (req: AuthRequest, res, next) => {
router.put('/org', requireAdmin, async (req: AuthRequest, res, next) => {
try {
const { name, payrollFrequency } = req.body as { name?: string; payrollFrequency?: number }
const updateData: any = {}
@@ -67,7 +68,7 @@ router.get('/users', async (req: AuthRequest, res, next) => {
})
// 添加用户
router.post('/users', async (req: AuthRequest, res, next) => {
router.post('/users', requireAdmin, async (req: AuthRequest, res, next) => {
try {
const data = createUserSchema.parse(req.body)
const existing = await prisma.user.findFirst({ where: { phone: data.phone, orgId: req.user!.orgId } })
@@ -92,7 +93,7 @@ router.post('/users', async (req: AuthRequest, res, next) => {
})
// 更新用户
router.put('/users/:id', async (req: AuthRequest, res, next) => {
router.put('/users/:id', requireAdmin, async (req: AuthRequest, res, next) => {
try {
const data = updateUserSchema.parse(req.body)
const user = await prisma.user.update({
@@ -107,7 +108,7 @@ router.put('/users/:id', async (req: AuthRequest, res, next) => {
})
// 删除用户
router.delete('/users/:id', async (req: AuthRequest, res, next) => {
router.delete('/users/:id', requireAdmin, async (req: AuthRequest, res, next) => {
try {
if (req.params.id === req.user!.id) {
return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '不能删除自己' } })
@@ -120,7 +121,7 @@ router.delete('/users/:id', async (req: AuthRequest, res, next) => {
})
// 禁用/启用用户
router.patch('/users/:id/toggle-disable', async (req: AuthRequest, res, next) => {
router.patch('/users/:id/toggle-disable', requireAdmin, async (req: AuthRequest, res, next) => {
try {
if (req.params.id === req.user!.id) {
return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '不能禁用自己' } })
@@ -141,7 +142,7 @@ router.patch('/users/:id/toggle-disable', async (req: AuthRequest, res, next) =>
})
// 切换套餐
router.put('/plan', async (req: AuthRequest, res, next) => {
router.put('/plan', requireAdmin, async (req: AuthRequest, res, next) => {
try {
const { plan } = req.body as { plan: 'FREE' | 'PRO' | 'ENTERPRISE' }
if (!['FREE', 'PRO', 'ENTERPRISE'].includes(plan)) {