feat: 重构用户角色系统为管理员标识
- 将用户角色字段从role改为is_admin布尔值 - 更新相关API权限检查逻辑 - 修改数据库schema和迁移文件 - 调整前端用户显示逻辑 - 添加API响应工具函数 - 优化权限检查中间件 - 重构英雄组件为原子组件
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { NextRequest } from 'next/server';
|
||||
import { db } from '@/db';
|
||||
import { users } from '@/db/schema';
|
||||
import { auth } from '@/lib/auth';
|
||||
import { hasPermission } from '@/lib/auth/permissions';
|
||||
import { checkIsAdmin } from '@/lib/auth/check-permission';
|
||||
import { forbidden, notFound, success, handleApiError } from '@/lib/api-response';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
@@ -11,26 +11,24 @@ export async function GET(
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const session = await auth();
|
||||
const { isAdmin, userId } = await checkIsAdmin();
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
|
||||
|
||||
if (!hasPermission(userRole, 'users', 'read')) {
|
||||
return NextResponse.json({ error: '无权限' }, { status: 403 });
|
||||
if (!isAdmin) {
|
||||
return forbidden();
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
if (id !== userId) {
|
||||
return forbidden('只能查看自己的信息');
|
||||
}
|
||||
|
||||
const user = await db
|
||||
.select({
|
||||
id: users.id,
|
||||
email: users.email,
|
||||
name: users.name,
|
||||
role: users.role,
|
||||
isAdmin: users.isAdmin,
|
||||
createdAt: users.createdAt,
|
||||
updatedAt: users.updatedAt,
|
||||
})
|
||||
@@ -39,13 +37,12 @@ export async function GET(
|
||||
.limit(1);
|
||||
|
||||
if (user.length === 0) {
|
||||
return NextResponse.json({ error: '用户不存在' }, { status: 404 });
|
||||
return notFound('用户不存在');
|
||||
}
|
||||
|
||||
return NextResponse.json({ user: user[0] });
|
||||
return success({ user: user[0] });
|
||||
} catch (error) {
|
||||
console.error('获取用户详情失败:', error);
|
||||
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
|
||||
return handleApiError(error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,21 +51,20 @@ export async function PUT(
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const session = await auth();
|
||||
const { isAdmin, userId } = await checkIsAdmin();
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
|
||||
|
||||
if (!hasPermission(userRole, 'users', 'update')) {
|
||||
return NextResponse.json({ error: '无权限' }, { status: 403 });
|
||||
if (!isAdmin) {
|
||||
return forbidden();
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
if (id !== userId) {
|
||||
return forbidden('只能修改自己的信息');
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { email, name, password, role } = body;
|
||||
const { email, name, password } = body;
|
||||
|
||||
const existingUser = await db
|
||||
.select()
|
||||
@@ -77,16 +73,15 @@ export async function PUT(
|
||||
.limit(1);
|
||||
|
||||
if (existingUser.length === 0) {
|
||||
return NextResponse.json({ error: '用户不存在' }, { status: 404 });
|
||||
return notFound('用户不存在');
|
||||
}
|
||||
|
||||
const updateData: Record<string, any> = {
|
||||
const updateData: Record<string, unknown> = {
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
if (email) updateData.email = email;
|
||||
if (name) updateData.name = name;
|
||||
if (role) updateData.role = role;
|
||||
if (password) {
|
||||
updateData.passwordHash = await bcrypt.hash(password, 10);
|
||||
}
|
||||
@@ -97,18 +92,16 @@ export async function PUT(
|
||||
.where(eq(users.id, id))
|
||||
.returning();
|
||||
|
||||
return NextResponse.json({
|
||||
return success({
|
||||
user: {
|
||||
id: updated[0]!.id,
|
||||
email: updated[0]!.email,
|
||||
name: updated[0]!.name,
|
||||
role: updated[0]!.role,
|
||||
createdAt: updated[0]!.createdAt,
|
||||
}
|
||||
isAdmin: updated[0]!.isAdmin,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('更新用户失败:', error);
|
||||
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
|
||||
return handleApiError(error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,39 +110,24 @@ export async function DELETE(
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const session = await auth();
|
||||
const { isAdmin, userId } = await checkIsAdmin();
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
|
||||
|
||||
if (!hasPermission(userRole, 'users', 'delete')) {
|
||||
return NextResponse.json({ error: '无权限' }, { status: 403 });
|
||||
if (!isAdmin) {
|
||||
return forbidden();
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
if (session.user.id === id) {
|
||||
return NextResponse.json({ error: '不能删除自己的账号' }, { status: 400 });
|
||||
if (id !== userId) {
|
||||
return forbidden('不能删除其他用户');
|
||||
}
|
||||
|
||||
const existingUser = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, id))
|
||||
.limit(1);
|
||||
await db
|
||||
.delete(users)
|
||||
.where(eq(users.id, id));
|
||||
|
||||
if (existingUser.length === 0) {
|
||||
return NextResponse.json({ error: '用户不存在' }, { status: 404 });
|
||||
}
|
||||
|
||||
await db.delete(users).where(eq(users.id, id));
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
return success({ success: true });
|
||||
} catch (error) {
|
||||
console.error('删除用户失败:', error);
|
||||
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
|
||||
return handleApiError(error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { NextRequest } from 'next/server';
|
||||
import { db } from '@/db';
|
||||
import { users } from '@/db/schema';
|
||||
import { auth } from '@/lib/auth';
|
||||
import { hasPermission } from '@/lib/auth/permissions';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { nanoid } from 'nanoid';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import { checkIsAdmin } from '@/lib/auth/check-permission';
|
||||
import { forbidden, success, handleApiError } from '@/lib/api-response';
|
||||
import { desc } from 'drizzle-orm';
|
||||
|
||||
export async function GET(_request: NextRequest) {
|
||||
try {
|
||||
const session = await auth();
|
||||
const { isAdmin } = await checkIsAdmin();
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
|
||||
|
||||
if (!hasPermission(userRole, 'users', 'read')) {
|
||||
return NextResponse.json({ error: '无权限' }, { status: 403 });
|
||||
if (!isAdmin) {
|
||||
return forbidden();
|
||||
}
|
||||
|
||||
const allUsers = await db
|
||||
@@ -26,77 +18,16 @@ export async function GET(_request: NextRequest) {
|
||||
id: users.id,
|
||||
email: users.email,
|
||||
name: users.name,
|
||||
role: users.role,
|
||||
isAdmin: users.isAdmin,
|
||||
createdAt: users.createdAt,
|
||||
updatedAt: users.updatedAt,
|
||||
})
|
||||
.from(users)
|
||||
.orderBy(users.createdAt);
|
||||
.orderBy(desc(users.createdAt));
|
||||
|
||||
return NextResponse.json({ users: allUsers });
|
||||
return success({ users: allUsers });
|
||||
} catch (error) {
|
||||
console.error('获取用户列表失败:', error);
|
||||
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const session = await auth();
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: '未授权' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userRole = session.user.role as 'admin' | 'editor' | 'viewer';
|
||||
|
||||
if (!hasPermission(userRole, 'users', 'create')) {
|
||||
return NextResponse.json({ error: '无权限' }, { status: 403 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { email, name, password, role } = body;
|
||||
|
||||
if (!email || !name || !password || !role) {
|
||||
return NextResponse.json({ error: '缺少必填字段' }, { status: 400 });
|
||||
}
|
||||
|
||||
const existingUser = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.email, email))
|
||||
.limit(1);
|
||||
|
||||
if (existingUser.length > 0) {
|
||||
return NextResponse.json({ error: '邮箱已被使用' }, { status: 400 });
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
|
||||
const newUser = await db
|
||||
.insert(users)
|
||||
.values({
|
||||
id: nanoid(),
|
||||
email,
|
||||
name,
|
||||
passwordHash: hashedPassword,
|
||||
role,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.returning();
|
||||
|
||||
return NextResponse.json({
|
||||
user: {
|
||||
id: newUser[0]!.id,
|
||||
email: newUser[0]!.email,
|
||||
name: newUser[0]!.name,
|
||||
role: newUser[0]!.role,
|
||||
createdAt: newUser[0]!.createdAt,
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('创建用户失败:', error);
|
||||
return NextResponse.json({ error: '服务器错误' }, { status: 500 });
|
||||
return handleApiError(error);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user