Procházet zdrojové kódy

Bugfix: Implement finishMailVerify functionality with validation and error handling

emrecevik106 před 1 měsícem
rodič
revize
4a0ef76d1a

+ 0 - 9
src/actions/auth/finishMailVerified/types.ts

@@ -1,9 +0,0 @@
-export interface FinishMailVerifyInput {
-    userID: string;
-    code: string;
-}
-
-export interface FinishMailVerifyResult {
-    message: string;
-    code: number;
-}

+ 10 - 17
src/actions/auth/finishMailVerified/index.ts → src/actions/auth/finishMailVerify/index.ts

@@ -1,31 +1,24 @@
 import {
-    User
+    User 
 } from "../../../models/User";
 import redis from "../../../config/redis";
 import {
-    FinishMailVerifyResult,
-    FinishMailVerifyInput
+    FinishMailVerifyResult, 
+    FinishMailVerifyInput 
 } from "./types";
 
 const finishMailVerify = async (input: FinishMailVerifyInput): Promise<FinishMailVerifyResult> => {
     try {
         const {
             userID,
-            code
+            code 
         } = input;
 
-        if (!userID || !code) {
-            return {
-                message: "userID-and-code-required",
-                code: 400,
-            };
-        }
-
         const user = await User.findById(userID);
         if (!user) {
             return {
                 message: "user-not-found",
-                code: 404
+                code: 404 
             };
         }
 
@@ -33,32 +26,32 @@ const finishMailVerify = async (input: FinishMailVerifyInput): Promise<FinishMai
         if (!cachedCode) {
             return {
                 message: "exceeded-time-limit-for-request",
-                code: 400
+                code: 400 
             };
         }
 
         if (cachedCode !== code) {
             return {
                 message: "invalid-code",
-                code: 400
+                code: 400 
             };
         }
 
         await User.findByIdAndUpdate(userID, {
-            isMailVerified: true
+            isMailVerified: true 
         });
         await redis.del(`mail-verify-${userID}`);
 
         return {
             message: "mail-verified",
-            code: 200
+            code: 200 
         };
 
     } catch (error) {
         console.error("FinishMailVerify error:", error);
         return {
             message: "internal-server-error",
-            code: 500
+            code: 500 
         };
     }
 };

+ 19 - 0
src/actions/auth/finishMailVerify/types.ts

@@ -0,0 +1,19 @@
+import {
+    IsNotEmpty, 
+    IsString 
+} from "class-validator";
+
+export class FinishMailVerifyInput {
+    @IsNotEmpty({ message: "userID-is-required" })
+    @IsString()
+    userID?: string;
+
+    @IsNotEmpty({ message: "code-is-required" })
+    @IsString()
+    code?: string;
+}
+
+export interface FinishMailVerifyResult {
+    message: string;
+    code: number;
+}

+ 1 - 1
src/actions/auth/index.ts

@@ -15,4 +15,4 @@ export {
 } from "./refreshToken";
 export {
     default as finishMailVerify 
-} from "./finishMailVerified";
+} from "./finishMailVerify";

+ 4 - 2
src/actions/auth/logout/index.ts

@@ -7,7 +7,7 @@ import {
 } from "../../../models/User";
 import redis from "../../../config/redis";
 
-export const logout = async (context?: ContextType): Promise<LogoutResult> => {
+const logout = async (context?: ContextType): Promise<LogoutResult> => {
     try {
         if (!context) {
             return {
@@ -44,4 +44,6 @@ export const logout = async (context?: ContextType): Promise<LogoutResult> => {
             code: 500,
         };
     }
-};
+};
+
+export default logout;

+ 12 - 14
src/actions/auth/refreshToken/index.ts

@@ -4,18 +4,13 @@ import {
     User 
 } from "../../../models/User";
 import {
+    RefreshTokenInput,
     RefreshTokenResult 
 } from "./types";
 
-const refreshToken = async (token: string): Promise<RefreshTokenResult> => {
+const refreshToken = async (input: RefreshTokenInput): Promise<RefreshTokenResult> => {
+    const token = input.refreshToken!;
     try {
-        if (!token) {
-            return {
-                message: "refreshToken-required",
-                code: 400
-            };
-        }
-
         const user = await User.findOne({
             refreshToken: token 
         });
@@ -32,6 +27,7 @@ const refreshToken = async (token: string): Promise<RefreshTokenResult> => {
             companyName: string;
             fullName: string;
             userID: string;
+            token: string;
         };
 
         try {
@@ -48,9 +44,10 @@ const refreshToken = async (token: string): Promise<RefreshTokenResult> => {
 
         const newAccessToken = jwt.sign(
             {
-                companyName: user.companyName,
-                fullName: user.fullName,
-                userID: user._id
+                companyName: decoded.companyName,
+                fullName: decoded.fullName,
+                userID: decoded.userID,
+                token: token
             },
             process.env.JWT_SECRET as string,
             {
@@ -60,9 +57,10 @@ const refreshToken = async (token: string): Promise<RefreshTokenResult> => {
 
         const newRefreshToken = jwt.sign(
             {
-                companyName: user.companyName,
-                fullName: user.fullName,
-                userID: user._id
+                companyName: decoded.companyName,
+                fullName: decoded.fullName,
+                userID: decoded.userID,
+                token: token
             },
             process.env.JWT_SECRET as string,
             {

+ 10 - 0
src/actions/auth/refreshToken/types.ts

@@ -1,3 +1,13 @@
+import {
+    IsNotEmpty,
+    IsString 
+} from "class-validator";
+
+export class RefreshTokenInput {
+    @IsNotEmpty({ message: "refreshToken-required" })
+    @IsString({ message: "refreshToken-must-be-string" })
+    refreshToken?: string;
+}
 export interface RefreshTokenResult {
     code: number;
     message: string;

+ 2 - 20
src/actions/auth/register/index.ts

@@ -1,30 +1,12 @@
-import {
-    plainToInstance 
-} from "class-transformer";
-import {
-    validate 
-} from "class-validator";
 import {
     User 
 } from "../../../models/User";
 import {
-    RegisterInput, RegisterResult 
+    RegisterInput,
+    RegisterResult 
 } from "./types";
-import {
-    formatValidationErrors 
-} from "../../../utils";
 
 const register = async (input: RegisterInput): Promise<RegisterResult> => {
-    const dto = plainToInstance(RegisterInput, input);
-    const errors = await validate(dto);
-
-    if (errors.length > 0) {
-        return {
-            message: formatValidationErrors(errors),
-            code: 400,
-        };
-    }
-
     const {
         companyName,
         phoneNumber,

+ 1 - 1
src/actions/auth/register/types.ts

@@ -30,6 +30,6 @@ export class RegisterInput {
 }
 
 export interface RegisterResult {
-    message: string | string[];
+    message: string;
     code: number;
 }

+ 19 - 74
src/controllers/authController.ts

@@ -3,8 +3,8 @@ import {
     Request
 } from "express";
 import {
-    refreshToken as _refreshToken,
     finishMailVerify as _finishMailVerify,
+    refreshToken as _refreshToken,
     register as _register,
     logout as _logout,
     login as _login,
@@ -15,39 +15,13 @@ import {
 } from "../middlewares/authMiddleware";
 
 export const register = async (req: Request, res: Response): Promise<void> => {
-    try {
-        const {
-            phoneNumber,
-            companyName,
-            firstName,
-            lastName,
-            password,
-            mail
-        } = req.body;
-
-        const result = await _register({
-            phoneNumber,
-            companyName,
-            firstName,
-            lastName,
-            password,
-            mail
+    const result = await _register(req.body);
+    
+    res.status(result.code)
+        .json({
+            message: result.message,
+            code: result.code
         });
-
-        res.status(result.code)
-            .json({
-                message: result.message,
-                code: result.code
-            });
-
-    } catch (error) {
-        console.error("Register error:", error);
-        res.status(500)
-            .json({
-                message: "internal-server-error",
-                code: 500,
-            });
-    }
 };
 
 export const login = async (req: Request, res: Response): Promise<void> => {
@@ -116,53 +90,24 @@ export const me = async (req: AuthRequest, res: Response): Promise<void> => {
 };
 
 export const refreshToken = async (req: Request, res: Response): Promise<void> => {
-    try {
-        const {
-            refreshToken
-        } = req.body;
-
-        const result = await _refreshToken(refreshToken);
+    const result = await _refreshToken(req.body);
 
-        res.status(result.code)
-            .json({
-                message: result.message,
-                code: result.code,
-                ...(result.payload && {
-                    payload: result.payload,
-                }),
-            });
-    } catch (error) {
-        console.error("RefreshToken controller error:", error);
-        res.status(500)
-            .json({
-                message: "internal-server-error",
-                code: 500,
-            });
-    }
+    res.status(result.code)
+        .json({
+            message: result.message,
+            code: result.code,
+            ...(result.payload && {
+                payload: result.payload,
+            }),
+        });
 };
 
 export const finishMailVerify = async (req: Request, res: Response): Promise<void> => {
-    try {
-        const {
-            userID,
-            code
-        } = req.body;
-
-        const result = await _finishMailVerify({
-            userID,
-            code
-        });
+    const result = await _finishMailVerify(req.body);
 
-        res.status(result.code).json({
+    res.status(result.code)
+        .json({
             message: result.message,
             code: result.code,
         });
-
-    } catch (error) {
-        console.error("FinishMailVerify controller error:", error);
-        res.status(500).json({
-            message: "internal-server-error",
-            code: 500
-        });
-    }
 };

+ 6 - 4
src/middlewares/authMiddleware.ts

@@ -29,16 +29,18 @@ export const authMiddleware = async (req: AuthRequest, res: Response, next: Next
         }
 
         let decoded: { 
-            userID: string;
-            fullName: string;
             companyName: string;
+            fullName: string;
+            userID: string;
+            token:string;
         };
         
         try {
             decoded = jwt.verify(token, process.env.JWT_SECRET as string) as { 
-                userID: string,
-                fullName: string;
                 companyName: string;
+                fullName: string;
+                userID: string,
+                token:string;
             };
         } catch (err) {
             res.status(401)

+ 32 - 0
src/middlewares/validateBody.ts

@@ -0,0 +1,32 @@
+import {
+    plainToInstance 
+} from "class-transformer";
+import {
+    validate 
+} from "class-validator";
+import {
+    Request,
+    Response,
+    NextFunction 
+} from "express";
+import {
+    formatValidationErrors 
+} from "../utils";
+
+export const validateBody = (dto: any) => {
+    return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
+        const instance = plainToInstance(dto, req.body);
+        const errors = await validate(instance);
+
+        if (errors.length > 0) {
+            res.status(400).json({
+                message: formatValidationErrors(errors),
+                code: 400 
+            });
+            return;
+        }
+
+        req.body = instance;
+        next();
+    };
+};

+ 19 - 5
src/routes/authRoutes.ts

@@ -13,13 +13,30 @@ import {
     authMiddleware, 
     AuthRequest
 } from "../middlewares/authMiddleware";
+import {
+    validateBody 
+} from "../middlewares/validateBody";
+import {
+    RegisterInput 
+} from "../actions/auth/register/types";
+import {
+    LoginInput 
+} from "../actions/auth/login/types";
+import {
+    FinishMailVerifyInput 
+} from "../actions/auth/finishMailVerify/types";
+import {
+    RefreshTokenInput
+} from "../actions/auth/refreshToken/types";
 
 const router = Router();
 
+router.post("/register", validateBody(RegisterInput), register);
+router.post("/login", validateBody(LoginInput), login);
+router.post("/refresh-token", validateBody(RefreshTokenInput), refreshToken);
+router.post("/finish-mail-verify", validateBody(FinishMailVerifyInput), finishMailVerify);
 router.post("/logout", authMiddleware, logout);
 router.get("/me", authMiddleware, me);
-router.post("/register", register);
-router.post("/login", login);
 
 router.get("/validate-token", authMiddleware, (req:AuthRequest, res) => {
     res.status(200)
@@ -30,7 +47,4 @@ router.get("/validate-token", authMiddleware, (req:AuthRequest, res) => {
         });
 });
 
-router.post("/refresh-token", refreshToken);
-router.post("/finish-mail-verify", finishMailVerify);
-
 export default router;