Files
shop-api/src/modules/user/user.controller.ts
T
2025-11-05 23:17:17 +03:30

216 lines
8.9 KiB
TypeScript

import { Request } from "express";
import rateLimit from "express-rate-limit";
import { inject } from "inversify";
import { controller, httpGet, httpPatch, httpPost, queryParam, request, requestBody } from "inversify-express-utils";
import { HydratedDocument } from "mongoose";
import { ChangeEmailDTO, UpdateUserDTO, VerifyEmailDTO } from "./DTO/userUpdate.dto";
import { IUser } from "./models/Abstraction/IUser";
import { UserService } from "./user.service";
import { HttpStatus } from "../../common";
import { BaseController } from "../../common/base/controller";
import { ApiAuth, ApiBody, ApiFile, ApiModel, ApiOperation, ApiQuery, ApiResponse, ApiTags } from "../../common/decorator/swggerDocs";
import { AuthMessage } from "../../common/enums/message.enum";
import { OrderStatusQuery } from "../../common/types/query.type";
import { appConfig } from "../../core/config/app.config";
import { Guard } from "../../core/middlewares/guard.middleware";
import { ValidationMiddleware } from "../../core/middlewares/validator.middleware";
import { IOCTYPES } from "../../IOC/ioc.types";
import { UploadService } from "../../utils/upload.service";
import { AddressService } from "../address/address.service";
import { AuthService } from "../auth/auth.service";
import { AuthDTO } from "../auth/DTO/Auth.dto";
import { AuthCheckOtpDTO } from "../auth/DTO/AuthCheckOtp.dto";
import { TokenDto } from "../auth/DTO/Token.dto";
import { OrderService } from "../order/order.service";
@controller("/user")
@ApiTags("User")
class UserController extends BaseController {
@inject(IOCTYPES.UserService) userService: UserService;
@inject(IOCTYPES.AuthService) authService: AuthService;
@inject(IOCTYPES.OrderService) orderService: OrderService;
@inject(IOCTYPES.AddressService) addressService: AddressService;
/**
*
* @param authDto
* @returns
*/
@ApiOperation("Authenticate to send OTP code")
@ApiResponse("Successful", 200, { message: AuthMessage.OtpSentToNo, phone: "09122569856" })
@ApiResponse("BadRequest", 400, { details: ["فرمت موبایل اشتباه است"] })
@ApiModel(AuthDTO)
@ApiBody("Authenticate with phone or email")
@httpPost("/authenticate", rateLimit(appConfig.rate), ValidationMiddleware.validateInput(AuthDTO))
async authUser(@requestBody() authDto: AuthDTO) {
const data = await this.authService.authenticate(authDto, "user");
return this.response({ data }, HttpStatus.Ok);
}
/**
*
* @param loginOtpDto
*/
@ApiOperation("login user -> check sent OTP and generate the token")
@ApiResponse("Successful login", 200, { message: AuthMessage.SuccessLogin, Accesstoken: "tokenValue", refreshToken: "tokenValue" })
@ApiModel(AuthCheckOtpDTO)
@ApiBody("login user with otp code")
@httpPost("/login/otp", rateLimit(appConfig.rate), ValidationMiddleware.validateInput(AuthCheckOtpDTO))
async loginOtp(@requestBody() loginOtpDto: AuthCheckOtpDTO) {
const data = await this.authService.loginOtpS(loginOtpDto, "user");
return this.response({ data }, HttpStatus.Created);
}
/**
*
* @param refreshToken
* @returns
*/
@ApiOperation("check the refresh token and generate access token base on that")
@ApiResponse("Successful", 200, { accessToken: "tokenValue", refreshToken: "tokenValue" })
@ApiResponse("unauthorized", 401, { message: AuthMessage.TokenExpired })
@ApiResponse("notFound", 404, { message: AuthMessage.TokenNotFound })
@ApiModel(TokenDto)
@httpPost("/token", rateLimit(appConfig.rate), ValidationMiddleware.validateInput(TokenDto))
public async refreshTokens(@requestBody() refreshToken: TokenDto) {
const data = await this.authService.refreshTokensS(refreshToken);
//return new tokens
return this.response({ data }, HttpStatus.Created);
}
/**
*
* @param req
* @returns
*/
@ApiOperation("logout the user based on the sent authorization token")
@ApiResponse("Successful", 200, { message: AuthMessage.LoggedOut })
@ApiAuth()
@httpPost("/logout", rateLimit(appConfig.rate), Guard.authUser())
public async logout(@request() req: Request) {
//this is maybe user or seller based on token
const user = req.user as IUser;
const data = await this.authService.logoutS(user._id.toString());
//return logout message
return this.response({ data });
}
@ApiOperation("get current logged in user info ")
@ApiResponse("successful", 200)
@ApiAuth()
@httpGet("/profile", Guard.authUser())
public async userProfile(@request() req: Request) {
const user = req.user as HydratedDocument<IUser>;
const data = await this.userService.getProfile(user);
return this.response(data);
}
@ApiOperation("update fields of the user with its current session")
@ApiResponse("successful", HttpStatus.Created)
@ApiModel(UpdateUserDTO)
@ApiAuth()
@httpPatch("/profile", Guard.authUser(), ValidationMiddleware.validateInput(UpdateUserDTO))
async updateUserProfile(@requestBody() updateUserDto: UpdateUserDTO, @request() req: Request) {
const user = req.user as IUser;
const data = await this.userService.updateUserProfileS(updateUserDto, user._id.toString());
return this.response({ data }, HttpStatus.Created);
}
@ApiOperation("change email of current session user")
@ApiResponse("successful", HttpStatus.Ok)
@ApiModel(ChangeEmailDTO)
@ApiAuth()
@httpPost("/profile/email/change", rateLimit(appConfig.rate), Guard.authUser(), ValidationMiddleware.validateInput(ChangeEmailDTO))
public async changeEmail(@requestBody() changeEmailDto: ChangeEmailDTO, @request() req: Request) {
const user = req.user as IUser;
const data = await this.authService.changeUserEmail(changeEmailDto, user._id.toString());
return this.response(data);
}
@ApiOperation("verify email of current session user")
@ApiResponse("successful", HttpStatus.Ok)
@ApiModel(VerifyEmailDTO)
@ApiAuth()
@httpPost("/profile/email/verify", rateLimit(appConfig.rate), Guard.authUser(), ValidationMiddleware.validateInput(VerifyEmailDTO))
public async verifyUserEmail(@requestBody() verifyEmailDto: VerifyEmailDTO, @request() req: Request) {
const user = req.user as IUser;
const data = await this.authService.verifyUserEmail(verifyEmailDto, user._id.toString());
return this.response(data);
}
@ApiOperation("get current logged in user address ")
@ApiResponse("successful", HttpStatus.Ok)
@ApiAuth()
@httpGet("/profile/address", Guard.authUser())
public async getUserAddress(@request() req: Request) {
const user = req.user as IUser;
const data = await this.addressService.getUserAddress(user.address.toString());
return this.response({ address: data });
}
@ApiOperation("get current logged in user comments ")
@ApiResponse("successful", HttpStatus.Ok)
@ApiAuth()
@httpGet("/profile/comments", Guard.authUser())
public async getUserComments(@request() req: Request) {
const user = req.user as IUser;
const data = await this.userService.getUserComments(user._id.toString());
return this.response(data);
}
@ApiOperation("get current logged in user questions ")
@ApiResponse("successful", HttpStatus.Ok)
@ApiAuth()
@httpGet("/profile/questions", Guard.authUser())
public async getUserQuestions(@request() req: Request) {
const user = req.user as IUser;
const data = await this.userService.getUserQuestions(user._id.toString());
return this.response(data);
}
@ApiOperation("get current logged in user product wishlist ")
@ApiResponse("successful", HttpStatus.Ok)
@ApiAuth()
@httpGet("/profile/wishlist", Guard.authUser())
public async getUserWishList(@request() req: Request) {
const user = req.user as IUser;
const data = await this.userService.getUserWishList(user._id.toString());
return this.response(data);
}
//###########################################
//order
@ApiOperation("get current logged in user order ")
@ApiResponse("successful", HttpStatus.Ok)
@ApiQuery("status", "the status of order ==> can be = Delivered | Cancelled | Processing | Returned | Shipped")
@ApiAuth()
@httpGet("/profile/orders", Guard.authUser())
public async getUserOrders(@request() req: Request, @queryParam("status") status: string) {
const statusQuery = status as OrderStatusQuery;
const user = req.user as IUser;
const data = await this.orderService.getUserOrders(user._id.toString(), statusQuery);
return this.response(data);
}
//uploader
@ApiOperation("Upload a user info image")
@ApiResponse("File uploaded successfully", HttpStatus.Accepted)
@ApiFile("image")
@ApiAuth()
@httpPost("/image/upload", Guard.authUser(), UploadService.single("image", "user-profile"))
public async uploadImage(@request() req: Request) {
// eslint-disable-next-line no-undef
const file = req.file as Express.MulterS3.File;
const data = {
message: "file uploaded!",
url: {
size: file?.size,
url: file?.location,
type: file?.mimetype,
},
};
return this.response({ data }, HttpStatus.Accepted);
}
}
export { UserController };