moahmedwafy commited on
Commit
484fdbc
·
1 Parent(s): 677259a

feat: crud service

Browse files
Files changed (30) hide show
  1. src/common/enums/authenticatable-type.enum.ts +4 -0
  2. src/common/enums/fitness-goal.enum.ts +5 -0
  3. src/common/enums/fitness-level.enum.ts +5 -0
  4. src/common/enums/gender.enum.ts +4 -0
  5. src/common/enums/injury.enum.ts +7 -0
  6. src/common/enums/preferred-day.enum.ts +9 -0
  7. src/common/enums/preferred-equipment.enum.ts +7 -0
  8. src/{modules/console/admins/enums/roles.enum.ts → common/enums/role.enum.ts} +0 -0
  9. src/common/enums/workout-place.enum.ts +5 -0
  10. src/{modules/common/templates → common}/models/template.model.ts +0 -0
  11. src/common/models/user.model.ts +103 -0
  12. src/{modules/common/users → common}/services/users.base.service.ts +2 -2
  13. src/{modules/common/users/validation → common/validations}/user-register.validation.ts +9 -12
  14. src/configs/config.ts +1 -1
  15. src/configs/env.ts +0 -25
  16. src/helpers/jwt.helper.ts +14 -14
  17. src/helpers/pagination.ts +11 -0
  18. src/lib/responses/json-response.ts +13 -15
  19. src/lib/services/crud.service.ts +68 -0
  20. src/modules/common/users/enums/roles.enum.ts +0 -45
  21. src/modules/common/users/models/user.model.ts +0 -90
  22. src/modules/console/admins/controllers/admins.controller.ts +48 -24
  23. src/modules/console/admins/models/admin.model.ts +3 -7
  24. src/modules/console/admins/services/admins.service.ts +3 -266
  25. src/modules/console/admins/validations/create-admin.validation.ts +1 -1
  26. src/modules/console/users/controllers/users.controller.ts +5 -3
  27. src/modules/console/users/services/users.service.ts +3 -2
  28. src/modules/users/auth/controllers/auth.controller.ts +7 -6
  29. src/modules/users/auth/services/users.service.ts +8 -2
  30. tsconfig.json +0 -1
src/common/enums/authenticatable-type.enum.ts ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ export enum AuthenticatableType {
2
+ USER = "user",
3
+ ADMIN = "admin",
4
+ }
src/common/enums/fitness-goal.enum.ts ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ export enum FitnessGoal {
2
+ LOSE_WEIGHT = "lose weight",
3
+ GAIN_MUSCLE = "gain muscle",
4
+ GET_FITTER = "get fitter",
5
+ }
src/common/enums/fitness-level.enum.ts ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ export enum FitnessLevel {
2
+ BEGINNER = "beginner",
3
+ INTERMEDIATE = "intermediate",
4
+ ADVANCED = "advanced",
5
+ }
src/common/enums/gender.enum.ts ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ export enum Gender {
2
+ MALE = "male",
3
+ FEMALE = "female",
4
+ }
src/common/enums/injury.enum.ts ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ export enum Injury {
2
+ NECK = "neck",
3
+ SHOULDERS = "shoulders",
4
+ BACK = "back",
5
+ ARMS = "arms",
6
+ KNEES = "knees",
7
+ }
src/common/enums/preferred-day.enum.ts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ export enum PreferredDay {
2
+ SATURDAY = "saturday",
3
+ SUNDAY = "sunday",
4
+ MONDAY = "monday",
5
+ TUESDAY = "tuesday",
6
+ WEDNESDAY = "wednesday",
7
+ THURSDAY = "thursday",
8
+ FRIDAY = "friday",
9
+ }
src/common/enums/preferred-equipment.enum.ts ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ export enum PreferredEquipment {
2
+ BARBELLS = "barbells",
3
+ DUMBBELLS = "dumbbells",
4
+ GYM_MACHINES = "gym machines",
5
+ RESISTANCE_BAND = "resistance band",
6
+ BODYWEIGHT = "bodyweight",
7
+ }
src/{modules/console/admins/enums/roles.enum.ts → common/enums/role.enum.ts} RENAMED
File without changes
src/common/enums/workout-place.enum.ts ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ export enum WorkoutPlace {
2
+ GYM = "gym",
3
+ HOME = "home",
4
+ BOTH = "both",
5
+ }
src/{modules/common/templates → common}/models/template.model.ts RENAMED
File without changes
src/common/models/user.model.ts ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import mongoose from "mongoose";
2
+ import bcrypt from "bcrypt";
3
+ import { AuthenticatableType } from "@common/enums/authenticatable-type.enum";
4
+ import { FitnessGoal } from "@common/enums/fitness-goal.enum";
5
+ import { FitnessLevel } from "@common/enums/fitness-level.enum";
6
+ import { Gender } from "@common/enums/gender.enum";
7
+ import { Injury } from "@common/enums/injury.enum";
8
+ import { PreferredDay } from "@common/enums/preferred-day.enum";
9
+ import { PreferredEquipment } from "@common/enums/preferred-equipment.enum";
10
+ import { WorkoutPlace } from "@common/enums/workout-place.enum";
11
+ export const saltrounds = 5;
12
+ const { Schema } = mongoose;
13
+
14
+ export interface IUser {
15
+ name: string;
16
+ email: string;
17
+ password: string;
18
+ image: object;
19
+ role: AuthenticatableType;
20
+ gender: string;
21
+ dob: Date;
22
+ height: number;
23
+ weight: number;
24
+ fitness_level: string;
25
+ preferences: {
26
+ fitness_goal: FitnessGoal;
27
+ target_weight: number;
28
+ workout_frequency: number;
29
+ preferred_days: [PreferredDay];
30
+ workout_place: WorkoutPlace;
31
+ preferred_equipment: [PreferredEquipment];
32
+ };
33
+ injuries: [Injury];
34
+ }
35
+
36
+ const userSchema = new Schema({
37
+ name: { type: String, required: true },
38
+ email: { type: String, required: true, unique: true, dropDups: true },
39
+ password: { type: String, required: true },
40
+ image: { type: Object },
41
+ gender: {
42
+ type: String,
43
+ enum: Gender,
44
+ required: true,
45
+ },
46
+ height: { type: Number, required: true },
47
+ weight: { type: Number, required: true },
48
+ fitness_level: {
49
+ type: String,
50
+ enum: FitnessLevel,
51
+ required: true,
52
+ },
53
+ preferences: {
54
+ fitness_goal: {
55
+ type: String,
56
+ enum: FitnessGoal,
57
+ required: true,
58
+ },
59
+ target_weight: { type: Number, required: true },
60
+ workout_frequency: { type: Number, required: true },
61
+ preferred_days: [
62
+ {
63
+ type: String,
64
+ enum: PreferredDay,
65
+ required: true,
66
+ },
67
+ ],
68
+ workout_place: {
69
+ type: String,
70
+ enum: WorkoutPlace,
71
+ required: true,
72
+ },
73
+ preferred_equipment: [
74
+ {
75
+ type: String,
76
+ enum: PreferredEquipment,
77
+ required: true,
78
+ },
79
+ ],
80
+ },
81
+ injuries: [
82
+ {
83
+ type: String,
84
+ enum: Injury,
85
+ required: true,
86
+ },
87
+ ],
88
+ dob: { type: Date },
89
+ role: {
90
+ type: String,
91
+ enum: AuthenticatableType,
92
+ default: AuthenticatableType.USER,
93
+ },
94
+ });
95
+
96
+ userSchema.pre("save", async function (next) {
97
+ this.password = await bcrypt.hash(this.password, saltrounds);
98
+ next();
99
+ });
100
+
101
+ export type UserDocument = IUser & mongoose.Document;
102
+
103
+ export const userModel = mongoose.model<UserDocument>("users", userSchema);
src/{modules/common/users → common}/services/users.base.service.ts RENAMED
@@ -1,6 +1,6 @@
1
- import { FilterQuery, QueryWithHelpers } from "mongoose";
2
- import { IUser, UserDocument, userModel } from "../models/user.model";
3
  import { HttpError } from "src/lib/error-handling/http-error";
 
4
 
5
  export abstract class BaseUsersService {
6
  async findOne(filterObject: FilterQuery<UserDocument>) {
 
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>) {
src/{modules/common/users/validation → common/validations}/user-register.validation.ts RENAMED
@@ -1,14 +1,12 @@
 
 
 
 
 
 
 
 
1
  import * as joi from "joi";
2
- import {
3
- Role,
4
- Gender,
5
- FitnessLevel,
6
- FitnessGoal,
7
- WorkoutPlace,
8
- PreferredDay,
9
- PreferredEquipment,
10
- Injury,
11
- } from "../enums/roles.enum";
12
  import { createSchema } from "src/helpers/create-schema";
13
 
14
  export interface IUserRegister {
@@ -34,7 +32,6 @@ export interface IUserRegister {
34
  };
35
  injuries: string[];
36
  dob?: Date;
37
- role?: Role;
38
  }
39
 
40
  export const userRegisterKeys = {
@@ -185,7 +182,7 @@ export const userRegisterKeys = {
185
  }),
186
  role: joi
187
  .string()
188
- .valid(...Object.values(Role))
189
  .optional()
190
  .messages({
191
  "string.base": "please enter a valid role",
 
1
+ import { AuthenticatableType } from "@common/enums/authenticatable-type.enum";
2
+ import { FitnessGoal } from "@common/enums/fitness-goal.enum";
3
+ import { FitnessLevel } from "@common/enums/fitness-level.enum";
4
+ import { Gender } from "@common/enums/gender.enum";
5
+ import { Injury } from "@common/enums/injury.enum";
6
+ import { PreferredDay } from "@common/enums/preferred-day.enum";
7
+ import { PreferredEquipment } from "@common/enums/preferred-equipment.enum";
8
+ import { WorkoutPlace } from "@common/enums/workout-place.enum";
9
  import * as joi from "joi";
 
 
 
 
 
 
 
 
 
 
10
  import { createSchema } from "src/helpers/create-schema";
11
 
12
  export interface IUserRegister {
 
32
  };
33
  injuries: string[];
34
  dob?: Date;
 
35
  }
36
 
37
  export const userRegisterKeys = {
 
182
  }),
183
  role: joi
184
  .string()
185
+ .valid(...Object.values(AuthenticatableType))
186
  .optional()
187
  .messages({
188
  "string.base": "please enter a valid role",
src/configs/config.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Env } from "./env";
2
  import dotenv from "dotenv";
 
3
  dotenv.config();
4
 
5
  export interface Config {
 
 
1
  import dotenv from "dotenv";
2
+ import { Env } from "src/lib/env/env";
3
  dotenv.config();
4
 
5
  export interface Config {
src/configs/env.ts DELETED
@@ -1,25 +0,0 @@
1
- export class EnvValue {
2
- constructor(public value: string | number | boolean) {}
3
-
4
- toString(): string {
5
- return String(this.value);
6
- }
7
- toNumber(): number {
8
- return Number(this.value);
9
- }
10
- toBoolean(): boolean {
11
- return this.value === "true";
12
- }
13
- }
14
-
15
- export class Env {
16
- static get(key: string, defaultValue?: string | number | boolean): EnvValue {
17
- const value = process.env[key] || defaultValue;
18
-
19
- if (!value) {
20
- throw new Error(`Environment variable ${key} not found`);
21
- }
22
-
23
- return new EnvValue(value);
24
- }
25
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/helpers/jwt.helper.ts CHANGED
@@ -12,23 +12,23 @@ export class JwtHelper {
12
  return (req: any, res: any, next: any) => {
13
  let authHeader = req.headers["authorization"];
14
  const token = authHeader && authHeader.split(" ")[1];
15
- if (token) {
16
- jwt.verify(token, config.jwt.secret, (err: any, tokenData: any) => {
17
- if (err)
18
- return res
19
- .status(403)
20
- .json({ success: false, code: 403, message: "Invalid Token!" });
21
- if (!role.includes(tokenData.role))
22
- return res
23
- .status(401)
24
- .json({ success: false, code: 401, message: "Unauthorized" });
25
- req.tokenData = tokenData;
26
- next();
27
- });
28
- } else
29
  return res
30
  .status(401)
31
  .json({ success: false, code: 401, message: "Unauthorized" });
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  };
33
  }
34
  }
 
12
  return (req: any, res: any, next: any) => {
13
  let authHeader = req.headers["authorization"];
14
  const token = authHeader && authHeader.split(" ")[1];
15
+ if (!token) {
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  return res
17
  .status(401)
18
  .json({ success: false, code: 401, message: "Unauthorized" });
19
+ }
20
+ jwt.verify(token, config.jwt.secret, (err: any, tokenData: any) => {
21
+ if (err)
22
+ return res
23
+ .status(403)
24
+ .json({ success: false, code: 403, message: "Invalid Token!" });
25
+ if (!role.includes(tokenData.role))
26
+ return res
27
+ .status(401)
28
+ .json({ success: false, code: 401, message: "Unauthorized" });
29
+ req.tokenData = tokenData;
30
+ next();
31
+ });
32
  };
33
  }
34
  }
src/helpers/pagination.ts ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Request } from "express";
2
+
3
+ export const parsePaginationQuery = (query: Request["query"]) => {
4
+ const limit = query.take && parseInt(query.limit as string);
5
+ const skip = query.skip && parseInt(query.skip as string);
6
+
7
+ return {
8
+ limit,
9
+ skip,
10
+ };
11
+ };
src/lib/responses/json-response.ts CHANGED
@@ -1,23 +1,21 @@
1
- export class JsonResponse {
2
- public status: number;
3
- public message: string;
4
- public data: Record<string, any> | Record<string, any>[];
5
- public meta?: {
6
  total: number;
7
  page: number;
8
  perPage: number;
9
  };
 
 
 
 
 
 
 
10
 
11
- constructor(props: {
12
- status?: number;
13
- message?: string;
14
- data?: Record<string, any> | Record<string, any>[];
15
- meta?: {
16
- total: number;
17
- page: number;
18
- perPage: number;
19
- };
20
- }) {
21
  this.status = props.status || 200;
22
  this.message = props.message || "Success";
23
  this.data = props.data || {};
 
1
+ interface JsonResponseProps {
2
+ status?: number;
3
+ message?: string;
4
+ data?: Record<string, any> | Record<string, any>[];
5
+ meta?: {
6
  total: number;
7
  page: number;
8
  perPage: number;
9
  };
10
+ }
11
+
12
+ export class JsonResponse {
13
+ public status: JsonResponseProps["status"];
14
+ public message: JsonResponseProps["message"];
15
+ public data: JsonResponseProps["data"];
16
+ public meta?: JsonResponseProps["meta"];
17
 
18
+ constructor(props: JsonResponseProps) {
 
 
 
 
 
 
 
 
 
19
  this.status = props.status || 200;
20
  this.message = props.message || "Success";
21
  this.data = props.data || {};
src/lib/services/crud.service.ts ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { HttpError } from "@lib/error-handling/http-error";
2
+ import { AnyKeys, Document, FilterQuery, Model } from "mongoose";
3
+
4
+ export const CrudService = <ModelDoc extends Document>(
5
+ model: Model<ModelDoc>
6
+ ) => {
7
+ return class CrudServiceClass {
8
+ protected model: Model<ModelDoc> = model;
9
+
10
+ async create(data: AnyKeys<ModelDoc>): Promise<ModelDoc> {
11
+ return this.model.create(data);
12
+ }
13
+
14
+ async update(
15
+ filter: FilterQuery<ModelDoc>,
16
+ data: AnyKeys<ModelDoc>
17
+ ): Promise<ModelDoc> {
18
+ return this.model.findOneAndUpdate(filter, data, { new: true });
19
+ }
20
+
21
+ async delete(filter: FilterQuery<ModelDoc>): Promise<ModelDoc> {
22
+ return this.model.findOneAndDelete(filter);
23
+ }
24
+
25
+ async list(
26
+ filter: FilterQuery<ModelDoc>,
27
+ paginationOptions: {
28
+ limit?: number;
29
+ skip?: number;
30
+ } = {
31
+ limit: 10,
32
+ skip: 0,
33
+ }
34
+ ): Promise<{
35
+ docs: ModelDoc[];
36
+ paginationData: {
37
+ total: number;
38
+ page: number;
39
+ perPage: number;
40
+ };
41
+ }> {
42
+ const docs = await this.model
43
+ .find(filter)
44
+ .limit(paginationOptions.limit)
45
+ .skip(paginationOptions.skip);
46
+
47
+ const total = await this.model.countDocuments(filter);
48
+ const paginationData = {
49
+ total: total,
50
+ page: paginationOptions.skip,
51
+ perPage: paginationOptions.limit,
52
+ };
53
+
54
+ return { docs, paginationData };
55
+ }
56
+
57
+ async findOne(filter: FilterQuery<ModelDoc>): Promise<ModelDoc | null> {
58
+ return this.model.findOne(filter);
59
+ }
60
+
61
+ async findOneOrFail(filter: FilterQuery<ModelDoc>): Promise<ModelDoc> {
62
+ const document = await this.findOne(filter);
63
+ if (!document) throw new HttpError(404, "No Matching Result Found.");
64
+
65
+ return document;
66
+ }
67
+ };
68
+ };
src/modules/common/users/enums/roles.enum.ts DELETED
@@ -1,45 +0,0 @@
1
- export enum Role {
2
- USER = "user"
3
- }
4
- export enum Gender {
5
- MALE = "male",
6
- FEMALE = "female"
7
- }
8
- export enum FitnessLevel {
9
- BEGINNER = "beginner",
10
- INTERMEDIATE = "intermediate",
11
- ADVANCED = "advanced"
12
- }
13
- export enum FitnessGoal {
14
- LOSE_WEIGHT = "lose weight",
15
- GAIN_MUSCLE = "gain muscle",
16
- GET_FITTER = "get fitter"
17
- }
18
- export enum WorkoutPlace {
19
- GYM = "gym",
20
- HOME = "home",
21
- BOTH = "both"
22
- }
23
- export enum PreferredDay {
24
- SATURDAY = "saturday",
25
- SUNDAY = "sunday",
26
- MONDAY = "monday",
27
- TUESDAY = "tuesday",
28
- WEDNESDAY = "wednesday",
29
- THURSDAY = "thursday",
30
- FRIDAY = "friday"
31
- }
32
- export enum PreferredEquipment {
33
- BARBELLS = "barbells",
34
- DUMBBELLS = "dumbbells",
35
- GYM_MACHINES = "gym machines",
36
- RESISTANCE_BAND = "resistance band",
37
- BODYWEIGHT = "bodyweight"
38
- }
39
- export enum Injury {
40
- NECK = "neck",
41
- SHOULDERS = "shoulders",
42
- BACK = "back",
43
- ARMS = "arms",
44
- KNEES = "knees"
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/modules/common/users/models/user.model.ts DELETED
@@ -1,90 +0,0 @@
1
- import mongoose from "mongoose";
2
- import bcrypt from "bcrypt";
3
- export const saltrounds = 5;
4
- import { Role, Gender, FitnessLevel, FitnessGoal, WorkoutPlace, PreferredDay, PreferredEquipment, Injury } from "../enums/roles.enum";
5
- const { Schema } = mongoose;
6
-
7
- export interface IUser {
8
- name: string;
9
- email: string;
10
- password: string;
11
- image: object;
12
- role: Role;
13
- gender: string;
14
- dob: Date;
15
- height: number;
16
- weight: number;
17
- fitness_level: string;
18
- preferences: {
19
- fitness_goal: FitnessGoal;
20
- target_weight: number;
21
- workout_frequency: number;
22
- preferred_days: [PreferredDay];
23
- workout_place: WorkoutPlace;
24
- preferred_equipment: [PreferredEquipment];
25
- };
26
- injuries: [Injury];
27
- }
28
-
29
- const userSchema = new Schema({
30
- name: { type: String, required: true },
31
- email: { type: String, required: true, unique: true, dropDups: true },
32
- password: { type: String, required: true },
33
- image: { type: Object },
34
- gender: {
35
- type: String,
36
- enum: Gender,
37
- required: true
38
- },
39
- height: { type: Number, required: true },
40
- weight: { type: Number, required: true },
41
- fitness_level: {
42
- type: String,
43
- enum: FitnessLevel,
44
- required: true
45
- },
46
- preferences: {
47
- fitness_goal: {
48
- type: String,
49
- enum: FitnessGoal,
50
- required: true
51
- },
52
- target_weight: { type: Number, required: true },
53
- workout_frequency: { type: Number, required: true },
54
- preferred_days: [{
55
- type: String,
56
- enum: PreferredDay,
57
- required: true
58
- }],
59
- workout_place: {
60
- type: String,
61
- enum: WorkoutPlace,
62
- required: true
63
- },
64
- preferred_equipment: [{
65
- type: String,
66
- enum: PreferredEquipment,
67
- required: true
68
- }]
69
- },
70
- injuries: [{
71
- type: String,
72
- enum: Injury,
73
- required: true
74
- }],
75
- dob: { type: Date },
76
- role: {
77
- type: String,
78
- enum: Role,
79
- default: Role.USER
80
- }
81
- });
82
-
83
- userSchema.pre("save", async function (next) {
84
- this.password = await bcrypt.hash(this.password, saltrounds);
85
- next();
86
- });
87
-
88
- export type UserDocument = IUser & mongoose.Document;
89
-
90
- export const userModel = mongoose.model<IUser>("users", userSchema);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/modules/console/admins/controllers/admins.controller.ts CHANGED
@@ -1,13 +1,12 @@
 
 
 
 
1
  import { Request, Response, Router } from "express";
2
- import { BaseController } from "../../../../lib/controllers/controller.base";
3
  import { AdminsService } from "../services/admins.service";
4
  import { createAdminSchema } from "../validations/create-admin.validation";
5
- import {
6
- bodyValidator,
7
- paramsValidator,
8
- } from "../../../../helpers/validation.helper";
9
- import { asyncHandler } from "../../../../helpers/async-handler";
10
- import { Prefix } from "../../../../lib/decorators/prefix.decorator";
11
 
12
  @Prefix("/console/admins")
13
  export class AdminsController extends BaseController {
@@ -34,36 +33,61 @@ export class AdminsController extends BaseController {
34
  );
35
  }
36
 
37
- list = (_, res: Response) => {
38
- this.adminsService
39
- .list({})
40
- .then((result) => {
41
- res.status(result.code).json(result);
42
- })
43
- .catch((err) => {
44
- res.status(500).json(err);
45
- });
 
 
46
  };
47
 
48
  get = async (req: Request, res: Response) => {
49
- const data = await this.adminsService.get({
50
  _id: req.params.id,
51
  });
52
- res.json(data);
 
 
 
53
  };
54
 
55
  create = async (req: Request, res: Response) => {
56
- const data = await this.adminsService.create(req.body);
57
- res.json(data);
 
 
 
58
  };
59
 
60
  update = async (req: Request, res: Response) => {
61
- const data = await this.adminsService.update(req.params.id, req.body);
62
- res.json(data);
 
 
 
 
 
 
 
 
 
 
63
  };
64
 
65
  delete = async (req: Request, res: Response) => {
66
- const data = await this.adminsService.remove(req.params.id);
67
- res.json(data);
 
 
 
 
 
 
 
68
  };
69
  }
 
1
+ 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 {
 
33
  );
34
  }
35
 
36
+ list = async (req: Request, res: Response) => {
37
+ const paginationQuery = parsePaginationQuery(req.query);
38
+ const { docs, paginationData } = await this.adminsService.list(
39
+ {},
40
+ paginationQuery
41
+ );
42
+ const response = new JsonResponse({
43
+ data: docs,
44
+ meta: paginationData,
45
+ });
46
+ return res.json(response);
47
  };
48
 
49
  get = async (req: Request, res: Response) => {
50
+ const data = await this.adminsService.findOneOrFail({
51
  _id: req.params.id,
52
  });
53
+ const response = new JsonResponse({
54
+ data,
55
+ });
56
+ res.json(response);
57
  };
58
 
59
  create = async (req: Request, res: Response) => {
60
+ const admin = await this.adminsService.create(req.body);
61
+ const response = new JsonResponse({
62
+ data: admin,
63
+ });
64
+ res.json(response);
65
  };
66
 
67
  update = async (req: Request, res: Response) => {
68
+ const admin = await this.adminsService.update(
69
+ {
70
+ _id: req.params.id,
71
+ },
72
+ req.body
73
+ );
74
+
75
+ const response = new JsonResponse({
76
+ data: admin,
77
+ });
78
+
79
+ res.json(response);
80
  };
81
 
82
  delete = async (req: Request, res: Response) => {
83
+ const admin = await this.adminsService.delete({
84
+ _id: req.params.id,
85
+ });
86
+
87
+ const response = new JsonResponse({
88
+ data: admin,
89
+ });
90
+
91
+ res.json(response);
92
  };
93
  }
src/modules/console/admins/models/admin.model.ts CHANGED
@@ -1,6 +1,5 @@
1
  import mongoose from "mongoose";
2
  import bcrypt from "bcrypt";
3
- import { Role } from "../enums/roles.enum";
4
  import { config } from "../../../../configs/config";
5
  const { Schema } = mongoose;
6
 
@@ -9,7 +8,6 @@ export interface IAdmin {
9
  email: string;
10
  password: string;
11
  image: object;
12
- role: Role;
13
  gender: string;
14
  dob: Date;
15
  }
@@ -19,10 +17,6 @@ const AdminSchema = new Schema({
19
  email: { type: String, required: true, unique: true, dropDups: true },
20
  password: { type: String, required: true },
21
  image: { type: Object, default: {} },
22
- role: {
23
- type: String,
24
- enum: Role,
25
- },
26
  gender: { type: String, required: true },
27
  dob: { type: Date },
28
  });
@@ -32,4 +26,6 @@ AdminSchema.pre("save", async function (next) {
32
  next();
33
  });
34
 
35
- export const Admin = mongoose.model<IAdmin>("admins", AdminSchema);
 
 
 
1
  import mongoose from "mongoose";
2
  import bcrypt from "bcrypt";
 
3
  import { config } from "../../../../configs/config";
4
  const { Schema } = mongoose;
5
 
 
8
  email: string;
9
  password: string;
10
  image: object;
 
11
  gender: string;
12
  dob: Date;
13
  }
 
17
  email: { type: String, required: true, unique: true, dropDups: true },
18
  password: { type: String, required: true },
19
  image: { type: Object, default: {} },
 
 
 
 
20
  gender: { type: String, required: true },
21
  dob: { type: Date },
22
  });
 
26
  next();
27
  });
28
 
29
+ export type AdminDocument = mongoose.Document & IAdmin;
30
+
31
+ export const Admin = mongoose.model<AdminDocument>("admins", AdminSchema);
src/modules/console/admins/services/admins.service.ts CHANGED
@@ -1,267 +1,4 @@
1
- import bcrypt from "bcrypt";
2
- import { Admin, IAdmin } from "../models/admin.model";
3
- import { config } from "../../../../configs/config";
4
- import { FilterQuery } from "mongoose";
5
 
6
- export class AdminsService {
7
- async find(filterObject) {
8
- try {
9
- const resultObject = await Admin.findOne(filterObject).lean();
10
-
11
- if (!resultObject)
12
- return {
13
- success: false,
14
- code: 404,
15
- error: "No Matching Result Found.",
16
- };
17
-
18
- return {
19
- success: true,
20
- code: 200,
21
- record: resultObject,
22
- };
23
- } catch (err) {
24
- console.log(`err.message`, err.message);
25
- return {
26
- success: false,
27
- code: 500,
28
- error: "Unexpected Error Happened.",
29
- };
30
- }
31
- }
32
-
33
- async get(filterObject: FilterQuery<IAdmin>) {
34
- try {
35
- const resultObject = await Admin.findOne(filterObject)
36
- .lean()
37
- .select("-password");
38
- if (!resultObject)
39
- return {
40
- success: false,
41
- code: 404,
42
- error: "No Matching Result Found.",
43
- };
44
- return {
45
- success: true,
46
- code: 200,
47
- record: resultObject,
48
- };
49
- } catch (err) {
50
- console.log(`err.message`, err.message);
51
- return {
52
- success: false,
53
- code: 500,
54
- error: "Unexpected Error Happened.",
55
- };
56
- }
57
- }
58
-
59
- async list(filterObject) {
60
- try {
61
- const resultArray = await Admin.find(filterObject)
62
- .lean()
63
- .select("-password");
64
-
65
- if (!resultArray)
66
- return {
67
- success: false,
68
- code: 404,
69
- error: "No Matching Result Found.",
70
- };
71
- const count = await Admin.countDocuments(filterObject);
72
- return {
73
- success: true,
74
- code: 200,
75
- record: resultArray,
76
- count,
77
- };
78
- } catch (err) {
79
- console.log(`err.message`, err.message);
80
- return {
81
- success: false,
82
- code: 500,
83
- error: "Unexpected Error Happened.",
84
- };
85
- }
86
- }
87
-
88
- async create(formObject) {
89
- try {
90
- if (formObject.email) formObject.email = formObject.email.toLowerCase();
91
- const resultObject = new Admin(formObject);
92
- await resultObject.save();
93
-
94
- if (!resultObject)
95
- return {
96
- success: false,
97
- code: 500,
98
- error: "Unexpected Error Happened.",
99
- };
100
-
101
- return {
102
- success: true,
103
- code: 201,
104
- record: resultObject,
105
- };
106
- } catch (err) {
107
- console.log(`err.message`, err.message);
108
- return {
109
- success: false,
110
- code: 500,
111
- error: "Unexpected Error Happened.",
112
- };
113
- }
114
- }
115
-
116
- async update(_id, formObject) {
117
- try {
118
- const existingObject = await this.find({ _id });
119
- if (!existingObject.success)
120
- return {
121
- success: false,
122
- code: 404,
123
- error: "No Matching Result Found.",
124
- };
125
- if (formObject.email) {
126
- formObject.email = formObject.email.toLowerCase();
127
- const duplicate = await this.find({ email: formObject.email });
128
- if (
129
- duplicate.success &&
130
- duplicate.record._id.toString() !=
131
- existingObject.record._id.toString()
132
- )
133
- return {
134
- success: false,
135
- error: "This Email is taken by another user",
136
- code: 409,
137
- };
138
- }
139
-
140
- const resultObject = await Admin.findByIdAndUpdate({ _id }, formObject);
141
-
142
- if (!resultObject)
143
- return {
144
- success: false,
145
- code: 500,
146
- error: "Unexpected Error Happened.",
147
- };
148
-
149
- return {
150
- success: true,
151
- code: 200,
152
- record: resultObject,
153
- };
154
- } catch (err) {
155
- console.log(`err.message`, err.message);
156
- return {
157
- success: false,
158
- code: 500,
159
- error: "Unexpected Error Happened.",
160
- };
161
- }
162
- }
163
-
164
- async remove(_id) {
165
- try {
166
- const resultObject = await Admin.findByIdAndDelete({ _id });
167
- if (!resultObject)
168
- return {
169
- success: false,
170
- code: 404,
171
- error: "No Matching Result Found.",
172
- };
173
-
174
- return {
175
- success: true,
176
- code: 200,
177
- };
178
- } catch (err) {
179
- console.log(`err.message`, err.message);
180
- return {
181
- success: false,
182
- code: 500,
183
- error: "Unexpected Error Happened.",
184
- };
185
- }
186
- }
187
-
188
- async comparePassword(emailString, passwordString) {
189
- try {
190
- emailString = emailString.toLowerCase();
191
- const existingObject = await this.find({ email: emailString });
192
-
193
- if (!existingObject.success)
194
- return {
195
- success: false,
196
- code: 404,
197
- error: "No Matching Result Found.",
198
- };
199
-
200
- const matchingPasswords = await bcrypt.compare(
201
- passwordString,
202
- existingObject.record.password
203
- );
204
- if (!matchingPasswords)
205
- return {
206
- success: false,
207
- code: 409,
208
- error: "Incorrect Password.",
209
- };
210
-
211
- return {
212
- success: true,
213
- record: existingObject.record,
214
- code: 200,
215
- };
216
- } catch (err) {
217
- console.log(`err.message`, err.message);
218
- return {
219
- success: false,
220
- code: 500,
221
- error: "Unexpected Error Happened.",
222
- };
223
- }
224
- }
225
-
226
- async resetPassword(emailString, newPasswordString) {
227
- try {
228
- emailString = emailString.toLowerCase();
229
- const existingObject = await this.find({ email: emailString });
230
-
231
- if (!existingObject.success)
232
- return {
233
- success: false,
234
- code: 404,
235
- error: "No Matching Result Found.",
236
- };
237
-
238
- const hashedPassword = await bcrypt.hash(
239
- newPasswordString,
240
- config.saltRounds
241
- );
242
- const resultObject = await Admin.findOneAndUpdate(
243
- { email: emailString },
244
- { password: hashedPassword }
245
- );
246
-
247
- if (!resultObject)
248
- return {
249
- success: false,
250
- code: 500,
251
- error: "Unexpected Error Happened.",
252
- };
253
-
254
- return {
255
- success: true,
256
- code: 200,
257
- };
258
- } catch (err) {
259
- console.log(`err.message`, err.message);
260
- return {
261
- success: false,
262
- code: 500,
263
- error: "Unexpected Error Happened.",
264
- };
265
- }
266
- }
267
- }
 
1
+ import { Admin } from "../models/admin.model";
2
+ import { CrudService } from "@lib/services/crud.service";
 
 
3
 
4
+ export class AdminsService extends CrudService(Admin) {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/modules/console/admins/validations/create-admin.validation.ts CHANGED
@@ -1,5 +1,5 @@
 
1
  import * as joi from "joi";
2
- import { Role } from "../enums/roles.enum";
3
  import { createSchema } from "src/helpers/create-schema";
4
 
5
  export interface ICreateAdmin {
 
1
+ import { Role } from "@common/enums/role.enum";
2
  import * as joi from "joi";
 
3
  import { createSchema } from "src/helpers/create-schema";
4
 
5
  export interface ICreateAdmin {
src/modules/console/users/controllers/users.controller.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { userRegisterSchema } from "src/modules/common/users/validation/user-register.validation";
2
  import { asyncHandler } from "../../../../helpers/async-handler";
3
  import { JwtHelper } from "../../../../helpers/jwt.helper";
4
  import { bodyValidator } from "../../../../helpers/validation.helper";
@@ -6,6 +6,7 @@ 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
 
10
  const allowedRoles = ["superAdmin", "admin"];
11
 
@@ -22,10 +23,11 @@ export class AdminUsersController extends BaseController {
22
  );
23
  }
24
 
25
- create = async (req, res) => {
26
  let user = await this.usersService.create(req.body);
27
- return new JsonResponse({
28
  data: user,
29
  });
 
30
  };
31
  }
 
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";
 
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
 
 
23
  );
24
  }
25
 
26
+ create = async (req: Request, res: Response) => {
27
  let user = await this.usersService.create(req.body);
28
+ const response = new JsonResponse({
29
  data: user,
30
  });
31
+ return res.json(response);
32
  };
33
  }
src/modules/console/users/services/users.service.ts CHANGED
@@ -1,3 +1,4 @@
1
- import { BaseUsersService } from "../../../common/users/services/users.base.service";
 
2
 
3
- export class UsersService extends BaseUsersService {}
 
1
+ import { userModel } from "@common/models/user.model";
2
+ import { CrudService } from "@lib/services/crud.service";
3
 
4
+ export class UsersService extends CrudService(userModel) {}
src/modules/users/auth/controllers/auth.controller.ts CHANGED
@@ -4,10 +4,9 @@ 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 { userRegisterSchema } from "src/modules/common/users/validation/user-register.validation";
8
  import { Request, Response } from "express";
9
- import { IUser } from "src/modules/common/users/models/user.model";
10
  import { JsonResponse } from "src/lib/responses/json-response";
 
11
 
12
  @Prefix("/users/auth")
13
  export class UsersAuthController extends BaseController {
@@ -27,16 +26,18 @@ export class UsersAuthController extends BaseController {
27
  }
28
 
29
  register = async (req: Request, res: Response) => {
30
- let user = await this.authService.create(req.body as IUser);
31
- return new JsonResponse({
32
  data: user,
33
  });
 
34
  };
35
 
36
- login = async (req, res) => {
37
  const { user, token } = await this.authService.login(req.body);
38
- return new JsonResponse({
39
  data: { user, token },
40
  });
 
41
  };
42
  }
 
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 {
 
26
  }
27
 
28
  register = async (req: Request, res: Response) => {
29
+ const user = await this.authService.register(req.body as IUserRegister);
30
+ const response = new JsonResponse({
31
  data: user,
32
  });
33
+ return res.json(response);
34
  };
35
 
36
+ login = async (req: Request, res: Response) => {
37
  const { user, token } = await this.authService.login(req.body);
38
+ const response = new JsonResponse({
39
  data: { user, token },
40
  });
41
+ return res.json(response);
42
  };
43
  }
src/modules/users/auth/services/users.service.ts CHANGED
@@ -1,10 +1,16 @@
1
- import { BaseUsersService } from "../../../common/users/services/users.base.service";
2
  import bcrypt from "bcrypt";
3
  import { ILogin } from "../validation/login.validation";
4
  import { HttpError } from "src/lib/error-handling/http-error";
5
  import { JwtHelper } from "src/helpers/jwt.helper";
 
 
 
 
 
 
 
 
6
 
7
- export class UsersAuthService extends BaseUsersService {
8
  async login(loginRequest: ILogin) {
9
  const user = await this.findOneOrFail({ email: loginRequest.email });
10
  const isPasswordCorrect = await bcrypt.compare(
 
 
1
  import bcrypt from "bcrypt";
2
  import { ILogin } from "../validation/login.validation";
3
  import { HttpError } from "src/lib/error-handling/http-error";
4
  import { JwtHelper } from "src/helpers/jwt.helper";
5
+ import { userModel } from "src/common/models/user.model";
6
+ import { IUserRegister } from "src/common/validations/user-register.validation";
7
+ import { CrudService } from "@lib/services/crud.service";
8
+
9
+ export class UsersAuthService extends CrudService(userModel) {
10
+ async register(createParams: IUserRegister) {
11
+ return this.create(createParams);
12
+ }
13
 
 
14
  async login(loginRequest: ILogin) {
15
  const user = await this.findOneOrFail({ email: loginRequest.email });
16
  const isPasswordCorrect = await bcrypt.compare(
tsconfig.json CHANGED
@@ -10,7 +10,6 @@
10
  "experimentalDecorators": true,
11
  "baseUrl": ".",
12
  "paths": {
13
- "src/*": ["src/*"],
14
  "@lib/*": ["src/lib/*"],
15
  "@common/*": ["src/common/*"],
16
  "@configs/*": ["src/configs/*"],
 
10
  "experimentalDecorators": true,
11
  "baseUrl": ".",
12
  "paths": {
 
13
  "@lib/*": ["src/lib/*"],
14
  "@common/*": ["src/common/*"],
15
  "@configs/*": ["src/configs/*"],