Skip to content

Commit f15a38c

Browse files
authored
Merge pull request #90 from codeit-moving/release
Release -> main 20241230 10:07
2 parents a225914 + 01daf7a commit f15a38c

File tree

14 files changed

+323
-198
lines changed

14 files changed

+323
-198
lines changed

prisma/ERD.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ erDiagram
1515
Boolean isOAuth
1616
DateTime createAt
1717
DateTime updateAt
18+
String userType
1819
}
1920
"Customer" {
2021
Int id PK
@@ -162,6 +163,7 @@ erDiagram
162163
- `isOAuth`:
163164
- `createAt`:
164165
- `updateAt`:
166+
- `userType`:
165167

166168
### `Customer`
167169

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "User" ADD COLUMN "userType" TEXT NOT NULL DEFAULT 'customer';

prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ model User {
3232
notification notification[]
3333
mover Mover? @relation
3434
customer Customer? @relation
35+
userType String @default("customer") // customer | mover
3536
}
3637

3738
// 일반 고객 프로필

src/controllers/oauthController.ts

Lines changed: 79 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { Router } from "express";
1+
import { RequestHandler, Router } from "express";
22
import passport from "passport";
33
import cookieConfig from "../config/cookie.config";
44
import createToken from "../utils/token.utils";
55
import {
6+
FRONTEND_URL,
67
KAKAO_CALLBACK_URL,
78
KAKAO_CLIENT_ID,
89
NAVER_CLIENT_ID,
@@ -11,54 +12,50 @@ import {
1112

1213
const router = Router();
1314

14-
// router.get(
15-
// "/naver",
16-
// passport.authenticate("naver", {
17-
// scope: ["email"],
18-
// prompt: "consent",
19-
// })
20-
// );
21-
22-
router.get("/naver", (req, res) => {
15+
router.get("/naver/customer", (req, res) => {
2316
const baseURL = "https://nid.naver.com/oauth2.0/authorize";
2417
const query = new URLSearchParams({
2518
scope: "email",
2619
response_type: "code",
2720
client_id: NAVER_CLIENT_ID!,
2821
redirect_uri: NAVER_REDIRECT_URI!,
2922
auth_type: "reprompt",
23+
state: "customer",
3024
});
3125

3226
res.redirect(`${baseURL}?${query.toString()}`);
3327
});
3428

35-
router.get(
36-
"/naver/callback",
37-
passport.authenticate("naver", { failureRedirect: "/login" }),
38-
(req, res) => {
39-
if (!req.user) {
40-
return res.redirect("/login");
41-
}
42-
const user = req.user as any;
29+
router.get("/naver/mover", (req, res) => {
30+
const baseURL = "https://nid.naver.com/oauth2.0/authorize";
31+
const query = new URLSearchParams({
32+
scope: "email",
33+
response_type: "code",
34+
client_id: NAVER_CLIENT_ID!,
35+
redirect_uri: NAVER_REDIRECT_URI!,
36+
auth_type: "reprompt",
37+
state: "mover",
38+
});
4339

44-
const accessToken = createToken(user, "access");
45-
const refreshToken = createToken(user, "refresh");
40+
res.redirect(`${baseURL}?${query.toString()}`);
41+
});
4642

47-
res.cookie("accessToken", accessToken, cookieConfig.accessTokenOption);
48-
res.cookie("refreshToken", refreshToken, cookieConfig.refreshTokenOption);
43+
router.get("/kakao/customer", (req, res) => {
44+
const baseURL = "https://kauth.kakao.com/oauth/authorize";
4945

50-
res.redirect(process.env.FRONTEND_URL || "http://localhost:3001");
51-
}
52-
);
46+
const query = new URLSearchParams({
47+
client_id: KAKAO_CLIENT_ID!,
48+
redirect_uri: KAKAO_CALLBACK_URL!,
49+
response_type: "code",
50+
scope: "account_email",
51+
prompt: "login",
52+
state: "customer",
53+
});
5354

54-
// router.get(
55-
// "/kakao",
56-
// passport.authenticate("kakao", {
57-
// scope: ["account_email"],
58-
// })
59-
// );
55+
res.redirect(`${baseURL}?${query.toString()}`);
56+
});
6057

61-
router.get("/kakao", (req, res) => {
58+
router.get("/kakao/mover", (req, res) => {
6259
const baseURL = "https://kauth.kakao.com/oauth/authorize";
6360

6461
const query = new URLSearchParams({
@@ -67,60 +64,74 @@ router.get("/kakao", (req, res) => {
6764
response_type: "code",
6865
scope: "account_email",
6966
prompt: "login",
67+
state: "mover",
7068
});
7169

7270
res.redirect(`${baseURL}?${query.toString()}`);
7371
});
7472

7573
router.get(
76-
"/kakao/callback",
77-
passport.authenticate("kakao", { failureRedirect: "/login" }),
78-
(req, res) => {
79-
if (!req.user) {
80-
return res.redirect("/login");
81-
}
82-
const user = req.user as any;
83-
84-
const accessToken = createToken(user, "access");
85-
const refreshToken = createToken(user, "refresh");
86-
87-
res.cookie("accessToken", accessToken, cookieConfig.accessTokenOption);
88-
res.cookie("refreshToken", refreshToken, cookieConfig.refreshTokenOption);
89-
90-
res.redirect(process.env.FRONTEND_URL || "http://localhost:3001");
91-
}
74+
"/google/customer",
75+
passport.authenticate("google", {
76+
scope: ["profile", "email"],
77+
state: "customer",
78+
})
9279
);
9380

9481
router.get(
95-
"/google",
82+
"/google/mover",
9683
passport.authenticate("google", {
9784
scope: ["profile", "email"],
85+
state: "mover",
9886
})
9987
);
10088

101-
router.get(
102-
"/google/callback",
103-
passport.authenticate("google", { failureRedirect: "/login" }),
104-
(req, res) => {
105-
if (!req.user) {
106-
return res.redirect("/login");
107-
}
108-
const user = req.user as any;
89+
const handleOAuthCallback: RequestHandler = (req, res) => {
90+
if (!req.user) {
91+
return res.redirect("/login");
92+
}
93+
const user = req.user as any;
94+
const userType = req.query.state as string;
10995

110-
const accessToken = createToken(user, "access");
111-
const refreshToken = createToken(user, "refresh");
96+
const accessToken = createToken(user, "access");
97+
const refreshToken = createToken(user, "refresh");
11298

113-
res.cookie("accessToken", accessToken, cookieConfig.accessTokenOption);
114-
res.cookie("refreshToken", refreshToken, cookieConfig.refreshTokenOption);
99+
res.cookie("accessToken", accessToken, cookieConfig.accessTokenOption);
100+
res.cookie("refreshToken", refreshToken, cookieConfig.refreshTokenOption);
115101

116-
res.redirect(process.env.FRONTEND_URL || "http://localhost:3001");
117-
}
102+
const messages: Record<string, string> = {
103+
customer: "고객 프로필을 등록해주세요.",
104+
mover: "기사 프로필을 등록해주세요.",
105+
};
106+
107+
const redirectUrls: Record<string, string> = {
108+
customer: "/me/profile",
109+
mover: "/mover/profile",
110+
};
111+
112+
res.status(204).send({
113+
message: messages[userType] || "프로필을 등록해주세요.",
114+
redirectUrl: FRONTEND_URL + redirectUrls[userType],
115+
redirect: true,
116+
});
117+
};
118+
119+
router.get(
120+
"/naver/callback",
121+
passport.authenticate("naver", { failureRedirect: "/login" }),
122+
handleOAuthCallback
118123
);
119124

120-
router.get("/kakao/signout", (req, res) => {
121-
res.clearCookie("accessToken");
122-
res.clearCookie("refreshToken");
123-
res.redirect(process.env.FRONTEND_URL || "http://localhost:3001");
124-
});
125+
router.get(
126+
"/kakao/callback",
127+
passport.authenticate("kakao", { failureRedirect: "/login" }),
128+
handleOAuthCallback
129+
);
130+
131+
router.get(
132+
"/google/callback",
133+
passport.authenticate("google", { failureRedirect: "/login" }),
134+
handleOAuthCallback
135+
);
125136

126137
export default router;

src/controllers/quoteController.ts

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -65,40 +65,39 @@ router.get(
6565
})
6666
);
6767

68-
// (기사님이 작성한)특정 견적서 상세 조회
68+
// (기사님이) 반려한 이사 요청 목록 조회
6969
router.get(
70-
"/mover/:quoteId",
70+
"/mover/rejected",
7171
passport.authenticate("jwt", { session: false }),
7272
asyncHandle(async (req, res, next) => {
7373
const user = req.user as any;
7474
const moverId = user.moverId;
7575

76+
// moverId 유효성 검사
7677
if (!moverId) {
77-
const error: customError = new Error("Unauthorized");
78-
error.status = 401;
79-
error.message = "Unauthorized";
80-
error.data = {
81-
message: "기사 정보를 찾을 수 없습니다.",
82-
};
83-
throw error;
84-
}
85-
86-
const quoteId = parseInt(req.params.quoteId);
87-
const cost = parseInt(req.query.cost as string);
88-
89-
if (isNaN(quoteId) || isNaN(cost)) {
9078
const error: customError = new Error("Bad Request");
9179
error.status = 400;
9280
error.message = "Bad Request";
9381
error.data = {
94-
message: "올바르지 않은 파라미터입니다.",
82+
message: "기사 ID가 필요합니다.",
9583
};
9684
throw error;
9785
}
9886

99-
const quote = await quoteService.getQuoteDetail(moverId, quoteId, cost);
87+
// 쿼리 파라미터 처리 (페이지네이션)
88+
const limit = parseInt(req.query.limit as string) || 10;
89+
const nextCursorId = req.query.nextCursorId
90+
? Number(req.query.nextCursorId)
91+
: null;
10092

101-
return res.status(200).send(quote);
93+
// 서비스 호출
94+
const result = await quoteService.getRejectedRequestList(moverId, {
95+
limit,
96+
cursor: nextCursorId,
97+
});
98+
99+
// 응답
100+
res.status(200).send(result);
102101
})
103102
);
104103

@@ -130,39 +129,40 @@ router.post(
130129
})
131130
);
132131

133-
// (기사님이) 반려한 이사 요청 목록 조회
132+
// (기사님이 작성한)특정 견적서 상세 조회
134133
router.get(
135-
"/mover/rejected",
134+
"/mover/:quoteId",
136135
passport.authenticate("jwt", { session: false }),
137136
asyncHandle(async (req, res, next) => {
138137
const user = req.user as any;
139138
const moverId = user.moverId;
140139

141-
// moverId 유효성 검사
142140
if (!moverId) {
141+
const error: customError = new Error("Unauthorized");
142+
error.status = 401;
143+
error.message = "Unauthorized";
144+
error.data = {
145+
message: "기사 정보를 찾을 수 없습니다.",
146+
};
147+
throw error;
148+
}
149+
150+
const quoteId = parseInt(req.params.quoteId);
151+
const cost = parseInt(req.query.cost as string);
152+
153+
if (isNaN(quoteId) || isNaN(cost)) {
143154
const error: customError = new Error("Bad Request");
144155
error.status = 400;
145156
error.message = "Bad Request";
146157
error.data = {
147-
message: "기사 ID가 필요합니다.",
158+
message: "올바르지 않은 파라미터입니다.",
148159
};
149160
throw error;
150161
}
151162

152-
// 쿼리 파라미터 처리 (페이지네이션)
153-
const limit = parseInt(req.query.limit as string) || 10;
154-
const nextCursorId = req.query.nextCursorId
155-
? Number(req.query.nextCursorId)
156-
: null;
157-
158-
// 서비스 호출
159-
const result = await quoteService.getRejectedRequestList(moverId, {
160-
limit,
161-
cursor: nextCursorId,
162-
});
163+
const quote = await quoteService.getQuoteDetail(moverId, quoteId, cost);
163164

164-
// 응답
165-
res.status(200).send(result);
165+
return res.status(200).send(quote);
166166
})
167167
);
168168

src/controllers/reviewController.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import passport from "passport";
33
import { asyncHandle } from "../utils/asyncHandler";
44
import reviewService from "../services/reviewService";
55
import customError from "../utils/interfaces/customError";
6+
import { ReviewCreateData, ReviewQuery } from "../utils/review/types";
67

78
const router = Router();
89

@@ -63,9 +64,10 @@ router.post(
6364
throw error;
6465
}
6566

66-
const { confirmedQuoteId, moverId, rating, content, imageUrl } = req.body;
67+
const { confirmedQuoteId, rating, content, imageUrl } = req.body; // moverId 제거
6768

68-
if (!confirmedQuoteId || !moverId || !rating) {
69+
if (!confirmedQuoteId || !rating) {
70+
// moverId 체크 제거
6971
const error: customError = new Error("Bad Request");
7072
error.status = 400;
7173
error.message = "필수 항목이 누락되었습니다.";
@@ -74,7 +76,6 @@ router.post(
7476

7577
const result = await reviewService.createNewReview(customerId, {
7678
confirmedQuoteId,
77-
moverId,
7879
rating,
7980
content,
8081
imageUrl,
@@ -106,8 +107,13 @@ router.get(
106107
pageNum: pageNum ? parseInt(pageNum as string) : undefined,
107108
});
108109

110+
console.log(result);
109111
res.status(200).send(result);
110112
})
111113
);
112114

113115
export default router;
116+
117+
118+
119+

0 commit comments

Comments
 (0)