strapi-plugin-magic-mail 2.9.0 → 2.9.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.
@@ -1007,6 +1007,10 @@ const attributes = {
1007
1007
  type: "boolean",
1008
1008
  "default": true,
1009
1009
  configurable: false
1010
+ },
1011
+ trackingFallbackUrl: {
1012
+ type: "string",
1013
+ configurable: false
1010
1014
  }
1011
1015
  };
1012
1016
  const require$$7 = {
@@ -48884,7 +48888,11 @@ const schemas = {
48884
48888
  defaultFromName: headerSafe.optional(),
48885
48889
  defaultFromEmail: emailString.optional().or(z2.literal("")),
48886
48890
  unsubscribeUrl: z2.string().url().optional().or(z2.literal("")),
48887
- enableUnsubscribeHeader: z2.boolean().optional()
48891
+ enableUnsubscribeHeader: z2.boolean().optional(),
48892
+ // Where to redirect the recipient when a tracking link is no longer
48893
+ // resolvable (e.g. retention cleanup removed the row). If empty the
48894
+ // tracker renders a static HTML fallback page instead.
48895
+ trackingFallbackUrl: z2.string().url().optional().or(z2.literal(""))
48888
48896
  }),
48889
48897
  // ── Content-API send payloads ───────────────────────────────────────────
48890
48898
  // Bounded attachments to prevent OOM from huge base64 payloads.
@@ -49344,7 +49352,7 @@ var oauthState = {
49344
49352
  verifyAndConsumeState: verifyAndConsumeState$1
49345
49353
  };
49346
49354
  const { createState, verifyAndConsumeState } = oauthState;
49347
- function escapeHtml(str2) {
49355
+ function escapeHtml$1(str2) {
49348
49356
  return String(str2 || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
49349
49357
  }
49350
49358
  function escapeJs(str2) {
@@ -49409,7 +49417,7 @@ var oauth$3 = {
49409
49417
  </head>
49410
49418
  <body>
49411
49419
  <div class="error">[ERROR] OAuth Authorization Failed</div>
49412
- <p>Error: ${escapeHtml(error2)}</p>
49420
+ <p>Error: ${escapeHtml$1(error2)}</p>
49413
49421
  <p>You can close this window and try again.</p>
49414
49422
  <script>
49415
49423
  setTimeout(() => window.close(), 3000);
@@ -49520,7 +49528,7 @@ var oauth$3 = {
49520
49528
  </head>
49521
49529
  <body>
49522
49530
  <div class="error">[ERROR] OAuth Authorization Failed</div>
49523
- <p>Error: ${escapeHtml(error2)}</p>
49531
+ <p>Error: ${escapeHtml$1(error2)}</p>
49524
49532
  <p>You can close this window and try again.</p>
49525
49533
  <script>
49526
49534
  setTimeout(() => window.close(), 3000);
@@ -49628,7 +49636,7 @@ var oauth$3 = {
49628
49636
  </head>
49629
49637
  <body>
49630
49638
  <div class="error">[ERROR] OAuth Authorization Failed</div>
49631
- <p>Error: ${escapeHtml(error2)}</p>
49639
+ <p>Error: ${escapeHtml$1(error2)}</p>
49632
49640
  <p>You can close this window and try again.</p>
49633
49641
  <script>
49634
49642
  setTimeout(() => window.close(), 3000);
@@ -50711,6 +50719,52 @@ var emailDesigner$3 = ({ strapi: strapi2 }) => ({
50711
50719
  const EMAIL_LOG_UID$1 = "plugin::magic-mail.email-log";
50712
50720
  const EMAIL_EVENT_UID$1 = "plugin::magic-mail.email-event";
50713
50721
  const EMAIL_ACCOUNT_UID$1 = "plugin::magic-mail.email-account";
50722
+ const escapeHtml = (value) => String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
50723
+ const renderTrackingFallbackHtml = (reason, fallbackUrl) => {
50724
+ const safeReason = escapeHtml(reason);
50725
+ const safeUrl = fallbackUrl ? escapeHtml(fallbackUrl) : "";
50726
+ const refreshMeta = fallbackUrl ? `<meta http-equiv="refresh" content="3;url=${safeUrl}">` : "";
50727
+ const manualLink = fallbackUrl ? `<p style="margin-top:24px;font-size:14px;color:#6b7280;">
50728
+ You will be redirected in a few seconds. If nothing happens,
50729
+ <a href="${safeUrl}" style="color:#4f46e5;">click here</a>.
50730
+ </p>` : `<p style="margin-top:24px;font-size:14px;color:#6b7280;">
50731
+ You can safely close this tab.
50732
+ </p>`;
50733
+ return `<!doctype html>
50734
+ <html lang="en">
50735
+ <head>
50736
+ <meta charset="utf-8">
50737
+ <meta name="viewport" content="width=device-width,initial-scale=1">
50738
+ ${refreshMeta}
50739
+ <title>Link unavailable</title>
50740
+ <style>
50741
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background:#f9fafb; margin:0; padding:40px 20px; color:#111827; }
50742
+ .card { max-width: 480px; margin: 60px auto; background:#fff; border-radius: 12px; padding: 32px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); text-align:center; }
50743
+ h1 { font-size: 22px; margin: 0 0 12px; }
50744
+ p { font-size: 15px; line-height: 1.5; color:#374151; }
50745
+ </style>
50746
+ </head>
50747
+ <body>
50748
+ <main class="card">
50749
+ <h1>This link is no longer available</h1>
50750
+ <p>${safeReason}</p>
50751
+ ${manualLink}
50752
+ </main>
50753
+ </body>
50754
+ </html>`;
50755
+ };
50756
+ const respondWithTrackingFallback = async (ctx, reason) => {
50757
+ let fallbackUrl = null;
50758
+ try {
50759
+ const settings = await strapi.plugin("magic-mail").service("plugin-settings").getSettings();
50760
+ fallbackUrl = settings?.trackingFallbackUrl || null;
50761
+ } catch (err) {
50762
+ strapi.log.debug(`[magic-mail] Could not load tracking fallback setting: ${err.message}`);
50763
+ }
50764
+ ctx.status = 410;
50765
+ ctx.type = "text/html; charset=utf-8";
50766
+ ctx.body = renderTrackingFallbackHtml(reason, fallbackUrl);
50767
+ };
50714
50768
  var analytics$3 = ({ strapi: strapi2 }) => ({
50715
50769
  /**
50716
50770
  * Tracking pixel endpoint
@@ -50731,7 +50785,18 @@ var analytics$3 = ({ strapi: strapi2 }) => ({
50731
50785
  ctx.body = pixel;
50732
50786
  },
50733
50787
  /**
50734
- * Click tracking endpoint with open-redirect protection
50788
+ * Click tracking endpoint with open-redirect protection.
50789
+ *
50790
+ * Resolves the destination URL exclusively from the database — never
50791
+ * from query parameters — so the endpoint cannot be used as an open
50792
+ * redirect. When the URL is no longer resolvable (retention cleanup
50793
+ * deleted the row, the hash is wrong, the stored URL is malformed),
50794
+ * the end-user used to receive a Strapi JSON error envelope, which is
50795
+ * the single biggest UX regression in any tracking setup. Now the
50796
+ * user sees a branded HTML fallback page that either redirects to the
50797
+ * admin-configured `trackingFallbackUrl` or apologises and invites
50798
+ * them to close the tab.
50799
+ *
50735
50800
  * GET /magic-mail/track/click/:emailId/:linkHash/:recipientHash
50736
50801
  */
50737
50802
  async trackClick(ctx) {
@@ -50744,15 +50809,25 @@ var analytics$3 = ({ strapi: strapi2 }) => ({
50744
50809
  strapi2.log.error("[magic-mail] Error getting original URL:", err.message);
50745
50810
  }
50746
50811
  if (!url) {
50747
- return ctx.badRequest("Invalid or expired tracking link");
50812
+ return respondWithTrackingFallback(
50813
+ ctx,
50814
+ "The page behind this link is no longer tracked. It may have been removed by our retention policy."
50815
+ );
50748
50816
  }
50749
50817
  try {
50750
50818
  const parsed = new URL(url);
50751
50819
  if (!["http:", "https:"].includes(parsed.protocol)) {
50752
- return ctx.badRequest("Invalid URL protocol");
50820
+ strapi2.log.warn(`[magic-mail] Blocked non-http(s) tracking URL for email ${emailId}`);
50821
+ return respondWithTrackingFallback(
50822
+ ctx,
50823
+ "This link points to an unsupported destination and cannot be opened for your safety."
50824
+ );
50753
50825
  }
50754
50826
  } catch {
50755
- return ctx.badRequest("Invalid URL format");
50827
+ return respondWithTrackingFallback(
50828
+ ctx,
50829
+ "This link is no longer valid."
50830
+ );
50756
50831
  }
50757
50832
  try {
50758
50833
  await strapi2.plugin("magic-mail").service("analytics").recordClick(emailId, linkHash, recipientHash, url, ctx.request);
@@ -51493,16 +51568,24 @@ var controllers$1 = {
51493
51568
  whatsapp: whatsapp$2,
51494
51569
  pluginSettings: pluginSettings$2
51495
51570
  };
51571
+ const PLUGIN_ACCESS_ACTION = "plugin::magic-mail.access";
51572
+ const adminPolicy = () => [
51573
+ "admin::isAuthenticatedAdmin",
51574
+ {
51575
+ name: "admin::hasPermissions",
51576
+ config: { actions: [PLUGIN_ACCESS_ACTION] }
51577
+ }
51578
+ ];
51496
51579
  var admin$1 = {
51497
51580
  type: "admin",
51498
51581
  routes: [
51499
- // Account Management
51582
+ // ─────────────────────── Account Management ───────────────────────
51500
51583
  {
51501
51584
  method: "GET",
51502
51585
  path: "/accounts",
51503
51586
  handler: "accounts.getAll",
51504
51587
  config: {
51505
- policies: ["admin::isAuthenticatedAdmin"],
51588
+ policies: adminPolicy(),
51506
51589
  description: "Get all email accounts"
51507
51590
  }
51508
51591
  },
@@ -51511,7 +51594,7 @@ var admin$1 = {
51511
51594
  path: "/accounts/:accountId",
51512
51595
  handler: "accounts.getOne",
51513
51596
  config: {
51514
- policies: ["admin::isAuthenticatedAdmin"],
51597
+ policies: adminPolicy(),
51515
51598
  description: "Get single email account with decrypted config"
51516
51599
  }
51517
51600
  },
@@ -51520,7 +51603,7 @@ var admin$1 = {
51520
51603
  path: "/accounts",
51521
51604
  handler: "accounts.create",
51522
51605
  config: {
51523
- policies: ["admin::isAuthenticatedAdmin"],
51606
+ policies: adminPolicy(),
51524
51607
  description: "Create email account"
51525
51608
  }
51526
51609
  },
@@ -51529,7 +51612,7 @@ var admin$1 = {
51529
51612
  path: "/accounts/:accountId",
51530
51613
  handler: "accounts.update",
51531
51614
  config: {
51532
- policies: ["admin::isAuthenticatedAdmin"],
51615
+ policies: adminPolicy(),
51533
51616
  description: "Update email account"
51534
51617
  }
51535
51618
  },
@@ -51538,7 +51621,7 @@ var admin$1 = {
51538
51621
  path: "/accounts/:accountId/test",
51539
51622
  handler: "accounts.test",
51540
51623
  config: {
51541
- policies: ["admin::isAuthenticatedAdmin"],
51624
+ policies: adminPolicy(),
51542
51625
  description: "Test email account"
51543
51626
  }
51544
51627
  },
@@ -51547,7 +51630,7 @@ var admin$1 = {
51547
51630
  path: "/test-strapi-service",
51548
51631
  handler: "accounts.testStrapiService",
51549
51632
  config: {
51550
- policies: ["admin::isAuthenticatedAdmin"],
51633
+ policies: adminPolicy(),
51551
51634
  description: "Test Strapi Email Service integration (MagicMail intercept)"
51552
51635
  }
51553
51636
  },
@@ -51556,17 +51639,17 @@ var admin$1 = {
51556
51639
  path: "/accounts/:accountId",
51557
51640
  handler: "accounts.delete",
51558
51641
  config: {
51559
- policies: ["admin::isAuthenticatedAdmin"],
51642
+ policies: adminPolicy(),
51560
51643
  description: "Delete email account"
51561
51644
  }
51562
51645
  },
51563
- // Routing Rules
51646
+ // ─────────────────────── Routing Rules ───────────────────────
51564
51647
  {
51565
51648
  method: "GET",
51566
51649
  path: "/routing-rules",
51567
51650
  handler: "routingRules.getAll",
51568
51651
  config: {
51569
- policies: ["admin::isAuthenticatedAdmin"],
51652
+ policies: adminPolicy(),
51570
51653
  description: "Get all routing rules"
51571
51654
  }
51572
51655
  },
@@ -51575,7 +51658,7 @@ var admin$1 = {
51575
51658
  path: "/routing-rules/:ruleId",
51576
51659
  handler: "routingRules.getOne",
51577
51660
  config: {
51578
- policies: ["admin::isAuthenticatedAdmin"],
51661
+ policies: adminPolicy(),
51579
51662
  description: "Get single routing rule"
51580
51663
  }
51581
51664
  },
@@ -51584,7 +51667,7 @@ var admin$1 = {
51584
51667
  path: "/routing-rules",
51585
51668
  handler: "routingRules.create",
51586
51669
  config: {
51587
- policies: ["admin::isAuthenticatedAdmin"],
51670
+ policies: adminPolicy(),
51588
51671
  description: "Create routing rule"
51589
51672
  }
51590
51673
  },
@@ -51593,7 +51676,7 @@ var admin$1 = {
51593
51676
  path: "/routing-rules/:ruleId",
51594
51677
  handler: "routingRules.update",
51595
51678
  config: {
51596
- policies: ["admin::isAuthenticatedAdmin"],
51679
+ policies: adminPolicy(),
51597
51680
  description: "Update routing rule"
51598
51681
  }
51599
51682
  },
@@ -51602,23 +51685,21 @@ var admin$1 = {
51602
51685
  path: "/routing-rules/:ruleId",
51603
51686
  handler: "routingRules.delete",
51604
51687
  config: {
51605
- policies: ["admin::isAuthenticatedAdmin"],
51688
+ policies: adminPolicy(),
51606
51689
  description: "Delete routing rule"
51607
51690
  }
51608
51691
  },
51609
- // OAuth Routes - Gmail
51610
- // The /auth endpoints are admin-only (they produce OAuth URLs for the
51611
- // currently-authenticated admin). The /callback endpoints must stay
51612
- // public because the upstream OAuth provider (Google/Microsoft/Yahoo)
51613
- // cannot send a bearer token on the redirect back — security is
51614
- // enforced by the signed, one-time-use state parameter that callback
51615
- // + token exchange verify.
51692
+ // ─────────────────────── OAuth Gmail ───────────────────────
51693
+ // /auth endpoints are admin-only (they generate the OAuth URL for
51694
+ // the currently-authenticated admin). /callback MUST remain public
51695
+ // because Google/Microsoft/Yahoo can't send a bearer token on the
51696
+ // redirect security is enforced by the signed single-use state.
51616
51697
  {
51617
51698
  method: "GET",
51618
51699
  path: "/oauth/gmail/auth",
51619
51700
  handler: "oauth.gmailAuth",
51620
51701
  config: {
51621
- policies: ["admin::isAuthenticatedAdmin"],
51702
+ policies: adminPolicy(),
51622
51703
  description: "Initiate Gmail OAuth flow"
51623
51704
  }
51624
51705
  },
@@ -51632,13 +51713,13 @@ var admin$1 = {
51632
51713
  description: "Gmail OAuth callback"
51633
51714
  }
51634
51715
  },
51635
- // OAuth Routes - Microsoft
51716
+ // ─────────────────────── OAuth Microsoft ───────────────────────
51636
51717
  {
51637
51718
  method: "GET",
51638
51719
  path: "/oauth/microsoft/auth",
51639
51720
  handler: "oauth.microsoftAuth",
51640
51721
  config: {
51641
- policies: ["admin::isAuthenticatedAdmin"],
51722
+ policies: adminPolicy(),
51642
51723
  description: "Initiate Microsoft OAuth flow"
51643
51724
  }
51644
51725
  },
@@ -51652,13 +51733,13 @@ var admin$1 = {
51652
51733
  description: "Microsoft OAuth callback"
51653
51734
  }
51654
51735
  },
51655
- // OAuth Routes - Yahoo
51736
+ // ─────────────────────── OAuth Yahoo ───────────────────────
51656
51737
  {
51657
51738
  method: "GET",
51658
51739
  path: "/oauth/yahoo/auth",
51659
51740
  handler: "oauth.yahooAuth",
51660
51741
  config: {
51661
- policies: ["admin::isAuthenticatedAdmin"],
51742
+ policies: adminPolicy(),
51662
51743
  description: "Initiate Yahoo OAuth flow"
51663
51744
  }
51664
51745
  },
@@ -51672,23 +51753,23 @@ var admin$1 = {
51672
51753
  description: "Yahoo OAuth callback"
51673
51754
  }
51674
51755
  },
51675
- // OAuth Routes - Generic
51756
+ // ─────────────────────── OAuth Generic ───────────────────────
51676
51757
  {
51677
51758
  method: "POST",
51678
51759
  path: "/oauth/create-account",
51679
51760
  handler: "oauth.createOAuthAccount",
51680
51761
  config: {
51681
- policies: ["admin::isAuthenticatedAdmin"],
51762
+ policies: adminPolicy(),
51682
51763
  description: "Create account from OAuth"
51683
51764
  }
51684
51765
  },
51685
- // License Routes
51766
+ // ─────────────────────── License ───────────────────────
51686
51767
  {
51687
51768
  method: "GET",
51688
51769
  path: "/license/status",
51689
51770
  handler: "license.getStatus",
51690
51771
  config: {
51691
- policies: ["admin::isAuthenticatedAdmin"],
51772
+ policies: adminPolicy(),
51692
51773
  description: "Get license status"
51693
51774
  }
51694
51775
  },
@@ -51697,7 +51778,7 @@ var admin$1 = {
51697
51778
  path: "/license/auto-create",
51698
51779
  handler: "license.autoCreate",
51699
51780
  config: {
51700
- policies: ["admin::isAuthenticatedAdmin"],
51781
+ policies: adminPolicy(),
51701
51782
  description: "Auto-create license with admin user data"
51702
51783
  }
51703
51784
  },
@@ -51706,7 +51787,7 @@ var admin$1 = {
51706
51787
  path: "/license/store-key",
51707
51788
  handler: "license.storeKey",
51708
51789
  config: {
51709
- policies: ["admin::isAuthenticatedAdmin"],
51790
+ policies: adminPolicy(),
51710
51791
  description: "Store and validate existing license key"
51711
51792
  }
51712
51793
  },
@@ -51715,7 +51796,7 @@ var admin$1 = {
51715
51796
  path: "/license/limits",
51716
51797
  handler: "license.getLimits",
51717
51798
  config: {
51718
- policies: ["admin::isAuthenticatedAdmin"],
51799
+ policies: adminPolicy(),
51719
51800
  description: "Get license limits and available features"
51720
51801
  }
51721
51802
  },
@@ -51724,17 +51805,17 @@ var admin$1 = {
51724
51805
  path: "/license/debug",
51725
51806
  handler: "license.debugLicense",
51726
51807
  config: {
51727
- policies: ["admin::isAuthenticatedAdmin"],
51808
+ policies: adminPolicy(),
51728
51809
  description: "Debug license data"
51729
51810
  }
51730
51811
  },
51731
- // Email Designer Routes
51812
+ // ─────────────────────── Email Designer ───────────────────────
51732
51813
  {
51733
51814
  method: "GET",
51734
51815
  path: "/designer/templates",
51735
51816
  handler: "emailDesigner.findAll",
51736
51817
  config: {
51737
- policies: ["admin::isAuthenticatedAdmin"],
51818
+ policies: adminPolicy(),
51738
51819
  description: "Get all email templates"
51739
51820
  }
51740
51821
  },
@@ -51743,7 +51824,7 @@ var admin$1 = {
51743
51824
  path: "/designer/templates/:id",
51744
51825
  handler: "emailDesigner.findOne",
51745
51826
  config: {
51746
- policies: ["admin::isAuthenticatedAdmin"],
51827
+ policies: adminPolicy(),
51747
51828
  description: "Get email template by ID"
51748
51829
  }
51749
51830
  },
@@ -51752,7 +51833,7 @@ var admin$1 = {
51752
51833
  path: "/designer/templates",
51753
51834
  handler: "emailDesigner.create",
51754
51835
  config: {
51755
- policies: ["admin::isAuthenticatedAdmin"],
51836
+ policies: adminPolicy(),
51756
51837
  description: "Create email template"
51757
51838
  }
51758
51839
  },
@@ -51761,7 +51842,7 @@ var admin$1 = {
51761
51842
  path: "/designer/templates/:id",
51762
51843
  handler: "emailDesigner.update",
51763
51844
  config: {
51764
- policies: ["admin::isAuthenticatedAdmin"],
51845
+ policies: adminPolicy(),
51765
51846
  description: "Update email template"
51766
51847
  }
51767
51848
  },
@@ -51770,7 +51851,7 @@ var admin$1 = {
51770
51851
  path: "/designer/templates/:id",
51771
51852
  handler: "emailDesigner.delete",
51772
51853
  config: {
51773
- policies: ["admin::isAuthenticatedAdmin"],
51854
+ policies: adminPolicy(),
51774
51855
  description: "Delete email template"
51775
51856
  }
51776
51857
  },
@@ -51779,7 +51860,7 @@ var admin$1 = {
51779
51860
  path: "/designer/templates/:id/versions",
51780
51861
  handler: "emailDesigner.getVersions",
51781
51862
  config: {
51782
- policies: ["admin::isAuthenticatedAdmin"],
51863
+ policies: adminPolicy(),
51783
51864
  description: "Get template versions"
51784
51865
  }
51785
51866
  },
@@ -51788,7 +51869,7 @@ var admin$1 = {
51788
51869
  path: "/designer/templates/:id/versions/:versionId/restore",
51789
51870
  handler: "emailDesigner.restoreVersion",
51790
51871
  config: {
51791
- policies: ["admin::isAuthenticatedAdmin"],
51872
+ policies: adminPolicy(),
51792
51873
  description: "Restore template from version"
51793
51874
  }
51794
51875
  },
@@ -51797,7 +51878,7 @@ var admin$1 = {
51797
51878
  path: "/designer/templates/:id/versions/:versionId/delete",
51798
51879
  handler: "emailDesigner.deleteVersion",
51799
51880
  config: {
51800
- policies: ["admin::isAuthenticatedAdmin"],
51881
+ policies: adminPolicy(),
51801
51882
  description: "Delete a single version"
51802
51883
  }
51803
51884
  },
@@ -51806,7 +51887,7 @@ var admin$1 = {
51806
51887
  path: "/designer/templates/:id/versions/delete-all",
51807
51888
  handler: "emailDesigner.deleteAllVersions",
51808
51889
  config: {
51809
- policies: ["admin::isAuthenticatedAdmin"],
51890
+ policies: adminPolicy(),
51810
51891
  description: "Delete all versions for a template"
51811
51892
  }
51812
51893
  },
@@ -51815,7 +51896,7 @@ var admin$1 = {
51815
51896
  path: "/designer/render/:templateReferenceId",
51816
51897
  handler: "emailDesigner.renderTemplate",
51817
51898
  config: {
51818
- policies: ["admin::isAuthenticatedAdmin"],
51899
+ policies: adminPolicy(),
51819
51900
  description: "Render template with data"
51820
51901
  }
51821
51902
  },
@@ -51824,7 +51905,7 @@ var admin$1 = {
51824
51905
  path: "/designer/export",
51825
51906
  handler: "emailDesigner.exportTemplates",
51826
51907
  config: {
51827
- policies: ["admin::isAuthenticatedAdmin"],
51908
+ policies: adminPolicy(),
51828
51909
  description: "Export templates (ADVANCED+)"
51829
51910
  }
51830
51911
  },
@@ -51833,7 +51914,7 @@ var admin$1 = {
51833
51914
  path: "/designer/import",
51834
51915
  handler: "emailDesigner.importTemplates",
51835
51916
  config: {
51836
- policies: ["admin::isAuthenticatedAdmin"],
51917
+ policies: adminPolicy(),
51837
51918
  description: "Import templates (ADVANCED+)"
51838
51919
  }
51839
51920
  },
@@ -51842,7 +51923,7 @@ var admin$1 = {
51842
51923
  path: "/designer/stats",
51843
51924
  handler: "emailDesigner.getStats",
51844
51925
  config: {
51845
- policies: ["admin::isAuthenticatedAdmin"],
51926
+ policies: adminPolicy(),
51846
51927
  description: "Get template statistics"
51847
51928
  }
51848
51929
  },
@@ -51851,7 +51932,7 @@ var admin$1 = {
51851
51932
  path: "/designer/core/:coreEmailType",
51852
51933
  handler: "emailDesigner.getCoreTemplate",
51853
51934
  config: {
51854
- policies: ["admin::isAuthenticatedAdmin"],
51935
+ policies: adminPolicy(),
51855
51936
  description: "Get core email template"
51856
51937
  }
51857
51938
  },
@@ -51860,7 +51941,7 @@ var admin$1 = {
51860
51941
  path: "/designer/core/:coreEmailType",
51861
51942
  handler: "emailDesigner.updateCoreTemplate",
51862
51943
  config: {
51863
- policies: ["admin::isAuthenticatedAdmin"],
51944
+ policies: adminPolicy(),
51864
51945
  description: "Update core email template"
51865
51946
  }
51866
51947
  },
@@ -51869,7 +51950,7 @@ var admin$1 = {
51869
51950
  path: "/designer/templates/:id/download",
51870
51951
  handler: "emailDesigner.download",
51871
51952
  config: {
51872
- policies: ["admin::isAuthenticatedAdmin"],
51953
+ policies: adminPolicy(),
51873
51954
  description: "Download template as HTML or JSON"
51874
51955
  }
51875
51956
  },
@@ -51878,7 +51959,7 @@ var admin$1 = {
51878
51959
  path: "/designer/templates/:id/duplicate",
51879
51960
  handler: "emailDesigner.duplicate",
51880
51961
  config: {
51881
- policies: ["admin::isAuthenticatedAdmin"],
51962
+ policies: adminPolicy(),
51882
51963
  description: "Duplicate template"
51883
51964
  }
51884
51965
  },
@@ -51887,17 +51968,17 @@ var admin$1 = {
51887
51968
  path: "/designer/templates/:id/test-send",
51888
51969
  handler: "emailDesigner.testSend",
51889
51970
  config: {
51890
- policies: ["admin::isAuthenticatedAdmin"],
51971
+ policies: adminPolicy(),
51891
51972
  description: "Send test email for template"
51892
51973
  }
51893
51974
  },
51894
- // Analytics & Tracking
51975
+ // ─────────────────────── Analytics & Tracking ───────────────────────
51895
51976
  {
51896
51977
  method: "GET",
51897
51978
  path: "/analytics/stats",
51898
51979
  handler: "analytics.getStats",
51899
51980
  config: {
51900
- policies: ["admin::isAuthenticatedAdmin"],
51981
+ policies: adminPolicy(),
51901
51982
  description: "Get analytics statistics"
51902
51983
  }
51903
51984
  },
@@ -51906,7 +51987,7 @@ var admin$1 = {
51906
51987
  path: "/analytics/emails",
51907
51988
  handler: "analytics.getEmailLogs",
51908
51989
  config: {
51909
- policies: ["admin::isAuthenticatedAdmin"],
51990
+ policies: adminPolicy(),
51910
51991
  description: "Get email logs"
51911
51992
  }
51912
51993
  },
@@ -51915,7 +51996,7 @@ var admin$1 = {
51915
51996
  path: "/analytics/emails/:emailId",
51916
51997
  handler: "analytics.getEmailDetails",
51917
51998
  config: {
51918
- policies: ["admin::isAuthenticatedAdmin"],
51999
+ policies: adminPolicy(),
51919
52000
  description: "Get email details"
51920
52001
  }
51921
52002
  },
@@ -51924,7 +52005,7 @@ var admin$1 = {
51924
52005
  path: "/analytics/users/:userId",
51925
52006
  handler: "analytics.getUserActivity",
51926
52007
  config: {
51927
- policies: ["admin::isAuthenticatedAdmin"],
52008
+ policies: adminPolicy(),
51928
52009
  description: "Get user email activity"
51929
52010
  }
51930
52011
  },
@@ -51933,7 +52014,7 @@ var admin$1 = {
51933
52014
  path: "/analytics/debug",
51934
52015
  handler: "analytics.debug",
51935
52016
  config: {
51936
- policies: ["admin::isAuthenticatedAdmin"],
52017
+ policies: adminPolicy(),
51937
52018
  description: "Debug analytics state"
51938
52019
  }
51939
52020
  },
@@ -51942,7 +52023,7 @@ var admin$1 = {
51942
52023
  path: "/analytics/emails/:emailId",
51943
52024
  handler: "analytics.deleteEmailLog",
51944
52025
  config: {
51945
- policies: ["admin::isAuthenticatedAdmin"],
52026
+ policies: adminPolicy(),
51946
52027
  description: "Delete single email log"
51947
52028
  }
51948
52029
  },
@@ -51951,27 +52032,27 @@ var admin$1 = {
51951
52032
  path: "/analytics/emails",
51952
52033
  handler: "analytics.clearAllEmailLogs",
51953
52034
  config: {
51954
- policies: ["admin::isAuthenticatedAdmin"],
52035
+ policies: adminPolicy(),
51955
52036
  description: "Clear all email logs"
51956
52037
  }
51957
52038
  },
51958
- // Test Routes (Development)
52039
+ // ─────────────────────── Test (Dev) ───────────────────────
51959
52040
  {
51960
52041
  method: "POST",
51961
52042
  path: "/test/relations",
51962
52043
  handler: "test.testRelations",
51963
52044
  config: {
51964
- policies: ["admin::isAuthenticatedAdmin"],
52045
+ policies: adminPolicy(),
51965
52046
  description: "Test template-version relations"
51966
52047
  }
51967
52048
  },
51968
- // WhatsApp Routes
52049
+ // ─────────────────────── WhatsApp ───────────────────────
51969
52050
  {
51970
52051
  method: "GET",
51971
52052
  path: "/whatsapp/available",
51972
52053
  handler: "whatsapp.checkAvailable",
51973
52054
  config: {
51974
- policies: ["admin::isAuthenticatedAdmin"],
52055
+ policies: adminPolicy(),
51975
52056
  description: "Check if WhatsApp/Baileys is available"
51976
52057
  }
51977
52058
  },
@@ -51980,7 +52061,7 @@ var admin$1 = {
51980
52061
  path: "/whatsapp/status",
51981
52062
  handler: "whatsapp.getStatus",
51982
52063
  config: {
51983
- policies: ["admin::isAuthenticatedAdmin"],
52064
+ policies: adminPolicy(),
51984
52065
  description: "Get WhatsApp connection status"
51985
52066
  }
51986
52067
  },
@@ -51989,7 +52070,7 @@ var admin$1 = {
51989
52070
  path: "/whatsapp/connect",
51990
52071
  handler: "whatsapp.connect",
51991
52072
  config: {
51992
- policies: ["admin::isAuthenticatedAdmin"],
52073
+ policies: adminPolicy(),
51993
52074
  description: "Connect to WhatsApp (generates QR if needed)"
51994
52075
  }
51995
52076
  },
@@ -51998,7 +52079,7 @@ var admin$1 = {
51998
52079
  path: "/whatsapp/disconnect",
51999
52080
  handler: "whatsapp.disconnect",
52000
52081
  config: {
52001
- policies: ["admin::isAuthenticatedAdmin"],
52082
+ policies: adminPolicy(),
52002
52083
  description: "Disconnect from WhatsApp"
52003
52084
  }
52004
52085
  },
@@ -52007,7 +52088,7 @@ var admin$1 = {
52007
52088
  path: "/whatsapp/send-test",
52008
52089
  handler: "whatsapp.sendTest",
52009
52090
  config: {
52010
- policies: ["admin::isAuthenticatedAdmin"],
52091
+ policies: adminPolicy(),
52011
52092
  description: "Send a test WhatsApp message"
52012
52093
  }
52013
52094
  },
@@ -52016,7 +52097,7 @@ var admin$1 = {
52016
52097
  path: "/whatsapp/send-template",
52017
52098
  handler: "whatsapp.sendTemplateMessage",
52018
52099
  config: {
52019
- policies: ["admin::isAuthenticatedAdmin"],
52100
+ policies: adminPolicy(),
52020
52101
  description: "Send WhatsApp message using template"
52021
52102
  }
52022
52103
  },
@@ -52025,7 +52106,7 @@ var admin$1 = {
52025
52106
  path: "/whatsapp/check-number",
52026
52107
  handler: "whatsapp.checkNumber",
52027
52108
  config: {
52028
- policies: ["admin::isAuthenticatedAdmin"],
52109
+ policies: adminPolicy(),
52029
52110
  description: "Check if phone number is on WhatsApp"
52030
52111
  }
52031
52112
  },
@@ -52034,7 +52115,7 @@ var admin$1 = {
52034
52115
  path: "/whatsapp/templates",
52035
52116
  handler: "whatsapp.getTemplates",
52036
52117
  config: {
52037
- policies: ["admin::isAuthenticatedAdmin"],
52118
+ policies: adminPolicy(),
52038
52119
  description: "Get all WhatsApp message templates"
52039
52120
  }
52040
52121
  },
@@ -52043,7 +52124,7 @@ var admin$1 = {
52043
52124
  path: "/whatsapp/templates",
52044
52125
  handler: "whatsapp.saveTemplate",
52045
52126
  config: {
52046
- policies: ["admin::isAuthenticatedAdmin"],
52127
+ policies: adminPolicy(),
52047
52128
  description: "Save a WhatsApp message template"
52048
52129
  }
52049
52130
  },
@@ -52052,7 +52133,7 @@ var admin$1 = {
52052
52133
  path: "/whatsapp/templates/:templateName",
52053
52134
  handler: "whatsapp.deleteTemplate",
52054
52135
  config: {
52055
- policies: ["admin::isAuthenticatedAdmin"],
52136
+ policies: adminPolicy(),
52056
52137
  description: "Delete a WhatsApp message template"
52057
52138
  }
52058
52139
  },
@@ -52061,17 +52142,17 @@ var admin$1 = {
52061
52142
  path: "/whatsapp/session",
52062
52143
  handler: "whatsapp.getSession",
52063
52144
  config: {
52064
- policies: ["admin::isAuthenticatedAdmin"],
52145
+ policies: adminPolicy(),
52065
52146
  description: "Get WhatsApp session info"
52066
52147
  }
52067
52148
  },
52068
- // Plugin Settings Routes
52149
+ // ─────────────────────── Plugin Settings ───────────────────────
52069
52150
  {
52070
52151
  method: "GET",
52071
52152
  path: "/settings",
52072
52153
  handler: "pluginSettings.getSettings",
52073
52154
  config: {
52074
- policies: ["admin::isAuthenticatedAdmin"],
52155
+ policies: adminPolicy(),
52075
52156
  description: "Get plugin settings"
52076
52157
  }
52077
52158
  },
@@ -52080,7 +52161,7 @@ var admin$1 = {
52080
52161
  path: "/settings",
52081
52162
  handler: "pluginSettings.updateSettings",
52082
52163
  config: {
52083
- policies: ["admin::isAuthenticatedAdmin"],
52164
+ policies: adminPolicy(),
52084
52165
  description: "Update plugin settings"
52085
52166
  }
52086
52167
  }
@@ -63348,7 +63429,7 @@ var oauth$1 = ({ strapi: strapi2 }) => ({
63348
63429
  return account;
63349
63430
  }
63350
63431
  });
63351
- const version = "2.8.4";
63432
+ const version = "2.9.1";
63352
63433
  const require$$2 = {
63353
63434
  version
63354
63435
  };
@@ -65232,7 +65313,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
65232
65313
  defaultFromName: null,
65233
65314
  defaultFromEmail: null,
65234
65315
  unsubscribeUrl: null,
65235
- enableUnsubscribeHeader: true
65316
+ enableUnsubscribeHeader: true,
65317
+ trackingFallbackUrl: null
65236
65318
  }
65237
65319
  });
65238
65320
  strapi2.log.info("[magic-mail] [SETTINGS] Created default plugin settings");
@@ -65247,7 +65329,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
65247
65329
  defaultFromName: null,
65248
65330
  defaultFromEmail: null,
65249
65331
  unsubscribeUrl: null,
65250
- enableUnsubscribeHeader: true
65332
+ enableUnsubscribeHeader: true,
65333
+ trackingFallbackUrl: null
65251
65334
  };
65252
65335
  }
65253
65336
  },
@@ -65263,7 +65346,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
65263
65346
  trackingBaseUrl: data.trackingBaseUrl?.trim() || null,
65264
65347
  defaultFromName: data.defaultFromName?.trim() || null,
65265
65348
  defaultFromEmail: data.defaultFromEmail?.trim()?.toLowerCase() || null,
65266
- unsubscribeUrl: data.unsubscribeUrl?.trim() || null
65349
+ unsubscribeUrl: data.unsubscribeUrl?.trim() || null,
65350
+ trackingFallbackUrl: data.trackingFallbackUrl?.trim() || null
65267
65351
  };
65268
65352
  let settings = await strapi2.documents(SETTINGS_UID).findFirst({});
65269
65353
  if (settings) {
@@ -65281,7 +65365,8 @@ var pluginSettings$1 = ({ strapi: strapi2 }) => ({
65281
65365
  defaultFromName: sanitizedData.defaultFromName,
65282
65366
  defaultFromEmail: sanitizedData.defaultFromEmail,
65283
65367
  unsubscribeUrl: sanitizedData.unsubscribeUrl,
65284
- enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true
65368
+ enableUnsubscribeHeader: sanitizedData.enableUnsubscribeHeader ?? true,
65369
+ trackingFallbackUrl: sanitizedData.trackingFallbackUrl
65285
65370
  }
65286
65371
  });
65287
65372
  strapi2.log.info("[magic-mail] [SETTINGS] Created plugin settings");