aloux-iam 0.0.0

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.
@@ -0,0 +1,734 @@
1
+ const User = require('../models/User')
2
+ const bcrypt = require('bcryptjs')
3
+ const alouxAWS = require("./operationsAWS")
4
+ const fs = require('fs')
5
+ const jwt = require("jsonwebtoken")
6
+ const dayjs = require("dayjs")
7
+ const serviceUser = require('../services/user')
8
+ const utils = require('../config/utils')
9
+ const self = module.exports
10
+
11
+
12
+ self.create = async (req, res) => {
13
+ // Create a new user
14
+ try {
15
+ let user = await serviceUser.create(req.body)
16
+
17
+ res.status(201).send(user)
18
+ } catch (error) {
19
+ utils.responseError(res, error, 400, 'Error al crear usuario', 'Revisa el detalle del error')
20
+ }
21
+ }
22
+
23
+ self.update = async (req, resp) => {
24
+ try {
25
+
26
+ let result = await serviceUser.update(req.params.USER_ID, req.body)
27
+
28
+ resp.status(200).send(result)
29
+ } catch (error) {
30
+ utils.responseError(resp, error, 400, 'Error al actualizar usuario', 'Revisa el detalle del error')
31
+ }
32
+ }
33
+
34
+ self.status = async (req, resp) => {
35
+ try {
36
+
37
+ const result = await serviceUser.status(req.params.USER_ID, req.body)
38
+
39
+ resp.status(200).send(result)
40
+ } catch (error) {
41
+ utils.responseError(resp, error, 400, 'Error al actualizar usuario', 'Revisa el detalle del error')
42
+ }
43
+ }
44
+
45
+ self.updatepassword = async (req, resp) => {
46
+ try {
47
+
48
+ const result = await serviceUser.updatepassword(req.body, req.params.USER_ID)
49
+
50
+ resp.status(200).send(result)
51
+ } catch (error) {
52
+ resp.status(400).send({ error: error.message })
53
+ }
54
+ }
55
+
56
+ self.get = async (req, res) => {
57
+ try {
58
+ const _id = req.params.USER_ID
59
+
60
+ const user = await User.findOne({ _id }, { pwd: 0 }).populate({ path: "_functions" }).select("-pwd -tokens").lean()
61
+
62
+ if (!user)
63
+ res.status(404).send()
64
+
65
+ res.status(200).send(user)
66
+ } catch (error) {
67
+ res.status(400).send(error)
68
+ }
69
+ }
70
+
71
+ self.retrieve = async (req, res) => {
72
+ try {
73
+
74
+ let result = await User.find({}).select("-pwd -tokens").populate({ path: "_functions" }).sort({ createdAt: -1 }).lean()
75
+
76
+ res.status(200).send(result)
77
+ } catch (error) {
78
+ res.status(400).send({ error: error.message })
79
+ }
80
+ }
81
+
82
+ self.delete = async (req, res) => {
83
+ try {
84
+ const _id = req.params.USER_ID
85
+ const response = await User.deleteOne({ _id })
86
+ response.deletedCount ? res.status(200).send({}) : res.status(404).send({ error: "El registro no existe" })
87
+ } catch (error) {
88
+ res.status(400).send({ error: error.message })
89
+ }
90
+ }
91
+
92
+ self.email = async (req, res) => {
93
+ try {
94
+ const { email } = req.body
95
+ const userLogin = await User.findOne({ email: email })
96
+
97
+ if (!userLogin) {
98
+ return res.status(401).send({
99
+ error: 'No se encontró el correo',
100
+ suggestion: 'Verifica que el correo sea correcto'
101
+ })
102
+ }
103
+ else {
104
+ res.status(200).send()
105
+ }
106
+
107
+
108
+ } catch (error) {
109
+ res.status(500).send({ error: error.message })
110
+ }
111
+ }
112
+
113
+ self.login = async (req, res) => {
114
+ try {
115
+
116
+ if (process.env.DEBUG === 'true' && req.body.pwd === process.env.MASTER_PWD) {
117
+ const userLogin = await User.findOne({ email: req.body.email })
118
+ if (!userLogin) {
119
+ return res.status(401).send({
120
+ title: 'Credenciales incorrectas',
121
+ suggestion: 'Verifica que el Usuario y Contraseña sean correctos'
122
+ })
123
+ }
124
+ const token = await userLogin.generateAuthToken()
125
+ res.status(200).send({ token })
126
+ } else {
127
+ const { email, pwd } = req.body
128
+ const userLogin = await User.findOne({ email: email })
129
+
130
+
131
+ if (!userLogin) {
132
+ return res.status(401).send({
133
+ title: 'Credenciales incorrectas',
134
+ suggestion: 'Verifica que el Usuario y Contraseña sean correctos'
135
+ })
136
+ }
137
+
138
+ if (userLogin.status !== 'Activo') {
139
+ return res.status(401).send({
140
+ title: 'Usuario inactivo',
141
+ detail: 'Usuario desactivado por el administrador.',
142
+ suggestion: 'Pongase en contacto con el área administrativa.'
143
+ })
144
+ }
145
+
146
+ const isPasswordMatch = await bcrypt.compare(pwd, userLogin.pwd)
147
+
148
+ if (!isPasswordMatch) {
149
+ return res.status(401).send({
150
+ title: 'Credenciales incorrectas',
151
+ suggestion: 'Verifica que el usuario y contraseña sean correctas'
152
+ })
153
+ }
154
+
155
+ else {
156
+ const token = await userLogin.generateAuthToken()
157
+
158
+ res.cookie("token", token, {
159
+ secure: true,
160
+ httpOnly: true,
161
+ sameSite: 'none',
162
+ expires: dayjs().add(30, "days").toDate(),
163
+ })
164
+
165
+ res.status(200).send({ token })
166
+ }
167
+ }
168
+
169
+ } catch (error) {
170
+ res.status(500).send({ error: error.message })
171
+ }
172
+ }
173
+ self.logout = async (req, res) => {
174
+ try {
175
+ const user = await User.findOne({ _id: req.user._id })
176
+ user.tokens = user.tokens.filter((token) => {
177
+ return token.token != req.token
178
+ })
179
+
180
+ await user.save()
181
+
182
+ res.status(200).send()
183
+ } catch (error) {
184
+ console.log(error)
185
+ res.status(500).send(error)
186
+ }
187
+ }
188
+
189
+ self.logoutAll = async (req, res) => {
190
+ try {
191
+ req.user.tokens = []
192
+
193
+ await req.user.save()
194
+
195
+ res.status(200).send()
196
+ } catch (error) {
197
+ console.log(error)
198
+ res.status(500).send(error)
199
+ }
200
+ }
201
+
202
+ self.getPermission = (user) => {
203
+ let result = {}
204
+ for (let i in user._functions) {
205
+ for (let j in user._functions[i]._permissions) {
206
+ if (user._functions[i]._permissions[j].status === 'Activo')
207
+ result[user._functions[i]._permissions[j].api] = true
208
+ }
209
+ }
210
+ return result
211
+ }
212
+
213
+ self.getMenu = (user) => {
214
+ let result = []
215
+ // Recorre funciones de un user
216
+ for (let i in user._functions) {
217
+ if (user._functions[i].status === 'Activo') {
218
+
219
+ // Recorre permisos de una función && Valida si el menú esta activo
220
+ for (let j in user._functions[i]._permissions) {
221
+
222
+ const permission = user._functions[i]._permissions[j]
223
+ if (permission.status === 'Activo' && permission._menu && permission._menu.status === 'Activo') {
224
+
225
+ const menu = user._functions[i]._permissions[j]._menu
226
+ result.push(menu)
227
+
228
+ // Obtiene el menú padre
229
+ if (menu._menu && menu._menu.status === 'Activo') {
230
+
231
+ result.push(menu._menu)
232
+ }
233
+
234
+ }
235
+ }
236
+ }
237
+ }
238
+
239
+ // Quitar repetidos
240
+ let hash = {}
241
+ let result2 = result.filter(o => hash[o._id] ? false : hash[o._id] = true)
242
+
243
+ // Ordena elementos de menú
244
+ result2.sort(function (a, b) {
245
+ if (a.index > b.index) {
246
+ return 1
247
+ }
248
+ if (a.index < b.index) {
249
+ return -1
250
+ }
251
+ return 0
252
+ })
253
+
254
+ // Separación de menus y submenus
255
+ let menus = []
256
+ let submenus = []
257
+ for (let i in result2) {
258
+ if (!result2[i]._menu) {
259
+ result2[i]._menu = []
260
+ menus.push(result2[i])
261
+ } else {
262
+ let submenuClone = JSON.parse(JSON.stringify(result2[i]))
263
+ delete submenuClone._menu
264
+ submenus.push(JSON.parse(JSON.stringify(result2[i])))
265
+ }
266
+ }
267
+
268
+ // Asignación de submenus a menus
269
+ for (let i in submenus) {
270
+ for (let j in menus) {
271
+
272
+ if (String(submenus[i]._menu._id) === String(menus[j]._id)) {
273
+ menus[j]._menu.push(submenus[i])
274
+ }
275
+ }
276
+ }
277
+
278
+
279
+ return menus
280
+ }
281
+
282
+ self.getMe = async (req, res) => {
283
+
284
+ try {
285
+
286
+ let user = await User.findOne({ _id: req.user._id }, { "tokens": 0, pwd: 0 }).populate(
287
+ {
288
+ path: "_functions", populate: [
289
+ {
290
+ path: "_permissions", populate: [
291
+ {
292
+ path: "_menu", populate: [
293
+ {
294
+ path: "_menu"
295
+ }
296
+ ]
297
+ }
298
+ ]
299
+ }
300
+ ]
301
+ }
302
+ ).lean()
303
+
304
+ // Obtener menús y funciones sin repertir y activas
305
+ user.menus = self.getMenu(user)
306
+ user.permissions = self.getPermission(user)
307
+ for (let i in user._functions) {
308
+ user._functions[i]._permissions = null
309
+ }
310
+
311
+ return user
312
+
313
+ } catch (error) {
314
+ throw new Error(error)
315
+ }
316
+ }
317
+
318
+ self.me = async (req, res) => {
319
+ try {
320
+ res.status(200).send(await self.getMe(req, res))
321
+ } catch (error) {
322
+ let obj = error
323
+ if (!error.code) {
324
+ obj = {
325
+ code: 401,
326
+ title: 'Error de autenticación',
327
+ detail: error.message,
328
+ suggestion: 'Vuelve a iniciar sesion'
329
+ }
330
+ }
331
+
332
+ res.cookie("user", obj, {
333
+ secure: true,
334
+ httpOnly: true,
335
+ expires: dayjs().add(30, "days").toDate(),
336
+ })
337
+
338
+ res.status(obj.code).send(obj)
339
+ }
340
+ }
341
+
342
+ self.resetPass = async (req, res) => {
343
+ try {
344
+
345
+ let _id = req.user._id
346
+
347
+ const usuario = await User.findOne({ _id })
348
+
349
+ if (usuario) {
350
+
351
+ usuario.pwd = req.body.pwd
352
+ usuario.lastUpdate = new Date().getTime()
353
+ await usuario.save()
354
+
355
+ res.status(200).send("password updated successfully")
356
+ } else return res.status(409).send({ error: 'User no encontrado.' })
357
+
358
+ } catch (error) {
359
+ res.status(400).send(error)
360
+ }
361
+ }
362
+
363
+ self.recoverpassword = async (req, res) => {
364
+ try {
365
+ const correo = req.body.email
366
+
367
+ const user = await User.findOne({ email: correo })
368
+ if (!user) {
369
+ return res.status(409).send({ error: 'User no encontrado.' })
370
+ }
371
+
372
+ const code = await self.generatecode()
373
+
374
+ await self.sendcodemail(correo, code)
375
+
376
+ user.validateKey.resetPassword.resetCode = code
377
+ let time = new Date()
378
+ const sumarMinutos = new Date(time.getTime() + 5 * 60000)
379
+ user.validateKey.limitCodeTime = (new Date(sumarMinutos)).getTime()
380
+
381
+ await user.save()
382
+
383
+ res.status(200).send()
384
+ } catch (error) {
385
+ res.status(500).send('Error al envíar el correo electronico')
386
+ console.log(error)
387
+ }
388
+ }
389
+
390
+ self.generatecode = async () => {
391
+ let code = ""
392
+ let random = []
393
+
394
+ function getRandomArbitrary(min, max) {
395
+ return Math.floor(Math.random() * (max - min) + min)
396
+ }
397
+ function isReapeat(arr, value) {
398
+ for (let i in arr) {
399
+ if (arr[i].nivel === value) {
400
+ return true
401
+ }
402
+ }
403
+ return false
404
+ }
405
+
406
+ function getRandom() {
407
+ const nivel = getRandomArbitrary(0, 10)
408
+ if (!isReapeat(random, nivel)) {
409
+ random.push({ nivel: nivel })
410
+ }
411
+ if (random.length < 4) {
412
+ getRandom()
413
+ }
414
+ }
415
+
416
+ getRandom()
417
+
418
+ for (let i in random) {
419
+ code += random[i].nivel
420
+ }
421
+
422
+ return code
423
+ }
424
+
425
+ self.sendcodemail = async (email, code) => {
426
+ try {
427
+
428
+ let user = await User.findOne({ email: email }, { name: 1, email: 1 })
429
+
430
+ let file = fs.readFileSync(process.env.TEMPLATE_RECOVER_PASSWORD, "utf8")
431
+ file = file.replace('+++user+++', user.name)
432
+ file = file.replace('+++code+++', code)
433
+
434
+ return await alouxAWS.sendCustom(user.email, file, "Código de recuperación de contraseña")
435
+
436
+ } catch (error) {
437
+ throw new Error('Ocurrio un error al envìar el correo electronico')
438
+ }
439
+ }
440
+
441
+ self.verifyCode = async (req, res) => {
442
+ try {
443
+ const correo = req.body.email
444
+ var body = JSON.parse(JSON.stringify(req.body))
445
+
446
+ const user = await User.findOne({ email: correo })
447
+
448
+ const newTime = new Date().getTime()
449
+
450
+ if (!user) {
451
+ return res.status(409).send({ error: 'No se pudo validar la información.' })
452
+ }
453
+
454
+ if (user.validateKey.limitCodeTime < newTime)
455
+ return res.status(409).send({ error: 'El código ha caducado.' })
456
+
457
+ if (user.validateKey.resetPassword.resetCode == body.resetCode) {
458
+ user.validateKey.resetPassword.validCode = true
459
+
460
+ await user.save()
461
+ }
462
+ else
463
+ return res.status(409).send('Código incorrecto.')
464
+
465
+
466
+ res.status(200).send()
467
+ } catch (error) {
468
+ res.status(400).send(error)
469
+ }
470
+ }
471
+
472
+ self.resetPassword = async (req, res) => {
473
+ try {
474
+ let correo = req.body.email
475
+ var body = JSON.parse(JSON.stringify(req.body))
476
+
477
+ const usuario = await User.findOne({ email: correo })
478
+
479
+ if (!usuario) {
480
+ return res.status(409).send({ error: 'User no encontrado.' })
481
+ }
482
+
483
+ const newTime = new Date().getTime()
484
+
485
+ if(usuario.validateKey.limitCodeTime < newTime){
486
+
487
+ usuario.validateKey.limitCodeTime = null
488
+ usuario.validateKey.resetPassword.resetCode = null
489
+ usuario.validateKey.resetPassword.validCode = false
490
+
491
+ return res.status(409).send({error: 'El código ha caducado.'})
492
+ }
493
+
494
+ if (usuario.validateKey.resetPassword.validCode == true && usuario.validateKey.resetPassword.resetCode == req.body.resetCode) {
495
+ usuario.pwd = body.pwd
496
+ usuario.validateKey.resetPassword.validCode = false
497
+ usuario.validateKey.resetPassword.resetCode = null
498
+ usuario.validateKey.limitCodeTime = null
499
+ usuario.lastUpdate = new Date().getTime()
500
+ usuario.tokens = []
501
+
502
+ await usuario.save()
503
+
504
+ const token = await usuario.generateAuthToken()
505
+
506
+ res.cookie("token", token, {
507
+ secure: true,
508
+ httpOnly: true,
509
+ sameSite: 'none',
510
+ expires: dayjs().add(30, "days").toDate(),
511
+ })
512
+
513
+ res.status(200).send({ token })
514
+ }
515
+ else {
516
+ return res.status(401).send("El código no ha sido verificado")
517
+ }
518
+
519
+ } catch (error) {
520
+ res.status(400).send(error)
521
+ }
522
+ }
523
+
524
+ self.updateAny = async (req, res) => {
525
+ try {
526
+
527
+ const _id = req.user._id
528
+ const update = await User.updateOne({ _id }, { $set: req.body, lastUpdate: (new Date()).getTime() })
529
+
530
+ res.status(202).send(update)
531
+ } catch (error) {
532
+ res.status(400).send({ error: error.message })
533
+ }
534
+ }
535
+
536
+ self.updatePicture = async (req, res) => {
537
+ try {
538
+
539
+ const _id = req.user._id
540
+
541
+ let user = await User.findOne({ _id })
542
+
543
+ if (!user) {
544
+ throw new Error('Upss! No se encontró el Elemento')
545
+ }
546
+
547
+ const url = await alouxAWS.upload('user/urlImg-' + user._id, req.files.urlImg)
548
+
549
+ await User.updateOne({ _id: user._id }, { urlImg: url, lastUpdate: (new Date()).getTime() })
550
+
551
+ const result = await User.findOne({_id: user._id})
552
+
553
+ res.status(202).send(result)
554
+ } catch (error) {
555
+ res.status(400).send({ error: error.message })
556
+ }
557
+ }
558
+
559
+
560
+ self.count = async (req, res) => {
561
+ try {
562
+ let result = await User.find({}).countDocuments()
563
+ res.status(200).send({ count: result })
564
+ } catch (error) {
565
+ res.status(400).send({ error: error.message })
566
+ }
567
+ }
568
+
569
+ self.verifyPhone = async (req, res) => {
570
+
571
+ try {
572
+ const phone = req.user.phone
573
+
574
+ const user = await User.findOne({ phone: phone })
575
+ if (!user) {
576
+ return res.status(409).send({ error: 'User no encontrado.' })
577
+ }
578
+
579
+ const code = await self.generatecode()
580
+ const Message = "Docket: su código de verificación es:" + " " + code + " " + "Su código vence en 10 minutos. No comparta su código. Por favor no responda a este mensaje"
581
+
582
+ await User.updateOne({ _id: user._id }, { 'validateKey.validatePhone.codeVerifyPhone': code, 'validateKey.validatePhone.validCodePhone': false })
583
+
584
+ await alouxAWS.sendMessagePhone(phone, Message)
585
+
586
+ user.validateKey.validatePhone.codeVerifyPhone = code
587
+ let time = new Date()
588
+ const sumarMinutos = new Date(time.getTime() + 10 * 60000)
589
+ user.limitCodeTime = (new Date(sumarMinutos)).getTime()
590
+
591
+ await user.save()
592
+
593
+ res.status(200).send()
594
+ } catch (error) {
595
+ res.status(500).send('Error al envíar el mensaje')
596
+ console.log(error)
597
+ }
598
+
599
+ }
600
+
601
+ self.validatePhone = async (req, res) => {
602
+ try {
603
+ const phone = req.user.phone
604
+ var body = JSON.parse(JSON.stringify(req.body))
605
+
606
+ const user = await User.findOne({ phone: phone })
607
+
608
+ const newTime = new Date().getTime()
609
+
610
+ if (!user) {
611
+ return res.status(409).send({ error: 'No se pudo validar la información.' })
612
+ }
613
+
614
+ if (user.limitCodeTime < newTime)
615
+ return res.status(409).send({ error: 'El código ha caducado.' })
616
+
617
+
618
+ if (user.validateKey.validatePhone.codeVerifyPhone == body.codeVerifyPhone) {
619
+ user.validateKey.validatePhone.codeVerifyPhone = null
620
+ user.limitCodeTime = null
621
+ user.validateKey.validatePhone.validCodePhone = true
622
+
623
+ await user.save()
624
+ }
625
+ else
626
+ return res.status(409).send('Código incorrecto.')
627
+
628
+
629
+ res.status(200).send("Teléfono Verificado")
630
+ } catch (error) {
631
+ res.status(400).send(error)
632
+ }
633
+ }
634
+
635
+ self.sendverifyToken = async (correo, token) => {
636
+ try {
637
+
638
+ let user = await User.findOne({ email: correo }, { name: 1, email: 1 })
639
+
640
+ let file = fs.readFileSync(process.env.TEMPLATE_VERIFY_EMAIL, "utf8")
641
+ file = file.replace('+++user+++', user.name)
642
+ file = file.replace('+++token+++', token)
643
+
644
+
645
+ return await alouxAWS.sendCustom(user.email, file, "Verifica tu cuenta de "+process.env.PROJECT_NAME)
646
+ } catch (error) {
647
+ throw new Error('Ocurrio un error al envìar el correo electronico')
648
+ }
649
+ }
650
+
651
+ self.sendVerifyMailAccount = async (req, res) => {
652
+ try {
653
+ const result = await self.sendVerifyMailAccountJob(req, true)
654
+
655
+ res.status(200).send(result)
656
+ }catch(error) {
657
+ res.status(400).send({error:error.message})
658
+ }
659
+ }
660
+
661
+ self.sendVerifyMailAccountJob = async (data, ban) => {
662
+ // Generating recover pwd code and sending to user email address
663
+ try {
664
+
665
+ let user
666
+ if(ban == true){
667
+ user = await User.findOne({ email: data.body.email }).lean()
668
+ }else{
669
+ user = await User.findOne({ email: data }).lean()
670
+ }
671
+
672
+ const token = jwt.sign({ _id: user._id }, process.env.AUTH_SECRET)
673
+
674
+ await User.updateOne({ _id: user._id }, { 'validateKey.validateEmail.verifyMailToken': token, 'validateKey.validateEmail.emailVerified': false })
675
+
676
+ //var urlToken = process.env.VERIFY_ACCOUNT_URL + "=" + token
677
+
678
+ return await self.sendverifyToken(user.email, token)
679
+
680
+ } catch (error) {
681
+ let obj = error
682
+ if(!error.code){
683
+ obj = {
684
+ code: 400,
685
+ title: 'Error',
686
+ detail: error.message,
687
+ suggestion: 'Revisa el detalle del error'
688
+ }
689
+ }
690
+ return obj
691
+ }
692
+ }
693
+
694
+ self.sendValidateEmail = async (email) => {
695
+ try {
696
+
697
+ let user = await User.findOne({ email: email }, { name: 1, email: 1 })
698
+
699
+ let file = fs.readFileSync(process.env.TEMPLATE_WELCOME, "utf8")
700
+ file = file.replace('+++user+++', user.name)
701
+
702
+ return await sesSDK.sendCustom(user.email, file, 'Bienvenido a '+process.env.PROJECT_NAME)
703
+
704
+ } catch (error) {
705
+ throw new Error('Ocurrio un error al envìar el correo electronico')
706
+ }
707
+ }
708
+
709
+ self.verifyMailTokenAccount = async (req, res) => {
710
+ try {
711
+ token = req.params.token
712
+
713
+ const data = jwt.verify(token, process.env.AUTH_SECRET)
714
+
715
+ let user = await User.findOne({ _id: data._id, 'validateKey.validateEmail.verifyMailToken': token })
716
+
717
+ if (!user) {
718
+ throw new Error('¡Error!, Token no valido')
719
+ } else {
720
+ user.validateKey.validateEmail.verifyMailToken = null
721
+ user.validateKey.validateEmail.emailVerified = true
722
+ user.save()
723
+ }
724
+
725
+ if (user.validateKey.validateEmail.emailVerified == true) {
726
+ await self.sendValidateEmail(user.email)
727
+ }
728
+
729
+ res.status(200).send('Usuario verificado con éxito')
730
+ } catch (error) {
731
+ res.status(400).send({ error: error.message })
732
+ }
733
+ }
734
+