Skip to content

Commit 98a9f17

Browse files
authored
Merge pull request #115 from codeit-moving/release
Release -> main 20250102 17:08
2 parents 81774b6 + a943c34 commit 98a9f17

21 files changed

+204
-385
lines changed

src/controllers/authController.ts

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,11 @@ router.post(
4747
email,
4848
password,
4949
});
50-
if (user) {
51-
const accessToken = createToken(user, "access");
52-
const refreshToken = createToken(user, "refresh");
53-
res.cookie("accessToken", accessToken, cookieConfig.accessTokenOption);
54-
res.cookie(
55-
"refreshToken",
56-
refreshToken,
57-
cookieConfig.refreshTokenOption
58-
);
59-
res.status(204).send();
60-
} else {
61-
return res.status(400).send({ message: "로그인에 실패하였습니다." });
62-
}
50+
const accessToken = createToken(user, "access");
51+
const refreshToken = createToken(user, "refresh");
52+
res.cookie("accessToken", accessToken, cookieConfig.accessTokenOption);
53+
res.cookie("refreshToken", refreshToken, cookieConfig.refreshTokenOption);
54+
res.status(204).send();
6355
} catch (error) {
6456
next(error);
6557
}
@@ -142,9 +134,6 @@ router.post(
142134
try {
143135
const user = req.user as Payload;
144136
const userData = await userService.getUserById(user.id);
145-
if (!userData) {
146-
return res.status(400).send({ message: "유효하지 않은 사용자입니다." });
147-
}
148137
const accessToken = createToken(
149138
{
150139
id: userData.id,

src/controllers/oauthController.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
NAVER_CLIENT_ID,
1010
NAVER_REDIRECT_URI,
1111
} from "../env";
12-
import CustomError from "../utils/interfaces/customError";
12+
import { throwRedirectError } from "../utils/constructors/redirectError";
1313

1414
const router = Router();
1515

@@ -113,14 +113,10 @@ const handleOAuthCallback: RequestHandler = (req, res, next) => {
113113
mover: "/mover/profile",
114114
};
115115

116-
const error: CustomError = new Error("Forbidden");
117-
error.status = 403;
118-
error.data = {
119-
message: messages[userType] || "프로필을 등록해주세요.",
120-
redirectUrl: FRONTEND_URL + redirectUrls[userType],
121-
redirect: true,
122-
};
123-
next(error);
116+
return throwRedirectError(
117+
messages[userType] || "프로필을 등록해주세요.",
118+
redirectUrls[userType]
119+
);
124120
}
125121
};
126122

src/middlewares/authMiddleware.ts

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import passport from "passport";
55
import CustomError from "../utils/interfaces/customError";
66
import userRepository from "../repositorys/userRepository";
77
import { FRONTEND_URL } from "../env";
8+
import { throwRedirectError } from "../utils/constructors/redirectError";
9+
import { throwHttpError } from "../utils/constructors/httpError";
810

911
interface authUser {
1012
id: number;
@@ -68,23 +70,10 @@ export const isCustomer = async (
6870
};
6971
const findUser = await userRepository.findById(user.id);
7072
if (!findUser) {
71-
const error: CustomError = new Error("Unauthorized");
72-
error.status = 403;
73-
error.data = {
74-
message: "유효하지 않은 사용자입니다.",
75-
};
76-
return next(error);
73+
return throwHttpError(403, "유효하지 않은 사용자입니다.");
7774
}
78-
7975
if (!user?.customerId) {
80-
const error: CustomError = new Error("Unauthorized");
81-
error.status = 403;
82-
error.data = {
83-
message: "고객 프로필을 먼저 등록해주세요",
84-
redirectUrl: FRONTEND_URL + "/me/profile",
85-
redirect: true,
86-
};
87-
return next(error);
76+
return throwRedirectError("고객 프로필을 먼저 등록해주세요", "/me/profile");
8877
}
8978

9079
next();
@@ -102,23 +91,13 @@ export const isMover = async (
10291
};
10392
const findUser = await userRepository.findById(user.id);
10493
if (!findUser) {
105-
const error: CustomError = new Error("Unauthorized");
106-
error.status = 403;
107-
error.data = {
108-
message: "유효하지 않은 사용자입니다.",
109-
};
110-
return next(error);
94+
return throwHttpError(403, "유효하지 않은 사용자입니다.");
11195
}
11296
if (!user?.moverId) {
113-
const error: CustomError = new Error("Unauthorized");
114-
error.status = 403;
115-
error.data = {
116-
message: "기사 프로필을 먼저 등록해 주세요.",
117-
redirectUrl: FRONTEND_URL + "/mover/profile",
118-
redirect: true,
119-
};
120-
return next(error);
97+
return throwRedirectError(
98+
"기사 프로필을 먼저 등록해 주세요.",
99+
"/mover/profile"
100+
);
121101
}
122-
123102
next();
124103
};

src/middlewares/passport.ts

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,24 @@ import {
1616
} from "../env";
1717
import { JWT_SECRET } from "../env";
1818
import oauthService from "../services/oauthService";
19-
import CustomError from "../utils/interfaces/customError";
2019
import { Strategy } from "passport-custom";
2120
import jwt from "jsonwebtoken";
21+
import { HttpError } from "../utils/constructors/httpError";
2222

2323
passport.use(
2424
"jwt",
2525
new Strategy(async (req, done) => {
2626
const token = req.cookies["accessToken"];
2727

2828
if (!token) {
29-
const error: CustomError = new Error("Token missing");
30-
error.status = 403;
31-
error.data = {
32-
message: "토큰이 존재하지 않습니다.",
33-
};
34-
return done(error, false); // 토큰이 없을 때 에러 반환
29+
return done(new HttpError(403, "토큰이 존재하지 않습니다."), false); // 토큰이 없을 때 에러 반환
3530
}
3631

3732
try {
3833
const decoded = jwt.verify(token, JWT_SECRET);
3934
return done(null, decoded); // 토큰이 있고 유효하면 유저 정보 반환
4035
} catch (err) {
41-
const error: CustomError = new Error("Invalid token");
42-
error.status = 403;
43-
error.data = {
44-
message: "유효하지 않은 토큰입니다.",
45-
};
46-
return done(error, false); // 토큰이 있지만 유효하지 않으면 false 반환
36+
return done(new HttpError(403, "유효하지 않은 토큰입니다."), false); // 토큰이 있지만 유효하지 않으면 false 반환
4737
}
4838
})
4939
);
@@ -71,24 +61,20 @@ passport.use(
7161
const refreshToken = req.cookies["refreshToken"];
7262

7363
if (!refreshToken) {
74-
const error: CustomError = new Error("Token missing");
75-
error.status = 403;
76-
error.data = {
77-
message: "리프레시 토큰이 존재하지 않습니다.",
78-
};
79-
return done(error, false);
64+
return done(
65+
new HttpError(403, "리프레시 토큰이 존재하지 않습니다."),
66+
false
67+
);
8068
}
8169

8270
try {
8371
const decoded = jwt.verify(refreshToken, REFRESH_SECRET);
8472
return done(null, decoded);
8573
} catch (err) {
86-
const error: CustomError = new Error("Invalid token");
87-
error.status = 403;
88-
error.data = {
89-
message: "유효하지 않은 리프레시 토큰입니다.",
90-
};
91-
return done(error, false);
74+
return done(
75+
new HttpError(403, "유효하지 않은 리프레시 토큰입니다."),
76+
false
77+
);
9278
}
9379
})
9480
);

src/middlewares/validations/movingRequest.ts

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,35 @@
11
import { RequestHandler } from "express";
22
import customError from "../../utils/interfaces/customError";
3+
import { throwHttpError } from "../../utils/constructors/httpError";
34

45
const createMovingRequestValidation: RequestHandler = (req, res, next) => {
56
const { service, movingDate, pickupAddress, dropOffAddress, region } =
67
req.body;
78

89
if (!service || typeof service !== "number" || service < 1 || service > 3) {
9-
const error: customError = new Error("Bad Request");
10-
error.status = 400;
11-
error.message = "Bad Request";
12-
error.data = {
13-
message: "이사 서비스 타입이 올바르지 않습니다.",
14-
};
15-
return next(error);
10+
return throwHttpError(400, "이사 서비스 타입이 올바르지 않습니다.");
1611
}
17-
1812
const date = new Date(movingDate);
19-
if (!movingDate || !(date instanceof Date)) {
20-
const error: customError = new Error("Bad Request");
21-
error.status = 400;
22-
error.message = "Bad Request";
23-
error.data = {
24-
message: "이사 날짜가 올바르지 않습니다.",
25-
};
26-
return next(error);
13+
14+
//이사 날짜 검증
15+
if (!movingDate || isNaN(date.getTime())) {
16+
return throwHttpError(400, "이사 날짜가 올바르지 않습니다.");
17+
}
18+
19+
if (date <= new Date()) {
20+
return throwHttpError(400, "이사 날짜는 오늘 이후여야 합니다.");
2721
}
2822

2923
if (!pickupAddress || typeof pickupAddress !== "string") {
30-
const error: customError = new Error("Bad Request");
31-
error.status = 400;
32-
error.message = "Bad Request";
33-
error.data = {
34-
message: "이사 출발지가 올바르지 않습니다.",
35-
};
36-
return next(error);
24+
return throwHttpError(400, "이사 출발지가 올바르지 않습니다.");
3725
}
3826

3927
if (!dropOffAddress || typeof dropOffAddress !== "string") {
40-
const error: customError = new Error("Bad Request");
41-
error.status = 400;
42-
error.message = "Bad Request";
43-
error.data = {
44-
message: "이사 도착지가 올바르지 않습니다.",
45-
};
46-
return next(error);
28+
return throwHttpError(400, "이사 도착지가 올바르지 않습니다.");
4729
}
4830

4931
if (!region || typeof region !== "number") {
50-
const error: customError = new Error("Bad Request");
51-
error.status = 400;
52-
error.message = "Bad Request";
53-
error.data = {
54-
message: "지역코드가 올바르지 않습니다.",
55-
};
56-
return next(error);
32+
return throwHttpError(400, "지역코드가 올바르지 않습니다.");
5733
}
5834

5935
next();

src/repositorys/moverRepository.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,6 @@ interface whereConditions {
77
OR?: object[];
88
}
99

10-
interface UpdateProfile {
11-
nickname?: string;
12-
career?: number;
13-
introduction?: string;
14-
description?: string;
15-
services?: number[];
16-
regions?: number[];
17-
}
18-
1910
interface Profile {
2011
userId: number;
2112
nickname: string;
@@ -52,14 +43,14 @@ const getMoverCount = async (where: whereConditions) => {
5243
const getMoverList = (
5344
orderBy: { [key: string]: object | string },
5445
where: whereConditions,
55-
cursor: number,
46+
cursor: number | null,
5647
limit: number
5748
) => {
5849
return prismaClient.mover.findMany({
59-
orderBy,
50+
orderBy: [orderBy, { id: "asc" }],
6051
where,
61-
take: limit + 1, //커서 페이지 넘버 계산을 위해 1개 더 조회
62-
skip: cursor ? 1 : 0, //커서 자신을 스킵하기 위함
52+
take: limit + 1,
53+
skip: cursor ? 1 : 0,
6354
cursor: cursor ? { id: cursor } : undefined,
6455
select: {
6556
...defaultSelect,

src/repositorys/movingRequestRepository.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ const getDesignatedMovers = (movingRequestId: number, moverId: number) => {
339339
mover: {
340340
select: {
341341
id: true,
342+
nickname: true,
342343
},
343344
},
344345
},

src/schedules/images.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import cron from "node-cron";
22
import { deleteImages } from "../utils/s3.utils";
33
import imageRepository from "../repositorys/imageRepository";
4-
import CustomError from "../utils/interfaces/customError";
4+
import { throwHttpError } from "../utils/constructors/httpError";
55

66
// 매일 자정에 실행되는 크론 작업
77
export const imageCleanup = () => {
88
cron.schedule("0 0 * * *", async () => {
9-
console.log("이미지 삭제 크론 작업 실행");
109
try {
1110
const inActiveImages = await imageRepository.findInActiveImage(); //비활성화 이미지 조회
1211
// 각 이미지 삭제 처리
@@ -16,14 +15,12 @@ export const imageCleanup = () => {
1615
await deleteImages(image.imageUrl); // S3에서 이미지 삭제
1716
await imageRepository.deleteImage(image.imageUrl); // DB에서 이미지 URL 제거
1817
} catch (e) {
19-
const error: CustomError = new Error();
20-
error.message = "이미지 삭제 실패";
21-
throw error;
18+
return throwHttpError(500, "이미지 삭제 실패");
2219
}
2320
}
2421
}
2522
} catch (error) {
26-
console.error("Error in cleanup job:", error);
23+
return throwHttpError(500, "이미지 삭제 크론 작업 실행 실패");
2724
}
2825
});
2926
};

src/schedules/notifications.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ const setMessage = async (confirmedQuote: ConfirmedQuote) => {
4747
);
4848
return [
4949
{
50-
content: `내일은 ,${pickupLocation} -> ${dropOffLocation} 이사 예정일,이에요.`,
50+
content: `내일은 ,${pickupLocation} ${dropOffLocation} 이사 예정일,이에요.`,
5151
isRead: false,
5252
userId: confirmedQuote.mover.user.id,
5353
},
5454
{
55-
content: `내일은 ,${pickupLocation} -> ${dropOffLocation} 이사 예정일,이에요.`,
55+
content: `내일은 ,${pickupLocation} ${dropOffLocation} 이사 예정일,이에요.`,
5656
isRead: false,
5757
userId: confirmedQuote.customer.user.id,
5858
},

0 commit comments

Comments
 (0)