Skip to content

Commit

Permalink
Merge branch 'develop' into feature/issue-199/protect-routing-with-role
Browse files Browse the repository at this point in the history
  • Loading branch information
lcaohoanq authored Jul 5, 2024
2 parents d96b6b6 + 267069f commit 89d8ae2
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 70 deletions.
71 changes: 64 additions & 7 deletions src/modules/user/user.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,26 @@ import { OTP_MESSAGES } from "../otp/otp.messages";
import { UserRole } from "./user.enum";
import { USER_MESSAGES } from "./user.messages";
import {

BlockBody,

ListAccountQuery,

LoginRequestBody,
LogoutReqBody,
RefreshTokenReqBody,
RegisterReqBody,
TokenPayload,
UpdateMeReqBody,
UserResponseAfterCheckEmailOrPhone,
} from "./user.requests";
import User from "./user.schema";
import usersService from "./user.services";
UserResponseAfterCheckEmailOrPhone
} from './user.requests'
import User from './user.schema'
import usersService from './user.services'
import adminService from "../admin/admin.services";
import { UserList } from "~/constants/user.type";
import { UserRole } from "./user.enum";



export const registerController = async (
req: Request<ParamsDictionary, any, RegisterReqBody>,
Expand Down Expand Up @@ -254,9 +263,56 @@ export const refreshTokenController = async (

return res.json({
message: USER_MESSAGES.REFRESH_TOKEN_SUCCESSFULLY,
data: { access_token },
});
};

data: { access_token }
})
}

export const blockAccountController = async (
req: Request<ParamsDictionary, any, BlockBody>,
res: Response
) => {
console.log(req.cookies['refresh_token'])
await usersService.logout(req.cookies['refresh_token'])
res.clearCookie('refresh_token')
try {
const reason = req.body.description_reason
const picture_image_prove = req.body.picture_image_prove
const timeBlock = new Date()
const user_id = req.body._id
await usersService.blockAccount(
user_id,
reason,
picture_image_prove,
timeBlock
)
return res.json({
message: USER_MESSAGES.USER_HAS_BEEN_BLOCKED
})
} catch (error) {
return res.status(400).json({
message: 'Bad request'
})
}
}

export const unblockAccountController = async (
req: Request<ParamsDictionary, any, BlockBody>,
res: Response
) => {
try {
const user_id = req.body._id
await usersService.unblockAccount(user_id)
return res.json({
message: USER_MESSAGES.USER_UNBLOCK_SUCCESSFULLY
})
} catch (error) {
return res.status(400).json({
message: 'Bad request'
})
}
}


export const getListUserController = async (req: Request, res: Response) => {
const query = req.queryListAccount as ListAccountQuery;
Expand Down Expand Up @@ -344,3 +400,4 @@ export const getListUserController = async (req: Request, res: Response) => {
});
}
};

9 changes: 7 additions & 2 deletions src/modules/user/user.messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,14 @@ export const USER_MESSAGES = {
WRONG_PASS_5_TIMES: "Entered wrong password over 5 times!",

//token
REFRESH_TOKEN_IS_REQUIRED: "Refresh token is required",
OTP_IS_INCORRECT: "OTP is incorrect",

REFRESH_TOKEN_IS_REQUIRED: 'Refresh token is required',
OTP_IS_INCORRECT: 'OTP is incorrect',
// block
USER_HAS_BEEN_BLOCKED: 'user has been blocked',
USER_UNBLOCK_SUCCESSFULLY: 'user unblock successfully'

//don't have permission
DONT_HAVE_PERMISSION: `You don't have permission`,
} as const;

8 changes: 5 additions & 3 deletions src/modules/user/user.middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { checkRole, routesConfig } from "../protectRouting/protect.utils";
import { NoticeUser, UserRole, UserVerifyStatus } from "./user.enum";
import { LoginRequestBody, TokenPayload } from "./user.requests";
import usersService from "./user.services";

//! Prevent db injection, XSS attack
export const paramSchema: ParamSchema = {
customSanitizer: {
Expand Down Expand Up @@ -290,7 +289,9 @@ export const loginValidator = validate(

if (
user.notice === NoticeUser.Banned ||
user.reasonBanned !== ""
user.reasonBanned !== '' ||
user.block === Subscription.True

) {
throw new ErrorWithStatus({
message: USER_MESSAGES.ACCOUNT_IS_BANNED,
Expand Down Expand Up @@ -375,7 +376,8 @@ export const loginValidator = validate(

if (
user.notice === NoticeUser.Banned ||
user.reasonBanned !== ""
user.reasonBanned !== '' ||
user.block === Subscription.True
) {
throw new ErrorWithStatus({
message: USER_MESSAGES.ACCOUNT_IS_BANNED,
Expand Down
11 changes: 9 additions & 2 deletions src/modules/user/user.requests.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ObjectId } from 'mongodb'
import { JwtPayload } from "jsonwebtoken";
import {
Subscription,
Expand Down Expand Up @@ -79,8 +80,14 @@ export type LogoutReqBody = {
};

export type RefreshTokenReqBody = {
refresh_token: string;
};
refresh_token: string
}
export interface BlockBody {
_id: ObjectId
description_reason?: string
picture_image_prove?: string
refresh_token: string
}

export type ListAccountQuery = {
page?: number;
Expand Down
15 changes: 13 additions & 2 deletions src/modules/user/user.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Router } from "express";
import { cronJobFake } from "~/utils/cronJobFake";
import { wrapAsync } from "~/utils/handler";
import {
blockAccountController,
changePasswordController,
forgotPasswordController,
getListUserController,
Expand All @@ -14,6 +15,7 @@ import {
resetPasswordController,
searchAccountController,
sendVerifyAccountOTPController,
unblockAccountController,
updateMeController,
verifyAccountController,
verifyForgotPasswordTokenController,
Expand Down Expand Up @@ -233,8 +235,17 @@ usersRouter.post(
usersRouter.post(
"/refresh-token",
refreshTokenCookieValidator,
wrapAsync(refreshTokenController),
);
wrapAsync(refreshTokenController)
)

usersRouter.post(
'/block',
accessTokenValidator,
refreshTokenCookieValidator,
wrapAsync(blockAccountController)
)

usersRouter.post('/unblock', wrapAsync(unblockAccountController))

usersRouter.get(
"/list-account",
Expand Down
97 changes: 55 additions & 42 deletions src/modules/user/user.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,56 +9,69 @@ import {
interface UserType {
_id?: ObjectId;
// username: string
first_name: string;
last_name: string;
phone_number?: string;
password: string;
email?: string;
role?: UserRole;
created_at?: Date;
updated_at?: Date;
status?: UserVerifyStatus;
notice?: NoticeUser;
wrongPasswordTimes?: number;
reasonBanned?: string;
avatar_url?: string;
subscription: Subscription;
first_name: string
last_name: string
phone_number?: string
password: string
email?: string
role?: UserRole
created_at?: Date
updated_at?: Date
status?: UserVerifyStatus
notice?: NoticeUser
block?: Subscription
reasonBlocked?: string
picture_image_prove?: string
block_time?: Date
wrongPasswordTimes?: number
reasonBanned?: string
avatar_url?: string
subscription: Subscription
}

export default class User {
_id?: ObjectId;
// username: string
first_name: string;
last_name: string;
phone_number: string;
password: string;
email: string;
role: UserRole;
created_at: Date;
updated_at: Date;
status: UserVerifyStatus;
notice: NoticeUser;
wrongPasswordTimes?: number;
reasonBanned?: string;
avatar_url: string;
subscription: Subscription;
first_name: string
last_name: string
phone_number: string
password: string
email: string
role: UserRole
created_at: Date
updated_at: Date
status: UserVerifyStatus
notice: NoticeUser
block: Subscription
reasonBlocked?: string
picture_image_prove?: string
block_time: Date
wrongPasswordTimes?: number
reasonBanned?: string
avatar_url: string
subscription: Subscription

constructor(user: UserType) {
const date = new Date();
this._id = user._id || new ObjectId();
// this.username = user.username || ''
this.first_name = user.first_name || "";
this.last_name = user.last_name || "";
this.phone_number = user.phone_number || "";
this.password = user.password;
this.email = user.email || "";
this.role = user.role || UserRole.Customer;
this.created_at = user.created_at || date;
this.updated_at = user.updated_at || date;
this.status = user.status || UserVerifyStatus.Unverified;
this.notice = NoticeUser.Active;
this.wrongPasswordTimes = 0;
this.reasonBanned = user.reasonBanned || "";
this.avatar_url = user.avatar_url || "";
this.subscription = user.subscription || Subscription.False;
this.first_name = user.first_name || ''
this.last_name = user.last_name || ''
this.phone_number = user.phone_number || ''
this.password = user.password
this.email = user.email || ''
this.role = user.role || UserRole.Customer
this.created_at = user.created_at || date
this.updated_at = user.updated_at || date
this.status = user.status || UserVerifyStatus.Unverified
this.notice = NoticeUser.Active
this.block = Subscription.False
this.reasonBlocked = user.reasonBlocked || ''
this.picture_image_prove = user.picture_image_prove || ''
this.block_time = user.block_time || date
this.wrongPasswordTimes = 0
this.reasonBanned = user.reasonBanned || ''
this.avatar_url = user.avatar_url || ''
this.subscription = user.subscription || Subscription.False
}
}
66 changes: 54 additions & 12 deletions src/modules/user/user.services.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import "dotenv/config";
import { capitalize, omit } from "lodash";
import { ObjectId } from "mongodb";
import otpGenerator from "otp-generator";
import 'dotenv/config'
import { capitalize, omit } from 'lodash'
import { ObjectId } from 'mongodb'
import otpGenerator from 'otp-generator'
import { UserList } from "~/constants/user.type";
import databaseService from "~/database/database.services";
import { capitalizePro } from "~/utils/capitalize";
import decrypt, { encrypt, hashPassword } from "~/utils/crypto";
import { signToken, verifyToken } from "~/utils/jwt";
import { OTP_KIND } from "../otp/otp.enum";
import otpService from "../otp/otp.services";
import RefreshToken from "../refreshToken/refreshToken.schema";
import { NoticeUser, TokenType, UserRole, UserVerifyStatus } from "./user.enum";
import databaseService from '~/database/database.services'
import { capitalizePro } from '~/utils/capitalize'
import decrypt, { encrypt, hashPassword } from '~/utils/crypto'
import { signToken, verifyToken } from '~/utils/jwt'
import { OTP_KIND } from '../otp/otp.enum'
import otpService from '../otp/otp.services'
import RefreshToken from '../refreshToken/refreshToken.schema'
import {
NoticeUser,
Subscription,
TokenType,
UserRole,
UserVerifyStatus
} from './user.enum'
import {
ListAccountQuery,
LogoutReqBody,
Expand Down Expand Up @@ -357,6 +363,42 @@ class UsersService {
return true;
}

async blockAccount(
user_id: ObjectId,
re?: string,
pi?: string,
time?: Date
) {
await databaseService.users.updateMany(
{ _id: new ObjectId(user_id) },
{
$set: {
block: Subscription.True,
reasonBlocked: re,
picture_image_prove: pi,
block_time: time
}
}
)

return true
}

async unblockAccount(user_id: ObjectId) {
await databaseService.users.updateMany(
{ _id: new ObjectId(user_id) },
{
$set: {
block: Subscription.False,
reasonBlocked: '',
picture_image_prove: ''
}
}
)

return true
}

async updateMe({
user_id,
payload,
Expand Down

0 comments on commit 89d8ae2

Please sign in to comment.