strapi-plugin-magic-sessionmanager 3.7.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +90 -0
  2. package/admin/src/components/LicenseGuard.jsx +6 -6
  3. package/admin/src/components/SessionDetailModal.jsx +12 -12
  4. package/admin/src/components/SessionInfoCard.jsx +3 -3
  5. package/admin/src/components/SessionInfoPanel.jsx +3 -2
  6. package/admin/src/hooks/useLicense.js +1 -1
  7. package/admin/src/index.js +2 -2
  8. package/admin/src/pages/Analytics.jsx +2 -2
  9. package/admin/src/pages/HomePage.jsx +11 -14
  10. package/admin/src/pages/License.jsx +2 -2
  11. package/admin/src/pages/Settings.jsx +24 -25
  12. package/admin/src/pages/SettingsNew.jsx +21 -21
  13. package/admin/src/utils/parseUserAgent.js +7 -7
  14. package/dist/_chunks/{Analytics-Bi-vcT63.js → Analytics-BBdv1I5y.js} +4 -4
  15. package/dist/_chunks/{Analytics-BM9i88xu.mjs → Analytics-Dv9f_0eZ.mjs} +4 -4
  16. package/dist/_chunks/{App-DcnJOCL9.mjs → App-CIQ-7sa7.mjs} +26 -31
  17. package/dist/_chunks/{App-BbiNy_cT.js → App-CJaZPNjt.js} +26 -31
  18. package/dist/_chunks/{License-kYo8j2yl.js → License-D24rgaZQ.js} +3 -3
  19. package/dist/_chunks/{License-DsxP-MAL.mjs → License-nrmFxoBm.mjs} +3 -3
  20. package/dist/_chunks/{Settings-jW0TOE_d.js → Settings-CqxgjU0y.js} +26 -26
  21. package/dist/_chunks/{Settings-C3sW9eBD.mjs → Settings-D5dLEGc_.mjs} +26 -26
  22. package/dist/_chunks/{index-DG9XeVSg.mjs → index-Duk1_Wrz.mjs} +15 -15
  23. package/dist/_chunks/{index-Dr2HT-Dd.js → index-WH04CS1c.js} +15 -15
  24. package/dist/_chunks/{useLicense-BL_3bX9O.js → useLicense-BwOlCyhc.js} +2 -2
  25. package/dist/_chunks/{useLicense-DOkJX-tk.mjs → useLicense-Ce8GaxB0.mjs} +2 -2
  26. package/dist/admin/index.js +1 -1
  27. package/dist/admin/index.mjs +1 -1
  28. package/dist/server/index.js +250 -119
  29. package/dist/server/index.mjs +250 -119
  30. package/package.json +1 -1
  31. package/server/src/bootstrap.js +106 -28
  32. package/server/src/controllers/license.js +4 -4
  33. package/server/src/controllers/session.js +67 -13
  34. package/server/src/destroy.js +1 -1
  35. package/server/src/middlewares/last-seen.js +13 -7
  36. package/server/src/register.js +4 -4
  37. package/server/src/routes/content-api.js +11 -2
  38. package/server/src/services/geolocation.js +4 -2
  39. package/server/src/services/license-guard.js +13 -10
  40. package/server/src/services/notifications.js +20 -20
  41. package/server/src/services/service.js +1 -1
  42. package/server/src/services/session.js +63 -33
  43. package/server/src/utils/encryption.js +1 -1
@@ -8,7 +8,7 @@ function getDefaultExportFromCjs(x) {
8
8
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
9
9
  }
10
10
  var register$1 = async ({ strapi: strapi2 }) => {
11
- strapi2.log.info("[magic-sessionmanager] 🚀 Plugin registration starting...");
11
+ strapi2.log.info("[magic-sessionmanager] [START] Plugin registration starting...");
12
12
  try {
13
13
  const userCT = strapi2.contentType("plugin::users-permissions.user");
14
14
  if (!userCT) {
@@ -17,11 +17,11 @@ var register$1 = async ({ strapi: strapi2 }) => {
17
17
  }
18
18
  if (userCT.attributes && userCT.attributes.sessions) {
19
19
  delete userCT.attributes.sessions;
20
- strapi2.log.info("[magic-sessionmanager] Removed sessions field from User content type");
20
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Removed sessions field from User content type");
21
21
  }
22
- strapi2.log.info("[magic-sessionmanager] Plugin registered successfully");
22
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Plugin registered successfully");
23
23
  } catch (err) {
24
- strapi2.log.error("[magic-sessionmanager] Registration error:", err);
24
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Registration error:", err);
25
25
  }
26
26
  };
27
27
  const getClientIp$1 = (ctx) => {
@@ -98,7 +98,7 @@ function getEncryptionKey() {
98
98
  }
99
99
  const strapiKeys = process.env.APP_KEYS || process.env.API_TOKEN_SALT || "default-insecure-key";
100
100
  const key = crypto$1.createHash("sha256").update(strapiKeys).digest();
101
- console.warn("[magic-sessionmanager/encryption] ⚠️ No SESSION_ENCRYPTION_KEY found. Using fallback (not recommended for production).");
101
+ console.warn("[magic-sessionmanager/encryption] [WARNING] No SESSION_ENCRYPTION_KEY found. Using fallback (not recommended for production).");
102
102
  console.warn("[magic-sessionmanager/encryption] Set SESSION_ENCRYPTION_KEY in .env for better security.");
103
103
  return key;
104
104
  }
@@ -149,20 +149,21 @@ var encryption = {
149
149
  decryptToken: decryptToken$3,
150
150
  generateSessionId: generateSessionId$1
151
151
  };
152
+ const SESSION_UID$3 = "plugin::magic-sessionmanager.session";
152
153
  var lastSeen = ({ strapi: strapi2, sessionService }) => {
153
154
  return async (ctx, next) => {
154
- if (ctx.state.user && ctx.state.user.id) {
155
+ if (ctx.state.user && ctx.state.user.documentId) {
155
156
  try {
156
- const userId = ctx.state.user.id;
157
- const activeSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
157
+ const userId = ctx.state.user.documentId;
158
+ const activeSessions = await strapi2.documents(SESSION_UID$3).findMany({
158
159
  filters: {
159
- user: { id: userId },
160
+ user: { documentId: userId },
160
161
  isActive: true
161
162
  },
162
163
  limit: 1
163
164
  });
164
165
  if (!activeSessions || activeSessions.length === 0) {
165
- strapi2.log.info(`[magic-sessionmanager] 🚫 Blocked request - User ${userId} has no active sessions`);
166
+ strapi2.log.info(`[magic-sessionmanager] [BLOCKED] Blocked request - User ${userId} has no active sessions`);
166
167
  return ctx.unauthorized("All sessions have been terminated. Please login again.");
167
168
  }
168
169
  } catch (err) {
@@ -170,9 +171,9 @@ var lastSeen = ({ strapi: strapi2, sessionService }) => {
170
171
  }
171
172
  }
172
173
  await next();
173
- if (ctx.state.user && ctx.state.user.id) {
174
+ if (ctx.state.user && ctx.state.user.documentId) {
174
175
  try {
175
- const userId = ctx.state.user.id;
176
+ const userId = ctx.state.user.documentId;
176
177
  const sessionId = ctx.state.sessionId;
177
178
  await sessionService.touch({
178
179
  userId,
@@ -186,15 +187,17 @@ var lastSeen = ({ strapi: strapi2, sessionService }) => {
186
187
  };
187
188
  const getClientIp = getClientIp_1;
188
189
  const { encryptToken: encryptToken$1, decryptToken: decryptToken$2 } = encryption;
190
+ const SESSION_UID$2 = "plugin::magic-sessionmanager.session";
191
+ const USER_UID$2 = "plugin::users-permissions.user";
189
192
  var bootstrap$1 = async ({ strapi: strapi2 }) => {
190
- strapi2.log.info("[magic-sessionmanager] 🚀 Bootstrap starting...");
193
+ strapi2.log.info("[magic-sessionmanager] [START] Bootstrap starting...");
191
194
  try {
192
195
  const licenseGuardService = strapi2.plugin("magic-sessionmanager").service("license-guard");
193
196
  setTimeout(async () => {
194
197
  const licenseStatus = await licenseGuardService.initialize();
195
198
  if (!licenseStatus.valid) {
196
199
  strapi2.log.error("╔════════════════════════════════════════════════════════════════╗");
197
- strapi2.log.error("║ SESSION MANAGER - NO VALID LICENSE ║");
200
+ strapi2.log.error("║ [ERROR] SESSION MANAGER - NO VALID LICENSE ║");
198
201
  strapi2.log.error("║ ║");
199
202
  strapi2.log.error("║ This plugin requires a valid license to operate. ║");
200
203
  strapi2.log.error("║ Please activate your license via Admin UI: ║");
@@ -210,7 +213,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
210
213
  });
211
214
  const storedKey = await pluginStore.get({ key: "licenseKey" });
212
215
  strapi2.log.info("╔════════════════════════════════════════════════════════════════╗");
213
- strapi2.log.info("║ SESSION MANAGER LICENSE ACTIVE ║");
216
+ strapi2.log.info("║ [SUCCESS] SESSION MANAGER LICENSE ACTIVE ║");
214
217
  strapi2.log.info("║ ║");
215
218
  if (licenseStatus.data) {
216
219
  strapi2.log.info(`║ License: ${licenseStatus.data.licenseKey}`.padEnd(66) + "║");
@@ -221,7 +224,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
221
224
  strapi2.log.info(`║ Status: Grace Period Active`.padEnd(66) + "║");
222
225
  }
223
226
  strapi2.log.info("║ ║");
224
- strapi2.log.info("║ 🔄 Auto-pinging every 15 minutes ║");
227
+ strapi2.log.info("║ [RELOAD] Auto-pinging every 15 minutes ║");
225
228
  strapi2.log.info("╚════════════════════════════════════════════════════════════════╝");
226
229
  }
227
230
  }, 3e3);
@@ -237,7 +240,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
237
240
  strapi2.log.error("[magic-sessionmanager] Periodic cleanup error:", err);
238
241
  }
239
242
  }, cleanupInterval);
240
- strapi2.log.info("[magic-sessionmanager] Periodic cleanup scheduled (every 30 minutes)");
243
+ strapi2.log.info("[magic-sessionmanager] [TIME] Periodic cleanup scheduled (every 30 minutes)");
241
244
  if (!strapi2.sessionManagerIntervals) {
242
245
  strapi2.sessionManagerIntervals = {};
243
246
  }
@@ -253,7 +256,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
253
256
  ctx.body = { message: "Logged out successfully" };
254
257
  return;
255
258
  }
256
- const allSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
259
+ const allSessions = await strapi2.documents(SESSION_UID$2).findMany({
257
260
  filters: {
258
261
  isActive: true
259
262
  }
@@ -268,8 +271,8 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
268
271
  }
269
272
  });
270
273
  if (matchingSession) {
271
- await sessionService.terminateSession({ sessionId: matchingSession.id });
272
- strapi2.log.info(`[magic-sessionmanager] 🚪 Logout via /api/auth/logout - Session ${matchingSession.id} terminated`);
274
+ await sessionService.terminateSession({ sessionId: matchingSession.documentId });
275
+ strapi2.log.info(`[magic-sessionmanager] [LOGOUT] Logout via /api/auth/logout - Session ${matchingSession.documentId} terminated`);
273
276
  }
274
277
  ctx.status = 200;
275
278
  ctx.body = { message: "Logged out successfully" };
@@ -283,7 +286,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
283
286
  auth: false
284
287
  }
285
288
  }]);
286
- strapi2.log.info("[magic-sessionmanager] /api/auth/logout route registered");
289
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] /api/auth/logout route registered");
287
290
  strapi2.server.use(async (ctx, next) => {
288
291
  await next();
289
292
  const isAuthLocal = ctx.path === "/api/auth/local" && ctx.method === "POST";
@@ -293,7 +296,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
293
296
  const user = ctx.body.user;
294
297
  const ip = getClientIp(ctx);
295
298
  const userAgent = ctx.request.headers?.["user-agent"] || ctx.request.header?.["user-agent"] || "unknown";
296
- strapi2.log.info(`[magic-sessionmanager] 🔍 Login detected! User: ${user.id} (${user.email || user.username}) from IP: ${ip}`);
299
+ strapi2.log.info(`[magic-sessionmanager] [CHECK] Login detected! User: ${user.documentId || user.id} (${user.email || user.username}) from IP: ${ip}`);
297
300
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
298
301
  let shouldBlock = false;
299
302
  let blockReason = "";
@@ -335,7 +338,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
335
338
  }
336
339
  }
337
340
  if (shouldBlock) {
338
- strapi2.log.warn(`[magic-sessionmanager] 🚫 Blocking login: ${blockReason}`);
341
+ strapi2.log.warn(`[magic-sessionmanager] [BLOCKED] Blocking login: ${blockReason}`);
339
342
  ctx.status = 403;
340
343
  ctx.body = {
341
344
  error: {
@@ -346,8 +349,13 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
346
349
  };
347
350
  return;
348
351
  }
352
+ let userDocId = user.documentId;
353
+ if (!userDocId && user.id) {
354
+ const fullUser = await strapi2.entityService.findOne(USER_UID$2, user.id);
355
+ userDocId = fullUser?.documentId || user.id;
356
+ }
349
357
  const newSession = await sessionService.createSession({
350
- userId: user.id,
358
+ userId: userDocId,
351
359
  ip,
352
360
  userAgent,
353
361
  token: ctx.body.jwt,
@@ -355,7 +363,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
355
363
  refreshToken: ctx.body.refreshToken
356
364
  // Store Refresh Token (encrypted) if exists
357
365
  });
358
- strapi2.log.info(`[magic-sessionmanager] Session created for user ${user.id} (IP: ${ip})`);
366
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session created for user ${userDocId} (IP: ${ip})`);
359
367
  if (geoData && (config2.enableEmailAlerts || config2.enableWebhooks)) {
360
368
  try {
361
369
  const notificationService = strapi2.plugin("magic-sessionmanager").service("notifications");
@@ -393,18 +401,18 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
393
401
  }
394
402
  }
395
403
  } catch (err) {
396
- strapi2.log.error("[magic-sessionmanager] Error creating session:", err);
404
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Error creating session:", err);
397
405
  }
398
406
  }
399
407
  });
400
- strapi2.log.info("[magic-sessionmanager] Login/Logout interceptor middleware mounted");
408
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Login/Logout interceptor middleware mounted");
401
409
  strapi2.server.use(async (ctx, next) => {
402
410
  const isRefreshToken = ctx.path === "/api/auth/refresh" && ctx.method === "POST";
403
411
  if (isRefreshToken) {
404
412
  try {
405
413
  const refreshToken = ctx.request.body?.refreshToken;
406
414
  if (refreshToken) {
407
- const allSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
415
+ const allSessions = await strapi2.documents(SESSION_UID$2).findMany({
408
416
  filters: {
409
417
  isActive: true
410
418
  }
@@ -419,7 +427,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
419
427
  }
420
428
  });
421
429
  if (!matchingSession) {
422
- strapi2.log.warn("[magic-sessionmanager] 🚫 Blocked refresh token request - no active session");
430
+ strapi2.log.warn("[magic-sessionmanager] [BLOCKED] Blocked refresh token request - no active session");
423
431
  ctx.status = 401;
424
432
  ctx.body = {
425
433
  error: {
@@ -430,7 +438,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
430
438
  };
431
439
  return;
432
440
  }
433
- strapi2.log.info(`[magic-sessionmanager] Refresh token allowed for session ${matchingSession.id}`);
441
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Refresh token allowed for session ${matchingSession.documentId}`);
434
442
  }
435
443
  } catch (err) {
436
444
  strapi2.log.error("[magic-sessionmanager] Error checking refresh token:", err);
@@ -443,7 +451,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
443
451
  const newAccessToken = ctx.body.jwt;
444
452
  const newRefreshToken = ctx.body.refreshToken;
445
453
  if (oldRefreshToken) {
446
- const allSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
454
+ const allSessions = await strapi2.documents(SESSION_UID$2).findMany({
447
455
  filters: {
448
456
  isActive: true
449
457
  }
@@ -460,14 +468,15 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
460
468
  if (matchingSession) {
461
469
  const encryptedToken = newAccessToken ? encryptToken$1(newAccessToken) : matchingSession.token;
462
470
  const encryptedRefreshToken = newRefreshToken ? encryptToken$1(newRefreshToken) : matchingSession.refreshToken;
463
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", matchingSession.id, {
471
+ await strapi2.documents(SESSION_UID$2).update({
472
+ documentId: matchingSession.documentId,
464
473
  data: {
465
474
  token: encryptedToken,
466
475
  refreshToken: encryptedRefreshToken,
467
476
  lastActive: /* @__PURE__ */ new Date()
468
477
  }
469
478
  });
470
- strapi2.log.info(`[magic-sessionmanager] 🔄 Tokens refreshed for session ${matchingSession.id}`);
479
+ strapi2.log.info(`[magic-sessionmanager] [REFRESH] Tokens refreshed for session ${matchingSession.documentId}`);
471
480
  }
472
481
  }
473
482
  } catch (err) {
@@ -475,17 +484,60 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
475
484
  }
476
485
  }
477
486
  });
478
- strapi2.log.info("[magic-sessionmanager] Refresh Token interceptor middleware mounted");
487
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Refresh Token interceptor middleware mounted");
479
488
  strapi2.server.use(
480
489
  lastSeen({ strapi: strapi2, sessionService })
481
490
  );
482
- strapi2.log.info("[magic-sessionmanager] LastSeen middleware mounted");
483
- strapi2.log.info("[magic-sessionmanager] ✅ Bootstrap complete");
484
- strapi2.log.info("[magic-sessionmanager] 🎉 Session Manager ready! Sessions stored in plugin::magic-sessionmanager.session");
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");
485
495
  } catch (err) {
486
- strapi2.log.error("[magic-sessionmanager] Bootstrap error:", err);
496
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Bootstrap error:", err);
487
497
  }
488
498
  };
499
+ async function ensureContentApiPermissions(strapi2) {
500
+ try {
501
+ const authenticatedRole = await strapi2.query("plugin::users-permissions.role").findOne({
502
+ where: { type: "authenticated" }
503
+ });
504
+ if (!authenticatedRole) {
505
+ strapi2.log.warn("[magic-sessionmanager] Authenticated role not found - skipping permission setup");
506
+ return;
507
+ }
508
+ const requiredActions = [
509
+ "plugin::magic-sessionmanager.session.logout",
510
+ "plugin::magic-sessionmanager.session.logoutAll",
511
+ "plugin::magic-sessionmanager.session.getOwnSessions",
512
+ "plugin::magic-sessionmanager.session.getUserSessions"
513
+ ];
514
+ const existingPermissions = await strapi2.query("plugin::users-permissions.permission").findMany({
515
+ where: {
516
+ role: authenticatedRole.id,
517
+ action: { $in: requiredActions }
518
+ }
519
+ });
520
+ const existingActions = existingPermissions.map((p) => p.action);
521
+ const missingActions = requiredActions.filter((action) => !existingActions.includes(action));
522
+ if (missingActions.length === 0) {
523
+ strapi2.log.debug("[magic-sessionmanager] Content-API permissions already configured");
524
+ return;
525
+ }
526
+ for (const action of missingActions) {
527
+ await strapi2.query("plugin::users-permissions.permission").create({
528
+ data: {
529
+ action,
530
+ role: authenticatedRole.id
531
+ }
532
+ });
533
+ strapi2.log.info(`[magic-sessionmanager] [PERMISSION] Enabled ${action} for authenticated users`);
534
+ }
535
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Content-API permissions configured for authenticated users");
536
+ } 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");
539
+ }
540
+ }
489
541
  var destroy$1 = async ({ strapi: strapi2 }) => {
490
542
  if (strapi2.licenseGuard && strapi2.licenseGuard.pingInterval) {
491
543
  clearInterval(strapi2.licenseGuard.pingInterval);
@@ -495,7 +547,7 @@ var destroy$1 = async ({ strapi: strapi2 }) => {
495
547
  clearInterval(strapi2.sessionManagerIntervals.cleanup);
496
548
  strapi2.log.info("[magic-sessionmanager] 🛑 Session cleanup interval stopped");
497
549
  }
498
- strapi2.log.info("[magic-sessionmanager] Plugin cleanup completed");
550
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Plugin cleanup completed");
499
551
  };
500
552
  var config$1 = {
501
553
  default: {
@@ -638,13 +690,22 @@ var contentApi$1 = {
638
690
  // ============================================================
639
691
  // SESSION QUERIES
640
692
  // ============================================================
693
+ {
694
+ method: "GET",
695
+ path: "/my-sessions",
696
+ handler: "session.getOwnSessions",
697
+ config: {
698
+ auth: { strategies: ["users-permissions"] },
699
+ description: "Get own sessions (automatically uses authenticated user)"
700
+ }
701
+ },
641
702
  {
642
703
  method: "GET",
643
704
  path: "/user/:userId/sessions",
644
705
  handler: "session.getUserSessions",
645
706
  config: {
646
707
  auth: { strategies: ["users-permissions"] },
647
- description: "Get own sessions (controller validates user can only see own sessions)"
708
+ description: "Get sessions by userId (validates user can only see own sessions)"
648
709
  }
649
710
  }
650
711
  ]
@@ -803,6 +864,8 @@ var routes$1 = {
803
864
  "content-api": contentApi
804
865
  };
805
866
  const { decryptToken: decryptToken$1 } = encryption;
867
+ const SESSION_UID$1 = "plugin::magic-sessionmanager.session";
868
+ const USER_UID$1 = "plugin::users-permissions.user";
806
869
  var session$3 = {
807
870
  /**
808
871
  * Get ALL sessions (active + inactive) - Admin only
@@ -842,6 +905,30 @@ var session$3 = {
842
905
  ctx.throw(500, "Error fetching active sessions");
843
906
  }
844
907
  },
908
+ /**
909
+ * Get own sessions (authenticated user)
910
+ * GET /api/magic-sessionmanager/my-sessions
911
+ * Automatically uses the authenticated user's documentId
912
+ */
913
+ async getOwnSessions(ctx) {
914
+ try {
915
+ const userId = ctx.state.user?.documentId;
916
+ if (!userId) {
917
+ return ctx.throw(401, "Unauthorized");
918
+ }
919
+ const sessionService = strapi.plugin("magic-sessionmanager").service("session");
920
+ const sessions = await sessionService.getUserSessions(userId);
921
+ ctx.body = {
922
+ data: sessions,
923
+ meta: {
924
+ count: sessions.length
925
+ }
926
+ };
927
+ } catch (err) {
928
+ strapi.log.error("[magic-sessionmanager] Error fetching own sessions:", err);
929
+ ctx.throw(500, "Error fetching sessions");
930
+ }
931
+ },
845
932
  /**
846
933
  * Get user's sessions
847
934
  * GET /magic-sessionmanager/user/:userId/sessions (Admin API)
@@ -852,9 +939,9 @@ var session$3 = {
852
939
  try {
853
940
  const { userId } = ctx.params;
854
941
  const isAdminRequest = ctx.state.userAbility || ctx.state.admin;
855
- const requestingUserId = ctx.state.user?.id;
856
- if (!isAdminRequest && requestingUserId && String(requestingUserId) !== String(userId)) {
857
- strapi.log.warn(`[magic-sessionmanager] Security: User ${requestingUserId} tried to access sessions of user ${userId}`);
942
+ const requestingUserDocId = ctx.state.user?.documentId;
943
+ if (!isAdminRequest && requestingUserDocId && String(requestingUserDocId) !== String(userId)) {
944
+ strapi.log.warn(`[magic-sessionmanager] Security: User ${requestingUserDocId} tried to access sessions of user ${userId}`);
858
945
  return ctx.forbidden("You can only access your own sessions");
859
946
  }
860
947
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
@@ -875,15 +962,15 @@ var session$3 = {
875
962
  */
876
963
  async logout(ctx) {
877
964
  try {
878
- const userId = ctx.state.user?.id;
965
+ const userId = ctx.state.user?.documentId;
879
966
  const token = ctx.request.headers.authorization?.replace("Bearer ", "");
880
967
  if (!userId) {
881
968
  return ctx.throw(401, "Unauthorized");
882
969
  }
883
970
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
884
- const sessions = await strapi.entityService.findMany("plugin::magic-sessionmanager.session", {
971
+ const sessions = await strapi.documents(SESSION_UID$1).findMany({
885
972
  filters: {
886
- user: { id: userId },
973
+ user: { documentId: userId },
887
974
  isActive: true
888
975
  }
889
976
  });
@@ -897,8 +984,8 @@ var session$3 = {
897
984
  }
898
985
  });
899
986
  if (matchingSession) {
900
- await sessionService.terminateSession({ sessionId: matchingSession.id });
901
- strapi.log.info(`[magic-sessionmanager] User ${userId} logged out (session ${matchingSession.id})`);
987
+ await sessionService.terminateSession({ sessionId: matchingSession.documentId });
988
+ strapi.log.info(`[magic-sessionmanager] User ${userId} logged out (session ${matchingSession.documentId})`);
902
989
  }
903
990
  ctx.body = {
904
991
  message: "Logged out successfully"
@@ -914,7 +1001,7 @@ var session$3 = {
914
1001
  */
915
1002
  async logoutAll(ctx) {
916
1003
  try {
917
- const userId = ctx.state.user?.id;
1004
+ const userId = ctx.state.user?.documentId;
918
1005
  if (!userId) {
919
1006
  return ctx.throw(401, "Unauthorized");
920
1007
  }
@@ -1054,23 +1141,34 @@ var session$3 = {
1054
1141
  /**
1055
1142
  * Toggle user blocked status
1056
1143
  * POST /magic-sessionmanager/user/:userId/toggle-block
1144
+ * Supports both numeric id (from Content Manager) and documentId
1057
1145
  */
1058
1146
  async toggleUserBlock(ctx) {
1059
1147
  try {
1060
1148
  const { userId } = ctx.params;
1061
- const user = await strapi.entityService.findOne("plugin::users-permissions.user", userId);
1149
+ let userDocumentId = userId;
1150
+ let user = null;
1151
+ user = await strapi.documents(USER_UID$1).findOne({ documentId: userId });
1152
+ if (!user && !isNaN(userId)) {
1153
+ const numericUser = await strapi.entityService.findOne(USER_UID$1, parseInt(userId, 10));
1154
+ if (numericUser) {
1155
+ userDocumentId = numericUser.documentId;
1156
+ user = numericUser;
1157
+ }
1158
+ }
1062
1159
  if (!user) {
1063
1160
  return ctx.throw(404, "User not found");
1064
1161
  }
1065
1162
  const newBlockedStatus = !user.blocked;
1066
- await strapi.entityService.update("plugin::users-permissions.user", userId, {
1163
+ await strapi.documents(USER_UID$1).update({
1164
+ documentId: userDocumentId,
1067
1165
  data: {
1068
1166
  blocked: newBlockedStatus
1069
1167
  }
1070
1168
  });
1071
1169
  if (newBlockedStatus) {
1072
1170
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
1073
- await sessionService.terminateSession({ userId });
1171
+ await sessionService.terminateSession({ userId: userDocumentId });
1074
1172
  }
1075
1173
  ctx.body = {
1076
1174
  message: `User ${newBlockedStatus ? "blocked" : "unblocked"} successfully`,
@@ -1257,16 +1355,16 @@ var license$1 = ({ strapi: strapi2 }) => ({
1257
1355
  const licenseGuard2 = strapi2.plugin("magic-sessionmanager").service("license-guard");
1258
1356
  const verification = await licenseGuard2.verifyLicense(trimmedKey);
1259
1357
  if (!verification.valid) {
1260
- strapi2.log.warn(`[magic-sessionmanager] ⚠️ Invalid license key attempted: ${trimmedKey.substring(0, 8)}...`);
1358
+ strapi2.log.warn(`[magic-sessionmanager] [WARNING] Invalid license key attempted: ${trimmedKey.substring(0, 8)}...`);
1261
1359
  return ctx.badRequest("Invalid or expired license key");
1262
1360
  }
1263
1361
  const license2 = await licenseGuard2.getLicenseByKey(trimmedKey);
1264
1362
  if (!license2) {
1265
- strapi2.log.warn(`[magic-sessionmanager] ⚠️ License not found in database: ${trimmedKey.substring(0, 8)}...`);
1363
+ strapi2.log.warn(`[magic-sessionmanager] [WARNING] License not found in database: ${trimmedKey.substring(0, 8)}...`);
1266
1364
  return ctx.badRequest("License not found");
1267
1365
  }
1268
1366
  if (license2.email.toLowerCase() !== trimmedEmail) {
1269
- strapi2.log.warn(`[magic-sessionmanager] ⚠️ Email mismatch for license key: ${trimmedKey.substring(0, 8)}... (Attempted: ${trimmedEmail})`);
1367
+ strapi2.log.warn(`[magic-sessionmanager] [WARNING] Email mismatch for license key: ${trimmedKey.substring(0, 8)}... (Attempted: ${trimmedEmail})`);
1270
1368
  return ctx.badRequest("Email address does not match this license key");
1271
1369
  }
1272
1370
  await licenseGuard2.storeLicenseKey(trimmedKey);
@@ -1276,7 +1374,7 @@ var license$1 = ({ strapi: strapi2 }) => ({
1276
1374
  pingInterval,
1277
1375
  data: verification.data
1278
1376
  };
1279
- strapi2.log.info(`[magic-sessionmanager] Existing license key validated and stored: ${trimmedKey.substring(0, 8)}... (Email: ${trimmedEmail})`);
1377
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Existing license key validated and stored: ${trimmedKey.substring(0, 8)}... (Email: ${trimmedEmail})`);
1280
1378
  return ctx.send({
1281
1379
  success: true,
1282
1380
  message: "License key validated and activated successfully",
@@ -1398,6 +1496,8 @@ var controllers$1 = {
1398
1496
  settings
1399
1497
  };
1400
1498
  const { encryptToken, decryptToken, generateSessionId } = encryption;
1499
+ const SESSION_UID = "plugin::magic-sessionmanager.session";
1500
+ const USER_UID = "plugin::users-permissions.user";
1401
1501
  var session$1 = ({ strapi: strapi2 }) => ({
1402
1502
  /**
1403
1503
  * Create a new session record
@@ -1410,23 +1510,24 @@ var session$1 = ({ strapi: strapi2 }) => ({
1410
1510
  const sessionId = generateSessionId(userId);
1411
1511
  const encryptedToken = token ? encryptToken(token) : null;
1412
1512
  const encryptedRefreshToken = refreshToken ? encryptToken(refreshToken) : null;
1413
- const session2 = await strapi2.entityService.create("plugin::magic-sessionmanager.session", {
1513
+ const session2 = await strapi2.documents(SESSION_UID).create({
1414
1514
  data: {
1415
1515
  user: userId,
1516
+ // userId should be documentId (string)
1416
1517
  ipAddress: ip.substring(0, 45),
1417
1518
  userAgent: userAgent.substring(0, 500),
1418
1519
  loginTime: now,
1419
1520
  lastActive: now,
1420
1521
  isActive: true,
1421
1522
  token: encryptedToken,
1422
- // Encrypted Access Token
1523
+ // [SUCCESS] Encrypted Access Token
1423
1524
  refreshToken: encryptedRefreshToken,
1424
- // Encrypted Refresh Token
1525
+ // [SUCCESS] Encrypted Refresh Token
1425
1526
  sessionId
1426
- // Unique identifier
1527
+ // [SUCCESS] Unique identifier
1427
1528
  }
1428
1529
  });
1429
- strapi2.log.info(`[magic-sessionmanager] Session ${session2.id} (${sessionId}) created for user ${userId}`);
1530
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session ${session2.documentId} (${sessionId}) created for user ${userId}`);
1430
1531
  return session2;
1431
1532
  } catch (err) {
1432
1533
  strapi2.log.error("[magic-sessionmanager] Error creating session:", err);
@@ -1435,6 +1536,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1435
1536
  },
1436
1537
  /**
1437
1538
  * Terminate a session or all sessions for a user
1539
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1438
1540
  * @param {Object} params - { sessionId | userId }
1439
1541
  * @returns {Promise<void>}
1440
1542
  */
@@ -1442,7 +1544,8 @@ var session$1 = ({ strapi: strapi2 }) => ({
1442
1544
  try {
1443
1545
  const now = /* @__PURE__ */ new Date();
1444
1546
  if (sessionId) {
1445
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", sessionId, {
1547
+ await strapi2.documents(SESSION_UID).update({
1548
+ documentId: sessionId,
1446
1549
  data: {
1447
1550
  isActive: false,
1448
1551
  logoutTime: now
@@ -1450,21 +1553,30 @@ var session$1 = ({ strapi: strapi2 }) => ({
1450
1553
  });
1451
1554
  strapi2.log.info(`[magic-sessionmanager] Session ${sessionId} terminated`);
1452
1555
  } else if (userId) {
1453
- const activeSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
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({
1454
1564
  filters: {
1455
- user: { id: userId },
1565
+ user: { documentId: userDocumentId },
1566
+ // Deep filtering syntax
1456
1567
  isActive: true
1457
1568
  }
1458
1569
  });
1459
1570
  for (const session2 of activeSessions) {
1460
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", session2.id, {
1571
+ await strapi2.documents(SESSION_UID).update({
1572
+ documentId: session2.documentId,
1461
1573
  data: {
1462
1574
  isActive: false,
1463
1575
  logoutTime: now
1464
1576
  }
1465
1577
  });
1466
1578
  }
1467
- strapi2.log.info(`[magic-sessionmanager] All sessions terminated for user ${userId}`);
1579
+ strapi2.log.info(`[magic-sessionmanager] All sessions terminated for user ${userDocumentId}`);
1468
1580
  }
1469
1581
  } catch (err) {
1470
1582
  strapi2.log.error("[magic-sessionmanager] Error terminating session:", err);
@@ -1477,7 +1589,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1477
1589
  */
1478
1590
  async getAllSessions() {
1479
1591
  try {
1480
- const sessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1592
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1481
1593
  populate: { user: { fields: ["id", "email", "username"] } },
1482
1594
  sort: { loginTime: "desc" },
1483
1595
  limit: 1e3
@@ -1509,7 +1621,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1509
1621
  */
1510
1622
  async getActiveSessions() {
1511
1623
  try {
1512
- const sessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1624
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1513
1625
  filters: { isActive: true },
1514
1626
  populate: { user: { fields: ["id", "email", "username"] } },
1515
1627
  sort: { loginTime: "desc" }
@@ -1536,13 +1648,21 @@ var session$1 = ({ strapi: strapi2 }) => ({
1536
1648
  },
1537
1649
  /**
1538
1650
  * Get all sessions for a specific user
1539
- * @param {number} userId
1651
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1652
+ * @param {string|number} userId - User documentId or numeric id
1540
1653
  * @returns {Promise<Array>} User's sessions with accurate online status
1541
1654
  */
1542
1655
  async getUserSessions(userId) {
1543
1656
  try {
1544
- const sessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1545
- filters: { user: { id: userId } },
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;
1662
+ }
1663
+ }
1664
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1665
+ filters: { user: { documentId: userDocumentId } },
1546
1666
  sort: { loginTime: "desc" }
1547
1667
  });
1548
1668
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
@@ -1576,17 +1696,19 @@ var session$1 = ({ strapi: strapi2 }) => ({
1576
1696
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1577
1697
  const rateLimit = config2.lastSeenRateLimit || 3e4;
1578
1698
  if (sessionId) {
1579
- const session2 = await strapi2.entityService.findOne("plugin::magic-sessionmanager.session", sessionId);
1699
+ const session2 = await strapi2.documents(SESSION_UID).findOne({ documentId: sessionId });
1580
1700
  if (session2 && session2.lastActive) {
1581
1701
  const lastActiveTime = new Date(session2.lastActive).getTime();
1582
1702
  const currentTime = now.getTime();
1583
1703
  if (currentTime - lastActiveTime > rateLimit) {
1584
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", sessionId, {
1704
+ await strapi2.documents(SESSION_UID).update({
1705
+ documentId: sessionId,
1585
1706
  data: { lastActive: now }
1586
1707
  });
1587
1708
  }
1588
1709
  } else if (session2) {
1589
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", sessionId, {
1710
+ await strapi2.documents(SESSION_UID).update({
1711
+ documentId: sessionId,
1590
1712
  data: { lastActive: now }
1591
1713
  });
1592
1714
  }
@@ -1605,22 +1727,23 @@ var session$1 = ({ strapi: strapi2 }) => ({
1605
1727
  const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1606
1728
  const now = /* @__PURE__ */ new Date();
1607
1729
  const cutoffTime = new Date(now.getTime() - inactivityTimeout);
1608
- strapi2.log.info(`[magic-sessionmanager] 🧹 Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
1609
- const activeSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1730
+ strapi2.log.info(`[magic-sessionmanager] [CLEANUP] Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
1731
+ const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1610
1732
  filters: { isActive: true },
1611
- fields: ["id", "lastActive", "loginTime"]
1733
+ fields: ["lastActive", "loginTime"]
1612
1734
  });
1613
1735
  let deactivatedCount = 0;
1614
1736
  for (const session2 of activeSessions) {
1615
1737
  const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1616
1738
  if (lastActiveTime < cutoffTime) {
1617
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", session2.id, {
1739
+ await strapi2.documents(SESSION_UID).update({
1740
+ documentId: session2.documentId,
1618
1741
  data: { isActive: false }
1619
1742
  });
1620
1743
  deactivatedCount++;
1621
1744
  }
1622
1745
  }
1623
- strapi2.log.info(`[magic-sessionmanager] Cleanup complete: ${deactivatedCount} sessions deactivated`);
1746
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Cleanup complete: ${deactivatedCount} sessions deactivated`);
1624
1747
  return deactivatedCount;
1625
1748
  } catch (err) {
1626
1749
  strapi2.log.error("[magic-sessionmanager] Error cleaning up inactive sessions:", err);
@@ -1635,8 +1758,8 @@ var session$1 = ({ strapi: strapi2 }) => ({
1635
1758
  */
1636
1759
  async deleteSession(sessionId) {
1637
1760
  try {
1638
- await strapi2.entityService.delete("plugin::magic-sessionmanager.session", sessionId);
1639
- strapi2.log.info(`[magic-sessionmanager] 🗑️ Session ${sessionId} permanently deleted`);
1761
+ await strapi2.documents(SESSION_UID).delete({ documentId: sessionId });
1762
+ strapi2.log.info(`[magic-sessionmanager] [DELETE] Session ${sessionId} permanently deleted`);
1640
1763
  return true;
1641
1764
  } catch (err) {
1642
1765
  strapi2.log.error("[magic-sessionmanager] Error deleting session:", err);
@@ -1650,17 +1773,16 @@ var session$1 = ({ strapi: strapi2 }) => ({
1650
1773
  */
1651
1774
  async deleteInactiveSessions() {
1652
1775
  try {
1653
- strapi2.log.info("[magic-sessionmanager] 🗑️ Deleting all inactive sessions...");
1654
- const inactiveSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1655
- filters: { isActive: false },
1656
- fields: ["id"]
1776
+ strapi2.log.info("[magic-sessionmanager] [DELETE] Deleting all inactive sessions...");
1777
+ const inactiveSessions = await strapi2.documents(SESSION_UID).findMany({
1778
+ filters: { isActive: false }
1657
1779
  });
1658
1780
  let deletedCount = 0;
1659
1781
  for (const session2 of inactiveSessions) {
1660
- await strapi2.entityService.delete("plugin::magic-sessionmanager.session", session2.id);
1782
+ await strapi2.documents(SESSION_UID).delete({ documentId: session2.documentId });
1661
1783
  deletedCount++;
1662
1784
  }
1663
- strapi2.log.info(`[magic-sessionmanager] Deleted ${deletedCount} inactive sessions`);
1785
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Deleted ${deletedCount} inactive sessions`);
1664
1786
  return deletedCount;
1665
1787
  } catch (err) {
1666
1788
  strapi2.log.error("[magic-sessionmanager] Error deleting inactive sessions:", err);
@@ -1668,8 +1790,13 @@ var session$1 = ({ strapi: strapi2 }) => ({
1668
1790
  }
1669
1791
  }
1670
1792
  });
1793
+ const version = "4.0.0";
1794
+ const require$$2 = {
1795
+ version
1796
+ };
1671
1797
  const crypto = require$$0__default.default;
1672
1798
  const os = require$$1__default.default;
1799
+ const pluginPkg = require$$2;
1673
1800
  const LICENSE_SERVER_URL = "https://magicapi.fitlex.me";
1674
1801
  var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1675
1802
  /**
@@ -1724,7 +1851,9 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1724
1851
  }
1725
1852
  },
1726
1853
  getUserAgent() {
1727
- return `Strapi/${strapi2.config.get("info.strapi") || "5.0.0"} Node/${process.version} ${os.platform()}/${os.release()}`;
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()}`;
1728
1857
  },
1729
1858
  async createLicense({ email, firstName, lastName }) {
1730
1859
  try {
@@ -1750,14 +1879,14 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1750
1879
  });
1751
1880
  const data = await response.json();
1752
1881
  if (data.success) {
1753
- strapi2.log.info("[magic-sessionmanager] License created:", data.data.licenseKey);
1882
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] License created:", data.data.licenseKey);
1754
1883
  return data.data;
1755
1884
  } else {
1756
- strapi2.log.error("[magic-sessionmanager] License creation failed:", data);
1885
+ strapi2.log.error("[magic-sessionmanager] [ERROR] License creation failed:", data);
1757
1886
  return null;
1758
1887
  }
1759
1888
  } catch (error) {
1760
- strapi2.log.error("[magic-sessionmanager] Error creating license:", error);
1889
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Error creating license:", error);
1761
1890
  return null;
1762
1891
  }
1763
1892
  },
@@ -1842,10 +1971,10 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1842
1971
  name: "magic-sessionmanager"
1843
1972
  });
1844
1973
  await pluginStore.set({ key: "licenseKey", value: licenseKey });
1845
- strapi2.log.info(`[magic-sessionmanager] License key stored: ${licenseKey.substring(0, 8)}...`);
1974
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] License key stored: ${licenseKey.substring(0, 8)}...`);
1846
1975
  },
1847
1976
  startPinging(licenseKey, intervalMinutes = 15) {
1848
- strapi2.log.info(`[magic-sessionmanager] Starting license pings every ${intervalMinutes} minutes`);
1977
+ strapi2.log.info(`[magic-sessionmanager] [TIME] Starting license pings every ${intervalMinutes} minutes`);
1849
1978
  this.pingLicense(licenseKey);
1850
1979
  const interval = setInterval(async () => {
1851
1980
  try {
@@ -1862,14 +1991,14 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1862
1991
  */
1863
1992
  async initialize() {
1864
1993
  try {
1865
- strapi2.log.info("[magic-sessionmanager] 🔐 Initializing License Guard...");
1994
+ strapi2.log.info("[magic-sessionmanager] [SECURE] Initializing License Guard...");
1866
1995
  const pluginStore = strapi2.store({
1867
1996
  type: "plugin",
1868
1997
  name: "magic-sessionmanager"
1869
1998
  });
1870
1999
  const licenseKey = await pluginStore.get({ key: "licenseKey" });
1871
2000
  if (!licenseKey) {
1872
- strapi2.log.info("[magic-sessionmanager] ℹ️ No license found - Running in demo mode");
2001
+ strapi2.log.info("[magic-sessionmanager] [INFO] No license found - Running in demo mode");
1873
2002
  return {
1874
2003
  valid: false,
1875
2004
  demo: true,
@@ -1904,7 +2033,7 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1904
2033
  gracePeriod: verification.gracePeriod || false
1905
2034
  };
1906
2035
  } else {
1907
- strapi2.log.error("[magic-sessionmanager] License validation failed");
2036
+ strapi2.log.error("[magic-sessionmanager] [ERROR] License validation failed");
1908
2037
  return {
1909
2038
  valid: false,
1910
2039
  demo: true,
@@ -1913,7 +2042,7 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1913
2042
  };
1914
2043
  }
1915
2044
  } catch (error) {
1916
- strapi2.log.error("[magic-sessionmanager] Error initializing License Guard:", error);
2045
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Error initializing License Guard:", error);
1917
2046
  return {
1918
2047
  valid: false,
1919
2048
  demo: true,
@@ -2026,9 +2155,11 @@ var geolocation$1 = ({ strapi: strapi2 }) => ({
2026
2155
  },
2027
2156
  /**
2028
2157
  * Get country flag emoji
2158
+ * @param {string} countryCode - ISO 2-letter country code
2159
+ * @returns {string} Flag emoji or empty string
2029
2160
  */
2030
2161
  getCountryFlag(countryCode) {
2031
- if (!countryCode) return "🏳️";
2162
+ if (!countryCode) return "";
2032
2163
  const codePoints = countryCode.toUpperCase().split("").map((char) => 127397 + char.charCodeAt());
2033
2164
  return String.fromCodePoint(...codePoints);
2034
2165
  },
@@ -2040,7 +2171,7 @@ var geolocation$1 = ({ strapi: strapi2 }) => ({
2040
2171
  ip: ipAddress,
2041
2172
  country: "Unknown",
2042
2173
  country_code: "XX",
2043
- country_flag: "🌍",
2174
+ country_flag: "[GEO]",
2044
2175
  city: "Unknown",
2045
2176
  region: "Unknown",
2046
2177
  timezone: "Unknown",
@@ -2090,12 +2221,12 @@ var notifications$1 = ({ strapi: strapi2 }) => ({
2090
2221
  strapi2.log.debug("[magic-sessionmanager/notifications] Using default fallback templates");
2091
2222
  return {
2092
2223
  suspiciousLogin: {
2093
- subject: "🚨 Suspicious Login Alert - Session Manager",
2224
+ subject: "[ALERT] Suspicious Login Alert - Session Manager",
2094
2225
  html: `
2095
2226
  <html>
2096
2227
  <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
2097
2228
  <div style="max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9fafb; border-radius: 10px;">
2098
- <h2 style="color: #dc2626;">🚨 Suspicious Login Detected</h2>
2229
+ <h2 style="color: #dc2626;">[ALERT] Suspicious Login Detected</h2>
2099
2230
  <p>A potentially suspicious login was detected for your account.</p>
2100
2231
 
2101
2232
  <div style="background: white; padding: 15px; border-radius: 8px; margin: 20px 0;">
@@ -2130,7 +2261,7 @@ var notifications$1 = ({ strapi: strapi2 }) => ({
2130
2261
  </div>
2131
2262
  </body>
2132
2263
  </html>`,
2133
- text: `🚨 Suspicious Login Detected
2264
+ text: `[ALERT] Suspicious Login Detected
2134
2265
 
2135
2266
  A potentially suspicious login was detected for your account.
2136
2267
 
@@ -2145,9 +2276,9 @@ Login Details:
2145
2276
  Security: VPN={{reason.isVpn}}, Proxy={{reason.isProxy}}, Threat={{reason.isThreat}}, Score={{reason.securityScore}}/100`
2146
2277
  },
2147
2278
  newLocation: {
2148
- subject: "📍 New Location Login Detected",
2149
- html: `<h2>📍 New Location Login</h2><p>Account: {{user.email}}</p><p>Time: {{session.loginTime}}</p><p>Location: {{geo.city}}, {{geo.country}}</p><p>IP: {{session.ipAddress}}</p>`,
2150
- text: `📍 New Location Login
2279
+ subject: "[LOCATION] New Location Login Detected",
2280
+ html: `<h2>[LOCATION] New Location Login</h2><p>Account: {{user.email}}</p><p>Time: {{session.loginTime}}</p><p>Location: {{geo.city}}, {{geo.country}}</p><p>IP: {{session.ipAddress}}</p>`,
2281
+ text: `[LOCATION] New Location Login
2151
2282
 
2152
2283
  Account: {{user.email}}
2153
2284
  Time: {{session.loginTime}}
@@ -2155,9 +2286,9 @@ Location: {{geo.city}}, {{geo.country}}
2155
2286
  IP: {{session.ipAddress}}`
2156
2287
  },
2157
2288
  vpnProxy: {
2158
- subject: "⚠️ VPN/Proxy Login Detected",
2159
- html: `<h2>⚠️ VPN/Proxy Detected</h2><p>Account: {{user.email}}</p><p>Time: {{session.loginTime}}</p><p>IP: {{session.ipAddress}}</p><p>VPN: {{reason.isVpn}}, Proxy: {{reason.isProxy}}</p>`,
2160
- text: `⚠️ VPN/Proxy Detected
2289
+ subject: "[WARNING] VPN/Proxy Login Detected",
2290
+ html: `<h2>[WARNING] VPN/Proxy Detected</h2><p>Account: {{user.email}}</p><p>Time: {{session.loginTime}}</p><p>IP: {{session.ipAddress}}</p><p>VPN: {{reason.isVpn}}, Proxy: {{reason.isProxy}}</p>`,
2291
+ text: `[WARNING] VPN/Proxy Detected
2161
2292
 
2162
2293
  Account: {{user.email}}
2163
2294
  Time: {{session.loginTime}}
@@ -2301,17 +2432,17 @@ VPN: {{reason.isVpn}}, Proxy: {{reason.isProxy}}`
2301
2432
  title: this.getEventTitle(event),
2302
2433
  color: this.getEventColor(event),
2303
2434
  fields: [
2304
- { name: "👤 User", value: `${user.email}
2435
+ { name: "User", value: `${user.email}
2305
2436
  ${user.username || "N/A"}`, inline: true },
2306
- { name: "🌐 IP", value: session2.ipAddress, inline: true },
2307
- { name: "📅 Time", value: new Date(session2.loginTime).toLocaleString(), inline: false }
2437
+ { name: "IP", value: session2.ipAddress, inline: true },
2438
+ { name: "Time", value: new Date(session2.loginTime).toLocaleString(), inline: false }
2308
2439
  ],
2309
2440
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2310
2441
  footer: { text: "Magic Session Manager" }
2311
2442
  };
2312
2443
  if (geoData) {
2313
2444
  embed.fields.push({
2314
- name: "📍 Location",
2445
+ name: "[LOCATION] Location",
2315
2446
  value: `${geoData.country_flag} ${geoData.city}, ${geoData.country}`,
2316
2447
  inline: true
2317
2448
  });
@@ -2321,7 +2452,7 @@ ${user.username || "N/A"}`, inline: true },
2321
2452
  if (geoData.isProxy) warnings.push("Proxy");
2322
2453
  if (geoData.isThreat) warnings.push("Threat");
2323
2454
  embed.fields.push({
2324
- name: "⚠️ Security",
2455
+ name: "[WARNING] Security",
2325
2456
  value: `${warnings.join(", ")} detected
2326
2457
  Score: ${geoData.securityScore}/100`,
2327
2458
  inline: true
@@ -2332,13 +2463,13 @@ Score: ${geoData.securityScore}/100`,
2332
2463
  },
2333
2464
  getEventTitle(event) {
2334
2465
  const titles = {
2335
- "login.suspicious": "🚨 Suspicious Login",
2336
- "login.new_location": "📍 New Location Login",
2337
- "login.vpn": "🔴 VPN Login Detected",
2338
- "login.threat": " Threat IP Login",
2339
- "session.terminated": "🔴 Session Terminated"
2466
+ "login.suspicious": "[ALERT] Suspicious Login",
2467
+ "login.new_location": "[LOCATION] New Location Login",
2468
+ "login.vpn": "[WARNING] VPN Login Detected",
2469
+ "login.threat": "[THREAT] Threat IP Login",
2470
+ "session.terminated": "[INFO] Session Terminated"
2340
2471
  };
2341
- return titles[event] || "📊 Session Event";
2472
+ return titles[event] || "[STATS] Session Event";
2342
2473
  },
2343
2474
  getEventColor(event) {
2344
2475
  const colors = {