Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE][Feat] : #42 : 로그인 api 구현 #144

Merged
merged 5 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"dotenv": "^16.4.5",
"express": "^4.21.1",
"express-validator": "^7.2.0",
"jsonwebtoken": "^9.0.2",
"pg": "^8.13.1",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1",
"ws": "^8.18.0"
"ws": "^8.11.0"
}
}
File renamed without changes.
16 changes: 16 additions & 0 deletions backend/src/controllers/authController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { loginUser } from '../services/authService.js';

export const login = async (req, res) => {
const { id, password } = req.body;

try {
const token = await loginUser(id, password);
if (!token) {
return res.status(401).json({ message: 'Invalid ID or password' });
}
return res.status(200).json({ token });
} catch (error) {
console.error('Login error:', error);
return res.status(500).json({ message: 'Server error occurred' });
}
};
File renamed without changes.
18 changes: 13 additions & 5 deletions backend/src/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import express from 'express';
import swaggerUi from 'swagger-ui-express';
import http from 'http';
import { specs } from '../swaggerConfig';
import { pool } from './db';
import { PORT } from './constants';
import { initializeWebSocketServer } from './websocketServer';
import { specs } from '../swaggerConfig.js';
import { pool } from './db/db.js';
import { PORT } from './constants/constants.js';
import { initializeWebSocketServer } from './websocketServer.js';
import { authRouter } from './routes/authRouter.js';

const app = express();
app.use(express.json());

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));

app.use('/api/auth', authRouter);

// TODO: 데이터베이스에서 데이터 가져오기 예시
app.get('/guests', async (req, res) => {
try {
Expand All @@ -31,7 +34,12 @@ app.get('/example', (req, res) => {
const server = http.createServer(app);

// WebSocket 서버 초기화
initializeWebSocketServer(server);
try {
initializeWebSocketServer(server);
console.log('WebSocket server initialized successfully.');
} catch (error) {
console.error('Failed to initialize WebSocket server:', error);
}

app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
Expand Down
9 changes: 9 additions & 0 deletions backend/src/middleware/validationMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { validationResult } from 'express-validator';

export const validationMiddleware = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
};
6 changes: 6 additions & 0 deletions backend/src/repositories/userRepository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { pool } from '../db/db.js';

export const findUserById = async id => {
const result = await pool.query('SELECT * FROM "main"."user" WHERE id = $1', [id]);
return result.rows[0];
};
18 changes: 18 additions & 0 deletions backend/src/routes/authRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import express from 'express';
import { body } from 'express-validator';
import { login } from '../controllers/authController.js';
import { validationMiddleware } from '../middleware/validationMiddleware.js';

export const authRouter = express.Router();

authRouter.post(
'/login',
[
body('id').notEmpty().withMessage('ID is required'),
body('password')
.isLength({ min: 6 })
.withMessage('Password must be at least 6 characters long'),
],
validationMiddleware,
login,
);
19 changes: 19 additions & 0 deletions backend/src/services/authService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { findUserById } from '../repositories/userRepository.js';

export const loginUser = async (id, password) => {
const user = await findUserById(id);
if (!user) {
throw new Error('User not found');
}

const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
throw new Error('Invalid password');
}

// JWT 생성
const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '1h' });
return { token, userId: user.id };
};
4 changes: 2 additions & 2 deletions backend/src/websocketServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { WebSocketServer } from 'ws';

const activeConnections = {}; // token별로 연결을 관리하기 위한 객체

export function initializeWebSocketServer(server) {
export const initializeWebSocketServer = server => {
const wss = new WebSocketServer({ server });

wss.on('connection', (ws, req) => {
Expand Down Expand Up @@ -38,4 +38,4 @@ export function initializeWebSocketServer(server) {
delete activeConnections[token];
});
});
}
};
8 changes: 5 additions & 3 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ export default [
'no-undef': 'off',
'import/extensions': [
'error',
'ignorePackages',
'always',
{
js: 'never',
jsx: 'never',
js: 'always',
jsx: 'always',
ts: 'never',
tsx: 'never',
},
Expand Down Expand Up @@ -111,6 +111,8 @@ export default [
'import/prefer-default-export': 'off',
'import/no-unresolved': 'warn',
'no-console': 'off',
'consistent-return': 'off',
'import/extensions': 'off',
},
},

Expand Down
Loading
Loading