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
@@ -4,7 +4,7 @@ function getDefaultExportFromCjs(x) {
4
4
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
5
5
  }
6
6
  var register$1 = async ({ strapi: strapi2 }) => {
7
- strapi2.log.info("[magic-sessionmanager] 🚀 Plugin registration starting...");
7
+ strapi2.log.info("[magic-sessionmanager] [START] Plugin registration starting...");
8
8
  try {
9
9
  const userCT = strapi2.contentType("plugin::users-permissions.user");
10
10
  if (!userCT) {
@@ -13,11 +13,11 @@ var register$1 = async ({ strapi: strapi2 }) => {
13
13
  }
14
14
  if (userCT.attributes && userCT.attributes.sessions) {
15
15
  delete userCT.attributes.sessions;
16
- strapi2.log.info("[magic-sessionmanager] Removed sessions field from User content type");
16
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Removed sessions field from User content type");
17
17
  }
18
- strapi2.log.info("[magic-sessionmanager] Plugin registered successfully");
18
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Plugin registered successfully");
19
19
  } catch (err) {
20
- strapi2.log.error("[magic-sessionmanager] Registration error:", err);
20
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Registration error:", err);
21
21
  }
22
22
  };
23
23
  const getClientIp$1 = (ctx) => {
@@ -94,7 +94,7 @@ function getEncryptionKey() {
94
94
  }
95
95
  const strapiKeys = process.env.APP_KEYS || process.env.API_TOKEN_SALT || "default-insecure-key";
96
96
  const key = crypto$1.createHash("sha256").update(strapiKeys).digest();
97
- console.warn("[magic-sessionmanager/encryption] ⚠️ No SESSION_ENCRYPTION_KEY found. Using fallback (not recommended for production).");
97
+ console.warn("[magic-sessionmanager/encryption] [WARNING] No SESSION_ENCRYPTION_KEY found. Using fallback (not recommended for production).");
98
98
  console.warn("[magic-sessionmanager/encryption] Set SESSION_ENCRYPTION_KEY in .env for better security.");
99
99
  return key;
100
100
  }
@@ -145,20 +145,21 @@ var encryption = {
145
145
  decryptToken: decryptToken$3,
146
146
  generateSessionId: generateSessionId$1
147
147
  };
148
+ const SESSION_UID$3 = "plugin::magic-sessionmanager.session";
148
149
  var lastSeen = ({ strapi: strapi2, sessionService }) => {
149
150
  return async (ctx, next) => {
150
- if (ctx.state.user && ctx.state.user.id) {
151
+ if (ctx.state.user && ctx.state.user.documentId) {
151
152
  try {
152
- const userId = ctx.state.user.id;
153
- const activeSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
153
+ const userId = ctx.state.user.documentId;
154
+ const activeSessions = await strapi2.documents(SESSION_UID$3).findMany({
154
155
  filters: {
155
- user: { id: userId },
156
+ user: { documentId: userId },
156
157
  isActive: true
157
158
  },
158
159
  limit: 1
159
160
  });
160
161
  if (!activeSessions || activeSessions.length === 0) {
161
- strapi2.log.info(`[magic-sessionmanager] 🚫 Blocked request - User ${userId} has no active sessions`);
162
+ strapi2.log.info(`[magic-sessionmanager] [BLOCKED] Blocked request - User ${userId} has no active sessions`);
162
163
  return ctx.unauthorized("All sessions have been terminated. Please login again.");
163
164
  }
164
165
  } catch (err) {
@@ -166,9 +167,9 @@ var lastSeen = ({ strapi: strapi2, sessionService }) => {
166
167
  }
167
168
  }
168
169
  await next();
169
- if (ctx.state.user && ctx.state.user.id) {
170
+ if (ctx.state.user && ctx.state.user.documentId) {
170
171
  try {
171
- const userId = ctx.state.user.id;
172
+ const userId = ctx.state.user.documentId;
172
173
  const sessionId = ctx.state.sessionId;
173
174
  await sessionService.touch({
174
175
  userId,
@@ -182,15 +183,17 @@ var lastSeen = ({ strapi: strapi2, sessionService }) => {
182
183
  };
183
184
  const getClientIp = getClientIp_1;
184
185
  const { encryptToken: encryptToken$1, decryptToken: decryptToken$2 } = encryption;
186
+ const SESSION_UID$2 = "plugin::magic-sessionmanager.session";
187
+ const USER_UID$2 = "plugin::users-permissions.user";
185
188
  var bootstrap$1 = async ({ strapi: strapi2 }) => {
186
- strapi2.log.info("[magic-sessionmanager] 🚀 Bootstrap starting...");
189
+ strapi2.log.info("[magic-sessionmanager] [START] Bootstrap starting...");
187
190
  try {
188
191
  const licenseGuardService = strapi2.plugin("magic-sessionmanager").service("license-guard");
189
192
  setTimeout(async () => {
190
193
  const licenseStatus = await licenseGuardService.initialize();
191
194
  if (!licenseStatus.valid) {
192
195
  strapi2.log.error("╔════════════════════════════════════════════════════════════════╗");
193
- strapi2.log.error("║ SESSION MANAGER - NO VALID LICENSE ║");
196
+ strapi2.log.error("║ [ERROR] SESSION MANAGER - NO VALID LICENSE ║");
194
197
  strapi2.log.error("║ ║");
195
198
  strapi2.log.error("║ This plugin requires a valid license to operate. ║");
196
199
  strapi2.log.error("║ Please activate your license via Admin UI: ║");
@@ -206,7 +209,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
206
209
  });
207
210
  const storedKey = await pluginStore.get({ key: "licenseKey" });
208
211
  strapi2.log.info("╔════════════════════════════════════════════════════════════════╗");
209
- strapi2.log.info("║ SESSION MANAGER LICENSE ACTIVE ║");
212
+ strapi2.log.info("║ [SUCCESS] SESSION MANAGER LICENSE ACTIVE ║");
210
213
  strapi2.log.info("║ ║");
211
214
  if (licenseStatus.data) {
212
215
  strapi2.log.info(`║ License: ${licenseStatus.data.licenseKey}`.padEnd(66) + "║");
@@ -217,7 +220,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
217
220
  strapi2.log.info(`║ Status: Grace Period Active`.padEnd(66) + "║");
218
221
  }
219
222
  strapi2.log.info("║ ║");
220
- strapi2.log.info("║ 🔄 Auto-pinging every 15 minutes ║");
223
+ strapi2.log.info("║ [RELOAD] Auto-pinging every 15 minutes ║");
221
224
  strapi2.log.info("╚════════════════════════════════════════════════════════════════╝");
222
225
  }
223
226
  }, 3e3);
@@ -233,7 +236,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
233
236
  strapi2.log.error("[magic-sessionmanager] Periodic cleanup error:", err);
234
237
  }
235
238
  }, cleanupInterval);
236
- strapi2.log.info("[magic-sessionmanager] Periodic cleanup scheduled (every 30 minutes)");
239
+ strapi2.log.info("[magic-sessionmanager] [TIME] Periodic cleanup scheduled (every 30 minutes)");
237
240
  if (!strapi2.sessionManagerIntervals) {
238
241
  strapi2.sessionManagerIntervals = {};
239
242
  }
@@ -249,7 +252,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
249
252
  ctx.body = { message: "Logged out successfully" };
250
253
  return;
251
254
  }
252
- const allSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
255
+ const allSessions = await strapi2.documents(SESSION_UID$2).findMany({
253
256
  filters: {
254
257
  isActive: true
255
258
  }
@@ -264,8 +267,8 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
264
267
  }
265
268
  });
266
269
  if (matchingSession) {
267
- await sessionService.terminateSession({ sessionId: matchingSession.id });
268
- strapi2.log.info(`[magic-sessionmanager] 🚪 Logout via /api/auth/logout - Session ${matchingSession.id} terminated`);
270
+ await sessionService.terminateSession({ sessionId: matchingSession.documentId });
271
+ strapi2.log.info(`[magic-sessionmanager] [LOGOUT] Logout via /api/auth/logout - Session ${matchingSession.documentId} terminated`);
269
272
  }
270
273
  ctx.status = 200;
271
274
  ctx.body = { message: "Logged out successfully" };
@@ -279,7 +282,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
279
282
  auth: false
280
283
  }
281
284
  }]);
282
- strapi2.log.info("[magic-sessionmanager] /api/auth/logout route registered");
285
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] /api/auth/logout route registered");
283
286
  strapi2.server.use(async (ctx, next) => {
284
287
  await next();
285
288
  const isAuthLocal = ctx.path === "/api/auth/local" && ctx.method === "POST";
@@ -289,7 +292,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
289
292
  const user = ctx.body.user;
290
293
  const ip = getClientIp(ctx);
291
294
  const userAgent = ctx.request.headers?.["user-agent"] || ctx.request.header?.["user-agent"] || "unknown";
292
- strapi2.log.info(`[magic-sessionmanager] 🔍 Login detected! User: ${user.id} (${user.email || user.username}) from IP: ${ip}`);
295
+ strapi2.log.info(`[magic-sessionmanager] [CHECK] Login detected! User: ${user.documentId || user.id} (${user.email || user.username}) from IP: ${ip}`);
293
296
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
294
297
  let shouldBlock = false;
295
298
  let blockReason = "";
@@ -331,7 +334,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
331
334
  }
332
335
  }
333
336
  if (shouldBlock) {
334
- strapi2.log.warn(`[magic-sessionmanager] 🚫 Blocking login: ${blockReason}`);
337
+ strapi2.log.warn(`[magic-sessionmanager] [BLOCKED] Blocking login: ${blockReason}`);
335
338
  ctx.status = 403;
336
339
  ctx.body = {
337
340
  error: {
@@ -342,8 +345,13 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
342
345
  };
343
346
  return;
344
347
  }
348
+ let userDocId = user.documentId;
349
+ if (!userDocId && user.id) {
350
+ const fullUser = await strapi2.entityService.findOne(USER_UID$2, user.id);
351
+ userDocId = fullUser?.documentId || user.id;
352
+ }
345
353
  const newSession = await sessionService.createSession({
346
- userId: user.id,
354
+ userId: userDocId,
347
355
  ip,
348
356
  userAgent,
349
357
  token: ctx.body.jwt,
@@ -351,7 +359,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
351
359
  refreshToken: ctx.body.refreshToken
352
360
  // Store Refresh Token (encrypted) if exists
353
361
  });
354
- strapi2.log.info(`[magic-sessionmanager] Session created for user ${user.id} (IP: ${ip})`);
362
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session created for user ${userDocId} (IP: ${ip})`);
355
363
  if (geoData && (config2.enableEmailAlerts || config2.enableWebhooks)) {
356
364
  try {
357
365
  const notificationService = strapi2.plugin("magic-sessionmanager").service("notifications");
@@ -389,18 +397,18 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
389
397
  }
390
398
  }
391
399
  } catch (err) {
392
- strapi2.log.error("[magic-sessionmanager] Error creating session:", err);
400
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Error creating session:", err);
393
401
  }
394
402
  }
395
403
  });
396
- strapi2.log.info("[magic-sessionmanager] Login/Logout interceptor middleware mounted");
404
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Login/Logout interceptor middleware mounted");
397
405
  strapi2.server.use(async (ctx, next) => {
398
406
  const isRefreshToken = ctx.path === "/api/auth/refresh" && ctx.method === "POST";
399
407
  if (isRefreshToken) {
400
408
  try {
401
409
  const refreshToken = ctx.request.body?.refreshToken;
402
410
  if (refreshToken) {
403
- const allSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
411
+ const allSessions = await strapi2.documents(SESSION_UID$2).findMany({
404
412
  filters: {
405
413
  isActive: true
406
414
  }
@@ -415,7 +423,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
415
423
  }
416
424
  });
417
425
  if (!matchingSession) {
418
- strapi2.log.warn("[magic-sessionmanager] 🚫 Blocked refresh token request - no active session");
426
+ strapi2.log.warn("[magic-sessionmanager] [BLOCKED] Blocked refresh token request - no active session");
419
427
  ctx.status = 401;
420
428
  ctx.body = {
421
429
  error: {
@@ -426,7 +434,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
426
434
  };
427
435
  return;
428
436
  }
429
- strapi2.log.info(`[magic-sessionmanager] Refresh token allowed for session ${matchingSession.id}`);
437
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Refresh token allowed for session ${matchingSession.documentId}`);
430
438
  }
431
439
  } catch (err) {
432
440
  strapi2.log.error("[magic-sessionmanager] Error checking refresh token:", err);
@@ -439,7 +447,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
439
447
  const newAccessToken = ctx.body.jwt;
440
448
  const newRefreshToken = ctx.body.refreshToken;
441
449
  if (oldRefreshToken) {
442
- const allSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
450
+ const allSessions = await strapi2.documents(SESSION_UID$2).findMany({
443
451
  filters: {
444
452
  isActive: true
445
453
  }
@@ -456,14 +464,15 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
456
464
  if (matchingSession) {
457
465
  const encryptedToken = newAccessToken ? encryptToken$1(newAccessToken) : matchingSession.token;
458
466
  const encryptedRefreshToken = newRefreshToken ? encryptToken$1(newRefreshToken) : matchingSession.refreshToken;
459
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", matchingSession.id, {
467
+ await strapi2.documents(SESSION_UID$2).update({
468
+ documentId: matchingSession.documentId,
460
469
  data: {
461
470
  token: encryptedToken,
462
471
  refreshToken: encryptedRefreshToken,
463
472
  lastActive: /* @__PURE__ */ new Date()
464
473
  }
465
474
  });
466
- strapi2.log.info(`[magic-sessionmanager] 🔄 Tokens refreshed for session ${matchingSession.id}`);
475
+ strapi2.log.info(`[magic-sessionmanager] [REFRESH] Tokens refreshed for session ${matchingSession.documentId}`);
467
476
  }
468
477
  }
469
478
  } catch (err) {
@@ -471,17 +480,60 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
471
480
  }
472
481
  }
473
482
  });
474
- strapi2.log.info("[magic-sessionmanager] Refresh Token interceptor middleware mounted");
483
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Refresh Token interceptor middleware mounted");
475
484
  strapi2.server.use(
476
485
  lastSeen({ strapi: strapi2, sessionService })
477
486
  );
478
- strapi2.log.info("[magic-sessionmanager] LastSeen middleware mounted");
479
- strapi2.log.info("[magic-sessionmanager] ✅ Bootstrap complete");
480
- strapi2.log.info("[magic-sessionmanager] 🎉 Session Manager ready! Sessions stored in plugin::magic-sessionmanager.session");
487
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] LastSeen middleware mounted");
488
+ await ensureContentApiPermissions(strapi2);
489
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Bootstrap complete");
490
+ strapi2.log.info("[magic-sessionmanager] [READY] Session Manager ready! Sessions stored in plugin::magic-sessionmanager.session");
481
491
  } catch (err) {
482
- strapi2.log.error("[magic-sessionmanager] Bootstrap error:", err);
492
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Bootstrap error:", err);
483
493
  }
484
494
  };
495
+ async function ensureContentApiPermissions(strapi2) {
496
+ try {
497
+ const authenticatedRole = await strapi2.query("plugin::users-permissions.role").findOne({
498
+ where: { type: "authenticated" }
499
+ });
500
+ if (!authenticatedRole) {
501
+ strapi2.log.warn("[magic-sessionmanager] Authenticated role not found - skipping permission setup");
502
+ return;
503
+ }
504
+ const requiredActions = [
505
+ "plugin::magic-sessionmanager.session.logout",
506
+ "plugin::magic-sessionmanager.session.logoutAll",
507
+ "plugin::magic-sessionmanager.session.getOwnSessions",
508
+ "plugin::magic-sessionmanager.session.getUserSessions"
509
+ ];
510
+ const existingPermissions = await strapi2.query("plugin::users-permissions.permission").findMany({
511
+ where: {
512
+ role: authenticatedRole.id,
513
+ action: { $in: requiredActions }
514
+ }
515
+ });
516
+ const existingActions = existingPermissions.map((p) => p.action);
517
+ const missingActions = requiredActions.filter((action) => !existingActions.includes(action));
518
+ if (missingActions.length === 0) {
519
+ strapi2.log.debug("[magic-sessionmanager] Content-API permissions already configured");
520
+ return;
521
+ }
522
+ for (const action of missingActions) {
523
+ await strapi2.query("plugin::users-permissions.permission").create({
524
+ data: {
525
+ action,
526
+ role: authenticatedRole.id
527
+ }
528
+ });
529
+ strapi2.log.info(`[magic-sessionmanager] [PERMISSION] Enabled ${action} for authenticated users`);
530
+ }
531
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Content-API permissions configured for authenticated users");
532
+ } catch (err) {
533
+ strapi2.log.warn("[magic-sessionmanager] Could not auto-configure permissions:", err.message);
534
+ strapi2.log.warn("[magic-sessionmanager] Please manually enable plugin permissions in Settings > Users & Permissions > Roles > Authenticated");
535
+ }
536
+ }
485
537
  var destroy$1 = async ({ strapi: strapi2 }) => {
486
538
  if (strapi2.licenseGuard && strapi2.licenseGuard.pingInterval) {
487
539
  clearInterval(strapi2.licenseGuard.pingInterval);
@@ -491,7 +543,7 @@ var destroy$1 = async ({ strapi: strapi2 }) => {
491
543
  clearInterval(strapi2.sessionManagerIntervals.cleanup);
492
544
  strapi2.log.info("[magic-sessionmanager] 🛑 Session cleanup interval stopped");
493
545
  }
494
- strapi2.log.info("[magic-sessionmanager] Plugin cleanup completed");
546
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] Plugin cleanup completed");
495
547
  };
496
548
  var config$1 = {
497
549
  default: {
@@ -634,13 +686,22 @@ var contentApi$1 = {
634
686
  // ============================================================
635
687
  // SESSION QUERIES
636
688
  // ============================================================
689
+ {
690
+ method: "GET",
691
+ path: "/my-sessions",
692
+ handler: "session.getOwnSessions",
693
+ config: {
694
+ auth: { strategies: ["users-permissions"] },
695
+ description: "Get own sessions (automatically uses authenticated user)"
696
+ }
697
+ },
637
698
  {
638
699
  method: "GET",
639
700
  path: "/user/:userId/sessions",
640
701
  handler: "session.getUserSessions",
641
702
  config: {
642
703
  auth: { strategies: ["users-permissions"] },
643
- description: "Get own sessions (controller validates user can only see own sessions)"
704
+ description: "Get sessions by userId (validates user can only see own sessions)"
644
705
  }
645
706
  }
646
707
  ]
@@ -799,6 +860,8 @@ var routes$1 = {
799
860
  "content-api": contentApi
800
861
  };
801
862
  const { decryptToken: decryptToken$1 } = encryption;
863
+ const SESSION_UID$1 = "plugin::magic-sessionmanager.session";
864
+ const USER_UID$1 = "plugin::users-permissions.user";
802
865
  var session$3 = {
803
866
  /**
804
867
  * Get ALL sessions (active + inactive) - Admin only
@@ -838,6 +901,30 @@ var session$3 = {
838
901
  ctx.throw(500, "Error fetching active sessions");
839
902
  }
840
903
  },
904
+ /**
905
+ * Get own sessions (authenticated user)
906
+ * GET /api/magic-sessionmanager/my-sessions
907
+ * Automatically uses the authenticated user's documentId
908
+ */
909
+ async getOwnSessions(ctx) {
910
+ try {
911
+ const userId = ctx.state.user?.documentId;
912
+ if (!userId) {
913
+ return ctx.throw(401, "Unauthorized");
914
+ }
915
+ const sessionService = strapi.plugin("magic-sessionmanager").service("session");
916
+ const sessions = await sessionService.getUserSessions(userId);
917
+ ctx.body = {
918
+ data: sessions,
919
+ meta: {
920
+ count: sessions.length
921
+ }
922
+ };
923
+ } catch (err) {
924
+ strapi.log.error("[magic-sessionmanager] Error fetching own sessions:", err);
925
+ ctx.throw(500, "Error fetching sessions");
926
+ }
927
+ },
841
928
  /**
842
929
  * Get user's sessions
843
930
  * GET /magic-sessionmanager/user/:userId/sessions (Admin API)
@@ -848,9 +935,9 @@ var session$3 = {
848
935
  try {
849
936
  const { userId } = ctx.params;
850
937
  const isAdminRequest = ctx.state.userAbility || ctx.state.admin;
851
- const requestingUserId = ctx.state.user?.id;
852
- if (!isAdminRequest && requestingUserId && String(requestingUserId) !== String(userId)) {
853
- strapi.log.warn(`[magic-sessionmanager] Security: User ${requestingUserId} tried to access sessions of user ${userId}`);
938
+ const requestingUserDocId = ctx.state.user?.documentId;
939
+ if (!isAdminRequest && requestingUserDocId && String(requestingUserDocId) !== String(userId)) {
940
+ strapi.log.warn(`[magic-sessionmanager] Security: User ${requestingUserDocId} tried to access sessions of user ${userId}`);
854
941
  return ctx.forbidden("You can only access your own sessions");
855
942
  }
856
943
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
@@ -871,15 +958,15 @@ var session$3 = {
871
958
  */
872
959
  async logout(ctx) {
873
960
  try {
874
- const userId = ctx.state.user?.id;
961
+ const userId = ctx.state.user?.documentId;
875
962
  const token = ctx.request.headers.authorization?.replace("Bearer ", "");
876
963
  if (!userId) {
877
964
  return ctx.throw(401, "Unauthorized");
878
965
  }
879
966
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
880
- const sessions = await strapi.entityService.findMany("plugin::magic-sessionmanager.session", {
967
+ const sessions = await strapi.documents(SESSION_UID$1).findMany({
881
968
  filters: {
882
- user: { id: userId },
969
+ user: { documentId: userId },
883
970
  isActive: true
884
971
  }
885
972
  });
@@ -893,8 +980,8 @@ var session$3 = {
893
980
  }
894
981
  });
895
982
  if (matchingSession) {
896
- await sessionService.terminateSession({ sessionId: matchingSession.id });
897
- strapi.log.info(`[magic-sessionmanager] User ${userId} logged out (session ${matchingSession.id})`);
983
+ await sessionService.terminateSession({ sessionId: matchingSession.documentId });
984
+ strapi.log.info(`[magic-sessionmanager] User ${userId} logged out (session ${matchingSession.documentId})`);
898
985
  }
899
986
  ctx.body = {
900
987
  message: "Logged out successfully"
@@ -910,7 +997,7 @@ var session$3 = {
910
997
  */
911
998
  async logoutAll(ctx) {
912
999
  try {
913
- const userId = ctx.state.user?.id;
1000
+ const userId = ctx.state.user?.documentId;
914
1001
  if (!userId) {
915
1002
  return ctx.throw(401, "Unauthorized");
916
1003
  }
@@ -1050,23 +1137,34 @@ var session$3 = {
1050
1137
  /**
1051
1138
  * Toggle user blocked status
1052
1139
  * POST /magic-sessionmanager/user/:userId/toggle-block
1140
+ * Supports both numeric id (from Content Manager) and documentId
1053
1141
  */
1054
1142
  async toggleUserBlock(ctx) {
1055
1143
  try {
1056
1144
  const { userId } = ctx.params;
1057
- const user = await strapi.entityService.findOne("plugin::users-permissions.user", userId);
1145
+ let userDocumentId = userId;
1146
+ let user = null;
1147
+ user = await strapi.documents(USER_UID$1).findOne({ documentId: userId });
1148
+ if (!user && !isNaN(userId)) {
1149
+ const numericUser = await strapi.entityService.findOne(USER_UID$1, parseInt(userId, 10));
1150
+ if (numericUser) {
1151
+ userDocumentId = numericUser.documentId;
1152
+ user = numericUser;
1153
+ }
1154
+ }
1058
1155
  if (!user) {
1059
1156
  return ctx.throw(404, "User not found");
1060
1157
  }
1061
1158
  const newBlockedStatus = !user.blocked;
1062
- await strapi.entityService.update("plugin::users-permissions.user", userId, {
1159
+ await strapi.documents(USER_UID$1).update({
1160
+ documentId: userDocumentId,
1063
1161
  data: {
1064
1162
  blocked: newBlockedStatus
1065
1163
  }
1066
1164
  });
1067
1165
  if (newBlockedStatus) {
1068
1166
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
1069
- await sessionService.terminateSession({ userId });
1167
+ await sessionService.terminateSession({ userId: userDocumentId });
1070
1168
  }
1071
1169
  ctx.body = {
1072
1170
  message: `User ${newBlockedStatus ? "blocked" : "unblocked"} successfully`,
@@ -1253,16 +1351,16 @@ var license$1 = ({ strapi: strapi2 }) => ({
1253
1351
  const licenseGuard2 = strapi2.plugin("magic-sessionmanager").service("license-guard");
1254
1352
  const verification = await licenseGuard2.verifyLicense(trimmedKey);
1255
1353
  if (!verification.valid) {
1256
- strapi2.log.warn(`[magic-sessionmanager] ⚠️ Invalid license key attempted: ${trimmedKey.substring(0, 8)}...`);
1354
+ strapi2.log.warn(`[magic-sessionmanager] [WARNING] Invalid license key attempted: ${trimmedKey.substring(0, 8)}...`);
1257
1355
  return ctx.badRequest("Invalid or expired license key");
1258
1356
  }
1259
1357
  const license2 = await licenseGuard2.getLicenseByKey(trimmedKey);
1260
1358
  if (!license2) {
1261
- strapi2.log.warn(`[magic-sessionmanager] ⚠️ License not found in database: ${trimmedKey.substring(0, 8)}...`);
1359
+ strapi2.log.warn(`[magic-sessionmanager] [WARNING] License not found in database: ${trimmedKey.substring(0, 8)}...`);
1262
1360
  return ctx.badRequest("License not found");
1263
1361
  }
1264
1362
  if (license2.email.toLowerCase() !== trimmedEmail) {
1265
- strapi2.log.warn(`[magic-sessionmanager] ⚠️ Email mismatch for license key: ${trimmedKey.substring(0, 8)}... (Attempted: ${trimmedEmail})`);
1363
+ strapi2.log.warn(`[magic-sessionmanager] [WARNING] Email mismatch for license key: ${trimmedKey.substring(0, 8)}... (Attempted: ${trimmedEmail})`);
1266
1364
  return ctx.badRequest("Email address does not match this license key");
1267
1365
  }
1268
1366
  await licenseGuard2.storeLicenseKey(trimmedKey);
@@ -1272,7 +1370,7 @@ var license$1 = ({ strapi: strapi2 }) => ({
1272
1370
  pingInterval,
1273
1371
  data: verification.data
1274
1372
  };
1275
- strapi2.log.info(`[magic-sessionmanager] Existing license key validated and stored: ${trimmedKey.substring(0, 8)}... (Email: ${trimmedEmail})`);
1373
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Existing license key validated and stored: ${trimmedKey.substring(0, 8)}... (Email: ${trimmedEmail})`);
1276
1374
  return ctx.send({
1277
1375
  success: true,
1278
1376
  message: "License key validated and activated successfully",
@@ -1394,6 +1492,8 @@ var controllers$1 = {
1394
1492
  settings
1395
1493
  };
1396
1494
  const { encryptToken, decryptToken, generateSessionId } = encryption;
1495
+ const SESSION_UID = "plugin::magic-sessionmanager.session";
1496
+ const USER_UID = "plugin::users-permissions.user";
1397
1497
  var session$1 = ({ strapi: strapi2 }) => ({
1398
1498
  /**
1399
1499
  * Create a new session record
@@ -1406,23 +1506,24 @@ var session$1 = ({ strapi: strapi2 }) => ({
1406
1506
  const sessionId = generateSessionId(userId);
1407
1507
  const encryptedToken = token ? encryptToken(token) : null;
1408
1508
  const encryptedRefreshToken = refreshToken ? encryptToken(refreshToken) : null;
1409
- const session2 = await strapi2.entityService.create("plugin::magic-sessionmanager.session", {
1509
+ const session2 = await strapi2.documents(SESSION_UID).create({
1410
1510
  data: {
1411
1511
  user: userId,
1512
+ // userId should be documentId (string)
1412
1513
  ipAddress: ip.substring(0, 45),
1413
1514
  userAgent: userAgent.substring(0, 500),
1414
1515
  loginTime: now,
1415
1516
  lastActive: now,
1416
1517
  isActive: true,
1417
1518
  token: encryptedToken,
1418
- // Encrypted Access Token
1519
+ // [SUCCESS] Encrypted Access Token
1419
1520
  refreshToken: encryptedRefreshToken,
1420
- // Encrypted Refresh Token
1521
+ // [SUCCESS] Encrypted Refresh Token
1421
1522
  sessionId
1422
- // Unique identifier
1523
+ // [SUCCESS] Unique identifier
1423
1524
  }
1424
1525
  });
1425
- strapi2.log.info(`[magic-sessionmanager] Session ${session2.id} (${sessionId}) created for user ${userId}`);
1526
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session ${session2.documentId} (${sessionId}) created for user ${userId}`);
1426
1527
  return session2;
1427
1528
  } catch (err) {
1428
1529
  strapi2.log.error("[magic-sessionmanager] Error creating session:", err);
@@ -1431,6 +1532,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1431
1532
  },
1432
1533
  /**
1433
1534
  * Terminate a session or all sessions for a user
1535
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1434
1536
  * @param {Object} params - { sessionId | userId }
1435
1537
  * @returns {Promise<void>}
1436
1538
  */
@@ -1438,7 +1540,8 @@ var session$1 = ({ strapi: strapi2 }) => ({
1438
1540
  try {
1439
1541
  const now = /* @__PURE__ */ new Date();
1440
1542
  if (sessionId) {
1441
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", sessionId, {
1543
+ await strapi2.documents(SESSION_UID).update({
1544
+ documentId: sessionId,
1442
1545
  data: {
1443
1546
  isActive: false,
1444
1547
  logoutTime: now
@@ -1446,21 +1549,30 @@ var session$1 = ({ strapi: strapi2 }) => ({
1446
1549
  });
1447
1550
  strapi2.log.info(`[magic-sessionmanager] Session ${sessionId} terminated`);
1448
1551
  } else if (userId) {
1449
- const activeSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1552
+ let userDocumentId = userId;
1553
+ if (!isNaN(userId)) {
1554
+ const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1555
+ if (user) {
1556
+ userDocumentId = user.documentId;
1557
+ }
1558
+ }
1559
+ const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1450
1560
  filters: {
1451
- user: { id: userId },
1561
+ user: { documentId: userDocumentId },
1562
+ // Deep filtering syntax
1452
1563
  isActive: true
1453
1564
  }
1454
1565
  });
1455
1566
  for (const session2 of activeSessions) {
1456
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", session2.id, {
1567
+ await strapi2.documents(SESSION_UID).update({
1568
+ documentId: session2.documentId,
1457
1569
  data: {
1458
1570
  isActive: false,
1459
1571
  logoutTime: now
1460
1572
  }
1461
1573
  });
1462
1574
  }
1463
- strapi2.log.info(`[magic-sessionmanager] All sessions terminated for user ${userId}`);
1575
+ strapi2.log.info(`[magic-sessionmanager] All sessions terminated for user ${userDocumentId}`);
1464
1576
  }
1465
1577
  } catch (err) {
1466
1578
  strapi2.log.error("[magic-sessionmanager] Error terminating session:", err);
@@ -1473,7 +1585,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1473
1585
  */
1474
1586
  async getAllSessions() {
1475
1587
  try {
1476
- const sessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1588
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1477
1589
  populate: { user: { fields: ["id", "email", "username"] } },
1478
1590
  sort: { loginTime: "desc" },
1479
1591
  limit: 1e3
@@ -1505,7 +1617,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1505
1617
  */
1506
1618
  async getActiveSessions() {
1507
1619
  try {
1508
- const sessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1620
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1509
1621
  filters: { isActive: true },
1510
1622
  populate: { user: { fields: ["id", "email", "username"] } },
1511
1623
  sort: { loginTime: "desc" }
@@ -1532,13 +1644,21 @@ var session$1 = ({ strapi: strapi2 }) => ({
1532
1644
  },
1533
1645
  /**
1534
1646
  * Get all sessions for a specific user
1535
- * @param {number} userId
1647
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1648
+ * @param {string|number} userId - User documentId or numeric id
1536
1649
  * @returns {Promise<Array>} User's sessions with accurate online status
1537
1650
  */
1538
1651
  async getUserSessions(userId) {
1539
1652
  try {
1540
- const sessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1541
- filters: { user: { id: userId } },
1653
+ let userDocumentId = userId;
1654
+ if (!isNaN(userId)) {
1655
+ const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1656
+ if (user) {
1657
+ userDocumentId = user.documentId;
1658
+ }
1659
+ }
1660
+ const sessions = await strapi2.documents(SESSION_UID).findMany({
1661
+ filters: { user: { documentId: userDocumentId } },
1542
1662
  sort: { loginTime: "desc" }
1543
1663
  });
1544
1664
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
@@ -1572,17 +1692,19 @@ var session$1 = ({ strapi: strapi2 }) => ({
1572
1692
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
1573
1693
  const rateLimit = config2.lastSeenRateLimit || 3e4;
1574
1694
  if (sessionId) {
1575
- const session2 = await strapi2.entityService.findOne("plugin::magic-sessionmanager.session", sessionId);
1695
+ const session2 = await strapi2.documents(SESSION_UID).findOne({ documentId: sessionId });
1576
1696
  if (session2 && session2.lastActive) {
1577
1697
  const lastActiveTime = new Date(session2.lastActive).getTime();
1578
1698
  const currentTime = now.getTime();
1579
1699
  if (currentTime - lastActiveTime > rateLimit) {
1580
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", sessionId, {
1700
+ await strapi2.documents(SESSION_UID).update({
1701
+ documentId: sessionId,
1581
1702
  data: { lastActive: now }
1582
1703
  });
1583
1704
  }
1584
1705
  } else if (session2) {
1585
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", sessionId, {
1706
+ await strapi2.documents(SESSION_UID).update({
1707
+ documentId: sessionId,
1586
1708
  data: { lastActive: now }
1587
1709
  });
1588
1710
  }
@@ -1601,22 +1723,23 @@ var session$1 = ({ strapi: strapi2 }) => ({
1601
1723
  const inactivityTimeout = config2.inactivityTimeout || 15 * 60 * 1e3;
1602
1724
  const now = /* @__PURE__ */ new Date();
1603
1725
  const cutoffTime = new Date(now.getTime() - inactivityTimeout);
1604
- strapi2.log.info(`[magic-sessionmanager] 🧹 Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
1605
- const activeSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1726
+ strapi2.log.info(`[magic-sessionmanager] [CLEANUP] Cleaning up sessions inactive since before ${cutoffTime.toISOString()}`);
1727
+ const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1606
1728
  filters: { isActive: true },
1607
- fields: ["id", "lastActive", "loginTime"]
1729
+ fields: ["lastActive", "loginTime"]
1608
1730
  });
1609
1731
  let deactivatedCount = 0;
1610
1732
  for (const session2 of activeSessions) {
1611
1733
  const lastActiveTime = session2.lastActive ? new Date(session2.lastActive) : new Date(session2.loginTime);
1612
1734
  if (lastActiveTime < cutoffTime) {
1613
- await strapi2.entityService.update("plugin::magic-sessionmanager.session", session2.id, {
1735
+ await strapi2.documents(SESSION_UID).update({
1736
+ documentId: session2.documentId,
1614
1737
  data: { isActive: false }
1615
1738
  });
1616
1739
  deactivatedCount++;
1617
1740
  }
1618
1741
  }
1619
- strapi2.log.info(`[magic-sessionmanager] Cleanup complete: ${deactivatedCount} sessions deactivated`);
1742
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Cleanup complete: ${deactivatedCount} sessions deactivated`);
1620
1743
  return deactivatedCount;
1621
1744
  } catch (err) {
1622
1745
  strapi2.log.error("[magic-sessionmanager] Error cleaning up inactive sessions:", err);
@@ -1631,8 +1754,8 @@ var session$1 = ({ strapi: strapi2 }) => ({
1631
1754
  */
1632
1755
  async deleteSession(sessionId) {
1633
1756
  try {
1634
- await strapi2.entityService.delete("plugin::magic-sessionmanager.session", sessionId);
1635
- strapi2.log.info(`[magic-sessionmanager] 🗑️ Session ${sessionId} permanently deleted`);
1757
+ await strapi2.documents(SESSION_UID).delete({ documentId: sessionId });
1758
+ strapi2.log.info(`[magic-sessionmanager] [DELETE] Session ${sessionId} permanently deleted`);
1636
1759
  return true;
1637
1760
  } catch (err) {
1638
1761
  strapi2.log.error("[magic-sessionmanager] Error deleting session:", err);
@@ -1646,17 +1769,16 @@ var session$1 = ({ strapi: strapi2 }) => ({
1646
1769
  */
1647
1770
  async deleteInactiveSessions() {
1648
1771
  try {
1649
- strapi2.log.info("[magic-sessionmanager] 🗑️ Deleting all inactive sessions...");
1650
- const inactiveSessions = await strapi2.entityService.findMany("plugin::magic-sessionmanager.session", {
1651
- filters: { isActive: false },
1652
- fields: ["id"]
1772
+ strapi2.log.info("[magic-sessionmanager] [DELETE] Deleting all inactive sessions...");
1773
+ const inactiveSessions = await strapi2.documents(SESSION_UID).findMany({
1774
+ filters: { isActive: false }
1653
1775
  });
1654
1776
  let deletedCount = 0;
1655
1777
  for (const session2 of inactiveSessions) {
1656
- await strapi2.entityService.delete("plugin::magic-sessionmanager.session", session2.id);
1778
+ await strapi2.documents(SESSION_UID).delete({ documentId: session2.documentId });
1657
1779
  deletedCount++;
1658
1780
  }
1659
- strapi2.log.info(`[magic-sessionmanager] Deleted ${deletedCount} inactive sessions`);
1781
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Deleted ${deletedCount} inactive sessions`);
1660
1782
  return deletedCount;
1661
1783
  } catch (err) {
1662
1784
  strapi2.log.error("[magic-sessionmanager] Error deleting inactive sessions:", err);
@@ -1664,8 +1786,13 @@ var session$1 = ({ strapi: strapi2 }) => ({
1664
1786
  }
1665
1787
  }
1666
1788
  });
1789
+ const version = "4.0.0";
1790
+ const require$$2 = {
1791
+ version
1792
+ };
1667
1793
  const crypto = require$$0$1;
1668
1794
  const os = require$$1;
1795
+ const pluginPkg = require$$2;
1669
1796
  const LICENSE_SERVER_URL = "https://magicapi.fitlex.me";
1670
1797
  var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1671
1798
  /**
@@ -1720,7 +1847,9 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1720
1847
  }
1721
1848
  },
1722
1849
  getUserAgent() {
1723
- return `Strapi/${strapi2.config.get("info.strapi") || "5.0.0"} Node/${process.version} ${os.platform()}/${os.release()}`;
1850
+ const pluginVersion = pluginPkg.version;
1851
+ const strapiVersion = strapi2.config.get("info.strapi") || "5.0.0";
1852
+ return `MagicSessionManager/${pluginVersion} Strapi/${strapiVersion} Node/${process.version} ${os.platform()}/${os.release()}`;
1724
1853
  },
1725
1854
  async createLicense({ email, firstName, lastName }) {
1726
1855
  try {
@@ -1746,14 +1875,14 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1746
1875
  });
1747
1876
  const data = await response.json();
1748
1877
  if (data.success) {
1749
- strapi2.log.info("[magic-sessionmanager] License created:", data.data.licenseKey);
1878
+ strapi2.log.info("[magic-sessionmanager] [SUCCESS] License created:", data.data.licenseKey);
1750
1879
  return data.data;
1751
1880
  } else {
1752
- strapi2.log.error("[magic-sessionmanager] License creation failed:", data);
1881
+ strapi2.log.error("[magic-sessionmanager] [ERROR] License creation failed:", data);
1753
1882
  return null;
1754
1883
  }
1755
1884
  } catch (error) {
1756
- strapi2.log.error("[magic-sessionmanager] Error creating license:", error);
1885
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Error creating license:", error);
1757
1886
  return null;
1758
1887
  }
1759
1888
  },
@@ -1838,10 +1967,10 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1838
1967
  name: "magic-sessionmanager"
1839
1968
  });
1840
1969
  await pluginStore.set({ key: "licenseKey", value: licenseKey });
1841
- strapi2.log.info(`[magic-sessionmanager] License key stored: ${licenseKey.substring(0, 8)}...`);
1970
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] License key stored: ${licenseKey.substring(0, 8)}...`);
1842
1971
  },
1843
1972
  startPinging(licenseKey, intervalMinutes = 15) {
1844
- strapi2.log.info(`[magic-sessionmanager] Starting license pings every ${intervalMinutes} minutes`);
1973
+ strapi2.log.info(`[magic-sessionmanager] [TIME] Starting license pings every ${intervalMinutes} minutes`);
1845
1974
  this.pingLicense(licenseKey);
1846
1975
  const interval = setInterval(async () => {
1847
1976
  try {
@@ -1858,14 +1987,14 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1858
1987
  */
1859
1988
  async initialize() {
1860
1989
  try {
1861
- strapi2.log.info("[magic-sessionmanager] 🔐 Initializing License Guard...");
1990
+ strapi2.log.info("[magic-sessionmanager] [SECURE] Initializing License Guard...");
1862
1991
  const pluginStore = strapi2.store({
1863
1992
  type: "plugin",
1864
1993
  name: "magic-sessionmanager"
1865
1994
  });
1866
1995
  const licenseKey = await pluginStore.get({ key: "licenseKey" });
1867
1996
  if (!licenseKey) {
1868
- strapi2.log.info("[magic-sessionmanager] ℹ️ No license found - Running in demo mode");
1997
+ strapi2.log.info("[magic-sessionmanager] [INFO] No license found - Running in demo mode");
1869
1998
  return {
1870
1999
  valid: false,
1871
2000
  demo: true,
@@ -1900,7 +2029,7 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1900
2029
  gracePeriod: verification.gracePeriod || false
1901
2030
  };
1902
2031
  } else {
1903
- strapi2.log.error("[magic-sessionmanager] License validation failed");
2032
+ strapi2.log.error("[magic-sessionmanager] [ERROR] License validation failed");
1904
2033
  return {
1905
2034
  valid: false,
1906
2035
  demo: true,
@@ -1909,7 +2038,7 @@ var licenseGuard$1 = ({ strapi: strapi2 }) => ({
1909
2038
  };
1910
2039
  }
1911
2040
  } catch (error) {
1912
- strapi2.log.error("[magic-sessionmanager] Error initializing License Guard:", error);
2041
+ strapi2.log.error("[magic-sessionmanager] [ERROR] Error initializing License Guard:", error);
1913
2042
  return {
1914
2043
  valid: false,
1915
2044
  demo: true,
@@ -2022,9 +2151,11 @@ var geolocation$1 = ({ strapi: strapi2 }) => ({
2022
2151
  },
2023
2152
  /**
2024
2153
  * Get country flag emoji
2154
+ * @param {string} countryCode - ISO 2-letter country code
2155
+ * @returns {string} Flag emoji or empty string
2025
2156
  */
2026
2157
  getCountryFlag(countryCode) {
2027
- if (!countryCode) return "🏳️";
2158
+ if (!countryCode) return "";
2028
2159
  const codePoints = countryCode.toUpperCase().split("").map((char) => 127397 + char.charCodeAt());
2029
2160
  return String.fromCodePoint(...codePoints);
2030
2161
  },
@@ -2036,7 +2167,7 @@ var geolocation$1 = ({ strapi: strapi2 }) => ({
2036
2167
  ip: ipAddress,
2037
2168
  country: "Unknown",
2038
2169
  country_code: "XX",
2039
- country_flag: "🌍",
2170
+ country_flag: "[GEO]",
2040
2171
  city: "Unknown",
2041
2172
  region: "Unknown",
2042
2173
  timezone: "Unknown",
@@ -2086,12 +2217,12 @@ var notifications$1 = ({ strapi: strapi2 }) => ({
2086
2217
  strapi2.log.debug("[magic-sessionmanager/notifications] Using default fallback templates");
2087
2218
  return {
2088
2219
  suspiciousLogin: {
2089
- subject: "🚨 Suspicious Login Alert - Session Manager",
2220
+ subject: "[ALERT] Suspicious Login Alert - Session Manager",
2090
2221
  html: `
2091
2222
  <html>
2092
2223
  <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
2093
2224
  <div style="max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9fafb; border-radius: 10px;">
2094
- <h2 style="color: #dc2626;">🚨 Suspicious Login Detected</h2>
2225
+ <h2 style="color: #dc2626;">[ALERT] Suspicious Login Detected</h2>
2095
2226
  <p>A potentially suspicious login was detected for your account.</p>
2096
2227
 
2097
2228
  <div style="background: white; padding: 15px; border-radius: 8px; margin: 20px 0;">
@@ -2126,7 +2257,7 @@ var notifications$1 = ({ strapi: strapi2 }) => ({
2126
2257
  </div>
2127
2258
  </body>
2128
2259
  </html>`,
2129
- text: `🚨 Suspicious Login Detected
2260
+ text: `[ALERT] Suspicious Login Detected
2130
2261
 
2131
2262
  A potentially suspicious login was detected for your account.
2132
2263
 
@@ -2141,9 +2272,9 @@ Login Details:
2141
2272
  Security: VPN={{reason.isVpn}}, Proxy={{reason.isProxy}}, Threat={{reason.isThreat}}, Score={{reason.securityScore}}/100`
2142
2273
  },
2143
2274
  newLocation: {
2144
- subject: "📍 New Location Login Detected",
2145
- 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>`,
2146
- text: `📍 New Location Login
2275
+ subject: "[LOCATION] New Location Login Detected",
2276
+ 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>`,
2277
+ text: `[LOCATION] New Location Login
2147
2278
 
2148
2279
  Account: {{user.email}}
2149
2280
  Time: {{session.loginTime}}
@@ -2151,9 +2282,9 @@ Location: {{geo.city}}, {{geo.country}}
2151
2282
  IP: {{session.ipAddress}}`
2152
2283
  },
2153
2284
  vpnProxy: {
2154
- subject: "⚠️ VPN/Proxy Login Detected",
2155
- 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>`,
2156
- text: `⚠️ VPN/Proxy Detected
2285
+ subject: "[WARNING] VPN/Proxy Login Detected",
2286
+ 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>`,
2287
+ text: `[WARNING] VPN/Proxy Detected
2157
2288
 
2158
2289
  Account: {{user.email}}
2159
2290
  Time: {{session.loginTime}}
@@ -2297,17 +2428,17 @@ VPN: {{reason.isVpn}}, Proxy: {{reason.isProxy}}`
2297
2428
  title: this.getEventTitle(event),
2298
2429
  color: this.getEventColor(event),
2299
2430
  fields: [
2300
- { name: "👤 User", value: `${user.email}
2431
+ { name: "User", value: `${user.email}
2301
2432
  ${user.username || "N/A"}`, inline: true },
2302
- { name: "🌐 IP", value: session2.ipAddress, inline: true },
2303
- { name: "📅 Time", value: new Date(session2.loginTime).toLocaleString(), inline: false }
2433
+ { name: "IP", value: session2.ipAddress, inline: true },
2434
+ { name: "Time", value: new Date(session2.loginTime).toLocaleString(), inline: false }
2304
2435
  ],
2305
2436
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2306
2437
  footer: { text: "Magic Session Manager" }
2307
2438
  };
2308
2439
  if (geoData) {
2309
2440
  embed.fields.push({
2310
- name: "📍 Location",
2441
+ name: "[LOCATION] Location",
2311
2442
  value: `${geoData.country_flag} ${geoData.city}, ${geoData.country}`,
2312
2443
  inline: true
2313
2444
  });
@@ -2317,7 +2448,7 @@ ${user.username || "N/A"}`, inline: true },
2317
2448
  if (geoData.isProxy) warnings.push("Proxy");
2318
2449
  if (geoData.isThreat) warnings.push("Threat");
2319
2450
  embed.fields.push({
2320
- name: "⚠️ Security",
2451
+ name: "[WARNING] Security",
2321
2452
  value: `${warnings.join(", ")} detected
2322
2453
  Score: ${geoData.securityScore}/100`,
2323
2454
  inline: true
@@ -2328,13 +2459,13 @@ Score: ${geoData.securityScore}/100`,
2328
2459
  },
2329
2460
  getEventTitle(event) {
2330
2461
  const titles = {
2331
- "login.suspicious": "🚨 Suspicious Login",
2332
- "login.new_location": "📍 New Location Login",
2333
- "login.vpn": "🔴 VPN Login Detected",
2334
- "login.threat": " Threat IP Login",
2335
- "session.terminated": "🔴 Session Terminated"
2462
+ "login.suspicious": "[ALERT] Suspicious Login",
2463
+ "login.new_location": "[LOCATION] New Location Login",
2464
+ "login.vpn": "[WARNING] VPN Login Detected",
2465
+ "login.threat": "[THREAT] Threat IP Login",
2466
+ "session.terminated": "[INFO] Session Terminated"
2336
2467
  };
2337
- return titles[event] || "📊 Session Event";
2468
+ return titles[event] || "[STATS] Session Event";
2338
2469
  },
2339
2470
  getEventColor(event) {
2340
2471
  const colors = {