import { Router } from 'express'; import bcrypt from 'bcrypt'; import { prisma } from '../lib/prisma'; import { authenticate, requireAdmin } from '../middleware/auth'; import { AppError } from '../middleware/errorHandler'; const router = Router(); router.use(authenticate); // GET /api/users — 전체 목록 (관리자) router.get('/', requireAdmin, async (_req, res, next) => { try { const users = await prisma.user.findMany({ select: { id: true, email: true, name: true, role: true, department: true, isActive: true, createdAt: true }, orderBy: { name: 'asc' }, }); res.json(users); } catch (err) { next(err); } }); // POST /api/users — 사용자 생성 (관리자) router.post('/', requireAdmin, async (req, res, next) => { try { const { email, password, name, role, department } = req.body as Record; if (!email || !password || !name) { throw new AppError(400, '이메일, 비밀번호, 이름은 필수입니다.'); } const exists = await prisma.user.findUnique({ where: { email } }); if (exists) throw new AppError(409, '이미 사용 중인 이메일입니다.'); const hashed = await bcrypt.hash(password, 12); const user = await prisma.user.create({ data: { email, password: hashed, name, role: (role as any) || 'MEMBER', department }, select: { id: true, email: true, name: true, role: true, department: true }, }); res.status(201).json(user); } catch (err) { next(err); } }); // PATCH /api/users/:id — 정보 수정 router.patch('/:id', async (req, res, next) => { try { const isAdmin = req.user!.role === 'ADMIN'; const isSelf = req.user!.userId === req.params.id; if (!isAdmin && !isSelf) { throw new AppError(403, '권한이 없습니다.'); } const { name, department, password, role, isActive } = req.body as Record; const data: Record = {}; if (name) data.name = name; if (department !== undefined) data.department = department; if (password) data.password = await bcrypt.hash(password, 12); if (isAdmin && role) data.role = role; if (isAdmin && isActive !== undefined) data.isActive = isActive === 'true'; const user = await prisma.user.update({ where: { id: req.params.id }, data, select: { id: true, email: true, name: true, role: true, department: true, isActive: true }, }); res.json(user); } catch (err) { next(err); } }); export default router;