- System2 신고: SSO JWT 인증 전환, API base 정리 - System3 부적합: SSO 인증 매니저 통합, 권한 체계 정비 - User Management: SSO 토큰 기반 사용자 관리 API 연동 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
148 lines
3.9 KiB
JavaScript
148 lines
3.9 KiB
JavaScript
/**
|
|
* User Controller
|
|
*
|
|
* 사용자 CRUD + 비밀번호 관리
|
|
*/
|
|
|
|
const userModel = require('../models/userModel');
|
|
|
|
/**
|
|
* GET /api/users - 전체 사용자 목록
|
|
*/
|
|
async function getUsers(req, res, next) {
|
|
try {
|
|
const users = await userModel.findAll();
|
|
res.json({ success: true, data: users });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /api/users - 사용자 생성
|
|
*/
|
|
async function createUser(req, res, next) {
|
|
try {
|
|
const { username, password, name, full_name, department, department_id, role } = req.body;
|
|
|
|
if (!username || !password) {
|
|
return res.status(400).json({ success: false, error: '사용자명과 비밀번호는 필수입니다' });
|
|
}
|
|
|
|
const existing = await userModel.findByUsername(username);
|
|
if (existing) {
|
|
return res.status(409).json({ success: false, error: '이미 존재하는 사용자명입니다' });
|
|
}
|
|
|
|
const user = await userModel.create({
|
|
username,
|
|
password,
|
|
name: name || full_name,
|
|
department,
|
|
department_id: department_id || null,
|
|
role
|
|
});
|
|
res.status(201).json({ success: true, data: user });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PUT /api/users/:id - 사용자 수정
|
|
*/
|
|
async function updateUser(req, res, next) {
|
|
try {
|
|
const userId = parseInt(req.params.id);
|
|
const data = { ...req.body };
|
|
|
|
// full_name → name 매핑
|
|
if (data.full_name !== undefined && data.name === undefined) {
|
|
data.name = data.full_name;
|
|
delete data.full_name;
|
|
}
|
|
|
|
const user = await userModel.update(userId, data);
|
|
if (!user) {
|
|
return res.status(404).json({ success: false, error: '사용자를 찾을 수 없습니다' });
|
|
}
|
|
res.json({ success: true, data: user });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* DELETE /api/users/:id - 사용자 비활성화
|
|
*/
|
|
async function deleteUser(req, res, next) {
|
|
try {
|
|
const userId = parseInt(req.params.id);
|
|
await userModel.deleteUser(userId);
|
|
res.json({ success: true, message: '사용자가 비활성화되었습니다' });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /api/users/:id/reset-password - 비밀번호 초기화 (admin)
|
|
*/
|
|
async function resetPassword(req, res, next) {
|
|
try {
|
|
const userId = parseInt(req.params.id);
|
|
const { new_password } = req.body;
|
|
const password = new_password || process.env.DEFAULT_PASSWORD || 'changeme!1';
|
|
|
|
const user = await userModel.update(userId, { password });
|
|
if (!user) {
|
|
return res.status(404).json({ success: false, error: '사용자를 찾을 수 없습니다' });
|
|
}
|
|
res.json({ success: true, message: '비밀번호가 초기화되었습니다' });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /api/users/change-password - 본인 비밀번호 변경
|
|
*/
|
|
async function changePassword(req, res, next) {
|
|
try {
|
|
const { current_password, new_password } = req.body;
|
|
const userId = req.user.user_id || req.user.id;
|
|
|
|
if (!current_password || !new_password) {
|
|
return res.status(400).json({ success: false, error: '현재 비밀번호와 새 비밀번호를 입력하세요' });
|
|
}
|
|
|
|
if (new_password.length < 6) {
|
|
return res.status(400).json({ success: false, error: '새 비밀번호는 최소 6자 이상이어야 합니다' });
|
|
}
|
|
|
|
const user = await userModel.findById(userId);
|
|
if (!user) {
|
|
return res.status(404).json({ success: false, error: '사용자를 찾을 수 없습니다' });
|
|
}
|
|
|
|
const valid = await userModel.verifyPassword(current_password, user.password_hash);
|
|
if (!valid) {
|
|
return res.status(401).json({ success: false, error: '현재 비밀번호가 올바르지 않습니다' });
|
|
}
|
|
|
|
await userModel.update(userId, { password: new_password });
|
|
res.json({ success: true, message: '비밀번호가 변경되었습니다' });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getUsers,
|
|
createUser,
|
|
updateUser,
|
|
deleteUser,
|
|
resetPassword,
|
|
changePassword
|
|
};
|