strapi-plugin-magic-sessionmanager 4.1.0 → 4.2.2

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