Spaces:
Sleeping
Sleeping
Commit
Β·
2f0e1b7
1
Parent(s):
484fdbc
feat: auth refactors
Browse files- src/common/interfaces/jwt-payload.interface.ts +15 -0
- src/common/services/users.base.service.ts +0 -54
- src/helpers/validation.helper.ts +1 -20
- src/modules/console/common/guards/admins.guard.ts +45 -0
- src/modules/console/{admins β common}/models/admin.model.ts +0 -0
- src/modules/console/{admins β modules/admins}/controllers/admins.controller.ts +5 -1
- src/modules/console/{admins β modules/admins}/services/admins.service.ts +1 -1
- src/modules/console/{admins β modules/admins}/validations/create-admin.validation.ts +0 -0
- src/modules/console/{users β modules/users}/controllers/users.controller.ts +4 -8
- src/modules/console/{users β modules/users}/services/users.service.ts +0 -0
- src/modules/users/auth/controllers/auth.controller.ts +4 -4
src/common/interfaces/jwt-payload.interface.ts
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Role } from "@common/enums/role.enum";
|
2 |
+
|
3 |
+
export type IJwtLoginPayload = {
|
4 |
+
id: string;
|
5 |
+
email: string;
|
6 |
+
name: string;
|
7 |
+
} & (
|
8 |
+
| {
|
9 |
+
role: Role;
|
10 |
+
type: "admin";
|
11 |
+
}
|
12 |
+
| {
|
13 |
+
type: "user";
|
14 |
+
}
|
15 |
+
);
|
src/common/services/users.base.service.ts
DELETED
@@ -1,54 +0,0 @@
|
|
1 |
-
import { FilterQuery } from "mongoose";
|
2 |
-
import { HttpError } from "src/lib/error-handling/http-error";
|
3 |
-
import { UserDocument, userModel, IUser } from "../models/user.model";
|
4 |
-
|
5 |
-
export abstract class BaseUsersService {
|
6 |
-
async findOne(filterObject: FilterQuery<UserDocument>) {
|
7 |
-
return userModel.findOne(filterObject);
|
8 |
-
}
|
9 |
-
|
10 |
-
async findOneOrFail(
|
11 |
-
filterObject: FilterQuery<UserDocument>
|
12 |
-
): Promise<UserDocument> {
|
13 |
-
try {
|
14 |
-
const document = await this.findOne(filterObject);
|
15 |
-
if (!document) throw new HttpError(404, "No Matching Result Found.");
|
16 |
-
|
17 |
-
return document;
|
18 |
-
} catch (err) {
|
19 |
-
console.error(err);
|
20 |
-
throw new HttpError(500, "Unexpected Error Happened.");
|
21 |
-
}
|
22 |
-
}
|
23 |
-
|
24 |
-
async userExists(filterObject: FilterQuery<UserDocument>): Promise<boolean> {
|
25 |
-
return (await this.findOne(filterObject)) !== null;
|
26 |
-
}
|
27 |
-
|
28 |
-
async create(createParams: IUser): Promise<UserDocument> {
|
29 |
-
if (await this.userExists({ email: createParams.email }))
|
30 |
-
throw new HttpError(409, "Email Already Exists.");
|
31 |
-
|
32 |
-
const newUser = new userModel(createParams) as UserDocument;
|
33 |
-
return newUser.save();
|
34 |
-
}
|
35 |
-
|
36 |
-
async get(filterObject: FilterQuery<UserDocument>): Promise<UserDocument> {
|
37 |
-
const user: UserDocument = await userModel
|
38 |
-
.findOne(filterObject)
|
39 |
-
.select("-password");
|
40 |
-
if (!user) throw new HttpError(404, "No Matching Result Found.");
|
41 |
-
return user;
|
42 |
-
}
|
43 |
-
|
44 |
-
async list(filterObject: FilterQuery<UserDocument>): Promise<{
|
45 |
-
docs: UserDocument[];
|
46 |
-
count: number;
|
47 |
-
}> {
|
48 |
-
const users = (await userModel
|
49 |
-
.find(filterObject)
|
50 |
-
.select("-password")) as UserDocument[];
|
51 |
-
const count = await userModel.countDocuments(filterObject);
|
52 |
-
return { docs: users, count };
|
53 |
-
}
|
54 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/helpers/validation.helper.ts
CHANGED
@@ -1,22 +1,3 @@
|
|
1 |
-
// export const validator = (schema: any) => {
|
2 |
-
// return (req: any, res: any, next: any) => {
|
3 |
-
// try {
|
4 |
-
// let validationResult = schema.body.validate(req.body);
|
5 |
-
// var validation = [];
|
6 |
-
// if (validationResult.error) {
|
7 |
-
// validation.push(validationResult.error.details[0].message);
|
8 |
-
// }
|
9 |
-
// if (validation.length) {
|
10 |
-
// return res.status(400).json({ success: false, error: validation.join(), code: 400 });
|
11 |
-
// }
|
12 |
-
// next();
|
13 |
-
// } catch (err) {
|
14 |
-
// console.log(`err`, err);
|
15 |
-
// return res.status(400).json({ success: false, error: "Bad Request!", code: 400 });
|
16 |
-
// }
|
17 |
-
// };
|
18 |
-
// };
|
19 |
-
|
20 |
import { NextFunction, Request, Response } from "express";
|
21 |
import { createValidator } from "express-joi-validation";
|
22 |
import Joi from "joi";
|
@@ -32,7 +13,7 @@ export const paramsValidator = (schemaOrParam: Joi.Schema | string) =>
|
|
32 |
|
33 |
export const validationErrorHandler = (
|
34 |
err,
|
35 |
-
|
36 |
res: Response,
|
37 |
next: NextFunction
|
38 |
) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import { NextFunction, Request, Response } from "express";
|
2 |
import { createValidator } from "express-joi-validation";
|
3 |
import Joi from "joi";
|
|
|
13 |
|
14 |
export const validationErrorHandler = (
|
15 |
err,
|
16 |
+
_req: Request,
|
17 |
res: Response,
|
18 |
next: NextFunction
|
19 |
) => {
|
src/modules/console/common/guards/admins.guard.ts
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { JwtPayload, verify } from "jsonwebtoken";
|
2 |
+
import { Request } from "express";
|
3 |
+
import { Role } from "@common/enums/role.enum";
|
4 |
+
import { HttpError } from "@lib/error-handling/http-error";
|
5 |
+
import { config } from "@configs/config";
|
6 |
+
import { IJwtLoginPayload } from "@common/interfaces/jwt-payload.interface";
|
7 |
+
|
8 |
+
type AdminGuardMiddlewareProps = {
|
9 |
+
roles?: Role[];
|
10 |
+
};
|
11 |
+
|
12 |
+
export const AdminGuardMiddleware =
|
13 |
+
(props?: AdminGuardMiddlewareProps) => (req: Request, res, next) => {
|
14 |
+
// get token from cookie
|
15 |
+
const token = req.headers.authorization?.split(" ")[1];
|
16 |
+
let payload: IJwtLoginPayload;
|
17 |
+
|
18 |
+
// validate token
|
19 |
+
if (!token) {
|
20 |
+
throw new HttpError(401, "Unauthorized");
|
21 |
+
}
|
22 |
+
|
23 |
+
try {
|
24 |
+
payload = verify(token, config.jwt.secret);
|
25 |
+
} catch (err) {
|
26 |
+
throw new HttpError(401, "Unauthorized");
|
27 |
+
}
|
28 |
+
|
29 |
+
if (payload.type !== "admin") {
|
30 |
+
throw new HttpError(401, "Unauthorized");
|
31 |
+
}
|
32 |
+
|
33 |
+
// check roles
|
34 |
+
if (props?.roles && props?.roles.length > 0) {
|
35 |
+
if (!props.roles.includes(payload.role)) {
|
36 |
+
throw new HttpError(401, "Unauthorized");
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
// inject payload in request
|
41 |
+
(req as unknown as { jwtPayload: JwtPayload }).jwtPayload = payload;
|
42 |
+
|
43 |
+
// go on
|
44 |
+
next();
|
45 |
+
};
|
src/modules/console/{admins β common}/models/admin.model.ts
RENAMED
File without changes
|
src/modules/console/{admins β modules/admins}/controllers/admins.controller.ts
RENAMED
@@ -2,13 +2,17 @@ import { asyncHandler } from "@helpers/async-handler";
|
|
2 |
import { paramsValidator, bodyValidator } from "@helpers/validation.helper";
|
3 |
import { BaseController } from "@lib/controllers/controller.base";
|
4 |
import { Prefix } from "@lib/decorators/prefix.decorator";
|
5 |
-
import { Request, Response
|
6 |
import { AdminsService } from "../services/admins.service";
|
7 |
import { createAdminSchema } from "../validations/create-admin.validation";
|
8 |
import { parsePaginationQuery } from "@helpers/pagination";
|
9 |
import { JsonResponse } from "@lib/responses/json-response";
|
|
|
|
|
|
|
10 |
|
11 |
@Prefix("/console/admins")
|
|
|
12 |
export class AdminsController extends BaseController {
|
13 |
private adminsService = new AdminsService();
|
14 |
|
|
|
2 |
import { paramsValidator, bodyValidator } from "@helpers/validation.helper";
|
3 |
import { BaseController } from "@lib/controllers/controller.base";
|
4 |
import { Prefix } from "@lib/decorators/prefix.decorator";
|
5 |
+
import { Request, Response } from "express";
|
6 |
import { AdminsService } from "../services/admins.service";
|
7 |
import { createAdminSchema } from "../validations/create-admin.validation";
|
8 |
import { parsePaginationQuery } from "@helpers/pagination";
|
9 |
import { JsonResponse } from "@lib/responses/json-response";
|
10 |
+
import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
|
11 |
+
import { AdminGuardMiddleware } from "src/modules/console/common/guards/admins.guard";
|
12 |
+
import { Role } from "@common/enums/role.enum";
|
13 |
|
14 |
@Prefix("/console/admins")
|
15 |
+
@ControllerMiddleware(AdminGuardMiddleware({ roles: [Role.SUPER_ADMIN] }))
|
16 |
export class AdminsController extends BaseController {
|
17 |
private adminsService = new AdminsService();
|
18 |
|
src/modules/console/{admins β modules/admins}/services/admins.service.ts
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { Admin } from "
|
2 |
import { CrudService } from "@lib/services/crud.service";
|
3 |
|
4 |
export class AdminsService extends CrudService(Admin) {}
|
|
|
1 |
+
import { Admin } from "../../../common/models/admin.model";
|
2 |
import { CrudService } from "@lib/services/crud.service";
|
3 |
|
4 |
export class AdminsService extends CrudService(Admin) {}
|
src/modules/console/{admins β modules/admins}/validations/create-admin.validation.ts
RENAMED
File without changes
|
src/modules/console/{users β modules/users}/controllers/users.controller.ts
RENAMED
@@ -1,14 +1,11 @@
|
|
1 |
import { userRegisterSchema } from "src/common/validations/user-register.validation";
|
2 |
-
import { asyncHandler } from "../../../../helpers/async-handler";
|
3 |
-
import { JwtHelper } from "../../../../helpers/jwt.helper";
|
4 |
-
import { bodyValidator } from "../../../../helpers/validation.helper";
|
5 |
-
import { BaseController } from "../../../../lib/controllers/controller.base";
|
6 |
-
import { Prefix } from "../../../../lib/decorators/prefix.decorator";
|
7 |
import { UsersService } from "../services/users.service";
|
8 |
import { JsonResponse } from "src/lib/responses/json-response";
|
9 |
import { Request, Response } from "express";
|
10 |
-
|
11 |
-
|
|
|
|
|
12 |
|
13 |
@Prefix("/console/users")
|
14 |
export class AdminUsersController extends BaseController {
|
@@ -17,7 +14,6 @@ export class AdminUsersController extends BaseController {
|
|
17 |
setRoutes() {
|
18 |
this.router.post(
|
19 |
"/create",
|
20 |
-
JwtHelper.verifyToken(allowedRoles),
|
21 |
bodyValidator(userRegisterSchema),
|
22 |
asyncHandler(this.create)
|
23 |
);
|
|
|
1 |
import { userRegisterSchema } from "src/common/validations/user-register.validation";
|
|
|
|
|
|
|
|
|
|
|
2 |
import { UsersService } from "../services/users.service";
|
3 |
import { JsonResponse } from "src/lib/responses/json-response";
|
4 |
import { Request, Response } from "express";
|
5 |
+
import { asyncHandler } from "@helpers/async-handler";
|
6 |
+
import { bodyValidator } from "@helpers/validation.helper";
|
7 |
+
import { BaseController } from "@lib/controllers/controller.base";
|
8 |
+
import { Prefix } from "@lib/decorators/prefix.decorator";
|
9 |
|
10 |
@Prefix("/console/users")
|
11 |
export class AdminUsersController extends BaseController {
|
|
|
14 |
setRoutes() {
|
15 |
this.router.post(
|
16 |
"/create",
|
|
|
17 |
bodyValidator(userRegisterSchema),
|
18 |
asyncHandler(this.create)
|
19 |
);
|
src/modules/console/{users β modules/users}/services/users.service.ts
RENAMED
File without changes
|
src/modules/users/auth/controllers/auth.controller.ts
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
import { UsersAuthService } from "../services/users.service";
|
2 |
-
import { BaseController } from "../../../../lib/controllers/controller.base";
|
3 |
-
import { bodyValidator } from "../../../../helpers/validation.helper";
|
4 |
-
import { asyncHandler } from "../../../../helpers/async-handler";
|
5 |
-
import { Prefix } from "../../../../lib/decorators/prefix.decorator";
|
6 |
import { loginValidationSchema } from "../validation/login.validation";
|
7 |
import { Request, Response } from "express";
|
8 |
import { JsonResponse } from "src/lib/responses/json-response";
|
9 |
import { userRegisterSchema, IUserRegister } from "src/common/validations/user-register.validation";
|
|
|
|
|
|
|
|
|
10 |
|
11 |
@Prefix("/users/auth")
|
12 |
export class UsersAuthController extends BaseController {
|
|
|
1 |
import { UsersAuthService } from "../services/users.service";
|
|
|
|
|
|
|
|
|
2 |
import { loginValidationSchema } from "../validation/login.validation";
|
3 |
import { Request, Response } from "express";
|
4 |
import { JsonResponse } from "src/lib/responses/json-response";
|
5 |
import { userRegisterSchema, IUserRegister } from "src/common/validations/user-register.validation";
|
6 |
+
import { asyncHandler } from "@helpers/async-handler";
|
7 |
+
import { bodyValidator } from "@helpers/validation.helper";
|
8 |
+
import { BaseController } from "@lib/controllers/controller.base";
|
9 |
+
import { Prefix } from "@lib/decorators/prefix.decorator";
|
10 |
|
11 |
@Prefix("/users/auth")
|
12 |
export class UsersAuthController extends BaseController {
|