164 lines
4.7 KiB
TypeScript
164 lines
4.7 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { withAdminAuth } from '@/lib/admin-middleware'
|
|
import { connectDB } from '@/lib/mongodb'
|
|
import { User } from '@/models/user'
|
|
import { z } from 'zod'
|
|
|
|
const UserUpdateSchema = z.object({
|
|
name: z.string().min(1).optional(),
|
|
email: z.string().email().optional(),
|
|
role: z.enum(['user', 'admin']).optional(),
|
|
isVerified: z.boolean().optional(),
|
|
balance: z.number().min(0).optional(),
|
|
})
|
|
|
|
const UserCreateSchema = z.object({
|
|
name: z.string().min(1),
|
|
email: z.string().email(),
|
|
password: z.string().min(6),
|
|
role: z.enum(['user', 'admin']).default('user'),
|
|
isVerified: z.boolean().default(false),
|
|
balance: z.number().min(0).default(0),
|
|
})
|
|
|
|
export async function GET(request: NextRequest) {
|
|
return withAdminAuth(request, async (req, admin) => {
|
|
try {
|
|
await connectDB()
|
|
|
|
const { searchParams } = new URL(request.url)
|
|
const page = parseInt(searchParams.get('page') || '1')
|
|
const limit = parseInt(searchParams.get('limit') || '20')
|
|
const search = searchParams.get('search') || ''
|
|
const role = searchParams.get('role') || ''
|
|
const verified = searchParams.get('verified') || ''
|
|
|
|
const skip = (page - 1) * limit
|
|
|
|
// Build filter query
|
|
const filter: any = {}
|
|
|
|
if (search) {
|
|
filter.$or = [
|
|
{ name: { $regex: search, $options: 'i' } },
|
|
{ email: { $regex: search, $options: 'i' } },
|
|
{ siliconId: { $regex: search, $options: 'i' } },
|
|
]
|
|
}
|
|
|
|
if (role && role !== 'all') {
|
|
filter.role = role
|
|
}
|
|
|
|
if (verified && verified !== 'all') {
|
|
filter.isVerified = verified === 'true'
|
|
}
|
|
|
|
const [users, totalUsers] = await Promise.all([
|
|
User.find(filter)
|
|
.select('-password -refreshToken')
|
|
.sort({ createdAt: -1 })
|
|
.skip(skip)
|
|
.limit(limit),
|
|
User.countDocuments(filter),
|
|
])
|
|
|
|
const totalPages = Math.ceil(totalUsers / limit)
|
|
|
|
return NextResponse.json({
|
|
users,
|
|
pagination: {
|
|
currentPage: page,
|
|
totalPages,
|
|
totalUsers,
|
|
hasNext: page < totalPages,
|
|
hasPrev: page > 1,
|
|
},
|
|
})
|
|
} catch (error) {
|
|
console.error('Admin users fetch error:', error)
|
|
return NextResponse.json({ error: 'Failed to fetch users' }, { status: 500 })
|
|
}
|
|
})
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
return withAdminAuth(request, async (req, admin) => {
|
|
try {
|
|
await connectDB()
|
|
|
|
const body = await request.json()
|
|
const { action, userId, data } = body
|
|
|
|
if (action === 'update') {
|
|
const validatedData = UserUpdateSchema.parse(data)
|
|
|
|
const user = await User.findByIdAndUpdate(userId, validatedData, {
|
|
new: true,
|
|
runValidators: true,
|
|
}).select('-password -refreshToken')
|
|
|
|
if (!user) {
|
|
return NextResponse.json({ error: 'User not found' }, { status: 404 })
|
|
}
|
|
|
|
return NextResponse.json({ user })
|
|
}
|
|
|
|
if (action === 'create') {
|
|
const validatedData = UserCreateSchema.parse(data)
|
|
|
|
// Check if user already exists
|
|
const existingUser = await User.findOne({ email: validatedData.email })
|
|
if (existingUser) {
|
|
return NextResponse.json(
|
|
{ error: 'User with this email already exists' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Generate unique Silicon ID
|
|
const generateSiliconId = () => {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
|
let result = 'SP'
|
|
for (let i = 0; i < 8; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length))
|
|
}
|
|
return result
|
|
}
|
|
|
|
let siliconId = generateSiliconId()
|
|
while (await User.findOne({ siliconId })) {
|
|
siliconId = generateSiliconId()
|
|
}
|
|
|
|
const user = new User({
|
|
...validatedData,
|
|
siliconId,
|
|
provider: 'local',
|
|
})
|
|
|
|
await user.save()
|
|
|
|
const userResponse = await User.findById(user._id).select('-password -refreshToken')
|
|
return NextResponse.json({ user: userResponse })
|
|
}
|
|
|
|
if (action === 'delete') {
|
|
const user = await User.findByIdAndDelete(userId)
|
|
|
|
if (!user) {
|
|
return NextResponse.json({ error: 'User not found' }, { status: 404 })
|
|
}
|
|
|
|
return NextResponse.json({ message: 'User deleted successfully' })
|
|
}
|
|
|
|
return NextResponse.json({ error: 'Invalid action' }, { status: 400 })
|
|
} catch (error) {
|
|
console.error('Admin user action error:', error)
|
|
return NextResponse.json({ error: 'Failed to perform user action' }, { status: 500 })
|
|
}
|
|
})
|
|
}
|