aloux-iam 0.0.142 → 0.0.144
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.
- package/lib/controllers/log.js +64 -25
- package/lib/controllers/user.js +0 -10
- package/lib/middleware.js +24 -9
- package/lib/models/User.js +0 -7
- package/lib/router.js +0 -1
- package/lib/services/user.js +0 -20
- package/package.json +1 -1
package/lib/controllers/log.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const Log = require("../models/Log");
|
|
2
2
|
const Label = require("../models/Label");
|
|
3
|
+
const Functions = require("../models/Functions");
|
|
3
4
|
const mongoose = require("mongoose");
|
|
4
5
|
const self = module.exports;
|
|
5
6
|
|
|
@@ -9,7 +10,8 @@ self.create = async (req, res) => {
|
|
|
9
10
|
req.header("Company") !== "undefined" ? req.header("Company") : null;
|
|
10
11
|
|
|
11
12
|
const log = new Log(req.body);
|
|
12
|
-
const businessId =
|
|
13
|
+
const businessId =
|
|
14
|
+
req.header("business") !== "undefined" ? req.header("business") : null;
|
|
13
15
|
log.createdAt = new Date().getTime();
|
|
14
16
|
log._user = req.user._id;
|
|
15
17
|
log._company = companyId;
|
|
@@ -56,6 +58,14 @@ self.retrieve = async (req, res) => {
|
|
|
56
58
|
const companyId =
|
|
57
59
|
req.header("Company") !== "undefined" ? req.header("Company") : null;
|
|
58
60
|
|
|
61
|
+
const excludeFunctions = req.body.excludeFunctions || [];
|
|
62
|
+
|
|
63
|
+
const excludeFuncs = await Functions.find({
|
|
64
|
+
name: { $in: excludeFunctions },
|
|
65
|
+
}).lean();
|
|
66
|
+
|
|
67
|
+
const excludeIds = excludeFuncs.map((f) => f._id);
|
|
68
|
+
|
|
59
69
|
const query = { _company: companyId };
|
|
60
70
|
|
|
61
71
|
if (req.body.users?.length) {
|
|
@@ -74,18 +84,29 @@ self.retrieve = async (req, res) => {
|
|
|
74
84
|
query._business = { $in: req.body.business };
|
|
75
85
|
}
|
|
76
86
|
|
|
77
|
-
const consulta = await Log.find(query).populate(
|
|
87
|
+
const consulta = await Log.find(query).populate({
|
|
88
|
+
path: "_user",
|
|
89
|
+
select: "name lastName email _functions",
|
|
90
|
+
match: excludeIds.length ? { _functions: { $nin: excludeIds } } : {},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const filtrados = consulta.filter((log) => log._user !== null);
|
|
78
94
|
|
|
79
95
|
const response = {
|
|
80
|
-
dataset0: { field: "Visualizaciones totales", count:
|
|
81
|
-
dataset1: processDataset1(
|
|
82
|
-
dataset2: processDataset2(
|
|
83
|
-
dataset3: processDataset3(
|
|
84
|
-
dataset4: processDataset4(
|
|
85
|
-
dataset5: processDataset5(
|
|
86
|
-
dataset6: processDataset6(
|
|
87
|
-
dataset7: processDataset7(
|
|
88
|
-
dataset8: processDataset8(
|
|
96
|
+
dataset0: { field: "Visualizaciones totales", count: filtrados.length },
|
|
97
|
+
dataset1: processDataset1(filtrados),
|
|
98
|
+
dataset2: processDataset2(filtrados),
|
|
99
|
+
dataset3: processDataset3(filtrados),
|
|
100
|
+
dataset4: processDataset4(filtrados),
|
|
101
|
+
dataset5: processDataset5(filtrados),
|
|
102
|
+
dataset6: processDataset6(filtrados),
|
|
103
|
+
dataset7: processDataset7(filtrados),
|
|
104
|
+
dataset8: processDataset8(
|
|
105
|
+
filtrados,
|
|
106
|
+
req.body.search,
|
|
107
|
+
req.body.page,
|
|
108
|
+
req.body.limit,
|
|
109
|
+
),
|
|
89
110
|
};
|
|
90
111
|
|
|
91
112
|
res.status(200).send(response);
|
|
@@ -98,8 +119,18 @@ self.retrieve = async (req, res) => {
|
|
|
98
119
|
function formatDate(isoDate) {
|
|
99
120
|
const [year, month, day] = isoDate.split("-");
|
|
100
121
|
const monthNames = [
|
|
101
|
-
"Ene",
|
|
102
|
-
"
|
|
122
|
+
"Ene",
|
|
123
|
+
"Feb",
|
|
124
|
+
"Mar",
|
|
125
|
+
"Abr",
|
|
126
|
+
"May",
|
|
127
|
+
"Jun",
|
|
128
|
+
"Jul",
|
|
129
|
+
"Ago",
|
|
130
|
+
"Sep",
|
|
131
|
+
"Oct",
|
|
132
|
+
"Nov",
|
|
133
|
+
"Dic",
|
|
103
134
|
];
|
|
104
135
|
return `${day} ${monthNames[parseInt(month) - 1]} ${year}`;
|
|
105
136
|
}
|
|
@@ -176,12 +207,12 @@ function processDataset5(consulta) {
|
|
|
176
207
|
});
|
|
177
208
|
|
|
178
209
|
const uniqueLabels = new Set(
|
|
179
|
-
Object.values(labelCountsByDate).flatMap(Object.keys)
|
|
210
|
+
Object.values(labelCountsByDate).flatMap(Object.keys),
|
|
180
211
|
);
|
|
181
212
|
const series = Array.from(uniqueLabels).map((label) => ({
|
|
182
213
|
name: label,
|
|
183
214
|
data: Array.from(categories).map(
|
|
184
|
-
(date) => labelCountsByDate[date]?.[label] || 0
|
|
215
|
+
(date) => labelCountsByDate[date]?.[label] || 0,
|
|
185
216
|
),
|
|
186
217
|
}));
|
|
187
218
|
|
|
@@ -230,7 +261,7 @@ function processDataset7(data) {
|
|
|
230
261
|
};
|
|
231
262
|
}
|
|
232
263
|
|
|
233
|
-
function processDataset8(data, search = "", page = 1, limit =
|
|
264
|
+
function processDataset8(data, search = "", page = 1, limit = null) {
|
|
234
265
|
const userActivity = {};
|
|
235
266
|
|
|
236
267
|
data.forEach((item) => {
|
|
@@ -249,24 +280,32 @@ function processDataset8(data, search = "", page = 1, limit = 10) {
|
|
|
249
280
|
let users = Object.values(userActivity).sort((a, b) => b.count - a.count);
|
|
250
281
|
|
|
251
282
|
if (search) {
|
|
252
|
-
const s = search
|
|
283
|
+
const s = search
|
|
284
|
+
.toLowerCase()
|
|
285
|
+
.normalize("NFD")
|
|
286
|
+
.replace(/[\u0300-\u036f]/g, "");
|
|
253
287
|
users = users.filter((u) => {
|
|
254
|
-
const full = `${u.name} ${u.lastName} ${u.email}
|
|
288
|
+
const full = `${u.name} ${u.lastName} ${u.email}`
|
|
289
|
+
.toLowerCase()
|
|
290
|
+
.normalize("NFD")
|
|
291
|
+
.replace(/[\u0300-\u036f]/g, "");
|
|
255
292
|
return full.includes(s);
|
|
256
293
|
});
|
|
257
294
|
}
|
|
258
295
|
|
|
259
296
|
const total = users.length;
|
|
260
|
-
const
|
|
261
|
-
const
|
|
262
|
-
const
|
|
297
|
+
const paginate = limit !== null && limit !== undefined;
|
|
298
|
+
const parsedLimit = paginate ? parseInt(limit) : total;
|
|
299
|
+
const parsedPage = parseInt(page);
|
|
300
|
+
const start = (parsedPage - 1) * parsedLimit;
|
|
301
|
+
const items = paginate ? users.slice(start, start + parsedLimit) : users;
|
|
263
302
|
|
|
264
303
|
return {
|
|
265
304
|
field: "Actividad de usuarios",
|
|
266
305
|
total,
|
|
267
|
-
page,
|
|
268
|
-
limit,
|
|
269
|
-
totalPages,
|
|
306
|
+
page: parsedPage,
|
|
307
|
+
limit: parsedLimit,
|
|
308
|
+
totalPages: paginate ? Math.ceil(total / parsedLimit) : 1,
|
|
270
309
|
items,
|
|
271
310
|
};
|
|
272
311
|
}
|
|
@@ -301,4 +340,4 @@ self.count = async (req, res) => {
|
|
|
301
340
|
} catch (error) {
|
|
302
341
|
res.status(400).send({ error: error.message });
|
|
303
342
|
}
|
|
304
|
-
};
|
|
343
|
+
};
|
package/lib/controllers/user.js
CHANGED
|
@@ -936,7 +936,6 @@ self.addTimeToken = async (req, res) => {
|
|
|
936
936
|
|
|
937
937
|
if (tokenObject) {
|
|
938
938
|
tokenObject.dateEnd = Date.now() + process.env.SESSION_TIME * 60 * 1000;
|
|
939
|
-
// Guarda los cambios en la base de datos
|
|
940
939
|
await User.updateOne(
|
|
941
940
|
{ _id: userTokens._id, "tokens.token": req.params.TOKEN },
|
|
942
941
|
{ $set: { "tokens.$.dateEnd": tokenObject.dateEnd } }
|
|
@@ -952,12 +951,3 @@ self.addTimeToken = async (req, res) => {
|
|
|
952
951
|
res.status(400).send({ error: error.message });
|
|
953
952
|
}
|
|
954
953
|
};
|
|
955
|
-
|
|
956
|
-
self.checkUsername = async (req, res) => {
|
|
957
|
-
try {
|
|
958
|
-
const result = await serviceUser.checkUsername(req.body.name)
|
|
959
|
-
res.status(200).send(result)
|
|
960
|
-
} catch (error) {
|
|
961
|
-
utils.responseError(res, error, 400, "Error al verificar username", "Revisa el detalle del error")
|
|
962
|
-
}
|
|
963
|
-
}
|
package/lib/middleware.js
CHANGED
|
@@ -4,6 +4,15 @@ const Permission = require("./models/Permission");
|
|
|
4
4
|
const historyController = require("./controllers/history");
|
|
5
5
|
|
|
6
6
|
const getAccess = (user, resource) => {
|
|
7
|
+
// Cuenta de servicio
|
|
8
|
+
const userApis = user?.data?.apis || [];
|
|
9
|
+
if (userApis.length > 0) {
|
|
10
|
+
return userApis.some(
|
|
11
|
+
(apiId) => apiId.toString() === resource._id.toString(),
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Flujo normal
|
|
7
16
|
for (let i in user._functions) {
|
|
8
17
|
for (let j in user._functions[i]._permissions) {
|
|
9
18
|
if (user._functions[i]._permissions[j].status === "Activo") {
|
|
@@ -50,7 +59,7 @@ const auth = async (req, res, next) => {
|
|
|
50
59
|
const data = jwt.verify(token, process.env.AUTH_SECRET);
|
|
51
60
|
const user = await User.findOne(
|
|
52
61
|
{ _id: data._id, "tokens.token": token, status: "Activo" },
|
|
53
|
-
{ tokens: 0, pwd: 0 }
|
|
62
|
+
{ tokens: 0, pwd: 0 },
|
|
54
63
|
)
|
|
55
64
|
.populate({ path: "_functions", populate: [{ path: "_permissions" }] })
|
|
56
65
|
.lean();
|
|
@@ -69,7 +78,7 @@ const auth = async (req, res, next) => {
|
|
|
69
78
|
if (process.env.SESSION_INTERRUPTOR === "true") {
|
|
70
79
|
const userTokens = await User.findOne(
|
|
71
80
|
{ _id: user._id, status: "Activo" },
|
|
72
|
-
{ tokens: 1 }
|
|
81
|
+
{ tokens: 1 },
|
|
73
82
|
).lean();
|
|
74
83
|
const tokenObject = userTokens.tokens.find((t) => t.token === token);
|
|
75
84
|
if (tokenObject.dateEnd <= Date.now()) {
|
|
@@ -79,7 +88,7 @@ const auth = async (req, res, next) => {
|
|
|
79
88
|
$pull: {
|
|
80
89
|
tokens: { token: tokenObject.token }, // Condición para eliminar el token específico
|
|
81
90
|
},
|
|
82
|
-
}
|
|
91
|
+
},
|
|
83
92
|
);
|
|
84
93
|
throw {
|
|
85
94
|
code: 401,
|
|
@@ -113,15 +122,21 @@ const auth = async (req, res, next) => {
|
|
|
113
122
|
if (resource.auth && !resource.default) {
|
|
114
123
|
const access = getAccess(user, resource);
|
|
115
124
|
if (!access) {
|
|
125
|
+
const userApis = user?.data?.apis || [];
|
|
116
126
|
throw {
|
|
117
127
|
code: 403,
|
|
118
|
-
title: "
|
|
128
|
+
title: "Acceso denegado",
|
|
119
129
|
detail:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
130
|
+
userApis.length > 0
|
|
131
|
+
? "No cuentas con acceso a esta API"
|
|
132
|
+
: "No cuentas con permisos para el recurso [" +
|
|
133
|
+
resource.api +
|
|
134
|
+
"] que: " +
|
|
135
|
+
(resource ? resource.description : "Recurso indefinido"),
|
|
136
|
+
suggestion:
|
|
137
|
+
userApis.length > 0
|
|
138
|
+
? "Contacta con el administrador para asignar acceso a esta API"
|
|
139
|
+
: "Contacta con el administrador",
|
|
125
140
|
error: new Error(),
|
|
126
141
|
};
|
|
127
142
|
}
|
package/lib/models/User.js
CHANGED
|
@@ -14,13 +14,6 @@ const adminSchema = mongoose.Schema({
|
|
|
14
14
|
sparse: true,
|
|
15
15
|
lowercase: true,
|
|
16
16
|
},
|
|
17
|
-
username: {
|
|
18
|
-
type: String,
|
|
19
|
-
trim: true,
|
|
20
|
-
unique: true,
|
|
21
|
-
sparse: true,
|
|
22
|
-
lowercase: true,
|
|
23
|
-
},
|
|
24
17
|
pwd: { type: String, trim: true, minLength: 8 },
|
|
25
18
|
phone: { type: String, trim: true, maxLength: 13 },
|
|
26
19
|
phoneObj: {
|
package/lib/router.js
CHANGED
|
@@ -46,7 +46,6 @@ router.get("/iam/user", middleware, user.retrieve);
|
|
|
46
46
|
router.post("/iam/user/pages", middleware, user.retrievePages);
|
|
47
47
|
router.get("/iam/business/user", middleware, user.retrieveByBusiness);
|
|
48
48
|
router.get("/iam/user/by/my/companies", middleware, user.retrieveByMyCompanies);
|
|
49
|
-
router.post('/iam/user/check/username', middleware, user.checkUsername);
|
|
50
49
|
router.get("/iam/user/:USER_ID", middleware, user.get);
|
|
51
50
|
router.patch("/iam/user/:USER_ID", middleware, user.update);
|
|
52
51
|
router.put("/iam/user/:USER_ID/status", middleware, user.status);
|
package/lib/services/user.js
CHANGED
|
@@ -2,29 +2,10 @@ const jwt = require("jsonwebtoken")
|
|
|
2
2
|
const User = require('../models/User')
|
|
3
3
|
const self = module.exports
|
|
4
4
|
|
|
5
|
-
const generateUniqueUsername = async (name) => {
|
|
6
|
-
const base = name
|
|
7
|
-
.toLowerCase()
|
|
8
|
-
.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
|
|
9
|
-
.replace(/\s+/g, '-')
|
|
10
|
-
.replace(/[^a-z0-9-]/g, '')
|
|
11
|
-
|
|
12
|
-
let username = base
|
|
13
|
-
let count = 1
|
|
14
|
-
|
|
15
|
-
while (await User.findOne({ username }).lean()) {
|
|
16
|
-
username = `${base}${count}`
|
|
17
|
-
count++
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return username
|
|
21
|
-
}
|
|
22
|
-
|
|
23
5
|
self.create = async (body) => {
|
|
24
6
|
let user
|
|
25
7
|
const isServiceAccount = !body.email && !body.pwd
|
|
26
8
|
|
|
27
|
-
// Limpieza de campos únicos que pueden llegar como null
|
|
28
9
|
const nullableUnique = ['username', 'phone', 'email']
|
|
29
10
|
nullableUnique.forEach(field => {
|
|
30
11
|
if (!body[field]) delete body[field]
|
|
@@ -32,7 +13,6 @@ self.create = async (body) => {
|
|
|
32
13
|
|
|
33
14
|
if (isServiceAccount) {
|
|
34
15
|
user = new User(body)
|
|
35
|
-
user.username = await generateUniqueUsername(body.name)
|
|
36
16
|
user.createdAt = new Date().getTime()
|
|
37
17
|
user.status = body?.status ?? 'Activo'
|
|
38
18
|
user.data = { changePwd: false }
|