fix: 캘린더 모달 중복 카드 문제 및 삭제 권한 개선
- monthly_worker_status 조회 시 GROUP BY로 중복 데이터 합산 - 작업보고서 삭제 권한을 그룹장 이상으로 제한 (admin, system, group_leader) - 중복 데이터 정리를 위한 마이그레이션 SQL 추가 (009_fix_duplicate_monthly_status.sql) - synology_deployment 버전에도 동일 수정 적용
This commit is contained in:
98
synology_deployment/api/services/auth.service.js
Normal file
98
synology_deployment/api/services/auth.service.js
Normal file
@@ -0,0 +1,98 @@
|
||||
const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const userModel = require('../models/userModel');
|
||||
const { getDb } = require('../dbPool');
|
||||
|
||||
// 로그인 이력 기록 (서비스 내부 헬퍼 함수)
|
||||
const recordLoginHistory = async (userId, success, ipAddress, userAgent, failureReason = null) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
await db.execute(
|
||||
`INSERT INTO login_logs (user_id, login_time, ip_address, user_agent, login_status, failure_reason)
|
||||
VALUES (?, NOW(), ?, ?, ?, ?)`,
|
||||
[userId, ipAddress || 'unknown', userAgent || 'unknown', success ? 'success' : 'failed', failureReason]
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('로그인 이력 기록 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const loginService = async (username, password, ipAddress, userAgent) => {
|
||||
// 서비스 레이어에서는 더 이상 DB 커넥션을 직접 다루지 않음
|
||||
try {
|
||||
const user = await userModel.findByUsername(username);
|
||||
|
||||
if (!user) {
|
||||
console.log(`[로그인 실패] 사용자를 찾을 수 없음: ${username}`);
|
||||
return { success: false, status: 401, error: '아이디 또는 비밀번호가 올바르지 않습니다.' };
|
||||
}
|
||||
|
||||
if (user.is_active === false) {
|
||||
await recordLoginHistory(user.user_id, false, ipAddress, userAgent, 'account_disabled');
|
||||
return { success: false, status: 403, error: '비활성화된 계정입니다. 관리자에게 문의하세요.' };
|
||||
}
|
||||
|
||||
if (user.locked_until && new Date(user.locked_until) > new Date()) {
|
||||
const remainingTime = Math.ceil((new Date(user.locked_until) - new Date()) / 1000 / 60);
|
||||
return { success: false, status: 429, error: `계정이 잠겨있습니다. ${remainingTime}분 후에 다시 시도하세요.` };
|
||||
}
|
||||
|
||||
const isValid = await bcrypt.compare(password, user.password);
|
||||
if (!isValid) {
|
||||
console.log(`[로그인 실패] 비밀번호 불일치: ${username}`);
|
||||
|
||||
// 모델 함수를 사용하여 로그인 실패 처리
|
||||
await userModel.incrementFailedLoginAttempts(user.user_id);
|
||||
|
||||
if (user.failed_login_attempts >= 4) {
|
||||
await userModel.lockUserAccount(user.user_id);
|
||||
}
|
||||
|
||||
await recordLoginHistory(user.user_id, false, ipAddress, userAgent, 'invalid_password');
|
||||
return { success: false, status: 401, error: '아이디 또는 비밀번호가 올바르지 않습니다.' };
|
||||
}
|
||||
|
||||
// 성공 시 모델 함수를 사용하여 상태 초기화
|
||||
await userModel.resetLoginAttempts(user.user_id);
|
||||
|
||||
|
||||
const token = jwt.sign(
|
||||
{ user_id: user.user_id, username: user.username, role: user.role, access_level: user.access_level, worker_id: user.worker_id, name: user.name || user.username },
|
||||
process.env.JWT_SECRET || 'your-secret-key',
|
||||
{ expiresIn: process.env.JWT_EXPIRES_IN || '24h' }
|
||||
);
|
||||
|
||||
const refreshToken = jwt.sign(
|
||||
{ user_id: user.user_id, type: 'refresh' },
|
||||
process.env.JWT_REFRESH_SECRET || process.env.JWT_SECRET || 'your-refresh-secret',
|
||||
{ expiresIn: process.env.JWT_REFRESH_EXPIRES_IN || '7d' }
|
||||
);
|
||||
|
||||
await recordLoginHistory(user.user_id, true, ipAddress, userAgent);
|
||||
console.log(`[로그인 성공] 사용자: ${user.username} (${user.access_level})`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
token,
|
||||
refreshToken,
|
||||
user: {
|
||||
user_id: user.user_id,
|
||||
username: user.username,
|
||||
name: user.name || user.username,
|
||||
role: user.role,
|
||||
access_level: user.access_level,
|
||||
worker_id: user.worker_id
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Login service error:', error);
|
||||
throw new Error('서버 오류가 발생했습니다.');
|
||||
}
|
||||
// 서비스 레이어에서는 더 이상 DB 커넥션을 직접 다루지 않음
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
loginService,
|
||||
};
|
||||
Reference in New Issue
Block a user