Skip to content

Commit 05fab7a

Browse files
authored
Merge pull request #3 from frckbrice/feature/blog
Feature/blog
2 parents ca06331 + 1a25b91 commit 05fab7a

31 files changed

Lines changed: 1030 additions & 828 deletions

application-business-rules/use-cases/products/product-handlers.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ const createProductUseCase = ({ makeProductModelHandler }) => async function
3232
const findOneProductUseCase = ({ productValidation }) => async function
3333
findOneProductUseCaseHandler({ productId, logEvents, findOneProductDbHandler, errorHandlers }) {
3434
const { InvalidPropertyError } = errorHandlers;
35-
const { validateUUID } = productValidation;
35+
const { } = productValidation;
3636
try {
3737
// validate id
38-
const uuid = validateUUID(productId, InvalidPropertyError);
38+
const uuid = validateObjectId(productId, InvalidPropertyError);
3939
// store product in database mongodb
4040
const newProduct = await findOneProductDbHandler({ productId: uuid });
4141
return Object.freeze(newProduct)
@@ -73,10 +73,10 @@ const deleteProductUseCase = () => async function deleteProductUseCaseHandler({
7373

7474
const { findOneProductDbHandler, deleteProductDbHandler } = dbProductHandler;
7575
const { InvalidPropertyError } = errorHandlers;
76-
const { validateUUID } = productValidation;
76+
const { validateObjectId } = productValidation;
7777
try {
7878
// validate id
79-
const uuid = validateUUID(productId, InvalidPropertyError);
79+
const uuid = validateObjectId(productId, InvalidPropertyError);
8080
// check first that the product exists
8181
const existingProduct = await findOneProductDbHandler({ productId: uuid });
8282
if (!existingProduct) {
@@ -105,10 +105,10 @@ const updateProductUseCase = ({ makeProductModelHandler }) => async function
105105

106106
const { findOneProductDbHandler, updateProductDbHandler } = dbProductHandler;
107107
const { InvalidPropertyError } = errorHandlers;
108-
const { validateUUID } = productValidation;
108+
const { } = productValidation;
109109
try {
110110
// validate id
111-
const uuid = validateUUID(productId, InvalidPropertyError);
111+
const uuid = validateObjectId(productId, InvalidPropertyError);
112112
// check first that the product exists
113113
const existingProduct = await findOneProductDbHandler({ productId: uuid });
114114
if (!existingProduct) {
Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
1-
const { registerUserUseCase,
2-
deleteUserUseCase,
3-
findAllUsersUseCase,
4-
findOneUserUseCase,
5-
loginUserUseCase,
6-
logoutUseCase,
7-
refreshTokenUseCase,
8-
updateUserUseCase,
9-
blockUserUseCase,
10-
unBlockUserUseCase
11-
} = require("./user-handlers");
12-
1+
const userUseCases = require("./user-handlers");
132
const { dbUserHandler } = require("../../../interface-adapters/database-access")
14-
// const {loginUserUseCase} = require("./login-user");
3+
const { makeUser, validateId, validateUserDataUpdates } = require("../../../enterprise-business-rules/entities");
4+
const { RequiredParameterError } = require("../../../interface-adapters/validators-errors/errors");
5+
const { logEvents } = require("../../../interface-adapters/middlewares/loggers/logger");
6+
const { makeHttpError } = require("../../../interface-adapters/validators-errors/http-error");
7+
158

169
const entityModels = require("../../../enterprise-business-rules/entities");
1710

18-
const registerUserUseCaseHandler = registerUserUseCase({ dbUserHandler, entityModels });
19-
const loginUserUseCaseHandler = loginUserUseCase({ dbUserHandler });
20-
const findOneUserUseCaseHandler = findOneUserUseCase({ dbUserHandler });
21-
const findAllUsersUseCaseHandler = findAllUsersUseCase({ dbUserHandler });
22-
const logoutUseCaseHandler = logoutUseCase();
23-
const refreshTokenUseCaseHandler = refreshTokenUseCase({ dbUserHandler });
24-
const updateUserUseCaseHandler = updateUserUseCase({ dbUserHandler });
25-
const deleteUserUseCaseHandler = deleteUserUseCase({ dbUserHandler });
26-
const blockUserUseCaseHandler = blockUserUseCase({ dbUserHandler });
27-
const unBlockUserUseCaseHandler = unBlockUserUseCase({ dbUserHandler });
11+
const registerUserUseCaseHandler = userUseCases.registerUserUseCase({ dbUserHandler, entityModels, logEvents, makeHttpError });
12+
13+
const loginUserUseCaseHandler = userUseCases.loginUserUseCase({ dbUserHandler, logEvents, makeHttpError });
14+
15+
const findOneUserUseCaseHandler = userUseCases.findOneUserUseCase({ dbUserHandler, validateId, logEvents });
16+
17+
const findAllUsersUseCaseHandler = userUseCases.findAllUsersUseCase({ dbUserHandler, logEvents });
18+
const logoutUseCaseHandler = userUseCases.logoutUseCase({ RequiredParameterError, logEvents });
19+
20+
const refreshTokenUseCaseHandler = userUseCases.refreshTokenUseCase({ dbUserHandler, RequiredParameterError, logEvents });
21+
22+
const updateUserUseCaseHandler = userUseCases.updateUserUseCase({ dbUserHandler, makeUser, validateId, RequiredParameterError, logEvents, makeHttpError });
23+
24+
const deleteUserUseCaseHandler = userUseCases.deleteUserUseCase({ dbUserHandler, validateId, RequiredParameterError, logEvents });
25+
26+
const blockUserUseCaseHandler = userUseCases.blockUserUseCase({ dbUserHandler, validateId, RequiredParameterError, logEvents });
27+
28+
const unBlockUserUseCaseHandler = userUseCases.unBlockUserUseCase({ dbUserHandler, validateId, RequiredParameterError, logEvents });
29+
30+
const forgotPasswordUseCaseHandler = userUseCases.forgotPasswordUseCase({ dbUserHandler, logEvents });
2831

32+
const resetPasswordUseCaseHandler = userUseCases.resetPasswordUseCase({ dbUserHandler, logEvents, makeHttpError });
2933

3034

3135
module.exports = {
@@ -39,5 +43,7 @@ module.exports = {
3943
registerUserUseCaseHandler,
4044
loginUserUseCaseHandler,
4145
blockUserUseCaseHandler,
42-
unBlockUserUseCaseHandler
46+
unBlockUserUseCaseHandler,
47+
forgotPasswordUseCaseHandler,
48+
resetPasswordUseCaseHandler
4349
}

application-business-rules/use-cases/user/user-handlers.js

Lines changed: 101 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
const { makeUser, validateId, validateUserDataUpdates } = require("../../../enterprise-business-rules/entities");
2-
const { UniqueConstraintError, InvalidPropertyError, RequiredParameterError } = require("../../../interface-adapters/validators-errors/errors");
3-
const { makeHttpError } = require("../../../interface-adapters/validators-errors/http-error");
4-
const jwt = require("jsonwebtoken");
5-
const bcrypt = require("bcrypt");
6-
const { logEvents } = require("../../../interface-adapters/middlewares/loggers/logger");
7-
81

92
module.exports = {
103

@@ -16,7 +9,7 @@ module.exports = {
169
* @return {Promise<Object|Error>} Returns a promise that resolves to the registered user object or rejects with an error.
1710
* @throws {HttpError} Throws an HttpError if the user already exists or if there is an error during registration.
1811
*/
19-
registerUserUseCase: ({ dbUserHandler, entityModels }) => async function registerUserUseCaseHandler(userData) {
12+
registerUserUseCase: ({ dbUserHandler, entityModels, logEvents, makeHttpError }) => async function registerUserUseCaseHandler(userData) {
2013

2114
const { makeUser } = entityModels;
2215
try {
@@ -34,7 +27,7 @@ module.exports = {
3427
}
3528

3629
} catch (error) {
37-
console.log("error from register use case handler: ", err);
30+
console.log("error from register use case handler: ", error);
3831
logEvents(
3932
`${error.no}:${error.code}\t${error.syscall}\t${error.hostname}`,
4033
"userHandlerErr.log"
@@ -57,11 +50,11 @@ module.exports = {
5750
* @throws {InvalidPropertyError} If the provided password does not match the stored password.
5851
* @return {Promise<Object>} An object containing the access token and an empty refresh token.
5952
*/
60-
loginUserUseCase: ({ dbUserHandler }) => {
53+
loginUserUseCase: ({ dbUserHandler, logEvents, makeHttpError }) => {
6154

6255
return async function loginUserUseCaseHandler(userData) {
6356

64-
const { email, password } = userData;
57+
const { email, password, bcrypt, jwt } = userData;
6558

6659
//basic verification
6760
if (!email || !password) {
@@ -133,7 +126,7 @@ module.exports = {
133126
* @return {Promise<{allUsers: Array}>} A promise that resolves to an object containing all users.
134127
* @throws {new Error} If no users are found in the database.
135128
*/
136-
findAllUsersUseCase: ({ dbUserHandler }) => {
129+
findAllUsersUseCase: ({ dbUserHandler, logEvents }) => {
137130

138131
return async function findAllUsersUseCaseHandler() {
139132
try {
@@ -158,7 +151,7 @@ module.exports = {
158151
* @return {Promise<{user: Object}>} A promise that resolves to an object containing the user.
159152
* @throws {new Error} If the user is not found.
160153
*/
161-
findOneUserUseCase: ({ dbUserHandler }) => {
154+
findOneUserUseCase: ({ dbUserHandler, validateId, logEvents }) => {
162155
return async function findOneUserUseCaseHandler({ userId, email }) {
163156

164157
const newId = validateId(userId);
@@ -198,7 +191,7 @@ module.exports = {
198191
* @throws {RequiredParameterError} If the ID is not provided.
199192
* @throws {new Error} If the user is not found.
200193
*/
201-
updateUserUseCase: ({ dbUserHandler }) => async function updateUserUseCaseHandler({ userId, ...userData }) {
194+
updateUserUseCase: ({ dbUserHandler, makeUser, validateId, RequiredParameterError, logEvents, makeHttpError }) => async function updateUserUseCaseHandler({ userId, ...userData }) {
202195

203196
const newId = validateId(userId);
204197
try {
@@ -245,7 +238,7 @@ module.exports = {
245238
* @throws {RequiredParameterError} If the ID is not provided.
246239
* @throws {new Error} If the user is not found.
247240
*/
248-
deleteUserUseCase: ({ dbUserHandler }) => {
241+
deleteUserUseCase: ({ dbUserHandler, validateId, RequiredParameterError, logEvents }) => {
249242
return async function deleteUserUseCaseHandler({ userId }) {
250243

251244
const newId = validateId(userId);
@@ -286,8 +279,8 @@ module.exports = {
286279
* @throws {new Error} If the user is not found.
287280
* @throws {Error} If there is an error refreshing the token.
288281
*/
289-
refreshTokenUseCase: ({ dbUserHandler }) => {
290-
return async function refreshTokenUseCaseHandler({ refreshToken }) {
282+
refreshTokenUseCase: ({ dbUserHandler, RequiredParameterError, logEvents }) => {
283+
return async function refreshTokenUseCaseHandler({ refreshToken, jwt }) {
291284

292285
try {
293286
console.log(`refreshToken: ${refreshToken}`);
@@ -330,7 +323,7 @@ module.exports = {
330323
* @param {string} refreshToken - The refresh token to be used for logout.
331324
* @return {Object} An object containing the access token and refresh token.
332325
*/
333-
logoutUseCase: () => {
326+
logoutUseCase: ({ RequiredParameterError, logEvents }) => {
334327
return async function logoutUseCaseHandler({ refreshToken }) {
335328
try {
336329
if (!refreshToken) {
@@ -348,7 +341,7 @@ module.exports = {
348341
},
349342

350343
//block user
351-
blockUserUseCase: ({ dbUserHandler }) => {
344+
blockUserUseCase: ({ dbUserHandler, validateId, RequiredParameterError, logEvents }) => {
352345
return async function blockUserUseCaseHandler({ userId }) {
353346

354347
const newId = validateId(userId);
@@ -378,7 +371,7 @@ module.exports = {
378371
},
379372

380373
//un-block user
381-
unBlockUserUseCase: ({ dbUserHandler }) => {
374+
unBlockUserUseCase: ({ dbUserHandler, validateId, RequiredParameterError, logEvents }) => {
382375
return async function unBlockUserUseCaseHandler({ userId }) {
383376

384377
const newId = validateId(userId);
@@ -405,5 +398,93 @@ module.exports = {
405398
throw new Error("Error unblock user: " + error.stack);
406399
}
407400
}
401+
},
402+
403+
// forgot password user handler
404+
forgotPasswordUseCase: ({ dbUserHandler, logEvents }) => {
405+
return async function forgotPasswordUseCaseHandler({ email }) {
406+
407+
try {
408+
const user = await dbUserHandler.findUserByEmail({ email });
409+
if (!user) {
410+
throw new Error("user not found");
411+
}
412+
//genrate token and create an expiration link
413+
const token = require("crypto").randomBytes(64).toString("hex");
414+
const tokenExpiration = new Date(Date.now() + 10 * 60 * 1000); // 10 min from now
415+
416+
// update user in DB with the new token expiration time
417+
const updatedUser = await dbUserHandler.updateUser({ id: user.id, passwordResetToken: token, passwordResetExpires: tokenExpiration });
418+
419+
if (!updatedUser) {
420+
throw new Error("user not found");
421+
}
422+
423+
//send back usr and the email will be fired at the controller level
424+
return {
425+
...user,
426+
token,
427+
tokenExpiration
428+
}
429+
430+
} catch (error) {
431+
console.log("Error from forgot password use case handler: ", error);
432+
logEvents(
433+
`${error.no}:${error.code}\t${error.name}\t${error.message}`,
434+
"userHandlerErr.log"
435+
);
436+
throw new Error("Error forgot password: " + error.stack);
437+
}
438+
}
439+
},
440+
441+
442+
// reset password
443+
resetPasswordUseCase: ({ dbUserHandler, logEvents, makeHttpError }) => {
444+
return async function resetPasswordUseCaseHandler({ token, password }) {
445+
446+
try {
447+
const user = await dbUserHandler.findUserByToken({ token });
448+
if (!user) {
449+
return makeHttpError({
450+
statusCode: 404,
451+
errorMessage: "No user with this token"
452+
})
453+
}
454+
// check if token has expired
455+
if (new Date(user.passwordResetExpires).getTime() < Date.now()) {
456+
return makeHttpError({
457+
statusCode: 500,
458+
errorMessage: "Your password reset token has expired"
459+
})
460+
}
461+
// update user in DB with new password
462+
const updatedUser = await dbUserHandler.updateUser({
463+
id: user.id,
464+
password,
465+
passwordChangedAt: new Date().toISOString(),
466+
passwordResetToken: null,
467+
passwordResetExpires: null
468+
});
469+
470+
if (!updatedUser) {
471+
return makeHttpError({
472+
statusCode: 500,
473+
errorMessage: "Reset password failed"
474+
})
475+
}
476+
return updatedUser;
477+
} catch (error) {
478+
console.log("Error from reset password use case handler: ", error);
479+
logEvents(
480+
`${error.no}:${error.code}\t${error.name}\t${error.message}`,
481+
"userHandlerErr.log"
482+
);
483+
return makeHttpError({
484+
statusCode: 500,
485+
errorMessage: "Your password reset failed"
486+
})
487+
}
488+
}
408489
}
409490
}

enterprise-business-rules/entities/blog-model.js

Whitespace-only changes.

enterprise-business-rules/entities/index.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
const { makeUserModel } = require("./user-model");
1+
2+
// user and product validation
3+
const userValidationData = require("../validate-models/user-validation-functions");
24
const productValidation = require("../validate-models/product-validation-fcts")();
5+
const { validateRatingModel } = require("../validate-models/rating-validation")();
36

4-
const {
5-
makeProductModel,
6-
makeRatingProductModel
7-
} = require("./product-model");
7+
//log errors
8+
const { logEvents } = require("../../interface-adapters/middlewares/loggers/logger");
89

10+
// user and product models
11+
const { makeUserModel } = require("./user-model");
12+
const productModels = require("./product-model");
13+
const { makeRatingProductModel } = require("./rating-model");
914

10-
const makeUser = makeUserModel({ productValidation });
11-
const makeProductModelHandler = makeProductModel({ productValidation });
12-
const makeProductRatingModelHandler = makeRatingProductModel({ productValidation });
15+
const makeUser = makeUserModel({ userValidationData, logEvents });
16+
const makeProductModelHandler = productModels.makeProductModel({ productValidation });
17+
const makeProductRatingModelHandler = makeRatingProductModel({ validateRatingModel });
1318

1419

1520
module.exports = {

enterprise-business-rules/entities/product-model.js

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ module.exports = {
44
makeProductModel: ({ productValidation }) => async function makeProductModelHandler({ productData, errorHandlers }) {
55

66
console.log(" hit makeProduct model: ");
7-
87
const { basicProductValidation } = productValidation;
98

109
try {
@@ -16,20 +15,4 @@ module.exports = {
1615
throw new Error(error.message);
1716
}
1817
},
19-
20-
//make rating model
21-
makeRatingProductModel: ({ productValidation }) => async function makeProductRatingModelHandler({ errorHandlers, ...ratingData }) {
22-
23-
console.log(" hit make Rating Product model: ");
24-
const { validateRatingModel } = productValidation;
25-
const { InvalidPropertyError } = errorHandlers;
26-
27-
try {
28-
const validatedRatingData = await validateRatingModel(ratingData, InvalidPropertyError);
29-
return Object.freeze(validatedRatingData)
30-
} catch (error) {
31-
console.log("Error from rating-model handler: ", error);
32-
throw new Error(error.message);
33-
}
34-
}
3518
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = {
2+
3+
//make rating model
4+
makeRatingProductModel: ({ validateRatingModel }) => async function makeProductRatingModelHandler({ errorHandlers, ...ratingData }) {
5+
6+
console.log(" hit make Rating Product model: ");
7+
const { InvalidPropertyError } = errorHandlers;
8+
9+
try {
10+
const validatedRatingData = await validateRatingModel(ratingData, InvalidPropertyError);
11+
return Object.freeze(validatedRatingData)
12+
} catch (error) {
13+
console.log("Error from rating-model handler: ", error);
14+
throw new Error(error.message);
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)