Files
bowlingManager/backend/controllers/authController.js
T
2025-06-08 20:21:37 +09:00

222 lines
6.4 KiB
JavaScript

/**
* 인증 컨트롤러
* 사용자 인증 관련 기능을 처리하는 컨트롤러
*/
const jwt = require('jsonwebtoken');
const { User, Member } = require('../models');
const { Op } = require('sequelize');
require('dotenv').config();
// 로그인
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
// 이메일 필수 확인
if (!email) {
return res.status(400).json({ message: '이메일은 필수 항목입니다.' });
}
// 사용자 조회
const user = await User.findOne({ where: { email } });
// 사용자가 존재하지 않는 경우
if (!user) {
return res.status(401).json({ message: '이메일 또는 비밀번호가 올바르지 않습니다.' });
}
// 비밀번호 검증
const isPasswordValid = await user.validatePassword(password);
if (!isPasswordValid) {
return res.status(401).json({ message: '이메일 또는 비밀번호가 올바르지 않습니다.' });
}
// 마지막 로그인 시간 업데이트
await user.update({ lastLogin: new Date() });
// JWT 토큰 생성
const token = jwt.sign(
{
id: user.id,
email: user.email,
role: user.role,
name: user.name
},
process.env.JWT_SECRET || 'your-secret-key',
{ expiresIn: process.env.JWT_EXPIRES_IN || '1d' }
);
// 모임장/운영진으로 참여 중인 클럽 ID 조회
const clubMembers = await Member.findAll({
where: {
userId: user.id,
memberType: {
[Op.in]: ['manager', 'owner']
}
},
attributes: ['clubId']
});
// console.log(`clubMembers: ${JSON.stringify(clubMembers)}`);
// 모임장/운영진 클럽 ID 배열 생성
const clubManagerIds = clubMembers.map(cm => cm.clubId);
let clubId = null;
if(clubManagerIds.length > 0) {
clubId = clubManagerIds[0];
}
// 사용자 정보에서 비밀번호 제외
const userData = {
id: user.id,
name: user.name,
email: user.email,
role: user.role,
status: user.status,
clubId: clubId
};
// console.log(`userData: ${JSON.stringify(userData)}`);
res.json({
token,
user: userData
});
} catch (error) {
console.error('로그인 오류:', error);
res.status(500).json({ message: '로그인 중 오류가 발생했습니다.' });
}
};
// 회원가입
exports.register = async (req, res) => {
try {
const { name, email, password, role, status } = req.body;
// 필수 필드 검증
if (!name || !email || !password) {
return res.status(400).json({ message: '이름, 이메일, 비밀번호는 필수 항목입니다.' });
}
// 이메일 중복 확인
const existingUser = await User.findOne({ where: { email } });
if (existingUser) {
return res.status(400).json({ message: '이미 등록된 이메일입니다.' });
}
// 사용자 생성
const newUser = await User.create({
name,
email,
password,
username: email,
role: role || 'user',
status: status || 'active'
});
// 민감한 정보 제외
const userResponse = {
id: newUser.id,
name: newUser.name,
email: newUser.email,
role: newUser.role,
status: newUser.status,
createdAt: newUser.createdAt
};
res.status(201).json(userResponse);
} catch (error) {
console.error('회원가입 오류:', error);
res.status(500).json({ message: '회원가입 중 오류가 발생했습니다.' });
}
};
// 현재 사용자 정보 조회
exports.getCurrentUser = async (req, res) => {
try {
const userId = req.user.id;
const user = await User.findByPk(userId, {
attributes: { exclude: ['password'] }
});
if (!user) {
return res.status(404).json({ message: '사용자를 찾을 수 없습니다.' });
}
res.json(user);
} catch (error) {
console.error('사용자 정보 조회 오류:', error);
res.status(500).json({ message: '사용자 정보를 조회하는 중 오류가 발생했습니다.' });
}
};
// 프로필 업데이트
exports.updateProfile = async (req, res) => {
try {
const userId = req.user.id;
const { name, email, password, currentPassword } = req.body;
// 사용자 조회
const user = await User.findByPk(userId);
if (!user) {
return res.status(404).json({ message: '사용자를 찾을 수 없습니다.' });
}
// 비밀번호 변경이 요청된 경우
if (password && currentPassword) {
// 현재 비밀번호 검증
const isPasswordValid = await user.validatePassword(currentPassword);
if (!isPasswordValid) {
return res.status(401).json({ message: '현재 비밀번호가 올바르지 않습니다.' });
}
}
// 이메일이 변경되는 경우
if (email && email !== user.email) {
// Users 테이블에서 이메일 중복 확인
const existingUser = await User.findOne({ where: { email } });
if (existingUser) {
return res.status(400).json({ message: '이미 사용 중인 이메일입니다.' });
}
// Members 테이블에서 이메일 중복 확인
const existingMember = await Member.findOne({ where: { email } });
if (existingMember) {
return res.status(400).json({ message: '이미 클럽 회원이 사용 중인 이메일입니다.' });
}
// 해당 사용자의 Members 테이블 레코드도 함께 업데이트
await Member.update(
{ email },
{ where: { userId } }
);
}
// 프로필 업데이트
const updateData = {
name: name || user.name,
email: email || user.email,
username: email || user.email // username도 이메일과 동일하게 업데이트
};
// 비밀번호가 제공된 경우에만 업데이트
if (password && currentPassword) {
updateData.password = password;
}
await user.update(updateData);
// 업데이트된 사용자 정보 반환 (비밀번호 제외)
const updatedUser = await User.findByPk(userId, {
attributes: { exclude: ['password'] }
});
res.json(updatedUser);
} catch (error) {
console.error('프로필 업데이트 오류:', error);
res.status(500).json({ message: '프로필 업데이트 중 오류가 발생했습니다.' });
}
};