2025-09-24 17:11:35 +09:00
|
|
|
const express = require('express');
|
|
|
|
|
const router = express.Router();
|
|
|
|
|
const {
|
|
|
|
|
createUser,
|
|
|
|
|
authenticateUser,
|
|
|
|
|
createApiKey,
|
|
|
|
|
getUserApiKeys,
|
|
|
|
|
deactivateApiKey,
|
|
|
|
|
deleteApiKey,
|
|
|
|
|
getAllUsers,
|
|
|
|
|
getApiUsageStats
|
|
|
|
|
} = require('../database/auth-queries');
|
|
|
|
|
const { generateToken, verifyToken, requireAdmin } = require('../middleware/auth');
|
|
|
|
|
|
|
|
|
|
// 사용자 등록
|
|
|
|
|
router.post('/register', async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const { username, email, password, role } = req.body;
|
|
|
|
|
|
|
|
|
|
if (!username || !email || !password) {
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '사용자명, 이메일, 비밀번호는 필수입니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 비밀번호 강도 검증
|
|
|
|
|
if (password.length < 8) {
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '비밀번호는 최소 8자 이상이어야 합니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await createUser({
|
|
|
|
|
username,
|
|
|
|
|
email,
|
|
|
|
|
password,
|
|
|
|
|
role: role || 'user'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
res.status(201).json({
|
|
|
|
|
success: true,
|
|
|
|
|
message: '사용자가 성공적으로 생성되었습니다',
|
|
|
|
|
rowsAffected: result
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('사용자 등록 오류:', error);
|
|
|
|
|
|
|
|
|
|
if (error.message.includes('ORA-00001')) {
|
|
|
|
|
return res.status(409).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '이미 존재하는 사용자명 또는 이메일입니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '사용자 등록 중 오류가 발생했습니다',
|
|
|
|
|
error: error.message
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 로그인
|
|
|
|
|
router.post('/login', async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const { username, password } = req.body;
|
|
|
|
|
|
|
|
|
|
if (!username || !password) {
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '사용자명과 비밀번호는 필수입니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const user = await authenticateUser(username, password);
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
return res.status(401).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '잘못된 사용자명 또는 비밀번호입니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const token = generateToken(user);
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
success: true,
|
|
|
|
|
message: '로그인 성공',
|
|
|
|
|
token: token,
|
|
|
|
|
user: {
|
|
|
|
|
id: user.id,
|
|
|
|
|
username: user.username,
|
|
|
|
|
email: user.email,
|
|
|
|
|
role: user.role
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('로그인 오류:', error);
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '로그인 중 오류가 발생했습니다',
|
|
|
|
|
error: error.message
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 사용자 정보 조회
|
|
|
|
|
router.get('/me', verifyToken, async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
res.json({
|
|
|
|
|
success: true,
|
|
|
|
|
user: {
|
|
|
|
|
id: req.user.id,
|
|
|
|
|
username: req.user.username,
|
|
|
|
|
email: req.user.email,
|
|
|
|
|
role: req.user.role
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('사용자 정보 조회 오류:', error);
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '사용자 정보 조회 중 오류가 발생했습니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// API 키 생성
|
|
|
|
|
router.post('/api-keys', verifyToken, async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const { keyName, permissions } = req.body;
|
|
|
|
|
|
|
|
|
|
if (!keyName) {
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: 'API 키 이름은 필수입니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-25 16:23:32 +09:00
|
|
|
// 기본 권한 설정 (권한이 지정되지 않은 경우)
|
|
|
|
|
const defaultPermissions = permissions && permissions.length > 0 ? permissions : ['read', 'write'];
|
|
|
|
|
const result = await createApiKey(req.user.id, keyName, defaultPermissions);
|
2025-09-24 17:11:35 +09:00
|
|
|
|
|
|
|
|
res.status(201).json({
|
|
|
|
|
success: true,
|
|
|
|
|
message: 'API 키가 성공적으로 생성되었습니다',
|
|
|
|
|
apiKey: result.apiKey,
|
|
|
|
|
keyName: keyName
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('API 키 생성 오류:', error);
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: 'API 키 생성 중 오류가 발생했습니다',
|
|
|
|
|
error: error.message
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 사용자의 API 키 목록 조회
|
|
|
|
|
router.get('/api-keys', verifyToken, async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const apiKeys = await getUserApiKeys(req.user.id);
|
|
|
|
|
|
|
|
|
|
// 전체 API 키를 반환 (사용자가 자신의 키를 관리할 수 있도록)
|
|
|
|
|
const safeApiKeys = apiKeys.map(key => ({
|
|
|
|
|
id: key.id,
|
|
|
|
|
keyName: key.keyName,
|
|
|
|
|
apiKey: key.apiKey,
|
2025-09-25 16:23:32 +09:00
|
|
|
permissions: key.permissions || [],
|
2025-09-24 17:11:35 +09:00
|
|
|
usageCount: key.usageCount || 0,
|
|
|
|
|
lastUsed: key.lastUsed ? new Date(key.lastUsed).toISOString() : null,
|
|
|
|
|
createdAt: key.createdAt ? new Date(key.createdAt).toISOString() : new Date().toISOString(),
|
|
|
|
|
isActive: Boolean(key.isActive)
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
success: true,
|
|
|
|
|
apiKeys: safeApiKeys
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('API 키 목록 조회 오류:', error);
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: 'API 키 목록 조회 중 오류가 발생했습니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// API 키 삭제
|
|
|
|
|
router.delete('/api-keys/:keyId', verifyToken, async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const { keyId } = req.params;
|
|
|
|
|
|
|
|
|
|
const result = await deleteApiKey(keyId, req.user.id);
|
|
|
|
|
|
|
|
|
|
if (result === 0) {
|
|
|
|
|
return res.status(404).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: 'API 키를 찾을 수 없습니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
success: true,
|
|
|
|
|
message: 'API 키가 삭제되었습니다'
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('API 키 삭제 오류:', error);
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: 'API 키 삭제 중 오류가 발생했습니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 모든 사용자 조회 (관리자 전용)
|
|
|
|
|
router.get('/users', verifyToken, requireAdmin, async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const users = await getAllUsers();
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
success: true,
|
|
|
|
|
users: users
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('사용자 목록 조회 오류:', error);
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: '사용자 목록 조회 중 오류가 발생했습니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// API 사용 통계 조회 (관리자 전용)
|
|
|
|
|
router.get('/stats', verifyToken, requireAdmin, async (req, res) => {
|
|
|
|
|
try {
|
|
|
|
|
const stats = await getApiUsageStats();
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
success: true,
|
|
|
|
|
stats: stats
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('API 통계 조회 오류:', error);
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
success: false,
|
|
|
|
|
message: 'API 통계 조회 중 오류가 발생했습니다'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
module.exports = router;
|