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.
@@ -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 = req.header("business") !== "undefined" ? req.header("business") : null;
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("_user", "name lastName email");
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: consulta.length },
81
- dataset1: processDataset1(consulta),
82
- dataset2: processDataset2(consulta),
83
- dataset3: processDataset3(consulta),
84
- dataset4: processDataset4(consulta),
85
- dataset5: processDataset5(consulta),
86
- dataset6: processDataset6(consulta),
87
- dataset7: processDataset7(consulta),
88
- dataset8: processDataset8(consulta, req.body.search, req.body.page, req.body.limit),
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", "Feb", "Mar", "Abr", "May", "Jun",
102
- "Jul", "Ago", "Sep", "Oct", "Nov", "Dic",
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 = 10) {
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.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
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}`.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
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 totalPages = Math.ceil(total / limit);
261
- const start = (page - 1) * limit;
262
- const items = users.slice(start, start + limit);
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
+ };
@@ -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: "Error de permisos",
128
+ title: "Acceso denegado",
119
129
  detail:
120
- "No cuentas con permisos para el recurso [" +
121
- resource.api +
122
- "] que: " +
123
- (resource ? resource.description : "Recurso indefinido"),
124
- suggestion: "Contacta con el administrador",
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
  }
@@ -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);
@@ -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 }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aloux-iam",
3
- "version": "0.0.142",
3
+ "version": "0.0.144",
4
4
  "description": "Aloux IAM for APIs ",
5
5
  "main": "index.js",
6
6
  "scripts": {