- 시스템 관리자 전용 웹페이지 구현 (system.html) - 깔끔한 흰색 배경의 올드스쿨 스타일 적용 - 반응형 그리드 레이아웃으로 카드 배치 개선 - ES6 모듈 방식으로 JavaScript 구조 개선 - 이벤트 리스너 방식으로 버튼 클릭 처리 변경 - 시스템 상태, 사용자 통계, 계정 관리 기능 구현 - 시스템 로그 조회 기능 추가 - 나머지 관리 기능들 스켈레톤 구현 (개발 중 상태) - 인코딩 문제 해결을 위한 영어 로그 메시지 적용 - hyungi 계정을 system 권한으로 설정 - JWT 토큰에 role 필드 추가 - 시스템 전용 API 엔드포인트 구현 주요 변경사항: - web-ui/pages/dashboard/system.html: 시스템 관리자 전용 페이지 - web-ui/css/system-dashboard.css: 시스템 대시보드 전용 스타일 - web-ui/js/system-dashboard.js: 시스템 대시보드 로직 - api.hyungi.net/controllers/systemController.js: 시스템 API 컨트롤러 - api.hyungi.net/routes/systemRoutes.js: 시스템 API 라우트 - api.hyungi.net/controllers/authController.js: 시스템 권한 로그인 처리 - api.hyungi.net/services/auth.service.js: JWT 토큰에 role 필드 추가
183 lines
5.0 KiB
JavaScript
183 lines
5.0 KiB
JavaScript
const { getDb } = require('../dbPool');
|
|
const bcrypt = require('bcryptjs');
|
|
const jwt = require('jsonwebtoken');
|
|
const authService = require('../services/auth.service');
|
|
|
|
const login = async (req, res) => {
|
|
try {
|
|
const { username, password } = req.body;
|
|
const ipAddress = req.ip || req.connection.remoteAddress;
|
|
const userAgent = req.headers['user-agent'];
|
|
|
|
if (!username || !password) {
|
|
return res.status(400).json({ error: '사용자명과 비밀번호를 입력해주세요.' });
|
|
}
|
|
|
|
const result = await authService.loginService(username, password, ipAddress, userAgent);
|
|
|
|
if (!result.success) {
|
|
return res.status(result.status || 400).json({ error: result.error });
|
|
}
|
|
|
|
// 로그인 성공 후, 역할에 따라 리디렉션 URL을 결정
|
|
const user = result.data.user;
|
|
let redirectUrl;
|
|
|
|
switch (user.role) {
|
|
case 'system': // 시스템 계정 전용 대시보드
|
|
redirectUrl = '/pages/dashboard/system.html';
|
|
break;
|
|
case 'admin':
|
|
redirectUrl = '/pages/dashboard/admin.html';
|
|
break;
|
|
case 'leader':
|
|
redirectUrl = '/pages/dashboard/group-leader.html';
|
|
break;
|
|
case 'support':
|
|
// 예시: 지원팀 대시보드가 있다면
|
|
// redirectUrl = '/pages/dashboard/support.html';
|
|
// 없다면 일반 사용자 대시보드로
|
|
redirectUrl = '/pages/dashboard/user.html';
|
|
break;
|
|
default:
|
|
redirectUrl = '/pages/dashboard/user.html';
|
|
}
|
|
|
|
// 최종 응답에 redirectUrl을 포함하여 전달
|
|
res.json({
|
|
...result.data,
|
|
redirectUrl: redirectUrl
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Login controller error:', error);
|
|
res.status(500).json({ error: error.message || '서버 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// ✅ 사용자 등록 기능 추가
|
|
exports.register = async (req, res) => {
|
|
try {
|
|
const { username, password, name, access_level, worker_id } = req.body;
|
|
const db = await getDb();
|
|
|
|
// 필수 필드 검증
|
|
if (!username || !password || !name || !access_level) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: '필수 정보가 누락되었습니다.'
|
|
});
|
|
}
|
|
|
|
// 중복 아이디 확인
|
|
const [existing] = await db.query(
|
|
'SELECT user_id FROM Users WHERE username = ?',
|
|
[username]
|
|
);
|
|
|
|
if (existing.length > 0) {
|
|
return res.status(409).json({
|
|
success: false,
|
|
error: '이미 존재하는 아이디입니다.'
|
|
});
|
|
}
|
|
|
|
// 비밀번호 해시화
|
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
|
|
// role 설정 (access_level에 따라)
|
|
const roleMap = {
|
|
'admin': 'admin',
|
|
'system': 'system', // 시스템 계정은 system role로 설정
|
|
'group_leader': 'leader',
|
|
'support_team': 'support',
|
|
'worker': 'user'
|
|
};
|
|
const role = roleMap[access_level] || 'user';
|
|
|
|
// 사용자 등록
|
|
const [result] = await db.query(
|
|
`INSERT INTO Users (username, password, name, role, access_level, worker_id)
|
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
[username, hashedPassword, name, role, access_level, worker_id]
|
|
);
|
|
|
|
console.log('[사용자 등록 성공]', username);
|
|
|
|
return res.status(201).json({
|
|
success: true,
|
|
message: '사용자 등록이 완료되었습니다.',
|
|
user_id: result.insertId
|
|
});
|
|
|
|
} catch (err) {
|
|
console.error('[사용자 등록 오류]', err);
|
|
return res.status(500).json({
|
|
success: false,
|
|
error: '서버 오류가 발생했습니다.',
|
|
detail: err.message
|
|
});
|
|
}
|
|
};
|
|
|
|
// ✅ 사용자 삭제 기능 추가
|
|
exports.deleteUser = async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const db = await getDb();
|
|
|
|
// 사용자 존재 확인
|
|
const [user] = await db.query(
|
|
'SELECT user_id FROM Users WHERE user_id = ?',
|
|
[id]
|
|
);
|
|
|
|
if (user.length === 0) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: '해당 사용자를 찾을 수 없습니다.'
|
|
});
|
|
}
|
|
|
|
// 사용자 삭제
|
|
await db.query('DELETE FROM Users WHERE user_id = ?', [id]);
|
|
|
|
console.log('[사용자 삭제 성공] ID:', id);
|
|
|
|
return res.status(200).json({
|
|
success: true,
|
|
message: '사용자가 삭제되었습니다.'
|
|
});
|
|
|
|
} catch (err) {
|
|
console.error('[사용자 삭제 오류]', err);
|
|
return res.status(500).json({
|
|
success: false,
|
|
error: '서버 오류가 발생했습니다.',
|
|
detail: err.message
|
|
});
|
|
}
|
|
};
|
|
|
|
// 모든 사용자 목록 조회
|
|
exports.getAllUsers = async (req, res) => {
|
|
try {
|
|
const db = await getDb();
|
|
|
|
// 비밀번호 제외하고 조회
|
|
const [rows] = await db.query(
|
|
`SELECT user_id, username, name, role, access_level, worker_id, created_at
|
|
FROM Users
|
|
ORDER BY created_at DESC`
|
|
);
|
|
|
|
res.status(200).json(rows);
|
|
} catch (err) {
|
|
console.error('[사용자 목록 조회 실패]', err);
|
|
res.status(500).json({ error: '서버 오류' });
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
login
|
|
}; |