222 lines
6.4 KiB
JavaScript
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: '프로필 업데이트 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|