Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.

Commit 388810c

Browse files
feat(base repository): implemented base repository
* Created BaseRepository class * Implemented UserRepository class
1 parent 2428721 commit 388810c

7 files changed

Lines changed: 406 additions & 16 deletions

File tree

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"prepare": "husky install"
4646
},
4747
"dependencies": {
48+
"bcrypt": "5.0.1",
4849
"body-parser": "1.19.0",
4950
"cookie-parser": "1.4.5",
5051
"cors": "2.8.5",
@@ -64,6 +65,7 @@
6465
"@commitlint/config-conventional": "^14.1.0",
6566
"@semantic-release/changelog": "6.0.1",
6667
"@semantic-release/git": "10.0.1",
68+
"@types/bcrypt": "5.0.0",
6769
"@types/body-parser": "1.19.1",
6870
"@types/chai": "^4.2.22",
6971
"@types/cookie-parser": "1.4.2",
@@ -72,9 +74,9 @@
7274
"@types/express": "^4.17.13",
7375
"@types/express-session": "1.17.4",
7476
"@types/helmet": "^4.0.0",
75-
"@types/node": "^16.11.6",
7677
"@types/mocha": "^9.0.0",
7778
"@types/mongoose": "5.11.97",
79+
"@types/node": "^16.11.6",
7880
"@types/socket.io": "^3.0.2",
7981
"@typescript-eslint/eslint-plugin": "^5.3.0",
8082
"@typescript-eslint/parser": "^5.3.0",

src/controllers/rest/PublicController.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { NextFunction, Request, Response } from "express";
22
import { iResponse } from "../../interfaces/IResponse";
3+
import UserModel from "../../models/UserModel";
4+
import UserRepository from "../../repositories/UserRepository";
5+
import { Logger } from "../../utils/Logger";
36

47
class PublicController {
58

@@ -11,6 +14,13 @@ class PublicController {
1114
*/
1215
public async indexAction(req: Request, res: Response, next: NextFunction): Promise<void> {
1316
try {
17+
const usersRepository: UserRepository = new UserRepository(UserModel);
18+
await usersRepository.createUserAccount({
19+
username: "admin",
20+
email: "admin@domain.com",
21+
avatar: "",
22+
password: "admin"
23+
});
1424
const response: iResponse = {
1525
error: false,
1626
statusCode: 200,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {Document} from 'mongoose';
2+
3+
export interface iUser {
4+
_id?: string,
5+
username: string,
6+
email: string,
7+
password: string,
8+
avatar?: string,
9+
roles?: string[],
10+
active?: boolean,
11+
enabled?: boolean,
12+
otpCode?: number,
13+
lastLogin?: Date,
14+
createdAt?: Date,
15+
updatedAt?: Date
16+
}

src/models/UserModel.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Schema, model } from "mongoose";
2+
import { iUser } from "../interfaces/models/IUserModel";
3+
4+
const UserSchema = new Schema({
5+
username: {
6+
type: String,
7+
required: true,
8+
unique: true,
9+
index: true,
10+
},
11+
email: {
12+
type: String,
13+
required: true,
14+
unique: true,
15+
index: true,
16+
},
17+
password: {
18+
type: String,
19+
required: true,
20+
},
21+
avatar: {
22+
type: String,
23+
required: false,
24+
},
25+
roles: {
26+
type: Array,
27+
required: true,
28+
default: ["ROLE_USER"],
29+
},
30+
active: {
31+
type: Boolean,
32+
required: true,
33+
default: false,
34+
},
35+
enabled: {
36+
type: Boolean,
37+
required: true,
38+
default: false,
39+
},
40+
otpCode: {
41+
type: Number,
42+
required: false,
43+
},
44+
lastLogin: {
45+
type: Date,
46+
required: false,
47+
},
48+
}, {
49+
timestamps: true,
50+
});
51+
52+
export default model<iUser>("User", UserSchema);

src/repositories/BaseRepository.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { Model } from "mongoose";
2+
3+
export default class BaseRepository<T> {
4+
5+
private readonly entityInstance: Model<T>;
6+
7+
// Constructor
8+
constructor(entity: Model<T>) {
9+
this.entityInstance = entity;
10+
}
11+
12+
protected createDocument<I>(documentObject: I): Promise<Document> {
13+
return new Promise(async (resolve, reject): Promise<void> => {
14+
try {
15+
const newDocumentInstance = new this.entityInstance(documentObject);
16+
await newDocumentInstance.save();
17+
resolve(newDocumentInstance._id);
18+
} catch (e) {
19+
reject(e);
20+
}
21+
});
22+
}
23+
24+
// Método encargado de obtener todos los documentos de una entidad
25+
protected getAllDocuments() {
26+
return new Promise(async (resolve, reject) => {
27+
try {
28+
const documents = await this.entityInstance.find();
29+
resolve(documents);
30+
} catch (e) {
31+
reject(e);
32+
}
33+
});
34+
}
35+
36+
// Método encargado de obtener un documento en base a parámetros
37+
protected getOneDocumentByParameters(parameters: object): Promise<object> {
38+
return new Promise(async (resolve, reject) => {
39+
try {
40+
const document = await this.entityInstance.findOne(parameters);
41+
resolve(document);
42+
} catch (e) {
43+
reject(e);
44+
}
45+
});
46+
}
47+
48+
// Método encargado de obtener todos los documentos de una entidad en base a parámetros
49+
protected getAllDocumentsByParameters(parameters: object = {}) {
50+
return new Promise(async (resolve, reject) => {
51+
try {
52+
const documents = await this.entityInstance.find(parameters);
53+
resolve(documents);
54+
} catch (e) {
55+
reject(e);
56+
}
57+
});
58+
}
59+
60+
// Método encargado de actualizar un documento de una entidad
61+
protected updateDocument(documentId: string, document: object = {}) {
62+
return new Promise(async (resolve, reject) => {
63+
try {
64+
const documentUpdated = await this.entityInstance.findByIdAndUpdate(documentId, document);
65+
resolve(documentUpdated);
66+
} catch (e) {
67+
reject(e);
68+
}
69+
});
70+
}
71+
72+
// Método encargado de eliminar un documento de una entidad
73+
protected deleteDocument(documentId: string) {
74+
return new Promise(async (resolve, reject) => {
75+
try {
76+
await this.entityInstance.findByIdAndDelete(documentId);
77+
resolve(true);
78+
} catch (e) {
79+
reject(e);
80+
}
81+
});
82+
}
83+
84+
}

src/repositories/UserRepository.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { genSaltSync, hashSync } from "bcrypt";
2+
import { iUser } from "../interfaces/models/IUserModel";
3+
import BaseRepository from "./BaseRepository";
4+
5+
export default class UserRepository extends BaseRepository<iUser> {
6+
7+
public countUsers () {
8+
return this.getAllDocuments();
9+
}
10+
11+
public async createUserAccount(userData: iUser) {
12+
try {
13+
let response = {
14+
exist: true,
15+
user: {}
16+
};
17+
const salt = genSaltSync(10);
18+
userData.password = hashSync(userData.password, salt);
19+
userData.otpCode = (userData.hasOwnProperty('otpCode')) ? userData.otpCode : 0;
20+
userData.active = (userData.hasOwnProperty('active')) ? userData.active : false;
21+
userData.enabled = (userData.hasOwnProperty('enabled')) ? userData.enabled : false;
22+
userData.roles = (userData.hasOwnProperty('roles')) ? userData.roles : ["ROLE_USER"];
23+
await this.createDocument(userData);
24+
const createdUser = await this.getOneDocumentByParameters({email: userData.email});
25+
// TODO - Enviar correo electrónico notificando el OTP para activar la cuenta
26+
response.exist = false;
27+
response.user = createdUser;
28+
return response;
29+
} catch (e) {
30+
console.log(e);
31+
throw new Error(e);
32+
}
33+
}
34+
35+
}

0 commit comments

Comments
 (0)