/** * 인증 컨트롤러 * 사용자 인증 관련 기능을 처리하는 컨트롤러 */ 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: '프로필 업데이트 중 오류가 발생했습니다.' }); } };