moahmedwafy commited on
Commit
2f0e1b7
Β·
1 Parent(s): 484fdbc

feat: auth refactors

Browse files
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
- req: Request,
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, Router } 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
 
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 "../models/admin.model";
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
- const allowedRoles = ["superAdmin", "admin"];
 
 
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 {