Skip to content

Commit

Permalink
Merge pull request #53 from TEAM-ITERVIEW/#52
Browse files Browse the repository at this point in the history
[feat] 중간발표
  • Loading branch information
cha2y0ung authored Apr 12, 2024
2 parents 06037ce + e6fa87e commit 17a41ea
Show file tree
Hide file tree
Showing 18 changed files with 879 additions and 126 deletions.
427 changes: 352 additions & 75 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@
},
"dependencies": {
"@prisma/client": "^5.12.1",
"@types/jsonwebtoken": "^9.0.6",
"axios": "^1.6.8",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-generator": "^4.14.1",
"express-generator": "^4.2.0",
"express-validator": "^7.0.1",
"global": "^4.4.0",
"jsonwebtoken": "^9.0.2",
"openai": "^4.32.2",
"prisma": "^5.12.1"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/node": "^20.12.4",
"nodemon": "^3.1.0"
Expand Down
3 changes: 3 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ model User {
userName String
pictureURL String?
refreshToken String?
social String? @db.VarChar(10)
snsId String? @db.VarChar
email String? @db.VarChar(40)
}

model interviewQuestion {
Expand Down
36 changes: 36 additions & 0 deletions src/config/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import axios from 'axios';
import { exceptionMessage } from '../module/constant';
import { SocialUser } from '../interface/SocialUser';

const googleAuth = async (googleAccessToken: string) => {
try {
//*사용자 정보 받기

const user = await axios({
method: 'get',
url: `https://www.googleapis.com/oauth2/v2/userinfo?access_token=${googleAccessToken}`,
headers: {
authorization: `Bearer ${googleAccessToken}`,
},
});
const userId = user.data.id;
if (!userId) return exceptionMessage.INVALID_USER;
const name = user.data.name;
const email = user.data.email;

const googleUser: SocialUser = {
userId: userId,
name: name,
email: email,
};

return googleUser;
} catch (error) {
console.log('googleAuth error', error);
return null;
}
};

export default {
googleAuth,
};
9 changes: 9 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,13 @@ export default {
* port
*/
port: parseInt(process.env.PORT as string, 10) as number,
/**
* EC2
*/
ec2URL: process.env.EC2_URL as string,
/**
* JWT
*/
jwtSecret: process.env.JWT_SECRET as string,
jwtAlgo: process.env.JWT_ALGORITHM as string,
};
20 changes: 17 additions & 3 deletions src/controller/interviewController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ const saveEmotion = async (req: Request, res: Response, next: NextFunction) => {

const endInterview = async (req: Request, res: Response, next: NextFunction) => {
const {interviewId} = req.params
const endDateTime = req.body
const endDateTime = req.body.endDateTime

try {
const data = await interviewService.endInterview(endDateTime, +interviewId);
const data = await interviewService.endInterview(+interviewId, endDateTime);

return res
.status(statusCode.CREATED)
Expand All @@ -77,10 +77,24 @@ const resultInterview = async (req: Request, res: Response, next: NextFunction)
}
}

const test = async (req: Request, res: Response, next: NextFunction) => {
const interviewId = req.body.interviewId

try {
const data = await interviewService.getQuestionDetails(interviewId);
return res
.status(statusCode.CREATED)
.send(success(statusCode.CREATED, message.RESULT_INTERVIEW_SUCCESS, data));
} catch (error) {
next(error);
}
}

export default {
startInterview,
makeFeedback,
saveEmotion,
endInterview,
resultInterview
resultInterview,
test
};
61 changes: 61 additions & 0 deletions src/controller/tokenController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Request, Response, NextFunction } from 'express';
import { exceptionMessage, message, statusCode } from '../module/constant';
import jwt from '../module/jwtHandler';
import { success, fail } from '../module/constant/utils';

/**
* [GET] accessToken 재발급
*/
const getValidAccessToken = async (
req: Request,
res: Response,
next: NextFunction,
) => {
const accessToken = req.headers.accesstoken;

//* 토큰이 없다면
if (!accessToken)
return res
.status(statusCode.BAD_REQUEST)
.send(fail(statusCode.BAD_REQUEST, message.EMPTY_TOKEN));

try {
const access = jwt.verify(accessToken as string);

// 유효하지 않은 accessToken
if (access == exceptionMessage.TOKEN_INVALID) {
return res
.status(statusCode.UNAUTHORIZED)
.send(fail(statusCode.UNAUTHORIZED, message.INVALID_TOKEN));
}

// 만료된 accessToken
if (access == exceptionMessage.TOKEN_EXPIRED) {
const data = {
isValid: false,
};

return res
.status(statusCode.OK)
.send(
success(statusCode.OK, message.READ_VALID_ACCESS_TOKEN_SUCCESS, data),
);
}

const data = {
isValid: true,
};

return res
.status(statusCode.OK)
.send(
success(statusCode.OK, message.READ_VALID_ACCESS_TOKEN_SUCCESS, data),
);
} catch (error) {
next(error);
}
};

export default {
getValidAccessToken,
};
95 changes: 90 additions & 5 deletions src/controller/userController.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,97 @@
import { Request, Response, NextFunction } from 'express';
import { message, statusCode } from '../module/constant';
import { success } from '../module/constant/utils';
import { exceptionMessage, message, statusCode } from '../module/constant';
import { success, fail } from '../module/constant/utils';
import { userService } from '../service';
import jwt from '../module/jwtHandler';
import { SocialUser } from '../interface/SocialUser';

/**
* @desc [POST] 유저 소셜 로그인
*/
const getSocialUser = async (
req: Request,
res: Response,
next: NextFunction,
) => {
const { social, token } = req.body;

//* token이 없다면
if (!token) {
return res
.status(statusCode.BAD_REQUEST)
.send(fail(statusCode.BAD_REQUEST, message.EMPTY_TOKEN));
}

try {
const user = await userService.getSocialUser(social, token);

//* user가 없다면
if (!user) {
return res
.status(statusCode.UNAUTHORIZED)
.send(fail(statusCode.UNAUTHORIZED, message.INVALID_TOKEN));
}
if (user == exceptionMessage.INVALID_USER) {
return res
.status(statusCode.UNAUTHORIZED)
.send(fail(statusCode.UNAUTHORIZED, message.NO_USER));
}
//* 가입된 유저인지 확인
const existUser = await userService.findUserById(
(user as SocialUser).userId,
);
if (!existUser) {
//* 가입되지 않은 유저라면 회원가입
const data = createUser(social, user as SocialUser);
return res
.status(statusCode.CREATED)
.send(success(statusCode.CREATED, message.SIGNUP_SUCCESS, await data));
}

//* 가입된 유저라면 로그인
const refreshToken = jwt.createRefresh();
const accessToken = jwt.sign(existUser.id);

await userService.updateRefreshToken(existUser.id, refreshToken);

const data = {
signUp: true,
accessToken: accessToken,
name: existUser.userName,
};

return res
.status(statusCode.OK)
.send(success(statusCode.OK, message.SIGNIN_SUCCESS, data));
} catch (error) {
next(error);
}

/**
* @desc 유저 회원 가입
*/
async function createUser(social: string, user: SocialUser) {
const refreshToken = jwt.createRefresh();
const newUser = await userService.signUpUser(
(user as SocialUser).userId,
(user as SocialUser).name,
(user as SocialUser).email,
social,
refreshToken,
);
const accessToken = jwt.sign(newUser.id);

return {
accessToken: accessToken,
name: newUser.userName,
};
}
};

const accessUserInfo = async (req: Request, res: Response, next: NextFunction) => {
//const refreshToken = req.headers['refreshtoken'] as string;
const refreshToken = req.body.refreshToken
try {
const data = await userService.accessUserInfo(refreshToken);
const userId = res.locals.JwtPayload;
const data = await userService.accessUserInfo(+userId);
return res
.status(statusCode.CREATED)
.send(success(statusCode.CREATED, message.ACCESS_USERINFO_SUCCESS, data));
Expand All @@ -18,4 +102,5 @@ const accessUserInfo = async (req: Request, res: Response, next: NextFunction) =

export default {
accessUserInfo,
getSocialUser,
};
32 changes: 28 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,43 @@
import express, { NextFunction, Request, Response } from 'express';
//import { Configuration, OpenAIApi } from 'openai';
import Configuration, { OpenAI } from 'openai';
import OpenAIApi from 'openai';
import config from './config';
import router from './router'
import * as dotenv from 'dotenv'
import errorHandler from './middleware/error/errorHandler';
import cors from 'cors';

dotenv.config()
const axios = require('axios')
const app = express(); // express 객체 받아옴
const app = express(); // express 객체 받아옴

const allowedOrigins = [
'http://localhost:8000',
'http://localhost:3000',
config.ec2URL,
];
const corsOptions = {
origin: allowedOrigins,
credentials: true,
};

app.use(cors(corsOptions));
app.use((req, res, next) => {
const origin: string = req.headers.origin!;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH');
res.header(
'Access-Control-Allow-Headers',
'X-Requested-With, content-type, x-access-token',
);
next();
});

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/', router);
app.use('/', router);

const openai = new OpenAI({
organization: "org-5IqT7dxuJeAfuyJEJJhg8VXq",
Expand All @@ -38,7 +62,7 @@ export const Score = async (questionText: string, text: string) => {
try {
const completion = await openai.completions.create({
model: "gpt-3.5-turbo-instruct",
prompt: "너는 컴퓨터공학과 교수야. 질문과 학생의 대답을 듣고 답변이 상, 중, 하 중에 어디에 속하는지 판단해서 상이면 1, 중이면 0.5, 하 면 0 값을 리턴해줘. 설명할 필요는 없어."+questionText+"이게 질문이고 다음이 학생의 답변이야."+text,
prompt: "너는 컴퓨터공학과 교수야. 질문과 학생의 대답을 1점, 0.5점, 0점 중에 하나를 int 값만 리턴."+questionText+"이게 질문이고 다음이 학생의 답변이야."+text,
max_tokens: 10
});
const result = completion.choices[0].text;
Expand Down
5 changes: 5 additions & 0 deletions src/interface/SocialUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface SocialUser {
userId: string;
name: string;
email: string;
}
Loading

0 comments on commit 17a41ea

Please sign in to comment.