strapi-plugin-magic-sessionmanager 4.2.0 → 4.2.3

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.
@@ -3,21 +3,83 @@ import require$$1 from "os";
3
3
  function getDefaultExportFromCjs(x) {
4
4
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
5
5
  }
6
+ const PLUGIN_NAME = "magic-sessionmanager";
7
+ const PREFIX = "[magic-sessionmanager]";
8
+ function formatMessage(prefix, args) {
9
+ if (args.length === 0) return prefix;
10
+ const parts = args.map(
11
+ (arg) => typeof arg === "string" ? arg : JSON.stringify(arg)
12
+ );
13
+ return `${prefix} ${parts.join(" ")}`;
14
+ }
15
+ function createLogger$5(strapi2) {
16
+ const getDebugMode = () => {
17
+ try {
18
+ const config2 = strapi2.config.get(`plugin::${PLUGIN_NAME}`) || {};
19
+ return config2.debug === true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ };
24
+ return {
25
+ /**
26
+ * Log info - only when debug: true
27
+ */
28
+ info: (...args) => {
29
+ if (getDebugMode()) {
30
+ strapi2.log.info(formatMessage(PREFIX, args));
31
+ }
32
+ },
33
+ /**
34
+ * Log debug - only when debug: true
35
+ */
36
+ debug: (...args) => {
37
+ if (getDebugMode()) {
38
+ strapi2.log.debug(formatMessage(PREFIX, args));
39
+ }
40
+ },
41
+ /**
42
+ * Log warning - only when debug: true
43
+ */
44
+ warn: (...args) => {
45
+ if (getDebugMode()) {
46
+ strapi2.log.warn(formatMessage(PREFIX, args));
47
+ }
48
+ },
49
+ /**
50
+ * Log error - only when debug: true
51
+ */
52
+ error: (...args) => {
53
+ if (getDebugMode()) {
54
+ strapi2.log.error(formatMessage(PREFIX, args));
55
+ }
56
+ },
57
+ /**
58
+ * Force log - always logged (for critical errors only)
59
+ */
60
+ forceError: (...args) => {
61
+ strapi2.log.error(formatMessage(PREFIX, args));
62
+ }
63
+ };
64
+ }
65
+ var logger = { createLogger: createLogger$5 };
66
+ const { createLogger: createLogger$4 } = logger;
6
67
  var register$1 = async ({ strapi: strapi2 }) => {
7
- strapi2.log.info("[magic-sessionmanager] [START] Plugin registration starting...");
68
+ const log = createLogger$4(strapi2);
69
+ log.info("[START] Plugin registration starting...");
8
70
  try {
9
71
  const userCT = strapi2.contentType("plugin::users-permissions.user");
10
72
  if (!userCT) {
11
- strapi2.log.error("[magic-sessionmanager] User content type not found");
73
+ log.error("User content type not found");
12
74
  return;
13
75
  }
14
76
  if (userCT.attributes && userCT.attributes.sessions) {
15
77
  delete userCT.attributes.sessions;
16
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] Removed sessions field from User content type");
78
+ log.info("[SUCCESS] Removed sessions field from User content type");
17
79
  }
18
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] Plugin registered successfully");
80
+ log.info("[SUCCESS] Plugin registered successfully");
19
81
  } catch (err) {
20
- strapi2.log.error("[magic-sessionmanager] [ERROR] Registration error:", err);
82
+ log.error("[ERROR] Registration error:", err);
21
83
  }
22
84
  };
23
85
  const getClientIp$1 = (ctx) => {
@@ -183,49 +245,51 @@ var lastSeen = ({ strapi: strapi2, sessionService }) => {
183
245
  };
184
246
  const getClientIp = getClientIp_1;
185
247
  const { encryptToken: encryptToken$1, decryptToken: decryptToken$2 } = encryption;
248
+ const { createLogger: createLogger$3 } = logger;
186
249
  const SESSION_UID$2 = "plugin::magic-sessionmanager.session";
187
250
  const USER_UID$2 = "plugin::users-permissions.user";
188
251
  var bootstrap$1 = async ({ strapi: strapi2 }) => {
189
- strapi2.log.info("[magic-sessionmanager] [START] Bootstrap starting...");
252
+ const log = createLogger$3(strapi2);
253
+ log.info("[START] Bootstrap starting...");
190
254
  try {
191
255
  const licenseGuardService = strapi2.plugin("magic-sessionmanager").service("license-guard");
192
256
  setTimeout(async () => {
193
257
  const licenseStatus = await licenseGuardService.initialize();
194
258
  if (!licenseStatus.valid) {
195
- strapi2.log.error("╔════════════════════════════════════════════════════════════════╗");
196
- strapi2.log.error("║ [ERROR] SESSION MANAGER - NO VALID LICENSE ║");
197
- strapi2.log.error("║ ║");
198
- strapi2.log.error("║ This plugin requires a valid license to operate. ║");
199
- strapi2.log.error("║ Please activate your license via Admin UI: ║");
200
- strapi2.log.error("║ Go to Settings → Sessions → License ║");
201
- strapi2.log.error("║ ║");
202
- strapi2.log.error("║ The plugin will run with limited functionality until ║");
203
- strapi2.log.error("║ a valid license is activated. ║");
204
- strapi2.log.error("╚════════════════════════════════════════════════════════════════╝");
259
+ log.error("╔════════════════════════════════════════════════════════════════╗");
260
+ log.error("║ [ERROR] SESSION MANAGER - NO VALID LICENSE ║");
261
+ log.error("║ ║");
262
+ log.error("║ This plugin requires a valid license to operate. ║");
263
+ log.error("║ Please activate your license via Admin UI: ║");
264
+ log.error("║ Go to Settings → Sessions → License ║");
265
+ log.error("║ ║");
266
+ log.error("║ The plugin will run with limited functionality until ║");
267
+ log.error("║ a valid license is activated. ║");
268
+ log.error("╚════════════════════════════════════════════════════════════════╝");
205
269
  } else if (licenseStatus.valid) {
206
270
  const pluginStore = strapi2.store({
207
271
  type: "plugin",
208
272
  name: "magic-sessionmanager"
209
273
  });
210
274
  const storedKey = await pluginStore.get({ key: "licenseKey" });
211
- strapi2.log.info("╔════════════════════════════════════════════════════════════════╗");
212
- strapi2.log.info("║ [SUCCESS] SESSION MANAGER LICENSE ACTIVE ║");
213
- strapi2.log.info("║ ║");
275
+ log.info("╔════════════════════════════════════════════════════════════════╗");
276
+ log.info("║ [SUCCESS] SESSION MANAGER LICENSE ACTIVE ║");
277
+ log.info("║ ║");
214
278
  if (licenseStatus.data) {
215
- strapi2.log.info(`║ License: ${licenseStatus.data.licenseKey}`.padEnd(66) + "║");
216
- strapi2.log.info(`║ User: ${licenseStatus.data.firstName} ${licenseStatus.data.lastName}`.padEnd(66) + "║");
217
- strapi2.log.info(`║ Email: ${licenseStatus.data.email}`.padEnd(66) + "║");
279
+ log.info(`║ License: ${licenseStatus.data.licenseKey}`.padEnd(66) + "║");
280
+ log.info(`║ User: ${licenseStatus.data.firstName} ${licenseStatus.data.lastName}`.padEnd(66) + "║");
281
+ log.info(`║ Email: ${licenseStatus.data.email}`.padEnd(66) + "║");
218
282
  } else if (storedKey) {
219
- strapi2.log.info(`║ License: ${storedKey} (Offline Mode)`.padEnd(66) + "║");
220
- strapi2.log.info(`║ Status: Grace Period Active`.padEnd(66) + "║");
283
+ log.info(`║ License: ${storedKey} (Offline Mode)`.padEnd(66) + "║");
284
+ log.info(`║ Status: Grace Period Active`.padEnd(66) + "║");
221
285
  }
222
- strapi2.log.info("║ ║");
223
- strapi2.log.info("║ [RELOAD] Auto-pinging every 15 minutes ║");
224
- strapi2.log.info("╚════════════════════════════════════════════════════════════════╝");
286
+ log.info("║ ║");
287
+ log.info("║ [RELOAD] Auto-pinging every 15 minutes ║");
288
+ log.info("╚════════════════════════════════════════════════════════════════╝");
225
289
  }
226
290
  }, 3e3);
227
291
  const sessionService = strapi2.plugin("magic-sessionmanager").service("session");
228
- strapi2.log.info("[magic-sessionmanager] Running initial session cleanup...");
292
+ log.info("Running initial session cleanup...");
229
293
  await sessionService.cleanupInactiveSessions();
230
294
  const cleanupInterval = 30 * 60 * 1e3;
231
295
  const cleanupIntervalHandle = setInterval(async () => {
@@ -233,10 +297,10 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
233
297
  const service = strapi2.plugin("magic-sessionmanager").service("session");
234
298
  await service.cleanupInactiveSessions();
235
299
  } catch (err) {
236
- strapi2.log.error("[magic-sessionmanager] Periodic cleanup error:", err);
300
+ log.error("Periodic cleanup error:", err);
237
301
  }
238
302
  }, cleanupInterval);
239
- strapi2.log.info("[magic-sessionmanager] [TIME] Periodic cleanup scheduled (every 30 minutes)");
303
+ log.info("[TIME] Periodic cleanup scheduled (every 30 minutes)");
240
304
  if (!strapi2.sessionManagerIntervals) {
241
305
  strapi2.sessionManagerIntervals = {};
242
306
  }
@@ -268,12 +332,12 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
268
332
  });
269
333
  if (matchingSession) {
270
334
  await sessionService.terminateSession({ sessionId: matchingSession.documentId });
271
- strapi2.log.info(`[magic-sessionmanager] [LOGOUT] Logout via /api/auth/logout - Session ${matchingSession.documentId} terminated`);
335
+ log.info(`[LOGOUT] Logout via /api/auth/logout - Session ${matchingSession.documentId} terminated`);
272
336
  }
273
337
  ctx.status = 200;
274
338
  ctx.body = { message: "Logged out successfully" };
275
339
  } catch (err) {
276
- strapi2.log.error("[magic-sessionmanager] Logout error:", err);
340
+ log.error("Logout error:", err);
277
341
  ctx.status = 200;
278
342
  ctx.body = { message: "Logged out successfully" };
279
343
  }
@@ -282,7 +346,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
282
346
  auth: false
283
347
  }
284
348
  }]);
285
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] /api/auth/logout route registered");
349
+ log.info("[SUCCESS] /api/auth/logout route registered");
286
350
  strapi2.server.use(async (ctx, next) => {
287
351
  await next();
288
352
  const isAuthLocal = ctx.path === "/api/auth/local" && ctx.method === "POST";
@@ -292,7 +356,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
292
356
  const user = ctx.body.user;
293
357
  const ip = getClientIp(ctx);
294
358
  const userAgent = ctx.request.headers?.["user-agent"] || ctx.request.header?.["user-agent"] || "unknown";
295
- strapi2.log.info(`[magic-sessionmanager] [CHECK] Login detected! User: ${user.documentId || user.id} (${user.email || user.username}) from IP: ${ip}`);
359
+ log.info(`[CHECK] Login detected! User: ${user.documentId || user.id} (${user.email || user.username}) from IP: ${ip}`);
296
360
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
297
361
  let shouldBlock = false;
298
362
  let blockReason = "";
@@ -330,11 +394,11 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
330
394
  }
331
395
  }
332
396
  } catch (geoErr) {
333
- strapi2.log.warn("[magic-sessionmanager] Geolocation check failed:", geoErr.message);
397
+ log.warn("Geolocation check failed:", geoErr.message);
334
398
  }
335
399
  }
336
400
  if (shouldBlock) {
337
- strapi2.log.warn(`[magic-sessionmanager] [BLOCKED] Blocking login: ${blockReason}`);
401
+ log.warn(`[BLOCKED] Blocking login: ${blockReason}`);
338
402
  ctx.status = 403;
339
403
  ctx.body = {
340
404
  error: {
@@ -359,7 +423,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
359
423
  refreshToken: ctx.body.refreshToken
360
424
  // Store Refresh Token (encrypted) if exists
361
425
  });
362
- strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session created for user ${userDocId} (IP: ${ip})`);
426
+ log.info(`[SUCCESS] Session created for user ${userDocId} (IP: ${ip})`);
363
427
  if (geoData && (config2.enableEmailAlerts || config2.enableWebhooks)) {
364
428
  try {
365
429
  const notificationService = strapi2.plugin("magic-sessionmanager").service("notifications");
@@ -393,15 +457,15 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
393
457
  }
394
458
  }
395
459
  } catch (notifErr) {
396
- strapi2.log.warn("[magic-sessionmanager] Notification failed:", notifErr.message);
460
+ log.warn("Notification failed:", notifErr.message);
397
461
  }
398
462
  }
399
463
  } catch (err) {
400
- strapi2.log.error("[magic-sessionmanager] [ERROR] Error creating session:", err);
464
+ log.error("[ERROR] Error creating session:", err);
401
465
  }
402
466
  }
403
467
  });
404
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] Login/Logout interceptor middleware mounted");
468
+ log.info("[SUCCESS] Login/Logout interceptor middleware mounted");
405
469
  strapi2.server.use(async (ctx, next) => {
406
470
  const isRefreshToken = ctx.path === "/api/auth/refresh" && ctx.method === "POST";
407
471
  if (isRefreshToken) {
@@ -423,7 +487,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
423
487
  }
424
488
  });
425
489
  if (!matchingSession) {
426
- strapi2.log.warn("[magic-sessionmanager] [BLOCKED] Blocked refresh token request - no active session");
490
+ log.warn("[BLOCKED] Blocked refresh token request - no active session");
427
491
  ctx.status = 401;
428
492
  ctx.body = {
429
493
  error: {
@@ -434,10 +498,10 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
434
498
  };
435
499
  return;
436
500
  }
437
- strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Refresh token allowed for session ${matchingSession.documentId}`);
501
+ log.info(`[SUCCESS] Refresh token allowed for session ${matchingSession.documentId}`);
438
502
  }
439
503
  } catch (err) {
440
- strapi2.log.error("[magic-sessionmanager] Error checking refresh token:", err);
504
+ log.error("Error checking refresh token:", err);
441
505
  }
442
506
  }
443
507
  await next();
@@ -472,33 +536,33 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
472
536
  lastActive: /* @__PURE__ */ new Date()
473
537
  }
474
538
  });
475
- strapi2.log.info(`[magic-sessionmanager] [REFRESH] Tokens refreshed for session ${matchingSession.documentId}`);
539
+ log.info(`[REFRESH] Tokens refreshed for session ${matchingSession.documentId}`);
476
540
  }
477
541
  }
478
542
  } catch (err) {
479
- strapi2.log.error("[magic-sessionmanager] Error updating refreshed tokens:", err);
543
+ log.error("Error updating refreshed tokens:", err);
480
544
  }
481
545
  }
482
546
  });
483
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] Refresh Token interceptor middleware mounted");
547
+ log.info("[SUCCESS] Refresh Token interceptor middleware mounted");
484
548
  strapi2.server.use(
485
549
  lastSeen({ strapi: strapi2, sessionService })
486
550
  );
487
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] LastSeen middleware mounted");
488
- await ensureContentApiPermissions(strapi2);
489
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] Bootstrap complete");
490
- strapi2.log.info("[magic-sessionmanager] [READY] Session Manager ready! Sessions stored in plugin::magic-sessionmanager.session");
551
+ log.info("[SUCCESS] LastSeen middleware mounted");
552
+ await ensureContentApiPermissions(strapi2, log);
553
+ log.info("[SUCCESS] Bootstrap complete");
554
+ log.info("[READY] Session Manager ready! Sessions stored in plugin::magic-sessionmanager.session");
491
555
  } catch (err) {
492
- strapi2.log.error("[magic-sessionmanager] [ERROR] Bootstrap error:", err);
556
+ log.error("[ERROR] Bootstrap error:", err);
493
557
  }
494
558
  };
495
- async function ensureContentApiPermissions(strapi2) {
559
+ async function ensureContentApiPermissions(strapi2, log) {
496
560
  try {
497
561
  const authenticatedRole = await strapi2.query("plugin::users-permissions.role").findOne({
498
562
  where: { type: "authenticated" }
499
563
  });
500
564
  if (!authenticatedRole) {
501
- strapi2.log.warn("[magic-sessionmanager] Authenticated role not found - skipping permission setup");
565
+ log.warn("Authenticated role not found - skipping permission setup");
502
566
  return;
503
567
  }
504
568
  const requiredActions = [
@@ -516,7 +580,7 @@ async function ensureContentApiPermissions(strapi2) {
516
580
  const existingActions = existingPermissions.map((p) => p.action);
517
581
  const missingActions = requiredActions.filter((action) => !existingActions.includes(action));
518
582
  if (missingActions.length === 0) {
519
- strapi2.log.debug("[magic-sessionmanager] Content-API permissions already configured");
583
+ log.debug("Content-API permissions already configured");
520
584
  return;
521
585
  }
522
586
  for (const action of missingActions) {
@@ -526,27 +590,31 @@ async function ensureContentApiPermissions(strapi2) {
526
590
  role: authenticatedRole.id
527
591
  }
528
592
  });
529
- strapi2.log.info(`[magic-sessionmanager] [PERMISSION] Enabled ${action} for authenticated users`);
593
+ log.info(`[PERMISSION] Enabled ${action} for authenticated users`);
530
594
  }
531
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] Content-API permissions configured for authenticated users");
595
+ log.info("[SUCCESS] Content-API permissions configured for authenticated users");
532
596
  } catch (err) {
533
- strapi2.log.warn("[magic-sessionmanager] Could not auto-configure permissions:", err.message);
534
- strapi2.log.warn("[magic-sessionmanager] Please manually enable plugin permissions in Settings > Users & Permissions > Roles > Authenticated");
597
+ log.warn("Could not auto-configure permissions:", err.message);
598
+ log.warn("Please manually enable plugin permissions in Settings > Users & Permissions > Roles > Authenticated");
535
599
  }
536
600
  }
601
+ const { createLogger: createLogger$2 } = logger;
537
602
  var destroy$1 = async ({ strapi: strapi2 }) => {
603
+ const log = createLogger$2(strapi2);
538
604
  if (strapi2.licenseGuard && strapi2.licenseGuard.pingInterval) {
539
605
  clearInterval(strapi2.licenseGuard.pingInterval);
540
- strapi2.log.info("[magic-sessionmanager] 🛑 License pinging stopped");
606
+ log.info("🛑 License pinging stopped");
541
607
  }
542
608
  if (strapi2.sessionManagerIntervals && strapi2.sessionManagerIntervals.cleanup) {
543
609
  clearInterval(strapi2.sessionManagerIntervals.cleanup);
544
- strapi2.log.info("[magic-sessionmanager] 🛑 Session cleanup interval stopped");
610
+ log.info("🛑 Session cleanup interval stopped");
545
611
  }
546
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] Plugin cleanup completed");
612
+ log.info("[SUCCESS] Plugin cleanup completed");
547
613
  };
548
614
  var config$1 = {
549
615
  default: {
616
+ // Enable debug logging (set to true to see all plugin logs)
617
+ debug: false,
550
618
  // Rate limit for lastSeen updates (in milliseconds)
551
619
  lastSeenRateLimit: 3e4,
552
620
  // 30 seconds
@@ -1492,562 +1560,570 @@ var controllers$1 = {
1492
1560
  settings
1493
1561
  };
1494
1562
  const { encryptToken, decryptToken, generateSessionId } = encryption;
1563
+ const { createLogger: createLogger$1 } = logger;
1495
1564
  const SESSION_UID = "plugin::magic-sessionmanager.session";
1496
1565
  const USER_UID = "plugin::users-permissions.user";
1497
- var session$1 = ({ strapi: strapi2 }) => ({
1498
- /**
1499
- * Create a new session record
1500
- * @param {Object} params - { userId, ip, userAgent, token, refreshToken }
1501
- * @returns {Promise<Object>} Created session
1502
- */
1503
- async createSession({ userId, ip = "unknown", userAgent = "unknown", token, refreshToken }) {
1504
- try {
1505
- const now = /* @__PURE__ */ new Date();
1506
- const sessionId = generateSessionId(userId);
1507
- const encryptedToken = token ? encryptToken(token) : null;
1508
- const encryptedRefreshToken = refreshToken ? encryptToken(refreshToken) : null;
1509
- const session2 = await strapi2.documents(SESSION_UID).create({
1510
- data: {
1511
- user: userId,
1512
- // userId should be documentId (string)
1513
- ipAddress: ip.substring(0, 45),
1514
- userAgent: userAgent.substring(0, 500),
1515
- loginTime: now,
1516
- lastActive: now,
1517
- isActive: true,
1518
- token: encryptedToken,
1519
- // [SUCCESS] Encrypted Access Token
1520
- refreshToken: encryptedRefreshToken,
1521
- // [SUCCESS] Encrypted Refresh Token
1522
- sessionId
1523
- // [SUCCESS] Unique identifier
1524
- }
1525
- });
1526
- strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session ${session2.documentId} (${sessionId}) created for user ${userId}`);
1527
- return session2;
1528
- } catch (err) {
1529
- strapi2.log.error("[magic-sessionmanager] Error creating session:", err);
1530
- throw err;
1531
- }
1532
- },
1533
- /**
1534
- * Terminate a session or all sessions for a user
1535
- * Supports both numeric id (legacy) and documentId (Strapi v5)
1536
- * @param {Object} params - { sessionId | userId }
1537
- * @returns {Promise<void>}
1538
- */
1539
- async terminateSession({ sessionId, userId }) {
1540
- try {
1541
- const now = /* @__PURE__ */ new Date();
1542
- if (sessionId) {
1543
- await strapi2.documents(SESSION_UID).update({
1544
- documentId: sessionId,
1566
+ var session$1 = ({ strapi: strapi2 }) => {
1567
+ const log = createLogger$1(strapi2);
1568
+ return {
1569
+ /**
1570
+ * Create a new session record
1571
+ * @param {Object} params - { userId, ip, userAgent, token, refreshToken }
1572
+ * @returns {Promise<Object>} Created session
1573
+ */
1574
+ async createSession({ userId, ip = "unknown", userAgent = "unknown", token, refreshToken }) {
1575
+ try {
1576
+ const now = /* @__PURE__ */ new Date();
1577
+ const sessionId = generateSessionId(userId);
1578
+ const encryptedToken = token ? encryptToken(token) : null;
1579
+ const encryptedRefreshToken = refreshToken ? encryptToken(refreshToken) : null;
1580
+ const session2 = await strapi2.documents(SESSION_UID).create({
1545
1581
  data: {
1546
- isActive: false,
1547
- logoutTime: now
1582
+ user: userId,
1583
+ // userId should be documentId (string)
1584
+ ipAddress: ip.substring(0, 45),
1585
+ userAgent: userAgent.substring(0, 500),
1586
+ loginTime: now,
1587
+ lastActive: now,
1588
+ isActive: true,
1589
+ token: encryptedToken,
1590
+ // [SUCCESS] Encrypted Access Token
1591
+ refreshToken: encryptedRefreshToken,
1592
+ // [SUCCESS] Encrypted Refresh Token
1593
+ sessionId
1594
+ // [SUCCESS] Unique identifier
1548
1595
  }
1549
1596
  });
1550
- strapi2.log.info(`[magic-sessionmanager] Session ${sessionId} terminated`);
1551
- } else if (userId) {
1552
- let userDocumentId = userId;
1553
- if (!isNaN(userId)) {
1554
- const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1555
- if (user) {
1556
- userDocumentId = user.documentId;
1557
- }
1558
- }
1559
- const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1560
- filters: {
1561
- user: { documentId: userDocumentId },
1562
- // Deep filtering syntax
1563
- isActive: true
1564
- }
1565
- });
1566
- for (const session2 of activeSessions) {
1597
+ log.info(`[SUCCESS] Session ${session2.documentId} (${sessionId}) created for user ${userId}`);
1598
+ return session2;
1599
+ } catch (err) {
1600
+ log.error("Error creating session:", err);
1601
+ throw err;
1602
+ }
1603
+ },
1604
+ /**
1605
+ * Terminate a session or all sessions for a user
1606
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1607
+ * @param {Object} params - { sessionId | userId }
1608
+ * @returns {Promise<void>}
1609
+ */
1610
+ async terminateSession({ sessionId, userId }) {
1611
+ try {
1612
+ const now = /* @__PURE__ */ new Date();
1613
+ if (sessionId) {
1567
1614
  await strapi2.documents(SESSION_UID).update({
1568
- documentId: session2.documentId,
1615
+ documentId: sessionId,
1569
1616
  data: {
1570
1617
  isActive: false,
1571
1618
  logoutTime: now
1572
1619
  }
1573
1620
  });
1621
+ log.info(`Session ${sessionId} terminated`);
1622
+ } else if (userId) {
1623
+ let userDocumentId = userId;
1624
+ if (!isNaN(userId)) {
1625
+ const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1626
+ if (user) {
1627
+ userDocumentId = user.documentId;
1628
+ }
1629
+ }
1630
+ const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1631
+ filters: {
1632
+ user: { documentId: userDocumentId },
1633
+ // Deep filtering syntax
1634
+ isActive: true
1635
+ }
1636
+ });
1637
+ for (const session2 of activeSessions) {
1638
+ await strapi2.documents(SESSION_UID).update({
1639
+ documentId: session2.documentId,
1640
+ data: {
1641
+ isActive: false,
1642
+ logoutTime: now
1643
+ }
1644
+ });
1645
+ }
1646
+ log.info(`All sessions terminated for user ${userDocumentId}`);
1574
1647
  }
1575
- strapi2.log.info(`[magic-sessionmanager] All sessions terminated for user ${userDocumentId}`);
1648
+ } catch (err) {
1649
+ log.error("Error terminating session:", err);
1650
+ throw err;
1576
1651
  }
1577
- } catch (err) {
1578
- strapi2.log.error("[magic-sessionmanager] Error terminating session:", err);
1579
- throw err;
1580
- }
1581
- },
1582
- /**
1583
- * Get ALL sessions (active + inactive) with accurate online status
1584
- * @returns {Promise<Array>} All sessions with enhanced data
1585
- */
1586
- async getAllSessions() {
1587
- try {
1588
- const sessions = await strapi2.documents(SESSION_UID).findMany({
1589
- populate: { user: { fields: ["id", "email", "username"] } },
1590
- sort: { loginTime: "desc" },
1591
- limit: 1e3
1592
- // Reasonable limit
1593
- });
1594
- const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1595
- const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1596
- const now = /* @__PURE__ */ new Date();
1597
- const enhancedSessions = sessions.map((session2) => {
1598
- const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1599
- const timeSinceActive = now - lastActiveTime;
1600
- const isTrulyActive = session2.isActive && timeSinceActive < inactivityTimeout;
1601
- const { token, ...sessionWithoutToken } = session2;
1602
- return {
1603
- ...sessionWithoutToken,
1604
- isTrulyActive,
1605
- minutesSinceActive: Math.floor(timeSinceActive / 1e3 / 60)
1606
- };
1607
- });
1608
- return enhancedSessions;
1609
- } catch (err) {
1610
- strapi2.log.error("[magic-sessionmanager] Error getting all sessions:", err);
1611
- throw err;
1612
- }
1613
- },
1614
- /**
1615
- * Get all active sessions with accurate online status
1616
- * @returns {Promise<Array>} Active sessions with user data and online status
1617
- */
1618
- async getActiveSessions() {
1619
- try {
1620
- const sessions = await strapi2.documents(SESSION_UID).findMany({
1621
- filters: { isActive: true },
1622
- populate: { user: { fields: ["id", "email", "username"] } },
1623
- sort: { loginTime: "desc" }
1624
- });
1625
- const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1626
- const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1627
- const now = /* @__PURE__ */ new Date();
1628
- const enhancedSessions = sessions.map((session2) => {
1629
- const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1630
- const timeSinceActive = now - lastActiveTime;
1631
- const isTrulyActive = timeSinceActive < inactivityTimeout;
1632
- const { token, ...sessionWithoutToken } = session2;
1633
- return {
1634
- ...sessionWithoutToken,
1635
- isTrulyActive,
1636
- minutesSinceActive: Math.floor(timeSinceActive / 1e3 / 60)
1637
- };
1638
- });
1639
- return enhancedSessions.filter((s) => s.isTrulyActive);
1640
- } catch (err) {
1641
- strapi2.log.error("[magic-sessionmanager] Error getting active sessions:", err);
1642
- throw err;
1643
- }
1644
- },
1645
- /**
1646
- * Get all sessions for a specific user
1647
- * Supports both numeric id (legacy) and documentId (Strapi v5)
1648
- * @param {string|number} userId - User documentId or numeric id
1649
- * @returns {Promise<Array>} User's sessions with accurate online status
1650
- */
1651
- async getUserSessions(userId) {
1652
- try {
1653
- let userDocumentId = userId;
1654
- if (!isNaN(userId)) {
1655
- const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1656
- if (user) {
1657
- userDocumentId = user.documentId;
1652
+ },
1653
+ /**
1654
+ * Get ALL sessions (active + inactive) with accurate online status
1655
+ * @returns {Promise<Array>} All sessions with enhanced data
1656
+ */
1657
+ async getAllSessions() {
1658
+ try {
1659
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1660
+ populate: { user: { fields: ["id", "email", "username"] } },
1661
+ sort: { loginTime: "desc" },
1662
+ limit: 1e3
1663
+ // Reasonable limit
1664
+ });
1665
+ const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1666
+ const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1667
+ const now = /* @__PURE__ */ new Date();
1668
+ const enhancedSessions = sessions.map((session2) => {
1669
+ const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1670
+ const timeSinceActive = now - lastActiveTime;
1671
+ const isTrulyActive = session2.isActive && timeSinceActive < inactivityTimeout;
1672
+ const { token, ...sessionWithoutToken } = session2;
1673
+ return {
1674
+ ...sessionWithoutToken,
1675
+ isTrulyActive,
1676
+ minutesSinceActive: Math.floor(timeSinceActive / 1e3 / 60)
1677
+ };
1678
+ });
1679
+ return enhancedSessions;
1680
+ } catch (err) {
1681
+ log.error("Error getting all sessions:", err);
1682
+ throw err;
1683
+ }
1684
+ },
1685
+ /**
1686
+ * Get all active sessions with accurate online status
1687
+ * @returns {Promise<Array>} Active sessions with user data and online status
1688
+ */
1689
+ async getActiveSessions() {
1690
+ try {
1691
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1692
+ filters: { isActive: true },
1693
+ populate: { user: { fields: ["id", "email", "username"] } },
1694
+ sort: { loginTime: "desc" }
1695
+ });
1696
+ const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1697
+ const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1698
+ const now = /* @__PURE__ */ new Date();
1699
+ const enhancedSessions = sessions.map((session2) => {
1700
+ const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1701
+ const timeSinceActive = now - lastActiveTime;
1702
+ const isTrulyActive = timeSinceActive < inactivityTimeout;
1703
+ const { token, ...sessionWithoutToken } = session2;
1704
+ return {
1705
+ ...sessionWithoutToken,
1706
+ isTrulyActive,
1707
+ minutesSinceActive: Math.floor(timeSinceActive / 1e3 / 60)
1708
+ };
1709
+ });
1710
+ return enhancedSessions.filter((s) => s.isTrulyActive);
1711
+ } catch (err) {
1712
+ log.error("Error getting active sessions:", err);
1713
+ throw err;
1714
+ }
1715
+ },
1716
+ /**
1717
+ * Get all sessions for a specific user
1718
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1719
+ * @param {string|number} userId - User documentId or numeric id
1720
+ * @returns {Promise<Array>} User's sessions with accurate online status
1721
+ */
1722
+ async getUserSessions(userId) {
1723
+ try {
1724
+ let userDocumentId = userId;
1725
+ if (!isNaN(userId)) {
1726
+ const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1727
+ if (user) {
1728
+ userDocumentId = user.documentId;
1729
+ }
1658
1730
  }
1731
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1732
+ filters: { user: { documentId: userDocumentId } },
1733
+ sort: { loginTime: "desc" }
1734
+ });
1735
+ const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1736
+ const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1737
+ const now = /* @__PURE__ */ new Date();
1738
+ const enhancedSessions = sessions.map((session2) => {
1739
+ const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1740
+ const timeSinceActive = now - lastActiveTime;
1741
+ const isTrulyActive = session2.isActive && timeSinceActive < inactivityTimeout;
1742
+ const { token, ...sessionWithoutToken } = session2;
1743
+ return {
1744
+ ...sessionWithoutToken,
1745
+ isTrulyActive,
1746
+ minutesSinceActive: Math.floor(timeSinceActive / 1e3 / 60)
1747
+ };
1748
+ });
1749
+ return enhancedSessions;
1750
+ } catch (err) {
1751
+ log.error("Error getting user sessions:", err);
1752
+ throw err;
1659
1753
  }
1660
- const sessions = await strapi2.documents(SESSION_UID).findMany({
1661
- filters: { user: { documentId: userDocumentId } },
1662
- sort: { loginTime: "desc" }
1663
- });
1664
- const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1665
- const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1666
- const now = /* @__PURE__ */ new Date();
1667
- const enhancedSessions = sessions.map((session2) => {
1668
- const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1669
- const timeSinceActive = now - lastActiveTime;
1670
- const isTrulyActive = session2.isActive && timeSinceActive < inactivityTimeout;
1671
- const { token, ...sessionWithoutToken } = session2;
1672
- return {
1673
- ...sessionWithoutToken,
1674
- isTrulyActive,
1675
- minutesSinceActive: Math.floor(timeSinceActive / 1e3 / 60)
1676
- };
1677
- });
1678
- return enhancedSessions;
1679
- } catch (err) {
1680
- strapi2.log.error("[magic-sessionmanager] Error getting user sessions:", err);
1681
- throw err;
1682
- }
1683
- },
1684
- /**
1685
- * Update lastActive timestamp on session (rate-limited to avoid DB noise)
1686
- * @param {Object} params - { userId, sessionId }
1687
- * @returns {Promise<void>}
1688
- */
1689
- async touch({ userId, sessionId }) {
1690
- try {
1691
- const now = /* @__PURE__ */ new Date();
1692
- const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1693
- const rateLimit = config2.lastSeenRateLimit || 3e4;
1694
- if (sessionId) {
1695
- const session2 = await strapi2.documents(SESSION_UID).findOne({ documentId: sessionId });
1696
- if (session2 && session2.lastActive) {
1697
- const lastActiveTime = new Date(session2.lastActive).getTime();
1698
- const currentTime = now.getTime();
1699
- if (currentTime - lastActiveTime > rateLimit) {
1754
+ },
1755
+ /**
1756
+ * Update lastActive timestamp on session (rate-limited to avoid DB noise)
1757
+ * @param {Object} params - { userId, sessionId }
1758
+ * @returns {Promise<void>}
1759
+ */
1760
+ async touch({ userId, sessionId }) {
1761
+ try {
1762
+ const now = /* @__PURE__ */ new Date();
1763
+ const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1764
+ const rateLimit = config2.lastSeenRateLimit || 3e4;
1765
+ if (sessionId) {
1766
+ const session2 = await strapi2.documents(SESSION_UID).findOne({ documentId: sessionId });
1767
+ if (session2 && session2.lastActive) {
1768
+ const lastActiveTime = new Date(session2.lastActive).getTime();
1769
+ const currentTime = now.getTime();
1770
+ if (currentTime - lastActiveTime > rateLimit) {
1771
+ await strapi2.documents(SESSION_UID).update({
1772
+ documentId: sessionId,
1773
+ data: { lastActive: now }
1774
+ });
1775
+ }
1776
+ } else if (session2) {
1700
1777
  await strapi2.documents(SESSION_UID).update({
1701
1778
  documentId: sessionId,
1702
1779
  data: { lastActive: now }
1703
1780
  });
1704
1781
  }
1705
- } else if (session2) {
1706
- await strapi2.documents(SESSION_UID).update({
1707
- documentId: sessionId,
1708
- data: { lastActive: now }
1709
- });
1710
1782
  }
1783
+ } catch (err) {
1784
+ log.debug("Error touching session:", err.message);
1711
1785
  }
1712
- } catch (err) {
1713
- strapi2.log.debug("[magic-sessionmanager] Error touching session:", err.message);
1714
- }
1715
- },
1716
- /**
1717
- * Cleanup inactive sessions - set isActive to false for sessions older than inactivityTimeout
1718
- * Should be called on bootstrap to clean up stale sessions
1719
- */
1720
- async cleanupInactiveSessions() {
1721
- try {
1722
- const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1723
- const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1724
- const now = /* @__PURE__ */ new Date();
1725
- const cutoffTime = new Date(now.getTime() - inactivityTimeout);
1726
- strapi2.log.info(`[magic-sessionmanager] [CLEANUP] Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
1727
- const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1728
- filters: { isActive: true },
1729
- fields: ["lastActive", "loginTime"]
1730
- });
1731
- let deactivatedCount = 0;
1732
- for (const session2 of activeSessions) {
1733
- const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1734
- if (lastActiveTime < cutoffTime) {
1735
- await strapi2.documents(SESSION_UID).update({
1736
- documentId: session2.documentId,
1737
- data: { isActive: false }
1738
- });
1739
- deactivatedCount++;
1786
+ },
1787
+ /**
1788
+ * Cleanup inactive sessions - set isActive to false for sessions older than inactivityTimeout
1789
+ * Should be called on bootstrap to clean up stale sessions
1790
+ */
1791
+ async cleanupInactiveSessions() {
1792
+ try {
1793
+ const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1794
+ const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1795
+ const now = /* @__PURE__ */ new Date();
1796
+ const cutoffTime = new Date(now.getTime() - inactivityTimeout);
1797
+ log.info(`[CLEANUP] Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
1798
+ const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1799
+ filters: { isActive: true },
1800
+ fields: ["lastActive", "loginTime"]
1801
+ });
1802
+ let deactivatedCount = 0;
1803
+ for (const session2 of activeSessions) {
1804
+ const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1805
+ if (lastActiveTime < cutoffTime) {
1806
+ await strapi2.documents(SESSION_UID).update({
1807
+ documentId: session2.documentId,
1808
+ data: { isActive: false }
1809
+ });
1810
+ deactivatedCount++;
1811
+ }
1740
1812
  }
1813
+ log.info(`[SUCCESS] Cleanup complete: ${deactivatedCount} sessions deactivated`);
1814
+ return deactivatedCount;
1815
+ } catch (err) {
1816
+ log.error("Error cleaning up inactive sessions:", err);
1817
+ throw err;
1741
1818
  }
1742
- strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Cleanup complete: ${deactivatedCount} sessions deactivated`);
1743
- return deactivatedCount;
1744
- } catch (err) {
1745
- strapi2.log.error("[magic-sessionmanager] Error cleaning up inactive sessions:", err);
1746
- throw err;
1747
- }
1748
- },
1749
- /**
1750
- * Delete a single session from database
1751
- * WARNING: This permanently deletes the record!
1752
- * @param {number} sessionId - Session ID to delete
1753
- * @returns {Promise<boolean>} Success status
1754
- */
1755
- async deleteSession(sessionId) {
1756
- try {
1757
- await strapi2.documents(SESSION_UID).delete({ documentId: sessionId });
1758
- strapi2.log.info(`[magic-sessionmanager] [DELETE] Session ${sessionId} permanently deleted`);
1759
- return true;
1760
- } catch (err) {
1761
- strapi2.log.error("[magic-sessionmanager] Error deleting session:", err);
1762
- throw err;
1763
- }
1764
- },
1765
- /**
1766
- * Delete all inactive sessions from database
1767
- * WARNING: This permanently deletes records!
1768
- * @returns {Promise<number>} Number of deleted sessions
1769
- */
1770
- async deleteInactiveSessions() {
1771
- try {
1772
- strapi2.log.info("[magic-sessionmanager] [DELETE] Deleting all inactive sessions...");
1773
- const inactiveSessions = await strapi2.documents(SESSION_UID).findMany({
1774
- filters: { isActive: false }
1775
- });
1776
- let deletedCount = 0;
1777
- for (const session2 of inactiveSessions) {
1778
- await strapi2.documents(SESSION_UID).delete({ documentId: session2.documentId });
1779
- deletedCount++;
1819
+ },
1820
+ /**
1821
+ * Delete a single session from database
1822
+ * WARNING: This permanently deletes the record!
1823
+ * @param {number} sessionId - Session ID to delete
1824
+ * @returns {Promise<boolean>} Success status
1825
+ */
1826
+ async deleteSession(sessionId) {
1827
+ try {
1828
+ await strapi2.documents(SESSION_UID).delete({ documentId: sessionId });
1829
+ log.info(`[DELETE] Session ${sessionId} permanently deleted`);
1830
+ return true;
1831
+ } catch (err) {
1832
+ log.error("Error deleting session:", err);
1833
+ throw err;
1834
+ }
1835
+ },
1836
+ /**
1837
+ * Delete all inactive sessions from database
1838
+ * WARNING: This permanently deletes records!
1839
+ * @returns {Promise<number>} Number of deleted sessions
1840
+ */
1841
+ async deleteInactiveSessions() {
1842
+ try {
1843
+ log.info("[DELETE] Deleting all inactive sessions...");
1844
+ const inactiveSessions = await strapi2.documents(SESSION_UID).findMany({
1845
+ filters: { isActive: false }
1846
+ });
1847
+ let deletedCount = 0;
1848
+ for (const session2 of inactiveSessions) {
1849
+ await strapi2.documents(SESSION_UID).delete({ documentId: session2.documentId });
1850
+ deletedCount++;
1851
+ }
1852
+ log.info(`[SUCCESS] Deleted ${deletedCount} inactive sessions`);
1853
+ return deletedCount;
1854
+ } catch (err) {
1855
+ log.error("Error deleting inactive sessions:", err);
1856
+ throw err;
1780
1857
  }
1781
- strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Deleted ${deletedCount} inactive sessions`);
1782
- return deletedCount;
1783
- } catch (err) {
1784
- strapi2.log.error("[magic-sessionmanager] Error deleting inactive sessions:", err);
1785
- throw err;
1786
1858
  }
1787
- }
1788
- });
1789
- const version = "4.1.0";
1859
+ };
1860
+ };
1861
+ const version = "4.2.2";
1790
1862
  const require$$2 = {
1791
1863
  version
1792
1864
  };
1793
1865
  const crypto = require$$0$1;
1794
1866
  const os = require$$1;
1795
1867
  const pluginPkg = require$$2;
1868
+ const { createLogger } = logger;
1796
1869
  const LICENSE_SERVER_URL = "https://magicapi.fitlex.me";
1797
- var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1798
- /**
1799
- * Get license server URL
1800
- */
1801
- getLicenseServerUrl() {
1802
- return LICENSE_SERVER_URL;
1803
- },
1804
- /**
1805
- * Generate device ID
1806
- */
1807
- generateDeviceId() {
1808
- try {
1809
- const networkInterfaces = os.networkInterfaces();
1810
- const macAddresses = [];
1811
- Object.values(networkInterfaces).forEach((interfaces) => {
1812
- interfaces?.forEach((iface) => {
1813
- if (iface.mac && iface.mac !== "00:00:00:00:00:00") {
1814
- macAddresses.push(iface.mac);
1815
- }
1870
+ var licenseGuard$1 = ({ strapi: strapi2 }) => {
1871
+ const log = createLogger(strapi2);
1872
+ return {
1873
+ /**
1874
+ * Get license server URL
1875
+ */
1876
+ getLicenseServerUrl() {
1877
+ return LICENSE_SERVER_URL;
1878
+ },
1879
+ /**
1880
+ * Generate device ID
1881
+ */
1882
+ generateDeviceId() {
1883
+ try {
1884
+ const networkInterfaces = os.networkInterfaces();
1885
+ const macAddresses = [];
1886
+ Object.values(networkInterfaces).forEach((interfaces) => {
1887
+ interfaces?.forEach((iface) => {
1888
+ if (iface.mac && iface.mac !== "00:00:00:00:00:00") {
1889
+ macAddresses.push(iface.mac);
1890
+ }
1891
+ });
1816
1892
  });
1817
- });
1818
- const identifier = `${macAddresses.join("-")}-${os.hostname()}`;
1819
- return crypto.createHash("sha256").update(identifier).digest("hex").substring(0, 32);
1820
- } catch (error) {
1821
- return crypto.randomBytes(16).toString("hex");
1822
- }
1823
- },
1824
- getDeviceName() {
1825
- try {
1826
- return os.hostname() || "Unknown Device";
1827
- } catch (error) {
1828
- return "Unknown Device";
1829
- }
1830
- },
1831
- getIpAddress() {
1832
- try {
1833
- const networkInterfaces = os.networkInterfaces();
1834
- for (const name of Object.keys(networkInterfaces)) {
1835
- const interfaces = networkInterfaces[name];
1836
- if (interfaces) {
1837
- for (const iface of interfaces) {
1838
- if (iface.family === "IPv4" && !iface.internal) {
1839
- return iface.address;
1893
+ const identifier = `${macAddresses.join("-")}-${os.hostname()}`;
1894
+ return crypto.createHash("sha256").update(identifier).digest("hex").substring(0, 32);
1895
+ } catch (error) {
1896
+ return crypto.randomBytes(16).toString("hex");
1897
+ }
1898
+ },
1899
+ getDeviceName() {
1900
+ try {
1901
+ return os.hostname() || "Unknown Device";
1902
+ } catch (error) {
1903
+ return "Unknown Device";
1904
+ }
1905
+ },
1906
+ getIpAddress() {
1907
+ try {
1908
+ const networkInterfaces = os.networkInterfaces();
1909
+ for (const name of Object.keys(networkInterfaces)) {
1910
+ const interfaces = networkInterfaces[name];
1911
+ if (interfaces) {
1912
+ for (const iface of interfaces) {
1913
+ if (iface.family === "IPv4" && !iface.internal) {
1914
+ return iface.address;
1915
+ }
1840
1916
  }
1841
1917
  }
1842
1918
  }
1919
+ return "127.0.0.1";
1920
+ } catch (error) {
1921
+ return "127.0.0.1";
1843
1922
  }
1844
- return "127.0.0.1";
1845
- } catch (error) {
1846
- return "127.0.0.1";
1847
- }
1848
- },
1849
- getUserAgent() {
1850
- const pluginVersion = pluginPkg.version;
1851
- const strapiVersion = strapi2.config.get("info.strapi") || "5.0.0";
1852
- return `MagicSessionManager/${pluginVersion} Strapi/${strapiVersion} Node/${process.version} ${os.platform()}/${os.release()}`;
1853
- },
1854
- async createLicense({ email, firstName, lastName }) {
1855
- try {
1856
- const deviceId = this.generateDeviceId();
1857
- const deviceName = this.getDeviceName();
1858
- const ipAddress = this.getIpAddress();
1859
- const userAgent = this.getUserAgent();
1860
- const licenseServerUrl = this.getLicenseServerUrl();
1861
- const response = await fetch(`${licenseServerUrl}/api/licenses/create`, {
1862
- method: "POST",
1863
- headers: { "Content-Type": "application/json" },
1864
- body: JSON.stringify({
1865
- email,
1866
- firstName,
1867
- lastName,
1868
- deviceName,
1869
- deviceId,
1870
- ipAddress,
1871
- userAgent,
1872
- pluginName: "magic-sessionmanager",
1873
- productName: "Magic Session Manager - Premium Session Tracking"
1874
- })
1875
- });
1876
- const data = await response.json();
1877
- if (data.success) {
1878
- strapi2.log.info("[magic-sessionmanager] [SUCCESS] License created:", data.data.licenseKey);
1879
- return data.data;
1880
- } else {
1881
- strapi2.log.error("[magic-sessionmanager] [ERROR] License creation failed:", data);
1923
+ },
1924
+ getUserAgent() {
1925
+ const pluginVersion = pluginPkg.version;
1926
+ const strapiVersion = strapi2.config.get("info.strapi") || "5.0.0";
1927
+ return `MagicSessionManager/${pluginVersion} Strapi/${strapiVersion} Node/${process.version} ${os.platform()}/${os.release()}`;
1928
+ },
1929
+ async createLicense({ email, firstName, lastName }) {
1930
+ try {
1931
+ const deviceId = this.generateDeviceId();
1932
+ const deviceName = this.getDeviceName();
1933
+ const ipAddress = this.getIpAddress();
1934
+ const userAgent = this.getUserAgent();
1935
+ const licenseServerUrl = this.getLicenseServerUrl();
1936
+ const response = await fetch(`${licenseServerUrl}/api/licenses/create`, {
1937
+ method: "POST",
1938
+ headers: { "Content-Type": "application/json" },
1939
+ body: JSON.stringify({
1940
+ email,
1941
+ firstName,
1942
+ lastName,
1943
+ deviceName,
1944
+ deviceId,
1945
+ ipAddress,
1946
+ userAgent,
1947
+ pluginName: "magic-sessionmanager",
1948
+ productName: "Magic Session Manager - Premium Session Tracking"
1949
+ })
1950
+ });
1951
+ const data = await response.json();
1952
+ if (data.success) {
1953
+ log.info("[SUCCESS] License created:", data.data.licenseKey);
1954
+ return data.data;
1955
+ } else {
1956
+ log.error("[ERROR] License creation failed:", data);
1957
+ return null;
1958
+ }
1959
+ } catch (error) {
1960
+ log.error("[ERROR] Error creating license:", error);
1882
1961
  return null;
1883
1962
  }
1884
- } catch (error) {
1885
- strapi2.log.error("[magic-sessionmanager] [ERROR] Error creating license:", error);
1886
- return null;
1887
- }
1888
- },
1889
- async verifyLicense(licenseKey, allowGracePeriod = false) {
1890
- try {
1891
- const controller = new AbortController();
1892
- const timeoutId = setTimeout(() => controller.abort(), 5e3);
1893
- const licenseServerUrl = this.getLicenseServerUrl();
1894
- const response = await fetch(`${licenseServerUrl}/api/licenses/verify`, {
1895
- method: "POST",
1896
- headers: { "Content-Type": "application/json" },
1897
- body: JSON.stringify({
1898
- licenseKey,
1899
- pluginName: "magic-sessionmanager",
1900
- productName: "Magic Session Manager - Premium Session Tracking"
1901
- }),
1902
- signal: controller.signal
1903
- });
1904
- clearTimeout(timeoutId);
1905
- const data = await response.json();
1906
- if (data.success && data.data) {
1907
- return { valid: true, data: data.data, gracePeriod: false };
1908
- } else {
1963
+ },
1964
+ async verifyLicense(licenseKey, allowGracePeriod = false) {
1965
+ try {
1966
+ const controller = new AbortController();
1967
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
1968
+ const licenseServerUrl = this.getLicenseServerUrl();
1969
+ const response = await fetch(`${licenseServerUrl}/api/licenses/verify`, {
1970
+ method: "POST",
1971
+ headers: { "Content-Type": "application/json" },
1972
+ body: JSON.stringify({
1973
+ licenseKey,
1974
+ pluginName: "magic-sessionmanager",
1975
+ productName: "Magic Session Manager - Premium Session Tracking"
1976
+ }),
1977
+ signal: controller.signal
1978
+ });
1979
+ clearTimeout(timeoutId);
1980
+ const data = await response.json();
1981
+ if (data.success && data.data) {
1982
+ return { valid: true, data: data.data, gracePeriod: false };
1983
+ } else {
1984
+ return { valid: false, data: null };
1985
+ }
1986
+ } catch (error) {
1987
+ if (allowGracePeriod) {
1988
+ return { valid: true, data: null, gracePeriod: true };
1989
+ }
1909
1990
  return { valid: false, data: null };
1910
1991
  }
1911
- } catch (error) {
1912
- if (allowGracePeriod) {
1913
- return { valid: true, data: null, gracePeriod: true };
1914
- }
1915
- return { valid: false, data: null };
1916
- }
1917
- },
1918
- async getLicenseByKey(licenseKey) {
1919
- try {
1920
- const licenseServerUrl = this.getLicenseServerUrl();
1921
- const url = `${licenseServerUrl}/api/licenses/key/${licenseKey}`;
1922
- strapi2.log.debug(`[magic-sessionmanager/license-guard] Fetching license from: ${url}`);
1923
- const response = await fetch(url, {
1924
- method: "GET",
1925
- headers: { "Content-Type": "application/json" }
1926
- });
1927
- const data = await response.json();
1928
- if (data.success && data.data) {
1929
- strapi2.log.debug(`[magic-sessionmanager/license-guard] License fetched: ${data.data.email}, featurePremium: ${data.data.featurePremium}`);
1930
- return data.data;
1992
+ },
1993
+ async getLicenseByKey(licenseKey) {
1994
+ try {
1995
+ const licenseServerUrl = this.getLicenseServerUrl();
1996
+ const url = `${licenseServerUrl}/api/licenses/key/${licenseKey}`;
1997
+ log.debug(`[magic-sessionmanager/license-guard] Fetching license from: ${url}`);
1998
+ const response = await fetch(url, {
1999
+ method: "GET",
2000
+ headers: { "Content-Type": "application/json" }
2001
+ });
2002
+ const data = await response.json();
2003
+ if (data.success && data.data) {
2004
+ log.debug(`[magic-sessionmanager/license-guard] License fetched: ${data.data.email}, featurePremium: ${data.data.featurePremium}`);
2005
+ return data.data;
2006
+ }
2007
+ log.warn(`[magic-sessionmanager/license-guard] License API returned no data`);
2008
+ return null;
2009
+ } catch (error) {
2010
+ log.error("[magic-sessionmanager/license-guard] Error fetching license by key:", error);
2011
+ return null;
1931
2012
  }
1932
- strapi2.log.warn(`[magic-sessionmanager/license-guard] License API returned no data`);
1933
- return null;
1934
- } catch (error) {
1935
- strapi2.log.error("[magic-sessionmanager/license-guard] Error fetching license by key:", error);
1936
- return null;
1937
- }
1938
- },
1939
- async pingLicense(licenseKey) {
1940
- try {
1941
- const deviceId = this.generateDeviceId();
1942
- const deviceName = this.getDeviceName();
1943
- const ipAddress = this.getIpAddress();
1944
- const userAgent = this.getUserAgent();
1945
- const licenseServerUrl = this.getLicenseServerUrl();
1946
- const response = await fetch(`${licenseServerUrl}/api/licenses/ping`, {
1947
- method: "POST",
1948
- headers: { "Content-Type": "application/json" },
1949
- body: JSON.stringify({
1950
- licenseKey,
1951
- deviceId,
1952
- deviceName,
1953
- ipAddress,
1954
- userAgent,
1955
- pluginName: "magic-sessionmanager"
1956
- })
1957
- });
1958
- const data = await response.json();
1959
- return data.success ? data.data : null;
1960
- } catch (error) {
1961
- return null;
1962
- }
1963
- },
1964
- async storeLicenseKey(licenseKey) {
1965
- const pluginStore = strapi2.store({
1966
- type: "plugin",
1967
- name: "magic-sessionmanager"
1968
- });
1969
- await pluginStore.set({ key: "licenseKey", value: licenseKey });
1970
- strapi2.log.info(`[magic-sessionmanager] [SUCCESS] License key stored: ${licenseKey.substring(0, 8)}...`);
1971
- },
1972
- startPinging(licenseKey, intervalMinutes = 15) {
1973
- strapi2.log.info(`[magic-sessionmanager] [TIME] Starting license pings every ${intervalMinutes} minutes`);
1974
- this.pingLicense(licenseKey);
1975
- const interval = setInterval(async () => {
2013
+ },
2014
+ async pingLicense(licenseKey) {
1976
2015
  try {
1977
- await this.pingLicense(licenseKey);
2016
+ const deviceId = this.generateDeviceId();
2017
+ const deviceName = this.getDeviceName();
2018
+ const ipAddress = this.getIpAddress();
2019
+ const userAgent = this.getUserAgent();
2020
+ const licenseServerUrl = this.getLicenseServerUrl();
2021
+ const response = await fetch(`${licenseServerUrl}/api/licenses/ping`, {
2022
+ method: "POST",
2023
+ headers: { "Content-Type": "application/json" },
2024
+ body: JSON.stringify({
2025
+ licenseKey,
2026
+ deviceId,
2027
+ deviceName,
2028
+ ipAddress,
2029
+ userAgent,
2030
+ pluginName: "magic-sessionmanager"
2031
+ })
2032
+ });
2033
+ const data = await response.json();
2034
+ return data.success ? data.data : null;
1978
2035
  } catch (error) {
1979
- strapi2.log.error("[magic-sessionmanager] Ping error:", error);
2036
+ return null;
1980
2037
  }
1981
- }, intervalMinutes * 60 * 1e3);
1982
- return interval;
1983
- },
1984
- /**
1985
- * Initialize license guard
1986
- * Checks for existing license and starts pinging
1987
- */
1988
- async initialize() {
1989
- try {
1990
- strapi2.log.info("[magic-sessionmanager] [SECURE] Initializing License Guard...");
2038
+ },
2039
+ async storeLicenseKey(licenseKey) {
1991
2040
  const pluginStore = strapi2.store({
1992
2041
  type: "plugin",
1993
2042
  name: "magic-sessionmanager"
1994
2043
  });
1995
- const licenseKey = await pluginStore.get({ key: "licenseKey" });
1996
- if (!licenseKey) {
1997
- strapi2.log.info("[magic-sessionmanager] [INFO] No license found - Running in demo mode");
1998
- return {
1999
- valid: false,
2000
- demo: true,
2001
- data: null
2002
- };
2003
- }
2004
- const lastValidated = await pluginStore.get({ key: "lastValidated" });
2005
- const now = /* @__PURE__ */ new Date();
2006
- const gracePeriodHours = 24;
2007
- let withinGracePeriod = false;
2008
- if (lastValidated) {
2009
- const lastValidatedDate = new Date(lastValidated);
2010
- const hoursSinceValidation = (now.getTime() - lastValidatedDate.getTime()) / (1e3 * 60 * 60);
2011
- withinGracePeriod = hoursSinceValidation < gracePeriodHours;
2012
- }
2013
- const verification = await this.verifyLicense(licenseKey, withinGracePeriod);
2014
- if (verification.valid) {
2015
- await pluginStore.set({
2016
- key: "lastValidated",
2017
- value: now.toISOString()
2044
+ await pluginStore.set({ key: "licenseKey", value: licenseKey });
2045
+ log.info(`[SUCCESS] License key stored: ${licenseKey.substring(0, 8)}...`);
2046
+ },
2047
+ startPinging(licenseKey, intervalMinutes = 15) {
2048
+ log.info(`[TIME] Starting license pings every ${intervalMinutes} minutes`);
2049
+ this.pingLicense(licenseKey);
2050
+ const interval = setInterval(async () => {
2051
+ try {
2052
+ await this.pingLicense(licenseKey);
2053
+ } catch (error) {
2054
+ log.error("Ping error:", error);
2055
+ }
2056
+ }, intervalMinutes * 60 * 1e3);
2057
+ return interval;
2058
+ },
2059
+ /**
2060
+ * Initialize license guard
2061
+ * Checks for existing license and starts pinging
2062
+ */
2063
+ async initialize() {
2064
+ try {
2065
+ log.info("[SECURE] Initializing License Guard...");
2066
+ const pluginStore = strapi2.store({
2067
+ type: "plugin",
2068
+ name: "magic-sessionmanager"
2018
2069
  });
2019
- const pingInterval = this.startPinging(licenseKey, 15);
2020
- strapi2.licenseGuard = {
2021
- licenseKey,
2022
- pingInterval,
2023
- data: verification.data
2024
- };
2025
- return {
2026
- valid: true,
2027
- demo: false,
2028
- data: verification.data,
2029
- gracePeriod: verification.gracePeriod || false
2030
- };
2031
- } else {
2032
- strapi2.log.error("[magic-sessionmanager] [ERROR] License validation failed");
2070
+ const licenseKey = await pluginStore.get({ key: "licenseKey" });
2071
+ if (!licenseKey) {
2072
+ log.info("[INFO] No license found - Running in demo mode");
2073
+ return {
2074
+ valid: false,
2075
+ demo: true,
2076
+ data: null
2077
+ };
2078
+ }
2079
+ const lastValidated = await pluginStore.get({ key: "lastValidated" });
2080
+ const now = /* @__PURE__ */ new Date();
2081
+ const gracePeriodHours = 24;
2082
+ let withinGracePeriod = false;
2083
+ if (lastValidated) {
2084
+ const lastValidatedDate = new Date(lastValidated);
2085
+ const hoursSinceValidation = (now.getTime() - lastValidatedDate.getTime()) / (1e3 * 60 * 60);
2086
+ withinGracePeriod = hoursSinceValidation < gracePeriodHours;
2087
+ }
2088
+ const verification = await this.verifyLicense(licenseKey, withinGracePeriod);
2089
+ if (verification.valid) {
2090
+ await pluginStore.set({
2091
+ key: "lastValidated",
2092
+ value: now.toISOString()
2093
+ });
2094
+ const pingInterval = this.startPinging(licenseKey, 15);
2095
+ strapi2.licenseGuard = {
2096
+ licenseKey,
2097
+ pingInterval,
2098
+ data: verification.data
2099
+ };
2100
+ return {
2101
+ valid: true,
2102
+ demo: false,
2103
+ data: verification.data,
2104
+ gracePeriod: verification.gracePeriod || false
2105
+ };
2106
+ } else {
2107
+ log.error("[ERROR] License validation failed");
2108
+ return {
2109
+ valid: false,
2110
+ demo: true,
2111
+ error: "Invalid or expired license",
2112
+ data: null
2113
+ };
2114
+ }
2115
+ } catch (error) {
2116
+ log.error("[ERROR] Error initializing License Guard:", error);
2033
2117
  return {
2034
2118
  valid: false,
2035
2119
  demo: true,
2036
- error: "Invalid or expired license",
2120
+ error: error.message,
2037
2121
  data: null
2038
2122
  };
2039
2123
  }
2040
- } catch (error) {
2041
- strapi2.log.error("[magic-sessionmanager] [ERROR] Error initializing License Guard:", error);
2042
- return {
2043
- valid: false,
2044
- demo: true,
2045
- error: error.message,
2046
- data: null
2047
- };
2048
2124
  }
2049
- }
2050
- });
2125
+ };
2126
+ };
2051
2127
  var geolocation$1 = ({ strapi: strapi2 }) => ({
2052
2128
  /**
2053
2129
  * Get IP information from ipapi.co