strapi-plugin-magic-link-v5 5.5.6 → 5.5.8

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [5.5.8](https://github.com/Schero94/strapi-plugin-magic-link-v5/compare/v5.5.7...v5.5.8) (2026-05-03)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **settings:** declare missing emailTemplates state — closes [#17](https://github.com/Schero94/strapi-plugin-magic-link-v5/issues/17) ([6ee2740](https://github.com/Schero94/strapi-plugin-magic-link-v5/commit/6ee2740c62e7772e5cfa8904416ab64be84bab5e))
7
+
8
+ ## [5.5.7](https://github.com/Schero94/strapi-plugin-magic-link-v5/compare/v5.5.6...v5.5.7) (2026-04-26)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **send-link:** use Email Designer 5 template on public endpoint ([8e0abbc](https://github.com/Schero94/strapi-plugin-magic-link-v5/commit/8e0abbc3f479b5a41d5a56c081592c2a2f4daffa)), closes [#17](https://github.com/Schero94/strapi-plugin-magic-link-v5/issues/17) [#17](https://github.com/Schero94/strapi-plugin-magic-link-v5/issues/17)
14
+
1
15
  ## [5.5.6](https://github.com/Schero94/strapi-plugin-magic-link-v5/compare/v5.5.5...v5.5.6) (2026-04-26)
2
16
 
3
17
 
package/README.md CHANGED
@@ -10,12 +10,12 @@ Secure, modern, and user-friendly authentication using email-based magic links,
10
10
 
11
11
  ## Why Magic Link?
12
12
 
13
- - **Zero Setup Time** - Install, activate license (free), and start using
14
- - **Production Ready** - Battle-tested with rate limiting, IP bans, and session management
15
- - **Multi-Factor Authentication** - Email OTP + TOTP Authenticator support
16
- - **WhatsApp Integration** - Send magic links via WhatsApp (FREE!)
17
- - **Beautiful UI** - Modern, responsive admin interface with German translations
18
- - **Enterprise Security** - License-based feature unlocking with Free, Premium & Advanced tiers
13
+ - **Zero Setup Time** - Install, configure SMTP, and start using.
14
+ - **Production Ready** - Battle-tested with rate limiting, IP bans, and session management.
15
+ - **Multi-Factor Authentication** - Email OTP + TOTP Authenticator support, included.
16
+ - **WhatsApp Integration** - Send magic links via WhatsApp messenger.
17
+ - **Beautiful UI** - Modern, responsive admin interface localized in 5 languages.
18
+ - **Free & Open** - MIT license, no paywall, every feature available out of the box.
19
19
 
20
20
  ## 📚 Quick Links
21
21
 
@@ -45,23 +45,16 @@ Users can switch languages in **Settings → Magic Link → Interface Language**
45
45
 
46
46
  ## 📜 License
47
47
 
48
- This plugin is licensed under the **MIT License** - free for everyone to use!
48
+ MIT-licensed. Free for personal and commercial use. See [LICENSE](./LICENSE).
49
49
 
50
- ### What you CAN do:
51
- - ✅ Use the plugin freely (personal & commercial)
52
- - ✅ View and study the source code
53
- - ✅ Report issues and contribute improvements
54
- - ✅ Deploy in production without fees
55
- - ✅ Integrate in your commercial projects
50
+ ### Optional license-key activation
56
51
 
57
- ### What you CANNOT do:
58
- - ❌ Remove or bypass the license validation system
59
- - ❌ Modify `license-guard.js` or license-related endpoints
60
- - ❌ Disable license activation requirements
52
+ The admin panel offers a "License" tab where you can register an optional
53
+ license key. This is purely cosmetic — it does **not** unlock any
54
+ feature, and the plugin is fully usable without it. Registering a key
55
+ just lets the project track installs and helps us prioritise issues.
61
56
 
62
- **Important:** The license validation system must remain intact and functional. This ensures quality, support, and continued development. Users must activate the plugin (free) through the admin interface.
63
-
64
- 📄 See [LICENSE](./LICENSE) for full terms
57
+ You can ignore the License tab entirely; nothing will be gated.
65
58
 
66
59
  ---
67
60
 
@@ -69,37 +62,25 @@ This plugin is licensed under the **MIT License** - free for everyone to use!
69
62
 
70
63
  ### Authentication Modes
71
64
 
72
- Choose the security level that fits your needs:
65
+ All modes are available in every install — pick whichever fits your security profile:
73
66
 
74
- | Mode | Description | License |
75
- |------|-------------|---------|
76
- | **Magic Link Only** | One-click email login - fast & user-friendly | Free |
77
- | **Magic Link via WhatsApp** | Send magic links via WhatsApp messenger | Free |
78
- | **Magic Link + Email OTP** | 6-digit code after magic link click | Premium |
79
- | **Magic Link + TOTP (MFA)** | Authenticator app (Google Auth, Authy) | Advanced |
80
- | **TOTP-Only Login** | Direct login with email + TOTP code | Advanced |
67
+ | Mode | Description |
68
+ |------|-------------|
69
+ | **Magic Link Only** | One-click email login — fast & user-friendly |
70
+ | **Magic Link via WhatsApp** | Send magic links via the WhatsApp messenger |
71
+ | **Magic Link + Email OTP** | 6-digit code sent after the magic link click |
72
+ | **Magic Link + TOTP (MFA)** | Authenticator app (Google Authenticator, Authy, …) |
73
+ | **TOTP-Only Login** | Direct login with email + TOTP code |
81
74
 
82
75
  ### 🛡️ Security Features
83
76
 
84
- - **Rate Limiting** - 5 requests per 15 minutes (configurable)
85
- - **IP Banning** - Block suspicious addresses with one click
86
- - **Session Management** - Monitor and revoke active JWT sessions
87
- - **Login Tracking** - Store IP addresses and user agents
88
- - **Token Expiration** - Configurable validity periods
89
- - **Brute Force Protection** - Login attempt limiting
90
- - **Security Score** - Real-time configuration assessment
91
-
92
- ### � License Tiers
93
-
94
- | Feature | Free | Premium | Advanced |
95
- |---------|------|---------|----------|
96
- | Magic Link Login | ✅ | ✅ | ✅ |
97
- | Token Management | ✅ | ✅ | ✅ |
98
- | IP Banning | ✅ | ✅ | ✅ |
99
- | Rate Limiting | ✅ | ✅ | ✅ |
100
- | Email OTP | ❌ | ✅ | ✅ |
101
- | TOTP Authenticator | ❌ | ❌ | ✅ |
102
- | TOTP-Only Login | ❌ | ❌ | ✅ |
77
+ - **Rate Limiting** — 5 requests per 15 minutes (configurable)
78
+ - **IP Banning** — Block suspicious addresses with one click
79
+ - **Session Management** — Monitor and revoke active JWT sessions
80
+ - **Login Tracking** — Store IP addresses and user agents
81
+ - **Token Expiration** — Configurable validity periods
82
+ - **Brute Force Protection** — Login attempt limiting
83
+ - **Security Score** — Real-time configuration assessment
103
84
 
104
85
  ### 🎨 Admin Interface
105
86
 
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const react = require("react");
4
+ const reactIntl = require("react-intl");
5
+ const en = require("./en-DnvSpXvu.js");
6
+ const de = require("./de-BSOk5suQ.js");
7
+ const fr = require("./fr-BKo8t7Fx.js");
8
+ const es = require("./es-B-tnwByt.js");
9
+ const pt = require("./pt-CjEkXBAz.js");
10
+ const LanguageContext = react.createContext();
11
+ const usePluginLanguage = () => {
12
+ const context = react.useContext(LanguageContext);
13
+ if (!context) {
14
+ throw new Error("usePluginLanguage must be used within LanguageProvider");
15
+ }
16
+ return context;
17
+ };
18
+ const translations = {
19
+ en: en.default,
20
+ de: de.default,
21
+ fr: fr.default,
22
+ es: es.default,
23
+ pt: pt.default
24
+ };
25
+ const LanguageProvider = ({ children }) => {
26
+ const [currentLanguage, setCurrentLanguage] = react.useState(() => {
27
+ return localStorage.getItem("magic-link-language") || "en";
28
+ });
29
+ const changeLanguage = (newLang) => {
30
+ setCurrentLanguage(newLang);
31
+ localStorage.setItem("magic-link-language", newLang);
32
+ };
33
+ const value = {
34
+ language: currentLanguage,
35
+ changeLanguage,
36
+ t: (key) => {
37
+ const messages = translations[currentLanguage] || translations.en;
38
+ return messages[key] || key;
39
+ }
40
+ };
41
+ return /* @__PURE__ */ jsxRuntime.jsx(LanguageContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(
42
+ reactIntl.IntlProvider,
43
+ {
44
+ locale: currentLanguage,
45
+ messages: translations[currentLanguage],
46
+ defaultLocale: "en",
47
+ children
48
+ }
49
+ ) });
50
+ };
51
+ const LicenseGuard = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
52
+ exports.LanguageProvider = LanguageProvider;
53
+ exports.LicenseGuard = LicenseGuard;
54
+ exports.usePluginLanguage = usePluginLanguage;
@@ -0,0 +1,55 @@
1
+ import { jsx, Fragment } from "react/jsx-runtime";
2
+ import { useState, createContext, useContext } from "react";
3
+ import { IntlProvider } from "react-intl";
4
+ import enTranslations from "./en-gXXgGDV1.mjs";
5
+ import deTranslations from "./de-CwhYs3O3.mjs";
6
+ import frTranslations from "./fr-BQn1OHOR.mjs";
7
+ import esTranslations from "./es-DG5gW3RZ.mjs";
8
+ import ptTranslations from "./pt-trziAOzT.mjs";
9
+ const LanguageContext = createContext();
10
+ const usePluginLanguage = () => {
11
+ const context = useContext(LanguageContext);
12
+ if (!context) {
13
+ throw new Error("usePluginLanguage must be used within LanguageProvider");
14
+ }
15
+ return context;
16
+ };
17
+ const translations = {
18
+ en: enTranslations,
19
+ de: deTranslations,
20
+ fr: frTranslations,
21
+ es: esTranslations,
22
+ pt: ptTranslations
23
+ };
24
+ const LanguageProvider = ({ children }) => {
25
+ const [currentLanguage, setCurrentLanguage] = useState(() => {
26
+ return localStorage.getItem("magic-link-language") || "en";
27
+ });
28
+ const changeLanguage = (newLang) => {
29
+ setCurrentLanguage(newLang);
30
+ localStorage.setItem("magic-link-language", newLang);
31
+ };
32
+ const value = {
33
+ language: currentLanguage,
34
+ changeLanguage,
35
+ t: (key) => {
36
+ const messages = translations[currentLanguage] || translations.en;
37
+ return messages[key] || key;
38
+ }
39
+ };
40
+ return /* @__PURE__ */ jsx(LanguageContext.Provider, { value, children: /* @__PURE__ */ jsx(
41
+ IntlProvider,
42
+ {
43
+ locale: currentLanguage,
44
+ messages: translations[currentLanguage],
45
+ defaultLocale: "en",
46
+ children
47
+ }
48
+ ) });
49
+ };
50
+ const LicenseGuard = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
51
+ export {
52
+ LicenseGuard as L,
53
+ LanguageProvider as a,
54
+ usePluginLanguage as u
55
+ };
@@ -176,8 +176,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
176
176
  if (error) {
177
177
  return /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "danger", title: "Error", children: error }) }) });
178
178
  }
179
- const isValid = licenseData?.valid;
180
- const isDemo = licenseData?.demo;
179
+ const isValid = licenseData?.valid !== false;
180
+ const hasKey = !!licenseData?.hasKey;
181
181
  const data = licenseData?.data || {};
182
182
  return /* @__PURE__ */ jsxRuntime.jsxs(Container, { children: [
183
183
  /* @__PURE__ */ jsxRuntime.jsx(StickySaveBar, { paddingTop: 5, paddingBottom: 5, paddingLeft: 6, paddingRight: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
@@ -202,7 +202,7 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
202
202
  )
203
203
  ] }) }),
204
204
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingTop: 6, paddingLeft: 6, paddingRight: 6, paddingBottom: 10, children: [
205
- isDemo ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "warning", title: "Demo Mode", children: "You're using the demo version. Upgrade to unlock all features." }) : isValid ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "success", title: "License Active", children: "Your license is active and all features are unlocked." }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "danger", title: "License Issue", children: "There's an issue with your license." }),
205
+ hasKey && isValid ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "success", title: "License Active", children: "License key registered. Thanks for supporting the plugin!" }) : hasKey && !isValid ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "warning", title: "License Verification", children: "We couldn't reach the license server right now. The plugin keeps working — try Refresh Status later." }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "default", title: "No license key registered", children: 'All Magic Link features are available without activation. If you want to register a license key, use the form below or run "Auto-Activate" to generate one for your admin email.' }),
206
206
  data.licenseKey && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 6, children: /* @__PURE__ */ jsxRuntime.jsx(LicenseKeyBanner, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "flex-start", children: [
207
207
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
208
208
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", style: { color: "rgba(255,255,255,0.8)", marginBottom: "12px", textTransform: "uppercase", fontSize: "11px", letterSpacing: "0.5px", display: "block" }, children: "License Key" }),
@@ -287,45 +287,16 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
287
287
  ] })
288
288
  ] }) }) })
289
289
  ] }),
290
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: "features", children: [
291
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { icon: icons.Sparkle, children: "Features & Capabilities" }) }),
292
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 8, wrap: "wrap", children: [
293
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
294
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Premium Features" }),
295
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.premium ? "✓ Enabled" : "✗ Disabled" })
296
- ] }),
297
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
298
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Advanced Features" }),
299
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.advanced ? "✓ Enabled" : "✗ Disabled" })
300
- ] }),
301
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "180px" }, children: [
302
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Enterprise Features" }),
303
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.enterprise ? "✓ Enabled" : "✗ Disabled" })
304
- ] })
305
- ] }) }) })
306
- ] }),
307
290
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: "status", children: [
308
291
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { icon: icons.ChartBubble, children: "System Status" }) }),
309
292
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 8, wrap: "wrap", children: [
310
293
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
311
294
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "License Status" }),
312
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.isActive ? "Active" : "Inactive" })
313
- ] }),
314
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
315
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Connection" }),
316
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.isOnline ? "Online" : "Offline" })
317
- ] }),
318
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
319
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Last Sync" }),
320
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: data.lastPingAt ? new Date(data.lastPingAt).toLocaleTimeString() : "Never" })
295
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: hasKey ? data.isActive ? "Active" : "Inactive" : "No key registered" })
321
296
  ] }),
322
297
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: "1", minWidth: "150px" }, children: [
323
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Device Limit" }),
324
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: [
325
- data.currentDevices || 0,
326
- " / ",
327
- data.maxDevices || 1
328
- ] })
298
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Plugin Mode" }),
299
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: "Fully unlocked" })
329
300
  ] })
330
301
  ] }) }) })
331
302
  ] })
@@ -5,9 +5,9 @@ import styled, { keyframes, css } from "styled-components";
5
5
  import { useIntl } from "react-intl";
6
6
  import { Box, Flex, Typography, Button, TextInput, Textarea, Checkbox, IconButton, Loader, Searchbar, SingleSelect, SingleSelectOption, Thead, Tr, Th, Tbody, Td, Pagination, PreviousLink, PageLink, NextLink, Table, Badge, VisuallyHidden, Main } from "@strapi/design-system";
7
7
  import { Cross, Sparkle, Check, Shield, Clock, Lock, Trash, ArrowClockwise, CaretDown, User, Monitor, Calendar, Plus, Earth, WarningCircle, Server, Eye, Mail, Cog, Key, Link } from "@strapi/icons";
8
- import { g as getTrad, P as PLUGIN_ID } from "./index-34ICAF9_.mjs";
8
+ import { g as getTrad, P as PLUGIN_ID } from "./index-Bj-erY7g.mjs";
9
9
  import { useFetchClient, useNotification } from "@strapi/strapi/admin";
10
- import { L as LicenseGuard, a as LanguageProvider } from "./LicenseGuard-5sMwgS6j.mjs";
10
+ import { L as LicenseGuard, a as LanguageProvider } from "./LicenseGuard-DJ5fq2UZ.mjs";
11
11
  const CreateTokenModal = ({ isOpen, onClose, onSubmit, formData, setFormData }) => {
12
12
  const { formatMessage } = useIntl();
13
13
  const [contextText, setContextText] = useState("");
@@ -60,7 +60,7 @@ const index = {
60
60
  },
61
61
  Component: () => import(
62
62
  /* webpackChunkName: "magic-link-tokens" */
63
- "./index-CxCULraY.mjs"
63
+ "./index-B9Ch8Jpe.mjs"
64
64
  ),
65
65
  permissions: pluginPermissions.access
66
66
  });
@@ -82,7 +82,7 @@ const index = {
82
82
  to: `${PLUGIN_ID}/config`,
83
83
  Component: () => import(
84
84
  /* webpackChunkName: "magic-link-settings" */
85
- "./index-ivgYEX37.mjs"
85
+ "./index-SCxv154G.mjs"
86
86
  ),
87
87
  permissions: pluginPermissions.readSettings
88
88
  },
@@ -95,20 +95,7 @@ const index = {
95
95
  to: `${PLUGIN_ID}/license`,
96
96
  Component: () => import(
97
97
  /* webpackChunkName: "magic-link-license" */
98
- "./index-B8urUtiz.mjs"
99
- ),
100
- permissions: pluginPermissions.access
101
- },
102
- {
103
- intlLabel: {
104
- id: getTrad("Form.title.Upgrade"),
105
- defaultMessage: "Upgrade"
106
- },
107
- id: "magic-link-upgrade",
108
- to: `${PLUGIN_ID}/upgrade`,
109
- Component: () => import(
110
- /* webpackChunkName: "magic-link-upgrade" */
111
- "./LicensePage-CCNW2hT6.mjs"
98
+ "./index-Dufv-daf.mjs"
112
99
  ),
113
100
  permissions: pluginPermissions.access
114
101
  },
@@ -121,7 +108,7 @@ const index = {
121
108
  to: `${PLUGIN_ID}/whatsapp`,
122
109
  Component: () => import(
123
110
  /* webpackChunkName: "magic-link-whatsapp" */
124
- "./index-BZFGxKmY.mjs"
111
+ "./index-DF3Edydl.mjs"
125
112
  ),
126
113
  permissions: pluginPermissions.access
127
114
  }
@@ -61,7 +61,7 @@ const index = {
61
61
  },
62
62
  Component: () => Promise.resolve().then(() => require(
63
63
  /* webpackChunkName: "magic-link-tokens" */
64
- "./index-CddEy_As.js"
64
+ "./index-XYWLmmEs.js"
65
65
  )),
66
66
  permissions: pluginPermissions.access
67
67
  });
@@ -83,7 +83,7 @@ const index = {
83
83
  to: `${PLUGIN_ID}/config`,
84
84
  Component: () => Promise.resolve().then(() => require(
85
85
  /* webpackChunkName: "magic-link-settings" */
86
- "./index-CuXnqVl4.js"
86
+ "./index-zzoovbM0.js"
87
87
  )),
88
88
  permissions: pluginPermissions.readSettings
89
89
  },
@@ -96,20 +96,7 @@ const index = {
96
96
  to: `${PLUGIN_ID}/license`,
97
97
  Component: () => Promise.resolve().then(() => require(
98
98
  /* webpackChunkName: "magic-link-license" */
99
- "./index-PgHpSdc8.js"
100
- )),
101
- permissions: pluginPermissions.access
102
- },
103
- {
104
- intlLabel: {
105
- id: getTrad("Form.title.Upgrade"),
106
- defaultMessage: "Upgrade"
107
- },
108
- id: "magic-link-upgrade",
109
- to: `${PLUGIN_ID}/upgrade`,
110
- Component: () => Promise.resolve().then(() => require(
111
- /* webpackChunkName: "magic-link-upgrade" */
112
- "./LicensePage-2M-vOJX8.js"
99
+ "./index-01GHNxSr.js"
113
100
  )),
114
101
  permissions: pluginPermissions.access
115
102
  },
@@ -122,7 +109,7 @@ const index = {
122
109
  to: `${PLUGIN_ID}/whatsapp`,
123
110
  Component: () => Promise.resolve().then(() => require(
124
111
  /* webpackChunkName: "magic-link-whatsapp" */
125
- "./index-M5s7QN5m.js"
112
+ "./index-I72rBTkL.js"
126
113
  )),
127
114
  permissions: pluginPermissions.access
128
115
  }
@@ -5,7 +5,7 @@ import { useIntl } from "react-intl";
5
5
  import { Flex, Loader, Box, Typography, Button, TextInput, Badge } from "@strapi/design-system";
6
6
  import { Phone, Check, Message, ArrowClockwise } from "@strapi/icons";
7
7
  import { useNotification, useFetchClient } from "@strapi/strapi/admin";
8
- import { g as getTrad } from "./index-34ICAF9_.mjs";
8
+ import { g as getTrad } from "./index-Bj-erY7g.mjs";
9
9
  const theme = {
10
10
  colors: {
11
11
  primary: { 700: "#075985", 100: "#E0F2FE", 50: "#F0F9FF" },
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useState, useEffect } from "react";
3
3
  import { Loader, Box, Alert, Flex, Typography, Button, Badge, Accordion } from "@strapi/design-system";
4
4
  import { useFetchClient, useNotification } from "@strapi/strapi/admin";
5
- import { ArrowClockwise, Duplicate, Download, User, Shield, Sparkle, ChartBubble } from "@strapi/icons";
5
+ import { ArrowClockwise, Duplicate, Download, User, Shield, ChartBubble } from "@strapi/icons";
6
6
  import styled, { keyframes } from "styled-components";
7
7
  const theme = {
8
8
  colors: {
@@ -172,8 +172,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
172
172
  if (error) {
173
173
  return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Box, { padding: 8, children: /* @__PURE__ */ jsx(Alert, { variant: "danger", title: "Error", children: error }) }) });
174
174
  }
175
- const isValid = licenseData?.valid;
176
- const isDemo = licenseData?.demo;
175
+ const isValid = licenseData?.valid !== false;
176
+ const hasKey = !!licenseData?.hasKey;
177
177
  const data = licenseData?.data || {};
178
178
  return /* @__PURE__ */ jsxs(Container, { children: [
179
179
  /* @__PURE__ */ jsx(StickySaveBar, { paddingTop: 5, paddingBottom: 5, paddingLeft: 6, paddingRight: 6, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
@@ -198,7 +198,7 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
198
198
  )
199
199
  ] }) }),
200
200
  /* @__PURE__ */ jsxs(Box, { paddingTop: 6, paddingLeft: 6, paddingRight: 6, paddingBottom: 10, children: [
201
- isDemo ? /* @__PURE__ */ jsx(Alert, { variant: "warning", title: "Demo Mode", children: "You're using the demo version. Upgrade to unlock all features." }) : isValid ? /* @__PURE__ */ jsx(Alert, { variant: "success", title: "License Active", children: "Your license is active and all features are unlocked." }) : /* @__PURE__ */ jsx(Alert, { variant: "danger", title: "License Issue", children: "There's an issue with your license." }),
201
+ hasKey && isValid ? /* @__PURE__ */ jsx(Alert, { variant: "success", title: "License Active", children: "License key registered. Thanks for supporting the plugin!" }) : hasKey && !isValid ? /* @__PURE__ */ jsx(Alert, { variant: "warning", title: "License Verification", children: "We couldn't reach the license server right now. The plugin keeps working — try Refresh Status later." }) : /* @__PURE__ */ jsx(Alert, { variant: "default", title: "No license key registered", children: 'All Magic Link features are available without activation. If you want to register a license key, use the form below or run "Auto-Activate" to generate one for your admin email.' }),
202
202
  data.licenseKey && /* @__PURE__ */ jsx(Box, { marginTop: 6, children: /* @__PURE__ */ jsx(LicenseKeyBanner, { children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "flex-start", children: [
203
203
  /* @__PURE__ */ jsxs(Box, { style: { flex: 1 }, children: [
204
204
  /* @__PURE__ */ jsx(Typography, { variant: "pi", style: { color: "rgba(255,255,255,0.8)", marginBottom: "12px", textTransform: "uppercase", fontSize: "11px", letterSpacing: "0.5px", display: "block" }, children: "License Key" }),
@@ -283,45 +283,16 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
283
283
  ] })
284
284
  ] }) }) })
285
285
  ] }),
286
- /* @__PURE__ */ jsxs(Accordion.Item, { value: "features", children: [
287
- /* @__PURE__ */ jsx(Accordion.Header, { children: /* @__PURE__ */ jsx(Accordion.Trigger, { icon: Sparkle, children: "Features & Capabilities" }) }),
288
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsxs(Flex, { gap: 8, wrap: "wrap", children: [
289
- /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
290
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Premium Features" }),
291
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.premium ? "✓ Enabled" : "✗ Disabled" })
292
- ] }),
293
- /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
294
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Advanced Features" }),
295
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.advanced ? "✓ Enabled" : "✗ Disabled" })
296
- ] }),
297
- /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "180px" }, children: [
298
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Enterprise Features" }),
299
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.features?.enterprise ? "✓ Enabled" : "✗ Disabled" })
300
- ] })
301
- ] }) }) })
302
- ] }),
303
286
  /* @__PURE__ */ jsxs(Accordion.Item, { value: "status", children: [
304
287
  /* @__PURE__ */ jsx(Accordion.Header, { children: /* @__PURE__ */ jsx(Accordion.Trigger, { icon: ChartBubble, children: "System Status" }) }),
305
288
  /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsxs(Flex, { gap: 8, wrap: "wrap", children: [
306
289
  /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
307
290
  /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "License Status" }),
308
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.isActive ? "Active" : "Inactive" })
309
- ] }),
310
- /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
311
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Connection" }),
312
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.isOnline ? "Online" : "Offline" })
313
- ] }),
314
- /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
315
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Last Sync" }),
316
- /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: data.lastPingAt ? new Date(data.lastPingAt).toLocaleTimeString() : "Never" })
291
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: hasKey ? data.isActive ? "Active" : "Inactive" : "No key registered" })
317
292
  ] }),
318
293
  /* @__PURE__ */ jsxs(Box, { style: { flex: "1", minWidth: "150px" }, children: [
319
- /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Device Limit" }),
320
- /* @__PURE__ */ jsxs(Typography, { variant: "omega", fontWeight: "semiBold", children: [
321
- data.currentDevices || 0,
322
- " / ",
323
- data.maxDevices || 1
324
- ] })
294
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", textTransform: "uppercase", style: { marginBottom: "8px", display: "block" }, children: "Plugin Mode" }),
295
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", children: "Fully unlocked" })
325
296
  ] })
326
297
  ] }) }) })
327
298
  ] })
@@ -7,7 +7,7 @@ const reactIntl = require("react-intl");
7
7
  const designSystem = require("@strapi/design-system");
8
8
  const icons = require("@strapi/icons");
9
9
  const admin = require("@strapi/strapi/admin");
10
- const index = require("./index-BFzW7Xex.js");
10
+ const index = require("./index-CGxbhJfg.js");
11
11
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
12
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
13
13
  const theme = {