strapi-plugin-magic-sessionmanager 3.6.0 → 4.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.
Files changed (43) hide show
  1. package/README.md +104 -0
  2. package/admin/src/hooks/useLicense.js +1 -1
  3. package/admin/src/index.js +5 -2
  4. package/admin/src/pages/Settings.jsx +0 -1
  5. package/admin/src/translations/es.json +21 -0
  6. package/admin/src/translations/fr.json +21 -0
  7. package/admin/src/translations/pt.json +21 -0
  8. package/admin/src/utils/parseUserAgent.js +1 -1
  9. package/dist/_chunks/{Analytics-DRzCKaDF.js → Analytics-ioaeEh-E.js} +2 -2
  10. package/dist/_chunks/{Analytics-CwyLwdOZ.mjs → Analytics-mYu_uGwU.mjs} +2 -2
  11. package/dist/_chunks/{App-Zhs_vt59.mjs → App-BXpIS12l.mjs} +2 -2
  12. package/dist/_chunks/{App-nGu2Eb87.js → App-DdnUYWbC.js} +2 -2
  13. package/dist/_chunks/{License-CPI0p_W8.mjs → License-C03C2j9P.mjs} +1 -1
  14. package/dist/_chunks/{License-k5vvhgKr.js → License-DZYrOgcx.js} +1 -1
  15. package/dist/_chunks/{Settings-CL2im8M3.mjs → Settings-0ocB3qHk.mjs} +2 -2
  16. package/dist/_chunks/{Settings-Lkmxisuv.js → Settings-C6_CqpCC.js} +2 -2
  17. package/dist/_chunks/es-CuLHazN1.js +23 -0
  18. package/dist/_chunks/es-Dkmjhy9c.mjs +23 -0
  19. package/dist/_chunks/fr-BAJp2yhI.js +23 -0
  20. package/dist/_chunks/fr-Bssg_3UF.mjs +23 -0
  21. package/dist/_chunks/{index-B-0VPfeF.mjs → index-DBRS3kt5.mjs} +11 -8
  22. package/dist/_chunks/{index-W_QbTAYU.js → index-DC8Y0qxx.js} +11 -8
  23. package/dist/_chunks/pt-BAP9cKs3.js +23 -0
  24. package/dist/_chunks/pt-BVNoNcuY.mjs +23 -0
  25. package/dist/_chunks/{useLicense-DUGjNbQ9.mjs → useLicense-DSLL9n3Y.mjs} +2 -2
  26. package/dist/_chunks/{useLicense-C_Rneohy.js → useLicense-qgGfMvse.js} +2 -2
  27. package/dist/admin/index.js +1 -1
  28. package/dist/admin/index.mjs +1 -1
  29. package/dist/server/index.js +117 -95
  30. package/dist/server/index.mjs +117 -95
  31. package/package.json +1 -1
  32. package/server/src/bootstrap.js +32 -26
  33. package/server/src/controllers/license.js +4 -4
  34. package/server/src/controllers/session.js +10 -6
  35. package/server/src/destroy.js +1 -1
  36. package/server/src/middlewares/last-seen.js +8 -3
  37. package/server/src/register.js +4 -4
  38. package/server/src/services/geolocation.js +4 -2
  39. package/server/src/services/license-guard.js +13 -10
  40. package/server/src/services/notifications.js +10 -10
  41. package/server/src/services/service.js +1 -1
  42. package/server/src/services/session.js +41 -31
  43. package/server/src/utils/encryption.js +1 -1
@@ -9,11 +9,17 @@ const { encryptToken, decryptToken, generateSessionId } = require('../utils/encr
9
9
  *
10
10
  * SECURITY: JWT tokens are encrypted before storing in database using AES-256-GCM
11
11
  *
12
+ * [SUCCESS] Migrated to strapi.documents() API (Strapi v5 Best Practice)
13
+ *
12
14
  * TODO: For production multi-instance deployments, use Redis for:
13
15
  * - Session store instead of DB
14
16
  * - Rate limiting locks
15
17
  * - Distributed session state
16
18
  */
19
+
20
+ const SESSION_UID = 'plugin::magic-sessionmanager.session';
21
+ const USER_UID = 'plugin::users-permissions.user';
22
+
17
23
  module.exports = ({ strapi }) => ({
18
24
  /**
19
25
  * Create a new session record
@@ -31,21 +37,22 @@ module.exports = ({ strapi }) => ({
31
37
  const encryptedToken = token ? encryptToken(token) : null;
32
38
  const encryptedRefreshToken = refreshToken ? encryptToken(refreshToken) : null;
33
39
 
34
- const session = await strapi.entityService.create('plugin::magic-sessionmanager.session', {
40
+ // Using Document Service API (Strapi v5)
41
+ const session = await strapi.documents(SESSION_UID).create({
35
42
  data: {
36
- user: userId,
43
+ user: userId, // userId should be documentId (string)
37
44
  ipAddress: ip.substring(0, 45),
38
45
  userAgent: userAgent.substring(0, 500),
39
46
  loginTime: now,
40
47
  lastActive: now,
41
48
  isActive: true,
42
- token: encryptedToken, // Encrypted Access Token
43
- refreshToken: encryptedRefreshToken, // Encrypted Refresh Token
44
- sessionId: sessionId, // Unique identifier
49
+ token: encryptedToken, // [SUCCESS] Encrypted Access Token
50
+ refreshToken: encryptedRefreshToken, // [SUCCESS] Encrypted Refresh Token
51
+ sessionId: sessionId, // [SUCCESS] Unique identifier
45
52
  },
46
53
  });
47
54
 
48
- strapi.log.info(`[magic-sessionmanager] Session ${session.id} (${sessionId}) created for user ${userId}`);
55
+ strapi.log.info(`[magic-sessionmanager] [SUCCESS] Session ${session.documentId} (${sessionId}) created for user ${userId}`);
49
56
 
50
57
  return session;
51
58
  } catch (err) {
@@ -64,7 +71,9 @@ module.exports = ({ strapi }) => ({
64
71
  const now = new Date();
65
72
 
66
73
  if (sessionId) {
67
- await strapi.entityService.update('plugin::magic-sessionmanager.session', sessionId, {
74
+ // Using Document Service API (Strapi v5)
75
+ await strapi.documents(SESSION_UID).update({
76
+ documentId: sessionId,
68
77
  data: {
69
78
  isActive: false,
70
79
  logoutTime: now,
@@ -73,17 +82,18 @@ module.exports = ({ strapi }) => ({
73
82
 
74
83
  strapi.log.info(`[magic-sessionmanager] Session ${sessionId} terminated`);
75
84
  } else if (userId) {
76
- // Find all active sessions for user
77
- const activeSessions = await strapi.entityService.findMany('plugin::magic-sessionmanager.session', {
85
+ // Find all active sessions for user - use Deep Filtering (Strapi v5)
86
+ const activeSessions = await strapi.documents(SESSION_UID).findMany({
78
87
  filters: {
79
- user: { id: userId },
88
+ user: { documentId: userId }, // Deep filtering syntax
80
89
  isActive: true,
81
90
  },
82
91
  });
83
92
 
84
93
  // Terminate all active sessions
85
94
  for (const session of activeSessions) {
86
- await strapi.entityService.update('plugin::magic-sessionmanager.session', session.id, {
95
+ await strapi.documents(SESSION_UID).update({
96
+ documentId: session.documentId,
87
97
  data: {
88
98
  isActive: false,
89
99
  logoutTime: now,
@@ -105,7 +115,7 @@ module.exports = ({ strapi }) => ({
105
115
  */
106
116
  async getAllSessions() {
107
117
  try {
108
- const sessions = await strapi.entityService.findMany('plugin::magic-sessionmanager.session', {
118
+ const sessions = await strapi.documents(SESSION_UID).findMany( {
109
119
  populate: { user: { fields: ['id', 'email', 'username'] } },
110
120
  sort: { loginTime: 'desc' },
111
121
  limit: 1000, // Reasonable limit
@@ -147,7 +157,7 @@ module.exports = ({ strapi }) => ({
147
157
  */
148
158
  async getActiveSessions() {
149
159
  try {
150
- const sessions = await strapi.entityService.findMany('plugin::magic-sessionmanager.session', {
160
+ const sessions = await strapi.documents(SESSION_UID).findMany( {
151
161
  filters: { isActive: true },
152
162
  populate: { user: { fields: ['id', 'email', 'username'] } },
153
163
  sort: { loginTime: 'desc' },
@@ -191,8 +201,8 @@ module.exports = ({ strapi }) => ({
191
201
  */
192
202
  async getUserSessions(userId) {
193
203
  try {
194
- const sessions = await strapi.entityService.findMany('plugin::magic-sessionmanager.session', {
195
- filters: { user: { id: userId } },
204
+ const sessions = await strapi.documents(SESSION_UID).findMany( {
205
+ filters: { user: { documentId: userId } },
196
206
  sort: { loginTime: 'desc' },
197
207
  });
198
208
 
@@ -241,20 +251,20 @@ module.exports = ({ strapi }) => ({
241
251
 
242
252
  // Update session lastActive only
243
253
  if (sessionId) {
244
- const session = await strapi.entityService.findOne('plugin::magic-sessionmanager.session', sessionId);
254
+ const session = await strapi.documents(SESSION_UID).findOne({ documentId: sessionId });
245
255
 
246
256
  if (session && session.lastActive) {
247
257
  const lastActiveTime = new Date(session.lastActive).getTime();
248
258
  const currentTime = now.getTime();
249
259
 
250
260
  if (currentTime - lastActiveTime > rateLimit) {
251
- await strapi.entityService.update('plugin::magic-sessionmanager.session', sessionId, {
261
+ await strapi.documents(SESSION_UID).update({ documentId: sessionId,
252
262
  data: { lastActive: now },
253
263
  });
254
264
  }
255
265
  } else if (session) {
256
266
  // First time or null
257
- await strapi.entityService.update('plugin::magic-sessionmanager.session', sessionId, {
267
+ await strapi.documents(SESSION_UID).update({ documentId: sessionId,
258
268
  data: { lastActive: now },
259
269
  });
260
270
  }
@@ -279,12 +289,12 @@ module.exports = ({ strapi }) => ({
279
289
  const now = new Date();
280
290
  const cutoffTime = new Date(now.getTime() - inactivityTimeout);
281
291
 
282
- strapi.log.info(`[magic-sessionmanager] 🧹 Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
292
+ strapi.log.info(`[magic-sessionmanager] [CLEANUP] Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
283
293
 
284
294
  // Find all active sessions
285
- const activeSessions = await strapi.entityService.findMany('plugin::magic-sessionmanager.session', {
295
+ const activeSessions = await strapi.documents(SESSION_UID).findMany({
286
296
  filters: { isActive: true },
287
- fields: ['id', 'lastActive', 'loginTime'],
297
+ fields: ['lastActive', 'loginTime'],
288
298
  });
289
299
 
290
300
  // Deactivate old sessions
@@ -293,14 +303,15 @@ module.exports = ({ strapi }) => ({
293
303
  const lastActiveTime = session.lastActive ? new Date(session.lastActive) : new Date(session.loginTime);
294
304
 
295
305
  if (lastActiveTime < cutoffTime) {
296
- await strapi.entityService.update('plugin::magic-sessionmanager.session', session.id, {
306
+ await strapi.documents(SESSION_UID).update({
307
+ documentId: session.documentId,
297
308
  data: { isActive: false },
298
309
  });
299
310
  deactivatedCount++;
300
311
  }
301
312
  }
302
313
 
303
- strapi.log.info(`[magic-sessionmanager] Cleanup complete: ${deactivatedCount} sessions deactivated`);
314
+ strapi.log.info(`[magic-sessionmanager] [SUCCESS] Cleanup complete: ${deactivatedCount} sessions deactivated`);
304
315
  return deactivatedCount;
305
316
  } catch (err) {
306
317
  strapi.log.error('[magic-sessionmanager] Error cleaning up inactive sessions:', err);
@@ -316,8 +327,8 @@ module.exports = ({ strapi }) => ({
316
327
  */
317
328
  async deleteSession(sessionId) {
318
329
  try {
319
- await strapi.entityService.delete('plugin::magic-sessionmanager.session', sessionId);
320
- strapi.log.info(`[magic-sessionmanager] 🗑️ Session ${sessionId} permanently deleted`);
330
+ await strapi.documents(SESSION_UID).delete({ documentId: sessionId });
331
+ strapi.log.info(`[magic-sessionmanager] [DELETE] Session ${sessionId} permanently deleted`);
321
332
  return true;
322
333
  } catch (err) {
323
334
  strapi.log.error('[magic-sessionmanager] Error deleting session:', err);
@@ -332,23 +343,22 @@ module.exports = ({ strapi }) => ({
332
343
  */
333
344
  async deleteInactiveSessions() {
334
345
  try {
335
- strapi.log.info('[magic-sessionmanager] 🗑️ Deleting all inactive sessions...');
346
+ strapi.log.info('[magic-sessionmanager] [DELETE] Deleting all inactive sessions...');
336
347
 
337
- // Find all inactive sessions
338
- const inactiveSessions = await strapi.entityService.findMany('plugin::magic-sessionmanager.session', {
348
+ // Find all inactive sessions (documentId is always included automatically)
349
+ const inactiveSessions = await strapi.documents(SESSION_UID).findMany({
339
350
  filters: { isActive: false },
340
- fields: ['id'],
341
351
  });
342
352
 
343
353
  let deletedCount = 0;
344
354
 
345
355
  // Delete each inactive session
346
356
  for (const session of inactiveSessions) {
347
- await strapi.entityService.delete('plugin::magic-sessionmanager.session', session.id);
357
+ await strapi.documents(SESSION_UID).delete({ documentId: session.documentId });
348
358
  deletedCount++;
349
359
  }
350
360
 
351
- strapi.log.info(`[magic-sessionmanager] Deleted ${deletedCount} inactive sessions`);
361
+ strapi.log.info(`[magic-sessionmanager] [SUCCESS] Deleted ${deletedCount} inactive sessions`);
352
362
  return deletedCount;
353
363
  } catch (err) {
354
364
  strapi.log.error('[magic-sessionmanager] Error deleting inactive sessions:', err);
@@ -31,7 +31,7 @@ function getEncryptionKey() {
31
31
  const strapiKeys = process.env.APP_KEYS || process.env.API_TOKEN_SALT || 'default-insecure-key';
32
32
  const key = crypto.createHash('sha256').update(strapiKeys).digest();
33
33
 
34
- console.warn('[magic-sessionmanager/encryption] ⚠️ No SESSION_ENCRYPTION_KEY found. Using fallback (not recommended for production).');
34
+ console.warn('[magic-sessionmanager/encryption] [WARNING] No SESSION_ENCRYPTION_KEY found. Using fallback (not recommended for production).');
35
35
  console.warn('[magic-sessionmanager/encryption] Set SESSION_ENCRYPTION_KEY in .env for better security.');
36
36
 
37
37
  return key;