strapi-plugin-magic-sessionmanager 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +2 -2
  2. package/admin/src/components/LicenseGuard.jsx +6 -6
  3. package/admin/src/components/OnlineUsersWidget.jsx +11 -7
  4. package/admin/src/components/SessionDetailModal.jsx +45 -41
  5. package/admin/src/components/SessionInfoCard.jsx +3 -3
  6. package/admin/src/components/SessionInfoPanel.jsx +31 -21
  7. package/admin/src/index.js +9 -0
  8. package/admin/src/pages/Analytics.jsx +2 -2
  9. package/admin/src/pages/HomePage.jsx +129 -165
  10. package/admin/src/pages/License.jsx +5 -5
  11. package/admin/src/pages/Settings.jsx +148 -144
  12. package/admin/src/pages/SettingsNew.jsx +21 -21
  13. package/admin/src/pages/UpgradePage.jsx +448 -0
  14. package/admin/src/pluginId.js +1 -0
  15. package/admin/src/translations/de.json +294 -15
  16. package/admin/src/translations/en.json +293 -14
  17. package/admin/src/translations/es.json +284 -18
  18. package/admin/src/translations/fr.json +284 -18
  19. package/admin/src/translations/pt.json +284 -18
  20. package/admin/src/utils/parseUserAgent.js +6 -6
  21. package/admin/src/utils/theme.js +85 -0
  22. package/dist/_chunks/{Analytics-mYu_uGwU.mjs → Analytics-DTE_zmRV.mjs} +4 -4
  23. package/dist/_chunks/{Analytics-ioaeEh-E.js → Analytics-lw_JaOVy.js} +4 -4
  24. package/dist/_chunks/{App-DdnUYWbC.js → App-DDKYCjKw.js} +221 -216
  25. package/dist/_chunks/{App-BXpIS12l.mjs → App-DJW1ZNl5.mjs} +221 -216
  26. package/dist/_chunks/{License-C03C2j9P.mjs → License-DaOFuImm.mjs} +6 -10
  27. package/dist/_chunks/{License-DZYrOgcx.js → License-Tk-6UfPl.js} +6 -10
  28. package/dist/_chunks/{OnlineUsersWidget-B8JS1xZu.js → OnlineUsersWidget-C1qTpsws.js} +11 -7
  29. package/dist/_chunks/{OnlineUsersWidget-ArMl0nen.mjs → OnlineUsersWidget-CADphbXG.mjs} +11 -7
  30. package/dist/_chunks/{Settings-0ocB3qHk.mjs → Settings-C9xvckgq.mjs} +200 -188
  31. package/dist/_chunks/{Settings-C6_CqpCC.js → Settings-DyEAuTNQ.js} +200 -188
  32. package/dist/_chunks/UpgradePage-Dssk8A0Z.js +354 -0
  33. package/dist/_chunks/UpgradePage-cINvE9zY.mjs +352 -0
  34. package/dist/_chunks/de-CDA1V0rF.mjs +292 -0
  35. package/dist/_chunks/de-I-Q-pWqu.js +292 -0
  36. package/dist/_chunks/en-Bd7_h-4e.js +292 -0
  37. package/dist/_chunks/en-DzmOCyzQ.mjs +292 -0
  38. package/dist/_chunks/es-BcAx18XG.js +277 -0
  39. package/dist/_chunks/es-Cx-SN6qV.mjs +277 -0
  40. package/dist/_chunks/fr-DCzYMuJ-.js +277 -0
  41. package/dist/_chunks/fr-DXlXE5Eo.mjs +277 -0
  42. package/dist/_chunks/{index-DC8Y0qxx.js → index-CWcvrfXc.js} +52 -49
  43. package/dist/_chunks/{index-DBRS3kt5.mjs → index-DQO9bNP7.mjs} +52 -49
  44. package/dist/_chunks/pt-21-MAb72.js +277 -0
  45. package/dist/_chunks/pt-zsdTSjba.mjs +277 -0
  46. package/dist/_chunks/{useLicense-qgGfMvse.js → useLicense-DtvJOszr.js} +1 -1
  47. package/dist/_chunks/{useLicense-DSLL9n3Y.mjs → useLicense-DxbD4Wf8.mjs} +1 -1
  48. package/dist/admin/index.js +1 -1
  49. package/dist/admin/index.mjs +1 -1
  50. package/dist/server/index.js +142 -33
  51. package/dist/server/index.mjs +142 -33
  52. package/package.json +1 -1
  53. package/server/src/bootstrap.js +76 -4
  54. package/server/src/controllers/session.js +59 -9
  55. package/server/src/middlewares/last-seen.js +5 -4
  56. package/server/src/routes/content-api.js +11 -2
  57. package/server/src/services/notifications.js +10 -10
  58. package/server/src/services/session.js +24 -4
  59. package/dist/_chunks/de-BxFx1pwE.js +0 -23
  60. package/dist/_chunks/de-CdO3s01z.mjs +0 -23
  61. package/dist/_chunks/en-CsPpPJL3.mjs +0 -23
  62. package/dist/_chunks/en-RqmpDHdS.js +0 -23
  63. package/dist/_chunks/es-CuLHazN1.js +0 -23
  64. package/dist/_chunks/es-Dkmjhy9c.mjs +0 -23
  65. package/dist/_chunks/fr-BAJp2yhI.js +0 -23
  66. package/dist/_chunks/fr-Bssg_3UF.mjs +0 -23
  67. package/dist/_chunks/pt-BAP9cKs3.js +0 -23
  68. package/dist/_chunks/pt-BVNoNcuY.mjs +0 -23
@@ -152,9 +152,9 @@ var encryption = {
152
152
  const SESSION_UID$3 = "plugin::magic-sessionmanager.session";
153
153
  var lastSeen = ({ strapi: strapi2, sessionService }) => {
154
154
  return async (ctx, next) => {
155
- if (ctx.state.user && ctx.state.user.id) {
155
+ if (ctx.state.user && ctx.state.user.documentId) {
156
156
  try {
157
- const userId = ctx.state.user.id;
157
+ const userId = ctx.state.user.documentId;
158
158
  const activeSessions = await strapi2.documents(SESSION_UID$3).findMany({
159
159
  filters: {
160
160
  user: { documentId: userId },
@@ -171,9 +171,9 @@ var lastSeen = ({ strapi: strapi2, sessionService }) => {
171
171
  }
172
172
  }
173
173
  await next();
174
- if (ctx.state.user && ctx.state.user.id) {
174
+ if (ctx.state.user && ctx.state.user.documentId) {
175
175
  try {
176
- const userId = ctx.state.user.id;
176
+ const userId = ctx.state.user.documentId;
177
177
  const sessionId = ctx.state.sessionId;
178
178
  await sessionService.touch({
179
179
  userId,
@@ -188,6 +188,7 @@ var lastSeen = ({ strapi: strapi2, sessionService }) => {
188
188
  const getClientIp = getClientIp_1;
189
189
  const { encryptToken: encryptToken$1, decryptToken: decryptToken$2 } = encryption;
190
190
  const SESSION_UID$2 = "plugin::magic-sessionmanager.session";
191
+ const USER_UID$2 = "plugin::users-permissions.user";
191
192
  var bootstrap$1 = async ({ strapi: strapi2 }) => {
192
193
  strapi2.log.info("[magic-sessionmanager] [START] Bootstrap starting...");
193
194
  try {
@@ -295,7 +296,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
295
296
  const user = ctx.body.user;
296
297
  const ip = getClientIp(ctx);
297
298
  const userAgent = ctx.request.headers?.["user-agent"] || ctx.request.header?.["user-agent"] || "unknown";
298
- strapi2.log.info(`[magic-sessionmanager] [CHECK] 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}`);
299
300
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
300
301
  let shouldBlock = false;
301
302
  let blockReason = "";
@@ -348,8 +349,13 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
348
349
  };
349
350
  return;
350
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
+ }
351
357
  const newSession = await sessionService.createSession({
352
- userId: user.id,
358
+ userId: userDocId,
353
359
  ip,
354
360
  userAgent,
355
361
  token: ctx.body.jwt,
@@ -357,7 +363,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
357
363
  refreshToken: ctx.body.refreshToken
358
364
  // Store Refresh Token (encrypted) if exists
359
365
  });
360
- strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session created for user ${user.id} (IP: ${ip})`);
366
+ strapi2.log.info(`[magic-sessionmanager] [SUCCESS] Session created for user ${userDocId} (IP: ${ip})`);
361
367
  if (geoData && (config2.enableEmailAlerts || config2.enableWebhooks)) {
362
368
  try {
363
369
  const notificationService = strapi2.plugin("magic-sessionmanager").service("notifications");
@@ -483,12 +489,55 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
483
489
  lastSeen({ strapi: strapi2, sessionService })
484
490
  );
485
491
  strapi2.log.info("[magic-sessionmanager] [SUCCESS] LastSeen middleware mounted");
492
+ await ensureContentApiPermissions(strapi2);
486
493
  strapi2.log.info("[magic-sessionmanager] [SUCCESS] Bootstrap complete");
487
494
  strapi2.log.info("[magic-sessionmanager] [READY] Session Manager ready! Sessions stored in plugin::magic-sessionmanager.session");
488
495
  } catch (err) {
489
496
  strapi2.log.error("[magic-sessionmanager] [ERROR] Bootstrap error:", err);
490
497
  }
491
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
+ }
492
541
  var destroy$1 = async ({ strapi: strapi2 }) => {
493
542
  if (strapi2.licenseGuard && strapi2.licenseGuard.pingInterval) {
494
543
  clearInterval(strapi2.licenseGuard.pingInterval);
@@ -641,13 +690,22 @@ var contentApi$1 = {
641
690
  // ============================================================
642
691
  // SESSION QUERIES
643
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
+ },
644
702
  {
645
703
  method: "GET",
646
704
  path: "/user/:userId/sessions",
647
705
  handler: "session.getUserSessions",
648
706
  config: {
649
707
  auth: { strategies: ["users-permissions"] },
650
- 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)"
651
709
  }
652
710
  }
653
711
  ]
@@ -807,7 +865,7 @@ var routes$1 = {
807
865
  };
808
866
  const { decryptToken: decryptToken$1 } = encryption;
809
867
  const SESSION_UID$1 = "plugin::magic-sessionmanager.session";
810
- const USER_UID = "plugin::users-permissions.user";
868
+ const USER_UID$1 = "plugin::users-permissions.user";
811
869
  var session$3 = {
812
870
  /**
813
871
  * Get ALL sessions (active + inactive) - Admin only
@@ -847,6 +905,30 @@ var session$3 = {
847
905
  ctx.throw(500, "Error fetching active sessions");
848
906
  }
849
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
+ },
850
932
  /**
851
933
  * Get user's sessions
852
934
  * GET /magic-sessionmanager/user/:userId/sessions (Admin API)
@@ -857,9 +939,9 @@ var session$3 = {
857
939
  try {
858
940
  const { userId } = ctx.params;
859
941
  const isAdminRequest = ctx.state.userAbility || ctx.state.admin;
860
- const requestingUserId = ctx.state.user?.id;
861
- if (!isAdminRequest && requestingUserId && String(requestingUserId) !== String(userId)) {
862
- 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}`);
863
945
  return ctx.forbidden("You can only access your own sessions");
864
946
  }
865
947
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
@@ -880,7 +962,7 @@ var session$3 = {
880
962
  */
881
963
  async logout(ctx) {
882
964
  try {
883
- const userId = ctx.state.user?.id;
965
+ const userId = ctx.state.user?.documentId;
884
966
  const token = ctx.request.headers.authorization?.replace("Bearer ", "");
885
967
  if (!userId) {
886
968
  return ctx.throw(401, "Unauthorized");
@@ -919,7 +1001,7 @@ var session$3 = {
919
1001
  */
920
1002
  async logoutAll(ctx) {
921
1003
  try {
922
- const userId = ctx.state.user?.id;
1004
+ const userId = ctx.state.user?.documentId;
923
1005
  if (!userId) {
924
1006
  return ctx.throw(401, "Unauthorized");
925
1007
  }
@@ -1059,24 +1141,34 @@ var session$3 = {
1059
1141
  /**
1060
1142
  * Toggle user blocked status
1061
1143
  * POST /magic-sessionmanager/user/:userId/toggle-block
1144
+ * Supports both numeric id (from Content Manager) and documentId
1062
1145
  */
1063
1146
  async toggleUserBlock(ctx) {
1064
1147
  try {
1065
1148
  const { userId } = ctx.params;
1066
- const user = await strapi.documents(USER_UID).findOne({ documentId: 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
+ }
1067
1159
  if (!user) {
1068
1160
  return ctx.throw(404, "User not found");
1069
1161
  }
1070
1162
  const newBlockedStatus = !user.blocked;
1071
- await strapi.documents(USER_UID).update({
1072
- documentId: userId,
1163
+ await strapi.documents(USER_UID$1).update({
1164
+ documentId: userDocumentId,
1073
1165
  data: {
1074
1166
  blocked: newBlockedStatus
1075
1167
  }
1076
1168
  });
1077
1169
  if (newBlockedStatus) {
1078
1170
  const sessionService = strapi.plugin("magic-sessionmanager").service("session");
1079
- await sessionService.terminateSession({ userId });
1171
+ await sessionService.terminateSession({ userId: userDocumentId });
1080
1172
  }
1081
1173
  ctx.body = {
1082
1174
  message: `User ${newBlockedStatus ? "blocked" : "unblocked"} successfully`,
@@ -1405,6 +1497,7 @@ var controllers$1 = {
1405
1497
  };
1406
1498
  const { encryptToken, decryptToken, generateSessionId } = encryption;
1407
1499
  const SESSION_UID = "plugin::magic-sessionmanager.session";
1500
+ const USER_UID = "plugin::users-permissions.user";
1408
1501
  var session$1 = ({ strapi: strapi2 }) => ({
1409
1502
  /**
1410
1503
  * Create a new session record
@@ -1443,6 +1536,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1443
1536
  },
1444
1537
  /**
1445
1538
  * Terminate a session or all sessions for a user
1539
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1446
1540
  * @param {Object} params - { sessionId | userId }
1447
1541
  * @returns {Promise<void>}
1448
1542
  */
@@ -1459,9 +1553,16 @@ var session$1 = ({ strapi: strapi2 }) => ({
1459
1553
  });
1460
1554
  strapi2.log.info(`[magic-sessionmanager] Session ${sessionId} terminated`);
1461
1555
  } else if (userId) {
1556
+ let userDocumentId = userId;
1557
+ if (!isNaN(userId)) {
1558
+ const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1559
+ if (user) {
1560
+ userDocumentId = user.documentId;
1561
+ }
1562
+ }
1462
1563
  const activeSessions = await strapi2.documents(SESSION_UID).findMany({
1463
1564
  filters: {
1464
- user: { documentId: userId },
1565
+ user: { documentId: userDocumentId },
1465
1566
  // Deep filtering syntax
1466
1567
  isActive: true
1467
1568
  }
@@ -1475,7 +1576,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1475
1576
  }
1476
1577
  });
1477
1578
  }
1478
- strapi2.log.info(`[magic-sessionmanager] All sessions terminated for user ${userId}`);
1579
+ strapi2.log.info(`[magic-sessionmanager] All sessions terminated for user ${userDocumentId}`);
1479
1580
  }
1480
1581
  } catch (err) {
1481
1582
  strapi2.log.error("[magic-sessionmanager] Error terminating session:", err);
@@ -1547,13 +1648,21 @@ var session$1 = ({ strapi: strapi2 }) => ({
1547
1648
  },
1548
1649
  /**
1549
1650
  * Get all sessions for a specific user
1550
- * @param {number} userId
1651
+ * Supports both numeric id (legacy) and documentId (Strapi v5)
1652
+ * @param {string|number} userId - User documentId or numeric id
1551
1653
  * @returns {Promise<Array>} User's sessions with accurate online status
1552
1654
  */
1553
1655
  async getUserSessions(userId) {
1554
1656
  try {
1657
+ let userDocumentId = userId;
1658
+ if (!isNaN(userId)) {
1659
+ const user = await strapi2.entityService.findOne(USER_UID, parseInt(userId, 10));
1660
+ if (user) {
1661
+ userDocumentId = user.documentId;
1662
+ }
1663
+ }
1555
1664
  const sessions = await strapi2.documents(SESSION_UID).findMany({
1556
- filters: { user: { documentId: userId } },
1665
+ filters: { user: { documentId: userDocumentId } },
1557
1666
  sort: { loginTime: "desc" }
1558
1667
  });
1559
1668
  const config2 = strapi2.config.get("plugin::magic-sessionmanager") || {};
@@ -1681,7 +1790,7 @@ var session$1 = ({ strapi: strapi2 }) => ({
1681
1790
  }
1682
1791
  }
1683
1792
  });
1684
- const version = "3.7.0";
1793
+ const version = "4.0.1";
1685
1794
  const require$$2 = {
1686
1795
  version
1687
1796
  };
@@ -2112,12 +2221,12 @@ var notifications$1 = ({ strapi: strapi2 }) => ({
2112
2221
  strapi2.log.debug("[magic-sessionmanager/notifications] Using default fallback templates");
2113
2222
  return {
2114
2223
  suspiciousLogin: {
2115
- subject: "🚨 Suspicious Login Alert - Session Manager",
2224
+ subject: "[ALERT] Suspicious Login Alert - Session Manager",
2116
2225
  html: `
2117
2226
  <html>
2118
2227
  <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
2119
2228
  <div style="max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9fafb; border-radius: 10px;">
2120
- <h2 style="color: #dc2626;">🚨 Suspicious Login Detected</h2>
2229
+ <h2 style="color: #dc2626;">[ALERT] Suspicious Login Detected</h2>
2121
2230
  <p>A potentially suspicious login was detected for your account.</p>
2122
2231
 
2123
2232
  <div style="background: white; padding: 15px; border-radius: 8px; margin: 20px 0;">
@@ -2152,7 +2261,7 @@ var notifications$1 = ({ strapi: strapi2 }) => ({
2152
2261
  </div>
2153
2262
  </body>
2154
2263
  </html>`,
2155
- text: `🚨 Suspicious Login Detected
2264
+ text: `[ALERT] Suspicious Login Detected
2156
2265
 
2157
2266
  A potentially suspicious login was detected for your account.
2158
2267
 
@@ -2323,10 +2432,10 @@ VPN: {{reason.isVpn}}, Proxy: {{reason.isProxy}}`
2323
2432
  title: this.getEventTitle(event),
2324
2433
  color: this.getEventColor(event),
2325
2434
  fields: [
2326
- { name: "👤 User", value: `${user.email}
2435
+ { name: "User", value: `${user.email}
2327
2436
  ${user.username || "N/A"}`, inline: true },
2328
- { name: "🌐 IP", value: session2.ipAddress, inline: true },
2329
- { 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 }
2330
2439
  ],
2331
2440
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2332
2441
  footer: { text: "Magic Session Manager" }
@@ -2354,11 +2463,11 @@ Score: ${geoData.securityScore}/100`,
2354
2463
  },
2355
2464
  getEventTitle(event) {
2356
2465
  const titles = {
2357
- "login.suspicious": "🚨 Suspicious Login",
2466
+ "login.suspicious": "[ALERT] Suspicious Login",
2358
2467
  "login.new_location": "[LOCATION] New Location Login",
2359
- "login.vpn": "🔴 VPN Login Detected",
2360
- "login.threat": " Threat IP Login",
2361
- "session.terminated": "🔴 Session Terminated"
2468
+ "login.vpn": "[WARNING] VPN Login Detected",
2469
+ "login.threat": "[THREAT] Threat IP Login",
2470
+ "session.terminated": "[INFO] Session Terminated"
2362
2471
  };
2363
2472
  return titles[event] || "[STATS] Session Event";
2364
2473
  },