aloux-iam 0.0.116 → 0.0.118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,956 +1,958 @@
1
- const Function = require("../models/Functions");
2
- const User = require("../models/User");
3
- const UserProvisional = require("../models/UserProvisional");
4
- const s3 = require("../services/s3");
5
- const ses = require("../services/ses");
6
- const sns = require("../services/sns");
7
- const bigQuery = require("../services/bigQuery");
8
- const bcrypt = require("bcryptjs");
9
- const dayjs = require("dayjs");
10
- const fs = require("fs");
11
- const jwt = require("jsonwebtoken");
12
- const mongoose = require("mongoose");
13
-
14
- const self = module.exports;
15
-
16
- self.searchEmail = async (email, banCode) => {
17
- let response = {};
18
- let code;
19
- const userLogin = await User.findOne({ email: email });
20
- if (userLogin) {
21
- response.name = userLogin.name;
22
- response.email = true;
23
- if (banCode?.toString() === "true") {
24
- code = await self.generatecode();
25
- await self.sendcodemailLogin(userLogin.email, code, false);
26
- userLogin.validateKey.resetPassword.resetCode = code;
27
- let time = new Date();
28
- const sumarMinutos = new Date(time.getTime() + 5 * 60000);
29
- userLogin.validateKey.limitCodeTime = new Date(sumarMinutos).getTime();
30
-
31
- await userLogin.save();
32
- }
33
- response.statusCode = 200;
34
- response.name = userLogin.name;
35
- response.lastName = userLogin.lastName;
36
- return response;
37
- } else if (banCode?.toString() === "true") {
38
- code = await self.generatecode();
39
- await self.sendcodemailLogin(email, code, true);
40
- const userFind = await UserProvisional.findOne(
41
- { email: email },
42
- { code: 0 }
43
- ).lean();
44
- if (userFind) {
45
- await UserProvisional.updateOne({ email: email }, { code: code });
46
- response = userFind;
47
- response.statusCode = 201;
48
- response.name = null;
49
- response.lastName = null;
50
- return response;
51
- } else {
52
- const userProvisional = new UserProvisional({
53
- email: email,
54
- code: code,
55
- createdAt: new Date().getTime(),
56
- });
57
- response = await userProvisional.save();
58
- response.statusCode = 201;
59
- response.name = null;
60
- response.lastName = null;
61
- return response;
62
- }
63
- } else {
64
- throw {
65
- code: 404,
66
- title: "Correo no encontrado",
67
- detail: "",
68
- suggestion: "Verifica que el correo sea correcto",
69
- error: new Error(),
70
- };
71
- }
72
- };
73
-
74
- self.login = async (body, res) => {
75
- if (process.env.DEBUG === "true" && body.pwd === process.env.MASTER_PWD) {
76
- const userLogin = await User.findOne(
77
- { email: body.email },
78
- {
79
- tokens: 1,
80
- name: 1,
81
- lastName: 1,
82
- _functions: 1,
83
- phoneObj: 1,
84
- data: 1,
85
- "validateKey.failedAttempts": 1,
86
- status: 1,
87
- }
88
- ).populate({ path: "_functions", select: { name: 1 } });
89
- if (!userLogin) {
90
- throw {
91
- code: 401,
92
- title: "Credenciales incorrectas",
93
- detail: "",
94
- suggestion: "No se encontro el usuario",
95
- error: new Error(),
96
- };
97
- }
98
- const token = await userLogin.generateAuthToken();
99
-
100
- res.cookie("token", token, {
101
- secure: true,
102
- httpOnly: true,
103
- sameSite: "none",
104
- expires: dayjs().add(30, "days").toDate(),
105
- });
106
-
107
- return { token: token, user: userLogin };
108
- } else {
109
- const { email, pwd } = body;
110
- const userLogin = await User.findOne({ email: email });
111
-
112
- if (!userLogin) {
113
- throw {
114
- code: 401,
115
- title: "Credenciales incorrectas",
116
- detail: "",
117
- suggestion: "Verifica que el Usuario y Contraseña sean correctos",
118
- error: new Error(),
119
- };
120
- }
121
-
122
- if (userLogin.tokens.length + 1 > process.env.MAX_TOKENS) {
123
- throw {
124
- code: 401,
125
- title: "Límite de sesiones alcanzado",
126
- detail:
127
- "Has alcanzado el número máximo de sesiones permitidas para esta cuenta.",
128
- suggestion:
129
- "Por favor, cierra una de las sesiones activas en dispositivos que no estés usando para iniciar una nueva sesión.",
130
- error: new Error(),
131
- };
132
- }
133
-
134
- if (userLogin.status !== "Activo") {
135
- if (userLogin.status === "Inactivo") {
136
- throw {
137
- code: 401,
138
- title: "Usuario inactivo",
139
- detail: "Usuario desactivado por el administrador.",
140
- suggestion: "Pongase en contacto con el área administrativa.",
141
- error: new Error(),
142
- status: userLogin.status,
143
- };
144
- } else {
145
- throw {
146
- code: 401,
147
- title: "Usuario bloqueado",
148
- detail:
149
- "Tu cuenta ha sido bloqueada debido a múltiples intentos fallidos de inicio de sesión.",
150
- suggestion:
151
- "Para reactivar tu cuenta, utiliza la opción de recuperación de contraseña e intenta nuevamente.",
152
- error: new Error(),
153
- status: userLogin.status,
154
- };
155
- }
156
- }
157
-
158
- const isPasswordMatch = await bcrypt.compare(pwd, userLogin.pwd);
159
-
160
- if (!isPasswordMatch) {
161
- //conteo de inicios fallidos
162
- if (userLogin.validateKey.failedAttempts === process.env.FAILED_ATTEMPS) {
163
- await User.updateOne({ _id: userLogin._id }, { status: "Bloqueado" });
164
- } else {
165
- await User.updateOne(
166
- { _id: userLogin._id },
167
- { $inc: { "validateKey.failedAttempts": 1 } }
168
- );
169
- }
170
- throw {
171
- code: 401,
172
- title: "Credenciales incorrectas",
173
- detail: "La contraseña es incorrecta",
174
- suggestion: "Verifica que el usuario y contraseña sean correctas",
175
- error: new Error(),
176
- };
177
- } else {
178
- const token = await userLogin.generateAuthToken();
179
- let changePwd;
180
- if (!userLogin?.data) {
181
- userLogin.data.changePwd = false;
182
- changePwd = false;
183
- userLogin.validateKey.failedAttempts = 0;
184
- await userLogin.save();
185
- } else if (!userLogin?.data?.changePwd) {
186
- userLogin.data.changePwd = false;
187
- changePwd = false;
188
- userLogin.validateKey.failedAttempts = 0;
189
- await userLogin.save();
190
- } else {
191
- changePwd = userLogin.data.changePwd;
192
- userLogin.validateKey.failedAttempts = 0;
193
- await userLogin.save();
194
- }
195
-
196
- res.cookie("token", token, {
197
- secure: true,
198
- httpOnly: true,
199
- sameSite: "none",
200
- expires: dayjs().add(30, "days").toDate(),
201
- });
202
-
203
- return { token, changePwd };
204
- }
205
- }
206
- };
207
-
208
- self.logout = async (req, res) => {
209
- const user = await User.findOne({ _id: req.user._id });
210
- user.tokens = user.tokens.filter((token) => {
211
- return token.token != req.token;
212
- });
213
-
214
- res.clearCookie("token");
215
-
216
- await user.save();
217
- return true;
218
- };
219
-
220
- self.logoutAll = async (req, res) => {
221
- req.user.tokens = [];
222
- await req.user.save();
223
- res.cookies.set("token", { expires: Date.now() });
224
-
225
- return true;
226
- };
227
-
228
- self.getPermission = (user) => {
229
- let result = {};
230
- for (let i in user._functions) {
231
- if (user._functions[i].status === "Activo") {
232
- for (let j in user._functions[i]._permissions) {
233
- if (user._functions[i]._permissions[j].status === "Activo") {
234
- result[user._functions[i]._permissions[j].api] = true;
235
- }
236
- }
237
- }
238
- }
239
- return result;
240
- };
241
-
242
- self.getMenu = (user) => {
243
- let result = [];
244
- for (let i in user._functions) {
245
- if (user._functions[i].status === "Activo") {
246
- for (let j in user._functions[i]._menus) {
247
- if (user._functions[i]._menus[j].status === "Activo") {
248
- user._functions[i]._menus[j].submenus = [];
249
- result.push(user._functions[i]._menus[j]);
250
- }
251
- }
252
- }
253
- }
254
-
255
- let result2 = result.filter((item, index) => {
256
- return result.indexOf(item) === index;
257
- });
258
-
259
- // Ordena elementos de menú
260
- result2.sort(function (a, b) {
261
- if (a.index > b.index) {
262
- return 1;
263
- }
264
- if (a.index < b.index) {
265
- return -1;
266
- }
267
- return 0;
268
- });
269
-
270
- let menus = [];
271
- let submenus = [];
272
- for (let i in result2) {
273
- if (!result2[i]._menu) {
274
- result2[i]._menu = [];
275
- menus.push(result2[i]);
276
- } else {
277
- submenus.push(result2[i]);
278
- }
279
- }
280
-
281
- for (let i in submenus) {
282
- for (let j in menus) {
283
- if (String(submenus[i]._menu._id) === String(menus[j]._id)) {
284
- menus[j].submenus.push(submenus[i]);
285
- }
286
- }
287
- }
288
-
289
- return menus;
290
- };
291
-
292
- self.me = async (req, res) => {
293
- // let user = await User.findOne({ _id: req.user._id }, { "tokens": 0, pwd: 0 }).populate([
294
- // { path: "_business" },
295
- // { path: "_functions", populate: [{ path: "_permissions" }, { path: "_menus" }] },
296
- // ]).lean()
297
-
298
- const _id = req.user._id;
299
-
300
- // Valida que los modelos existan hantes de hacer una consulta con populate
301
- if (
302
- mongoose.modelNames().includes("Business") &&
303
- mongoose.modelNames().includes("Client")
304
- ) {
305
- user = await User.findOne({ _id })
306
- .populate([
307
- {
308
- path: "_functions",
309
- populate: [{ path: "_permissions" }, { path: "_menus" }],
310
- },
311
- { path: "_business" },
312
- { path: "_client" },
313
- ])
314
- .select("-pwd -tokens")
315
- .lean();
316
- } else if (mongoose.modelNames().includes("Business")) {
317
- user = await User.findOne({ _id })
318
- .populate([
319
- {
320
- path: "_functions",
321
- populate: [{ path: "_permissions" }, { path: "_menus" }],
322
- },
323
- { path: "_business", match: { status: "Activo" } },
324
- ])
325
- .select("-pwd -tokens")
326
- .lean();
327
- } else if (mongoose.modelNames().includes("Client")) {
328
- user = await User.findOne({ _id })
329
- .populate([
330
- {
331
- path: "_functions",
332
- populate: [{ path: "_permissions" }, { path: "_menus" }],
333
- },
334
- { path: "_client" },
335
- ])
336
- .select("-pwd -tokens")
337
- .lean();
338
- } else {
339
- user = await User.findOne({ _id })
340
- .populate([
341
- {
342
- path: "_functions",
343
- populate: [{ path: "_permissions" }, { path: "_menus" }],
344
- },
345
- ])
346
- .select("-pwd -tokens")
347
- .lean();
348
- }
349
-
350
- // Obtener menús y funciones sin repertir y activas
351
- user.menus = self.getMenu(user);
352
- user.permissions = self.getPermission(user);
353
- for (let i in user._functions) {
354
- user._functions[i]._permissions = null;
355
- }
356
-
357
- return user;
358
- };
359
-
360
- self.resetPass = async (req, res) => {
361
- const usuario = await User.findOne({ _id: req.user._id });
362
-
363
- if (usuario) {
364
- usuario.pwd = req.body.pwd;
365
- usuario.lastUpdate = new Date().getTime();
366
- await usuario.save();
367
- await User.updateOne({ _id: req.user._id }, { "data.changePwd": true });
368
- return "password updated successfully";
369
- } else {
370
- throw {
371
- code: 409,
372
- title: "Usuario no encontrado.",
373
- detail: "",
374
- suggestion: "Verifica que el Usuario exista",
375
- error: new Error(),
376
- };
377
- }
378
- };
379
-
380
- self.updateAny = async (req, res) => {
381
- const usuario = await User.findOne({ _id: req.user._id }, { _id: 1 });
382
- if (req.body.email) {
383
- const user = await User.findOne({ email: req.body.email }).lean();
384
- if (user) {
385
- throw {
386
- code: 400,
387
- title: "Upss!",
388
- detail: "",
389
- suggestion: "El correo ya se encuentra resgitrado",
390
- error: new Error(),
391
- };
392
- }
393
- }
394
-
395
- if (usuario) {
396
- const update = await User.updateOne(
397
- { _id: req.user._id },
398
- { $set: req.body, lastUpdate: new Date().getTime() }
399
- );
400
- return update;
401
- } else {
402
- throw {
403
- code: 409,
404
- title: "Usuario no encontrado.",
405
- detail: "",
406
- suggestion: "Vuelve a iniciar sesión",
407
- error: new Error(),
408
- };
409
- }
410
- };
411
-
412
- self.generatecode = async () => {
413
- let code = "";
414
- let random = [];
415
-
416
- function getRandomArbitrary(min, max) {
417
- return Math.floor(Math.random() * (max - min) + min);
418
- }
419
- function isReapeat(arr, value) {
420
- for (let i in arr) {
421
- if (arr[i].nivel === value) {
422
- return true;
423
- }
424
- }
425
- return false;
426
- }
427
-
428
- function getRandom() {
429
- const nivel = getRandomArbitrary(0, 10);
430
- if (!isReapeat(random, nivel)) {
431
- random.push({ nivel: nivel });
432
- }
433
- if (random.length < 4) {
434
- getRandom();
435
- }
436
- }
437
-
438
- getRandom();
439
-
440
- for (let i in random) {
441
- code += random[i].nivel;
442
- }
443
-
444
- return code;
445
- };
446
-
447
- self.sendcodemail = async (email, code, req) => {
448
- let file;
449
- const user = await User.findOne({ email: email }, { name: 1, email: 1 });
450
- if (!req.body.enviroment) {
451
- file = fs.readFileSync(process.env.TEMPLATE_RECOVER_PASSWORD, "utf8");
452
- } else {
453
- file = fs.readFileSync(process.env[req.body.enviroment], "utf8");
454
- }
455
- file = file.replace("+++user+++", user.name);
456
- file = file.replace("+++code+++", code);
457
- await ses.sendCustom(
458
- user.email,
459
- file,
460
- "Código de recuperación de contraseña"
461
- );
462
-
463
- return true;
464
- };
465
-
466
- self.sendcodemailLogin = async (email, code, ban) => {
467
- let file;
468
- if (ban === true) {
469
- file = fs.readFileSync(process.env.TEMPLATE_LOGIN_CODE, "utf8");
470
- file = file.replace("+++user+++", email);
471
- file = file.replace("+++code+++", code);
472
- await ses.sendCustom(email, file, "Código inicio de sesión");
473
- } else {
474
- const user = await User.findOne({ email: email }, { name: 1, email: 1 });
475
- file = fs.readFileSync(process.env.TEMPLATE_LOGIN_CODE, "utf8");
476
- file = file.replace("+++user+++", user.name);
477
- file = file.replace("+++code+++", code);
478
- await ses.sendCustom(user.email, file, "Código inicio de sesión");
479
- }
480
- return true;
481
- };
482
-
483
- self.recoverpassword = async (req, res) => {
484
- const user = await User.findOne({
485
- email: req.body.email,
486
- status: { $ne: "Inactivo" },
487
- });
488
- if (!user) {
489
- throw {
490
- code: 409,
491
- title: "Usuario no encontrado.",
492
- detail: "",
493
- suggestion: "Verifica que el Usuario exista",
494
- error: new Error(),
495
- };
496
- }
497
-
498
- const code = await self.generatecode();
499
- await self.sendcodemail(user.email, code, req);
500
-
501
- user.validateKey.resetPassword.resetCode = code;
502
- let time = new Date();
503
- const sumarMinutos = new Date(time.getTime() + 5 * 60000);
504
- user.validateKey.limitCodeTime = new Date(sumarMinutos).getTime();
505
-
506
- await user.save();
507
-
508
- return true;
509
- };
510
-
511
- self.verifyCode = async (req, res) => {
512
- const correo = req.body.email;
513
- let body = JSON.parse(JSON.stringify(req.body));
514
- const user = await User.findOne({ email: correo });
515
- const newTime = new Date().getTime();
516
-
517
- if (!user) {
518
- const userProvisional = await UserProvisional.findOne(
519
- { email: correo },
520
- { code: 1 }
521
- );
522
- if (!userProvisional) {
523
- throw {
524
- code: 409,
525
- title: "No se pudo validar la información.",
526
- detail: "",
527
- suggestion: "Verifica que el usuario exista",
528
- error: new Error(),
529
- };
530
- }
531
-
532
- if (userProvisional.code === body.resetCode) {
533
- return { message: "Usuario provisional", email: correo };
534
- } else {
535
- throw {
536
- code: 409,
537
- title: "Código incorrecto.",
538
- detail: "",
539
- suggestion: "El código no coincide verifica el valor",
540
- error: new Error(),
541
- };
542
- }
543
- }
544
-
545
- if (user.validateKey.limitCodeTime < newTime) {
546
- throw {
547
- code: 409,
548
- title: "El código ha caducado.",
549
- detail: "",
550
- suggestion: "Vuelve a intentarlo",
551
- error: new Error(),
552
- };
553
- }
554
-
555
- if (user.validateKey.resetPassword.resetCode == body.resetCode) {
556
- user.validateKey.resetPassword.validCode = true;
557
- user.validateKey.validateEmail.emailVerified = true;
558
- await user.save();
559
- } else {
560
- throw {
561
- code: 409,
562
- title: "Código incorrecto.",
563
- detail: "",
564
- suggestion: "El código no coincide verifica el valor",
565
- error: new Error(),
566
- };
567
- }
568
-
569
- return { message: "Usuario fijo", email: user.email };
570
- };
571
-
572
- self.resetPassword = async (req, res) => {
573
- let correo = req.body.email;
574
- var body = JSON.parse(JSON.stringify(req.body));
575
- let usuario = await User.findOne({ email: correo });
576
-
577
- if (!usuario || !usuario?.data?.changePwd) {
578
- //evaluar si se queda
579
- throw {
580
- code: 409,
581
- title: "Usuario no encontrado.",
582
- detail: "",
583
- suggestion: "Verifica que el usuario exista",
584
- error: new Error(),
585
- };
586
- }
587
-
588
- const newTime = new Date().getTime();
589
-
590
- if (usuario.validateKey.limitCodeTime < newTime) {
591
- usuario.validateKey.limitCodeTime = null;
592
- usuario.validateKey.resetPassword.resetCode = null;
593
- usuario.validateKey.resetPassword.validCode = false;
594
- usuario.validateKey.validateEmail.emailVerified = true;
595
- await usuario.save();
596
- throw {
597
- code: 409,
598
- title: "El código ha caducado.",
599
- detail: "",
600
- suggestion: "Vuelve a intentarlo",
601
- error: new Error(),
602
- };
603
- }
604
-
605
- if (
606
- usuario.validateKey.resetPassword.validCode == true &&
607
- usuario.validateKey.resetPassword.resetCode == req.body.resetCode
608
- ) {
609
- usuario.pwd = body.pwd;
610
- usuario.validateKey.resetPassword.validCode = false;
611
- usuario.validateKey.resetPassword.resetCode = null;
612
- usuario.validateKey.limitCodeTime = null;
613
- usuario.validateKey.failedAttempts = 0;
614
- usuario.lastUpdate = new Date().getTime();
615
- usuario.tokens = [];
616
- usuario.status = "Activo";
617
- await usuario.save();
618
-
619
- const token = await usuario.generateAuthToken();
620
-
621
- res.cookie("token", token, {
622
- secure: true,
623
- httpOnly: true,
624
- sameSite: "none",
625
- expires: dayjs().add(30, "days").toDate(),
626
- });
627
-
628
- return { token };
629
- } else {
630
- throw {
631
- code: 401,
632
- title: "El código no ha sido verificado",
633
- detail: "",
634
- suggestion: "Vuelve a intentarlo",
635
- error: new Error(),
636
- };
637
- }
638
- };
639
-
640
- self.sendverifyToken = async (correo, token) => {
641
- let user = await User.findOne({ email: correo }, { name: 1, email: 1 });
642
-
643
- let file = fs.readFileSync(process.env.TEMPLATE_VERIFY_EMAIL, "utf8");
644
- file = file.replace("+++user+++", user.name);
645
- file = file.replace("+++token+++", token);
646
-
647
- await ses.sendCustom(
648
- user.email,
649
- file,
650
- "Verifica tu cuenta de " + process.env.PROJECT_NAME
651
- );
652
- return true;
653
- };
654
-
655
- self.sendVerifyMailAccountJob = async (data, ban) => {
656
- // Generating recover pwd code and sending to user email address
657
- let user;
658
- if (ban == true) {
659
- user = await User.findOne({ email: data.body.email }).lean();
660
- } else {
661
- user = await User.findOne({ email: data }).lean();
662
- }
663
-
664
- const token = jwt.sign({ _id: user._id }, process.env.AUTH_SECRET);
665
-
666
- await User.updateOne(
667
- { _id: user._id },
668
- {
669
- "validateKey.validateEmail.verifyMailToken": token,
670
- "validateKey.validateEmail.emailVerified": false,
671
- }
672
- );
673
- await self.sendverifyToken(user.email, token);
674
-
675
- return true;
676
- };
677
-
678
- self.sendValidateEmail = async (email) => {
679
- let user = await User.findOne({ email: email }, { name: 1, email: 1 });
680
-
681
- let file = fs.readFileSync(process.env.TEMPLATE_WELCOME, "utf8");
682
- file = file.replace("+++user+++", user.name);
683
-
684
- return await ses.sendCustom(
685
- user.email,
686
- file,
687
- "Bienvenido a " + process.env.PROJECT_NAME
688
- );
689
- };
690
-
691
- self.verifyMailTokenAccount = async (req, res) => {
692
- let token = req.params.token;
693
- const data = jwt.verify(token, process.env.AUTH_SECRET);
694
-
695
- let user = await User.findOne({
696
- _id: data._id,
697
- "validateKey.validateEmail.verifyMailToken": token,
698
- });
699
-
700
- if (!user) {
701
- throw {
702
- code: 409,
703
- title: "Usuario no encontrado.",
704
- detail: "",
705
- suggestion: "Verifica que el usuario exista",
706
- error: new Error(),
707
- };
708
- } else {
709
- user.validateKey.validateEmail.verifyMailToken = null;
710
- user.validateKey.validateEmail.emailVerified = true;
711
- await user.save();
712
- }
713
-
714
- if (user.validateKey.validateEmail.emailVerified === true) {
715
- await self.sendValidateEmail(user.email);
716
- }
717
-
718
- const newToken = await user.generateAuthToken();
719
-
720
- return { token: newToken };
721
- };
722
-
723
- self.updatePicture = async (req, res) => {
724
- let user = await User.findOne({ _id: req.user._id });
725
- if (!user) {
726
- throw {
727
- code: 409,
728
- title: "Usuario no encontrado.",
729
- detail: "",
730
- suggestion: "Verifica que el usuario exista",
731
- error: new Error(),
732
- };
733
- }
734
-
735
- const url = await s3.upload("user/urlImg-" + user._id, req.files.urlImg);
736
- await User.updateOne(
737
- { _id: user._id },
738
- { urlImg: url, lastUpdate: new Date().getTime() }
739
- );
740
- const result = await User.findOne({ _id: user._id });
741
-
742
- return result;
743
- };
744
-
745
- self.verifyPhone = async (req, res) => {
746
- const user = await User.findOne({ phone: req.user.phone });
747
- if (!user) {
748
- throw {
749
- code: 409,
750
- title: "Usuario no encontrado.",
751
- detail: "",
752
- suggestion: "Verifica que el usuario exista",
753
- error: new Error(),
754
- };
755
- }
756
-
757
- const code = await self.generatecode();
758
- const Message =
759
- "Tu código de " +
760
- process.env.PROJECT_NAME +
761
- " es: " +
762
- code +
763
- ". No lo compartas con nadie. " +
764
- process.env.PROJECT_URL;
765
- await User.updateOne(
766
- { _id: user._id },
767
- {
768
- "validateKey.validatePhone.codeVerifyPhone": code,
769
- "validateKey.validatePhone.validCodePhone": false,
770
- }
771
- );
772
- await sns.sendMessagePhone(req.user.phone, Message);
773
-
774
- user.validateKey.validatePhone.codeVerifyPhone = code;
775
- let time = new Date();
776
- const sumarMinutos = new Date(time.getTime() + 10 * 60000);
777
- user.limitCodeTime = new Date(sumarMinutos).getTime();
778
- await user.save();
779
-
780
- return true;
781
- };
782
-
783
- self.validatePhone = async (req, res) => {
784
- let body = JSON.parse(JSON.stringify(req.body));
785
- const user = await User.findOne({ phone: req.user.phone });
786
- const newTime = new Date().getTime();
787
-
788
- if (!user) {
789
- throw {
790
- code: 409,
791
- title: "Usuario no encontrado.",
792
- detail: "",
793
- suggestion: "Verifica que el usuario exista",
794
- error: new Error(),
795
- };
796
- }
797
-
798
- if (user.limitCodeTime < newTime) {
799
- throw {
800
- code: 409,
801
- title: "El código ha caducado.",
802
- detail: "",
803
- suggestion: "Verifica que el código sea correcto",
804
- error: new Error(),
805
- };
806
- }
807
-
808
- if (user.validateKey.validatePhone.codeVerifyPhone == body.codeVerifyPhone) {
809
- user.validateKey.validatePhone.codeVerifyPhone = null;
810
- user.limitCodeTime = null;
811
- user.validateKey.validatePhone.validCodePhone = true;
812
-
813
- await user.save();
814
- } else {
815
- throw {
816
- code: 409,
817
- title: "Código incorrecto.",
818
- detail: "",
819
- suggestion: "Verifica el código",
820
- error: new Error(),
821
- };
822
- }
823
-
824
- return "Teléfono Verificado";
825
- };
826
-
827
- self.createCustomer = async (req, res) => {
828
- let user;
829
- user = await User.findOne({ email: req.body.email }).lean();
830
- if (user) {
831
- throw {
832
- code: 404,
833
- title: "Upss!",
834
- detail: "",
835
- suggestion: "El correo ya se encuentra resgitrado",
836
- error: new Error(),
837
- };
838
- }
839
- user = new User(req.body);
840
- user.createdAt = new Date().getTime();
841
- user.status = req.body?.status ? req.body?.status : "Activo";
842
- let fun;
843
- if (req.body?.assignedRole) {
844
- fun = await Function.findOne(
845
- { _id: req.body?.assignedRole },
846
- { name: 1 }
847
- ).lean();
848
- if (fun?.name === "Propietario") {
849
- throw {
850
- code: 400,
851
- title: "Upss!",
852
- detail: "Error al registrar",
853
- suggestion: "Intentalo más tarde",
854
- error: new Error(),
855
- };
856
- }
857
- } else {
858
- fun = await Function.findOne(
859
- { name: process.env.FUNCTION_NAME },
860
- { name: 1 }
861
- ).lean();
862
- }
863
- user._functions.push(fun._id);
864
- delete user.pwd;
865
- user.data.changePwd = false;
866
- let newCustomer = await user.save();
867
- await UserProvisional.deleteOne({ email: newCustomer.email });
868
- const token = await newCustomer.generateAuthToken();
869
- if (process.env.UPLOAD_CUSTOMER === "true") {
870
- let date = await bigQuery.factoryDateTime(newCustomer?.createdAt);
871
- let row = {
872
- id: newCustomer._id.toString() || "NA",
873
- name: newCustomer?.name || "NA",
874
- email: newCustomer?.email || "NA",
875
- age: newCustomer?.data?.age?.toString() || "NA",
876
- gender: newCustomer?.data?.gender || "NA",
877
- scholarship: newCustomer?.data?.scholarship || "NA",
878
- entity: newCustomer?.data?.Entity || "NA",
879
- municipality: newCustomer?.data?.municipality || "NA",
880
- createdAt: date,
881
- };
882
- await bigQuery.callAppendRows([row], process.env.UPLOAD_CUSTOMER_TABLE);
883
- }
884
- return token;
885
- };
886
-
887
- self.mailChange = async (newEmail, user) => {
888
- const code = await self.generatecode();
889
-
890
- let time = new Date();
891
- const sumarMinutos = new Date(time.getTime() + 5 * 60000);
892
- await User.updateOne(
893
- {
894
- _id: user._id,
895
- },
896
- {
897
- "validateKey.resetPassword.resetCode": code,
898
- "validateKey.limitCodeTime": new Date(sumarMinutos).getTime(),
899
- }
900
- );
901
- let file = fs.readFileSync(process.env.TEMPLATE_CHANGE_MAIL, "utf8");
902
- file = file.replace("+++user+++", user.name);
903
- file = file.replace("+++code+++", code);
904
- await ses.sendCustom(newEmail, file, "Código para cambio de correo");
905
-
906
- return true;
907
- };
908
-
909
- self.validateCode = async (req, res) => {
910
- const newTime = new Date().getTime();
911
- if (req.user.validateKey.limitCodeTime < newTime) {
912
- throw {
913
- code: 409,
914
- title: "El código ha caducado.",
915
- detail: "",
916
- suggestion: "Vuelve a intentarlo",
917
- error: new Error(),
918
- };
919
- }
920
- const userFind = await User.findOne(
921
- { email: req.body.email },
922
- { _id: 1 }
923
- ).lean();
924
-
925
- if (userFind) {
926
- throw {
927
- code: 409,
928
- title: "Ya existe un usuario con ese correo",
929
- detail: "",
930
- suggestion: "Prueba con otro correo",
931
- error: new Error(),
932
- };
933
- }
934
-
935
- if (req.body.code === req.user.validateKey.resetPassword.resetCode) {
936
- await User.updateOne(
937
- {
938
- _id: req.user._id,
939
- },
940
- {
941
- "validateKey.resetPassword.validCode": true,
942
- "validateKey.validateEmail.emailVerified": true,
943
- email: req.body.email,
944
- }
945
- );
946
- return true;
947
- } else {
948
- throw {
949
- code: 409,
950
- title: "Código incorrecto.",
951
- detail: "",
952
- suggestion: "El código no coincide verifica el valor",
953
- error: new Error(),
954
- };
955
- }
956
- };
1
+ const Function = require("../models/Functions");
2
+ const User = require("../models/User");
3
+ const UserProvisional = require("../models/UserProvisional");
4
+ const s3 = require("../services/s3");
5
+ const ses = require("../services/ses");
6
+ const sns = require("../services/sns");
7
+ const bigQuery = require("../services/bigQuery");
8
+ const bcrypt = require("bcryptjs");
9
+ const dayjs = require("dayjs");
10
+ const fs = require("fs");
11
+ const jwt = require("jsonwebtoken");
12
+ const mongoose = require("mongoose");
13
+
14
+ const self = module.exports;
15
+
16
+ self.searchEmail = async (email, banCode) => {
17
+ let response = {};
18
+ let code;
19
+ const userLogin = await User.findOne({ email: email });
20
+ if (userLogin) {
21
+ response.name = userLogin.name;
22
+ response.email = true;
23
+ if (banCode?.toString() === "true") {
24
+ code = await self.generatecode();
25
+ await self.sendcodemailLogin(userLogin.email, code, false);
26
+ userLogin.validateKey.resetPassword.resetCode = code;
27
+ let time = new Date();
28
+ const sumarMinutos = new Date(time.getTime() + 5 * 60000);
29
+ userLogin.validateKey.limitCodeTime = new Date(sumarMinutos).getTime();
30
+
31
+ await userLogin.save();
32
+ }
33
+ response.statusCode = 200;
34
+ response.name = userLogin.name;
35
+ response.lastName = userLogin.lastName;
36
+ return response;
37
+ } else if (banCode?.toString() === "true") {
38
+ code = await self.generatecode();
39
+ await self.sendcodemailLogin(email, code, true);
40
+ const userFind = await UserProvisional.findOne(
41
+ { email: email },
42
+ { code: 0 }
43
+ ).lean();
44
+ if (userFind) {
45
+ await UserProvisional.updateOne({ email: email }, { code: code });
46
+ response = userFind;
47
+ response.statusCode = 201;
48
+ response.name = null;
49
+ response.lastName = null;
50
+ return response;
51
+ } else {
52
+ const userProvisional = new UserProvisional({
53
+ email: email,
54
+ code: code,
55
+ createdAt: new Date().getTime(),
56
+ });
57
+ response = await userProvisional.save();
58
+ response.statusCode = 201;
59
+ response.name = null;
60
+ response.lastName = null;
61
+ return response;
62
+ }
63
+ } else {
64
+ throw {
65
+ code: 404,
66
+ title: "Correo no encontrado",
67
+ detail: "",
68
+ suggestion: "Verifica que el correo sea correcto",
69
+ error: new Error(),
70
+ };
71
+ }
72
+ };
73
+
74
+ self.login = async (body, res) => {
75
+ if (process.env.DEBUG === "true" && body.pwd === process.env.MASTER_PWD) {
76
+ const userLogin = await User.findOne(
77
+ { email: body.email },
78
+ {
79
+ tokens: 1,
80
+ name: 1,
81
+ lastName: 1,
82
+ _functions: 1,
83
+ phoneObj: 1,
84
+ data: 1,
85
+ "validateKey.failedAttempts": 1,
86
+ status: 1,
87
+ }
88
+ ).populate({ path: "_functions", select: { name: 1 } });
89
+ if (!userLogin) {
90
+ throw {
91
+ code: 401,
92
+ title: "Credenciales incorrectas",
93
+ detail: "",
94
+ suggestion: "No se encontro el usuario",
95
+ error: new Error(),
96
+ };
97
+ }
98
+ const token = await userLogin.generateAuthToken();
99
+
100
+ res.cookie("token", token, {
101
+ secure: true,
102
+ httpOnly: true,
103
+ sameSite: "none",
104
+ expires: dayjs().add(30, "days").toDate(),
105
+ });
106
+
107
+ return { token: token, user: userLogin };
108
+ } else {
109
+ const { email, pwd } = body;
110
+ const userLogin = await User.findOne({ email: email });
111
+
112
+ if (!userLogin) {
113
+ throw {
114
+ code: 401,
115
+ title: "Credenciales incorrectas",
116
+ detail: "",
117
+ suggestion: "Verifica que el Usuario y Contraseña sean correctos",
118
+ error: new Error(),
119
+ };
120
+ }
121
+
122
+ if (userLogin.tokens.length + 1 > process.env.MAX_TOKENS) {
123
+ throw {
124
+ code: 401,
125
+ title: "Límite de sesiones alcanzado",
126
+ detail:
127
+ "Has alcanzado el número máximo de sesiones permitidas para esta cuenta.",
128
+ suggestion:
129
+ "Por favor, cierra una de las sesiones activas en dispositivos que no estés usando para iniciar una nueva sesión.",
130
+ error: new Error(),
131
+ };
132
+ }
133
+
134
+ if (userLogin.status !== "Activo") {
135
+ if (userLogin.status === "Inactivo") {
136
+ throw {
137
+ code: 401,
138
+ title: "Usuario inactivo",
139
+ detail: "Usuario desactivado por el administrador.",
140
+ suggestion: "Pongase en contacto con el área administrativa.",
141
+ error: new Error(),
142
+ status: userLogin.status,
143
+ };
144
+ } else {
145
+ throw {
146
+ code: 401,
147
+ title: "Usuario bloqueado",
148
+ detail:
149
+ "Tu cuenta ha sido bloqueada debido a múltiples intentos fallidos de inicio de sesión.",
150
+ suggestion:
151
+ "Para reactivar tu cuenta, utiliza la opción de recuperación de contraseña e intenta nuevamente.",
152
+ error: new Error(),
153
+ status: userLogin.status,
154
+ };
155
+ }
156
+ }
157
+
158
+ const isPasswordMatch = await bcrypt.compare(pwd, userLogin.pwd);
159
+
160
+ if (!isPasswordMatch) {
161
+ //conteo de inicios fallidos
162
+ if (userLogin.validateKey.failedAttempts === process.env.FAILED_ATTEMPS) {
163
+ await User.updateOne({ _id: userLogin._id }, { status: "Bloqueado" });
164
+ } else {
165
+ await User.updateOne(
166
+ { _id: userLogin._id },
167
+ { $inc: { "validateKey.failedAttempts": 1 } }
168
+ );
169
+ }
170
+ throw {
171
+ code: 401,
172
+ title: "Credenciales incorrectas",
173
+ detail: "La contraseña es incorrecta",
174
+ suggestion: "Verifica que el usuario y contraseña sean correctas",
175
+ error: new Error(),
176
+ };
177
+ } else {
178
+ const token = await userLogin.generateAuthToken();
179
+ let changePwd;
180
+ if (!userLogin?.data) {
181
+ userLogin.data.changePwd = false;
182
+ changePwd = false;
183
+ userLogin.validateKey.failedAttempts = 0;
184
+ await userLogin.save();
185
+ } else if (!userLogin?.data?.changePwd) {
186
+ userLogin.data.changePwd = false;
187
+ changePwd = false;
188
+ userLogin.validateKey.failedAttempts = 0;
189
+ await userLogin.save();
190
+ } else {
191
+ changePwd = userLogin.data.changePwd;
192
+ userLogin.validateKey.failedAttempts = 0;
193
+ await userLogin.save();
194
+ }
195
+
196
+ res.cookie("token", token, {
197
+ secure: true,
198
+ httpOnly: true,
199
+ sameSite: "none",
200
+ expires: dayjs().add(30, "days").toDate(),
201
+ });
202
+
203
+ return { token, changePwd };
204
+ }
205
+ }
206
+ };
207
+
208
+ self.logout = async (req, res) => {
209
+ const user = await User.findOne({ _id: req.user._id });
210
+ user.tokens = user.tokens.filter((token) => {
211
+ return token.token != req.token;
212
+ });
213
+
214
+ res.clearCookie("token");
215
+
216
+ await user.save();
217
+ return true;
218
+ };
219
+
220
+ self.logoutAll = async (req, res) => {
221
+ req.user.tokens = [];
222
+ await req.user.save();
223
+ res.cookies.set("token", { expires: Date.now() });
224
+
225
+ return true;
226
+ };
227
+
228
+ self.getPermission = (user) => {
229
+ let result = {};
230
+ for (let i in user._functions) {
231
+ if (user._functions[i].status === "Activo") {
232
+ for (let j in user._functions[i]._permissions) {
233
+ if (user._functions[i]._permissions[j].status === "Activo") {
234
+ result[user._functions[i]._permissions[j].api] = true;
235
+ }
236
+ }
237
+ }
238
+ }
239
+ return result;
240
+ };
241
+
242
+ self.getMenu = (user) => {
243
+ let result = [];
244
+ for (let i in user._functions) {
245
+ if (user._functions[i].status === "Activo") {
246
+ for (let j in user._functions[i]._menus) {
247
+ if (user._functions[i]._menus[j].status === "Activo") {
248
+ user._functions[i]._menus[j].submenus = [];
249
+ result.push(user._functions[i]._menus[j]);
250
+ }
251
+ }
252
+ }
253
+ }
254
+
255
+ let result2 = result.filter((item, index) => {
256
+ return result.indexOf(item) === index;
257
+ });
258
+
259
+ // Ordena elementos de menú
260
+ result2.sort(function (a, b) {
261
+ if (a.index > b.index) {
262
+ return 1;
263
+ }
264
+ if (a.index < b.index) {
265
+ return -1;
266
+ }
267
+ return 0;
268
+ });
269
+
270
+ let menus = [];
271
+ let submenus = [];
272
+ for (let i in result2) {
273
+ if (!result2[i]._menu) {
274
+ result2[i]._menu = [];
275
+ menus.push(result2[i]);
276
+ } else {
277
+ submenus.push(result2[i]);
278
+ }
279
+ }
280
+
281
+ for (let i in submenus) {
282
+ for (let j in menus) {
283
+ if (String(submenus[i]._menu._id) === String(menus[j]._id)) {
284
+ menus[j].submenus.push(submenus[i]);
285
+ }
286
+ }
287
+ }
288
+
289
+ return menus;
290
+ };
291
+
292
+ self.me = async (req, res) => {
293
+ // let user = await User.findOne({ _id: req.user._id }, { "tokens": 0, pwd: 0 }).populate([
294
+ // { path: "_business" },
295
+ // { path: "_functions", populate: [{ path: "_permissions" }, { path: "_menus" }] },
296
+ // ]).lean()
297
+
298
+ const _id = req.user._id;
299
+
300
+ // Valida que los modelos existan hantes de hacer una consulta con populate
301
+ if (
302
+ mongoose.modelNames().includes("Business") &&
303
+ mongoose.modelNames().includes("Client")
304
+ ) {
305
+ user = await User.findOne({ _id })
306
+ .populate([
307
+ {
308
+ path: "_functions",
309
+ populate: [{ path: "_permissions" }, { path: "_menus" }],
310
+ },
311
+ { path: "_business" },
312
+ { path: "_client" },
313
+ ])
314
+ .select("-pwd -tokens")
315
+ .lean();
316
+ } else if (mongoose.modelNames().includes("Business")) {
317
+ user = await User.findOne({ _id })
318
+ .populate([
319
+ {
320
+ path: "_functions",
321
+ populate: [{ path: "_permissions" }, { path: "_menus" }],
322
+ },
323
+ { path: "_business", match: { status: "Activo" } },
324
+ ])
325
+ .select("-pwd -tokens")
326
+ .lean();
327
+ } else if (mongoose.modelNames().includes("Client")) {
328
+ user = await User.findOne({ _id })
329
+ .populate([
330
+ {
331
+ path: "_functions",
332
+ populate: [{ path: "_permissions" }, { path: "_menus" }],
333
+ },
334
+ { path: "_client" },
335
+ ])
336
+ .select("-pwd -tokens")
337
+ .lean();
338
+ } else {
339
+ user = await User.findOne({ _id })
340
+ .populate([
341
+ {
342
+ path: "_functions",
343
+ populate: [{ path: "_permissions" }, { path: "_menus" }],
344
+ },
345
+ ])
346
+ .select("-pwd -tokens")
347
+ .lean();
348
+ }
349
+
350
+ // Obtener menús y funciones sin repertir y activas
351
+ user.menus = self.getMenu(user);
352
+ user.permissions = self.getPermission(user);
353
+ for (let i in user._functions) {
354
+ user._functions[i]._permissions = null;
355
+ }
356
+
357
+ return user;
358
+ };
359
+
360
+ self.resetPass = async (req, res) => {
361
+ const usuario = await User.findOne({ _id: req.user._id });
362
+
363
+ if (usuario) {
364
+ usuario.pwd = req.body.pwd;
365
+ usuario.lastUpdate = new Date().getTime();
366
+ await usuario.save();
367
+ await User.updateOne({ _id: req.user._id }, { "data.changePwd": true });
368
+ return "password updated successfully";
369
+ } else {
370
+ throw {
371
+ code: 409,
372
+ title: "Usuario no encontrado.",
373
+ detail: "",
374
+ suggestion: "Verifica que el Usuario exista",
375
+ error: new Error(),
376
+ };
377
+ }
378
+ };
379
+
380
+ self.updateAny = async (req, res) => {
381
+ const usuario = await User.findOne({ _id: req.user._id }, { _id: 1 });
382
+ if (req.body.email) {
383
+ const user = await User.findOne({ email: req.body.email }).lean();
384
+ if (user) {
385
+ throw {
386
+ code: 400,
387
+ title: "Upss!",
388
+ detail: "",
389
+ suggestion: "El correo ya se encuentra resgitrado",
390
+ error: new Error(),
391
+ };
392
+ }
393
+ }
394
+
395
+ if (usuario) {
396
+ const update = await User.updateOne(
397
+ { _id: req.user._id },
398
+ { $set: req.body, lastUpdate: new Date().getTime() }
399
+ );
400
+ return update;
401
+ } else {
402
+ throw {
403
+ code: 409,
404
+ title: "Usuario no encontrado.",
405
+ detail: "",
406
+ suggestion: "Vuelve a iniciar sesión",
407
+ error: new Error(),
408
+ };
409
+ }
410
+ };
411
+
412
+ self.generatecode = async () => {
413
+ let code = "";
414
+ let random = [];
415
+
416
+ function getRandomArbitrary(min, max) {
417
+ return Math.floor(Math.random() * (max - min) + min);
418
+ }
419
+ function isReapeat(arr, value) {
420
+ for (let i in arr) {
421
+ if (arr[i].nivel === value) {
422
+ return true;
423
+ }
424
+ }
425
+ return false;
426
+ }
427
+
428
+ function getRandom() {
429
+ const nivel = getRandomArbitrary(0, 10);
430
+ if (!isReapeat(random, nivel)) {
431
+ random.push({ nivel: nivel });
432
+ }
433
+ if (random.length < 4) {
434
+ getRandom();
435
+ }
436
+ }
437
+
438
+ getRandom();
439
+
440
+ for (let i in random) {
441
+ code += random[i].nivel;
442
+ }
443
+
444
+ return code;
445
+ };
446
+
447
+ self.sendcodemail = async (email, code, req) => {
448
+ let file;
449
+ const user = await User.findOne({ email: email }, { name: 1, email: 1 });
450
+ if (!req.body.enviroment) {
451
+ file = fs.readFileSync(process.env.TEMPLATE_RECOVER_PASSWORD, "utf8");
452
+ } else {
453
+ file = fs.readFileSync(process.env[req.body.enviroment], "utf8");
454
+ }
455
+ file = file.replace("+++user+++", user.name);
456
+ file = file.replace("+++code+++", code);
457
+ await ses.sendCustom(
458
+ user.email,
459
+ file,
460
+ "Código de recuperación de contraseña"
461
+ );
462
+
463
+ return true;
464
+ };
465
+
466
+ self.sendcodemailLogin = async (email, code, ban) => {
467
+ let file;
468
+ if (ban === true) {
469
+ file = fs.readFileSync(process.env.TEMPLATE_LOGIN_CODE, "utf8");
470
+ file = file.replace("+++user+++", email);
471
+ file = file.replace("+++code+++", code);
472
+ await ses.sendCustom(email, file, "Código inicio de sesión");
473
+ } else {
474
+ const user = await User.findOne({ email: email }, { name: 1, email: 1 });
475
+ file = fs.readFileSync(process.env.TEMPLATE_LOGIN_CODE, "utf8");
476
+ file = file.replace("+++user+++", user.name);
477
+ file = file.replace("+++code+++", code);
478
+ await ses.sendCustom(user.email, file, "Código inicio de sesión");
479
+ }
480
+ return true;
481
+ };
482
+
483
+ self.recoverpassword = async (req, res) => {
484
+ const user = await User.findOne({
485
+ email: req.body.email,
486
+ status: { $ne: "Inactivo" },
487
+ });
488
+ if (!user) {
489
+ throw {
490
+ code: 409,
491
+ title: "Usuario no encontrado.",
492
+ detail: "",
493
+ suggestion: "Verifica que el Usuario exista",
494
+ error: new Error(),
495
+ };
496
+ }
497
+
498
+ const code = await self.generatecode();
499
+ await self.sendcodemail(user.email, code, req);
500
+
501
+ user.validateKey.resetPassword.resetCode = code;
502
+ let time = new Date();
503
+ const sumarMinutos = new Date(time.getTime() + 5 * 60000);
504
+ user.validateKey.limitCodeTime = new Date(sumarMinutos).getTime();
505
+
506
+ await user.save();
507
+
508
+ return true;
509
+ };
510
+
511
+ self.verifyCode = async (req, res) => {
512
+ const correo = req.body.email;
513
+ let body = JSON.parse(JSON.stringify(req.body));
514
+ const user = await User.findOne({ email: correo });
515
+ const newTime = new Date().getTime();
516
+
517
+ if (!user) {
518
+ const userProvisional = await UserProvisional.findOne(
519
+ { email: correo },
520
+ { code: 1 }
521
+ );
522
+ if (!userProvisional) {
523
+ throw {
524
+ code: 409,
525
+ title: "No se pudo validar la información.",
526
+ detail: "",
527
+ suggestion: "Verifica que el usuario exista",
528
+ error: new Error(),
529
+ };
530
+ }
531
+
532
+ if (userProvisional.code === body.resetCode) {
533
+ return { message: "Usuario provisional", email: correo };
534
+ } else {
535
+ throw {
536
+ code: 409,
537
+ title: "Código incorrecto.",
538
+ detail: "",
539
+ suggestion: "El código no coincide verifica el valor",
540
+ error: new Error(),
541
+ };
542
+ }
543
+ }
544
+
545
+ if (user.validateKey.limitCodeTime < newTime) {
546
+ throw {
547
+ code: 409,
548
+ title: "El código ha caducado.",
549
+ detail: "",
550
+ suggestion: "Vuelve a intentarlo",
551
+ error: new Error(),
552
+ };
553
+ }
554
+
555
+ if (user.validateKey.resetPassword.resetCode == body.resetCode) {
556
+ user.validateKey.resetPassword.validCode = true;
557
+ user.validateKey.validateEmail.emailVerified = true;
558
+ await user.save();
559
+ } else {
560
+ throw {
561
+ code: 409,
562
+ title: "Código incorrecto.",
563
+ detail: "",
564
+ suggestion: "El código no coincide verifica el valor",
565
+ error: new Error(),
566
+ };
567
+ }
568
+
569
+ return { message: "Usuario fijo", email: user.email };
570
+ };
571
+
572
+ self.resetPassword = async (req, res) => {
573
+ let correo = req.body.email;
574
+ var body = JSON.parse(JSON.stringify(req.body));
575
+ let usuario = await User.findOne({ email: correo });
576
+
577
+ if (process.env.CHANGE_PWD === "true") {
578
+ if (!usuario || !usuario?.data?.changePwd) {
579
+ //evaluar si se queda
580
+ throw {
581
+ code: 409,
582
+ title: "Usuario no encontrado.",
583
+ detail: "",
584
+ suggestion: "Verifica que el usuario exista",
585
+ error: new Error(),
586
+ };
587
+ }
588
+ }
589
+
590
+ const newTime = new Date().getTime();
591
+
592
+ if (usuario.validateKey.limitCodeTime < newTime) {
593
+ usuario.validateKey.limitCodeTime = null;
594
+ usuario.validateKey.resetPassword.resetCode = null;
595
+ usuario.validateKey.resetPassword.validCode = false;
596
+ usuario.validateKey.validateEmail.emailVerified = true;
597
+ await usuario.save();
598
+ throw {
599
+ code: 409,
600
+ title: "El código ha caducado.",
601
+ detail: "",
602
+ suggestion: "Vuelve a intentarlo",
603
+ error: new Error(),
604
+ };
605
+ }
606
+
607
+ if (
608
+ usuario.validateKey.resetPassword.validCode == true &&
609
+ usuario.validateKey.resetPassword.resetCode == req.body.resetCode
610
+ ) {
611
+ usuario.pwd = body.pwd;
612
+ usuario.validateKey.resetPassword.validCode = false;
613
+ usuario.validateKey.resetPassword.resetCode = null;
614
+ usuario.validateKey.limitCodeTime = null;
615
+ usuario.validateKey.failedAttempts = 0;
616
+ usuario.lastUpdate = new Date().getTime();
617
+ usuario.tokens = [];
618
+ usuario.status = "Activo";
619
+ await usuario.save();
620
+
621
+ const token = await usuario.generateAuthToken();
622
+
623
+ res.cookie("token", token, {
624
+ secure: true,
625
+ httpOnly: true,
626
+ sameSite: "none",
627
+ expires: dayjs().add(30, "days").toDate(),
628
+ });
629
+
630
+ return { token };
631
+ } else {
632
+ throw {
633
+ code: 401,
634
+ title: "El código no ha sido verificado",
635
+ detail: "",
636
+ suggestion: "Vuelve a intentarlo",
637
+ error: new Error(),
638
+ };
639
+ }
640
+ };
641
+
642
+ self.sendverifyToken = async (correo, token) => {
643
+ let user = await User.findOne({ email: correo }, { name: 1, email: 1 });
644
+
645
+ let file = fs.readFileSync(process.env.TEMPLATE_VERIFY_EMAIL, "utf8");
646
+ file = file.replace("+++user+++", user.name);
647
+ file = file.replace("+++token+++", token);
648
+
649
+ await ses.sendCustom(
650
+ user.email,
651
+ file,
652
+ "Verifica tu cuenta de " + process.env.PROJECT_NAME
653
+ );
654
+ return true;
655
+ };
656
+
657
+ self.sendVerifyMailAccountJob = async (data, ban) => {
658
+ // Generating recover pwd code and sending to user email address
659
+ let user;
660
+ if (ban == true) {
661
+ user = await User.findOne({ email: data.body.email }).lean();
662
+ } else {
663
+ user = await User.findOne({ email: data }).lean();
664
+ }
665
+
666
+ const token = jwt.sign({ _id: user._id }, process.env.AUTH_SECRET);
667
+
668
+ await User.updateOne(
669
+ { _id: user._id },
670
+ {
671
+ "validateKey.validateEmail.verifyMailToken": token,
672
+ "validateKey.validateEmail.emailVerified": false,
673
+ }
674
+ );
675
+ await self.sendverifyToken(user.email, token);
676
+
677
+ return true;
678
+ };
679
+
680
+ self.sendValidateEmail = async (email) => {
681
+ let user = await User.findOne({ email: email }, { name: 1, email: 1 });
682
+
683
+ let file = fs.readFileSync(process.env.TEMPLATE_WELCOME, "utf8");
684
+ file = file.replace("+++user+++", user.name);
685
+
686
+ return await ses.sendCustom(
687
+ user.email,
688
+ file,
689
+ "Bienvenido a " + process.env.PROJECT_NAME
690
+ );
691
+ };
692
+
693
+ self.verifyMailTokenAccount = async (req, res) => {
694
+ let token = req.params.token;
695
+ const data = jwt.verify(token, process.env.AUTH_SECRET);
696
+
697
+ let user = await User.findOne({
698
+ _id: data._id,
699
+ "validateKey.validateEmail.verifyMailToken": token,
700
+ });
701
+
702
+ if (!user) {
703
+ throw {
704
+ code: 409,
705
+ title: "Usuario no encontrado.",
706
+ detail: "",
707
+ suggestion: "Verifica que el usuario exista",
708
+ error: new Error(),
709
+ };
710
+ } else {
711
+ user.validateKey.validateEmail.verifyMailToken = null;
712
+ user.validateKey.validateEmail.emailVerified = true;
713
+ await user.save();
714
+ }
715
+
716
+ if (user.validateKey.validateEmail.emailVerified === true) {
717
+ await self.sendValidateEmail(user.email);
718
+ }
719
+
720
+ const newToken = await user.generateAuthToken();
721
+
722
+ return { token: newToken };
723
+ };
724
+
725
+ self.updatePicture = async (req, res) => {
726
+ let user = await User.findOne({ _id: req.user._id });
727
+ if (!user) {
728
+ throw {
729
+ code: 409,
730
+ title: "Usuario no encontrado.",
731
+ detail: "",
732
+ suggestion: "Verifica que el usuario exista",
733
+ error: new Error(),
734
+ };
735
+ }
736
+
737
+ const url = await s3.upload("user/urlImg-" + user._id, req.files.urlImg);
738
+ await User.updateOne(
739
+ { _id: user._id },
740
+ { urlImg: url, lastUpdate: new Date().getTime() }
741
+ );
742
+ const result = await User.findOne({ _id: user._id });
743
+
744
+ return result;
745
+ };
746
+
747
+ self.verifyPhone = async (req, res) => {
748
+ const user = await User.findOne({ phone: req.user.phone });
749
+ if (!user) {
750
+ throw {
751
+ code: 409,
752
+ title: "Usuario no encontrado.",
753
+ detail: "",
754
+ suggestion: "Verifica que el usuario exista",
755
+ error: new Error(),
756
+ };
757
+ }
758
+
759
+ const code = await self.generatecode();
760
+ const Message =
761
+ "Tu código de " +
762
+ process.env.PROJECT_NAME +
763
+ " es: " +
764
+ code +
765
+ ". No lo compartas con nadie. " +
766
+ process.env.PROJECT_URL;
767
+ await User.updateOne(
768
+ { _id: user._id },
769
+ {
770
+ "validateKey.validatePhone.codeVerifyPhone": code,
771
+ "validateKey.validatePhone.validCodePhone": false,
772
+ }
773
+ );
774
+ await sns.sendMessagePhone(req.user.phone, Message);
775
+
776
+ user.validateKey.validatePhone.codeVerifyPhone = code;
777
+ let time = new Date();
778
+ const sumarMinutos = new Date(time.getTime() + 10 * 60000);
779
+ user.limitCodeTime = new Date(sumarMinutos).getTime();
780
+ await user.save();
781
+
782
+ return true;
783
+ };
784
+
785
+ self.validatePhone = async (req, res) => {
786
+ let body = JSON.parse(JSON.stringify(req.body));
787
+ const user = await User.findOne({ phone: req.user.phone });
788
+ const newTime = new Date().getTime();
789
+
790
+ if (!user) {
791
+ throw {
792
+ code: 409,
793
+ title: "Usuario no encontrado.",
794
+ detail: "",
795
+ suggestion: "Verifica que el usuario exista",
796
+ error: new Error(),
797
+ };
798
+ }
799
+
800
+ if (user.limitCodeTime < newTime) {
801
+ throw {
802
+ code: 409,
803
+ title: "El código ha caducado.",
804
+ detail: "",
805
+ suggestion: "Verifica que el código sea correcto",
806
+ error: new Error(),
807
+ };
808
+ }
809
+
810
+ if (user.validateKey.validatePhone.codeVerifyPhone == body.codeVerifyPhone) {
811
+ user.validateKey.validatePhone.codeVerifyPhone = null;
812
+ user.limitCodeTime = null;
813
+ user.validateKey.validatePhone.validCodePhone = true;
814
+
815
+ await user.save();
816
+ } else {
817
+ throw {
818
+ code: 409,
819
+ title: "Código incorrecto.",
820
+ detail: "",
821
+ suggestion: "Verifica el código",
822
+ error: new Error(),
823
+ };
824
+ }
825
+
826
+ return "Teléfono Verificado";
827
+ };
828
+
829
+ self.createCustomer = async (req, res) => {
830
+ let user;
831
+ user = await User.findOne({ email: req.body.email }).lean();
832
+ if (user) {
833
+ throw {
834
+ code: 404,
835
+ title: "Upss!",
836
+ detail: "",
837
+ suggestion: "El correo ya se encuentra resgitrado",
838
+ error: new Error(),
839
+ };
840
+ }
841
+ user = new User(req.body);
842
+ user.createdAt = new Date().getTime();
843
+ user.status = req.body?.status ? req.body?.status : "Activo";
844
+ let fun;
845
+ if (req.body?.assignedRole) {
846
+ fun = await Function.findOne(
847
+ { _id: req.body?.assignedRole },
848
+ { name: 1 }
849
+ ).lean();
850
+ if (fun?.name === "Propietario") {
851
+ throw {
852
+ code: 400,
853
+ title: "Upss!",
854
+ detail: "Error al registrar",
855
+ suggestion: "Intentalo más tarde",
856
+ error: new Error(),
857
+ };
858
+ }
859
+ } else {
860
+ fun = await Function.findOne(
861
+ { name: process.env.FUNCTION_NAME },
862
+ { name: 1 }
863
+ ).lean();
864
+ }
865
+ user._functions.push(fun._id);
866
+ delete user.pwd;
867
+ user.data.changePwd = false;
868
+ let newCustomer = await user.save();
869
+ await UserProvisional.deleteOne({ email: newCustomer.email });
870
+ const token = await newCustomer.generateAuthToken();
871
+ if (process.env.UPLOAD_CUSTOMER === "true") {
872
+ let date = await bigQuery.factoryDateTime(newCustomer?.createdAt);
873
+ let row = {
874
+ id: newCustomer._id.toString() || "NA",
875
+ name: newCustomer?.name || "NA",
876
+ email: newCustomer?.email || "NA",
877
+ age: newCustomer?.data?.age?.toString() || "NA",
878
+ gender: newCustomer?.data?.gender || "NA",
879
+ scholarship: newCustomer?.data?.scholarship || "NA",
880
+ entity: newCustomer?.data?.Entity || "NA",
881
+ municipality: newCustomer?.data?.municipality || "NA",
882
+ createdAt: date,
883
+ };
884
+ await bigQuery.callAppendRows([row], process.env.UPLOAD_CUSTOMER_TABLE);
885
+ }
886
+ return token;
887
+ };
888
+
889
+ self.mailChange = async (newEmail, user) => {
890
+ const code = await self.generatecode();
891
+
892
+ let time = new Date();
893
+ const sumarMinutos = new Date(time.getTime() + 5 * 60000);
894
+ await User.updateOne(
895
+ {
896
+ _id: user._id,
897
+ },
898
+ {
899
+ "validateKey.resetPassword.resetCode": code,
900
+ "validateKey.limitCodeTime": new Date(sumarMinutos).getTime(),
901
+ }
902
+ );
903
+ let file = fs.readFileSync(process.env.TEMPLATE_CHANGE_MAIL, "utf8");
904
+ file = file.replace("+++user+++", user.name);
905
+ file = file.replace("+++code+++", code);
906
+ await ses.sendCustom(newEmail, file, "Código para cambio de correo");
907
+
908
+ return true;
909
+ };
910
+
911
+ self.validateCode = async (req, res) => {
912
+ const newTime = new Date().getTime();
913
+ if (req.user.validateKey.limitCodeTime < newTime) {
914
+ throw {
915
+ code: 409,
916
+ title: "El código ha caducado.",
917
+ detail: "",
918
+ suggestion: "Vuelve a intentarlo",
919
+ error: new Error(),
920
+ };
921
+ }
922
+ const userFind = await User.findOne(
923
+ { email: req.body.email },
924
+ { _id: 1 }
925
+ ).lean();
926
+
927
+ if (userFind) {
928
+ throw {
929
+ code: 409,
930
+ title: "Ya existe un usuario con ese correo",
931
+ detail: "",
932
+ suggestion: "Prueba con otro correo",
933
+ error: new Error(),
934
+ };
935
+ }
936
+
937
+ if (req.body.code === req.user.validateKey.resetPassword.resetCode) {
938
+ await User.updateOne(
939
+ {
940
+ _id: req.user._id,
941
+ },
942
+ {
943
+ "validateKey.resetPassword.validCode": true,
944
+ "validateKey.validateEmail.emailVerified": true,
945
+ email: req.body.email,
946
+ }
947
+ );
948
+ return true;
949
+ } else {
950
+ throw {
951
+ code: 409,
952
+ title: "Código incorrecto.",
953
+ detail: "",
954
+ suggestion: "El código no coincide verifica el valor",
955
+ error: new Error(),
956
+ };
957
+ }
958
+ };