strapi-plugin-magic-link-v5 5.5.7 → 5.5.9
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 +14 -0
- package/README.md +28 -47
- package/dist/_chunks/LicenseGuard-CiyjFnrw.js +54 -0
- package/dist/_chunks/LicenseGuard-DJ5fq2UZ.mjs +55 -0
- package/dist/_chunks/{index-PgHpSdc8.js → index-01GHNxSr.js} +6 -35
- package/dist/_chunks/{index-BZFGxKmY.mjs → index-5jsDgD-q.mjs} +1 -1
- package/dist/_chunks/{index-CddEy_As.js → index-BWuj-5WE.js} +2 -2
- package/dist/_chunks/{index-BFzW7Xex.js → index-Bj3H_Z4B.js} +4 -17
- package/dist/_chunks/{index-M5s7QN5m.js → index-CC4Eu9Dm.js} +1 -1
- package/dist/_chunks/{index-ivgYEX37.mjs → index-Csyi13vd.mjs} +9 -141
- package/dist/_chunks/{index-CuXnqVl4.js → index-DJqXiiP1.js} +9 -141
- package/dist/_chunks/{index-34ICAF9_.mjs → index-DQUYFsLT.mjs} +4 -17
- package/dist/_chunks/{index-B8urUtiz.mjs → index-Dufv-daf.mjs} +7 -36
- package/dist/_chunks/{index-CxCULraY.mjs → index-szeYJKpN.mjs} +2 -2
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +224 -773
- package/dist/server/index.mjs +224 -773
- package/package.json +3 -3
- package/dist/_chunks/LicenseGuard-5sMwgS6j.mjs +0 -646
- package/dist/_chunks/LicenseGuard-DqyOwTlf.js +0 -647
- package/dist/_chunks/LicensePage-2M-vOJX8.js +0 -377
- package/dist/_chunks/LicensePage-CCNW2hT6.mjs +0 -375
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useEffect } from "react";
|
|
3
|
-
import { useFetchClient, useNotification } from "@strapi/strapi/admin";
|
|
4
|
-
import styled from "styled-components";
|
|
5
|
-
import { Flex, Typography, Box, Badge, Button } from "@strapi/design-system";
|
|
6
|
-
import { Check, Cross, Sparkle, Lightning, Rocket, Crown } from "@strapi/icons";
|
|
7
|
-
const Container = styled(Box)`
|
|
8
|
-
padding: 32px;
|
|
9
|
-
max-width: 1400px;
|
|
10
|
-
margin: 0 auto;
|
|
11
|
-
`;
|
|
12
|
-
const Header = styled(Box)`
|
|
13
|
-
text-align: center;
|
|
14
|
-
margin-bottom: 48px;
|
|
15
|
-
display: flex;
|
|
16
|
-
flex-direction: column;
|
|
17
|
-
align-items: center;
|
|
18
|
-
gap: 8px;
|
|
19
|
-
`;
|
|
20
|
-
const Title = styled(Typography)`
|
|
21
|
-
font-size: 2.5rem;
|
|
22
|
-
font-weight: 700;
|
|
23
|
-
margin-bottom: 8px;
|
|
24
|
-
background: linear-gradient(135deg, #4945ff, #7c3aed);
|
|
25
|
-
-webkit-background-clip: text;
|
|
26
|
-
-webkit-text-fill-color: transparent;
|
|
27
|
-
display: block;
|
|
28
|
-
`;
|
|
29
|
-
const Subtitle = styled(Typography)`
|
|
30
|
-
font-size: 1.125rem;
|
|
31
|
-
color: ${(p) => p.theme.colors.neutral600};
|
|
32
|
-
line-height: 1.6;
|
|
33
|
-
display: block;
|
|
34
|
-
`;
|
|
35
|
-
const TierGrid = styled(Flex)`
|
|
36
|
-
gap: 32px;
|
|
37
|
-
margin: 0 auto 48px;
|
|
38
|
-
max-width: 1080px;
|
|
39
|
-
justify-content: center;
|
|
40
|
-
flex-wrap: wrap;
|
|
41
|
-
`;
|
|
42
|
-
const TierWrapper = styled(Box)`
|
|
43
|
-
flex: 1;
|
|
44
|
-
min-width: 280px;
|
|
45
|
-
max-width: 340px;
|
|
46
|
-
`;
|
|
47
|
-
const TierCard = styled(Box)`
|
|
48
|
-
background: ${(p) => p.theme.colors.neutral0};
|
|
49
|
-
border-radius: 16px;
|
|
50
|
-
padding: 32px;
|
|
51
|
-
border: 2px solid ${(props) => props.$featured ? "#4945ff" : props.theme.colors.neutral200};
|
|
52
|
-
position: relative;
|
|
53
|
-
transition: all 0.3s ease;
|
|
54
|
-
box-shadow: ${(props) => props.$featured ? "0 20px 25px -5px rgba(73, 69, 255, 0.25), 0 8px 10px -6px rgba(73, 69, 255, 0.2)" : "0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.05)"};
|
|
55
|
-
|
|
56
|
-
&:hover {
|
|
57
|
-
transform: translateY(-4px);
|
|
58
|
-
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
|
59
|
-
}
|
|
60
|
-
`;
|
|
61
|
-
const PopularBadge = styled(Badge)`
|
|
62
|
-
position: absolute;
|
|
63
|
-
top: -12px;
|
|
64
|
-
right: 24px;
|
|
65
|
-
background: linear-gradient(135deg, #4945ff, #4338ca);
|
|
66
|
-
color: white;
|
|
67
|
-
padding: 4px 16px;
|
|
68
|
-
font-size: 12px;
|
|
69
|
-
font-weight: 600;
|
|
70
|
-
`;
|
|
71
|
-
const TierIcon = styled(Box)`
|
|
72
|
-
width: 48px;
|
|
73
|
-
height: 48px;
|
|
74
|
-
border-radius: 12px;
|
|
75
|
-
display: flex;
|
|
76
|
-
align-items: center;
|
|
77
|
-
justify-content: center;
|
|
78
|
-
margin-bottom: 16px;
|
|
79
|
-
background: ${(props) => props.$color};
|
|
80
|
-
|
|
81
|
-
svg {
|
|
82
|
-
width: 28px;
|
|
83
|
-
height: 28px;
|
|
84
|
-
color: white;
|
|
85
|
-
}
|
|
86
|
-
`;
|
|
87
|
-
const TierName = styled(Typography)`
|
|
88
|
-
font-size: 1.5rem;
|
|
89
|
-
font-weight: 700;
|
|
90
|
-
margin-bottom: 8px;
|
|
91
|
-
color: ${(p) => p.theme.colors.neutral800};
|
|
92
|
-
`;
|
|
93
|
-
const TierPrice = styled(Typography)`
|
|
94
|
-
font-size: 2rem;
|
|
95
|
-
font-weight: 800;
|
|
96
|
-
margin-bottom: 4px;
|
|
97
|
-
color: ${(p) => p.theme.colors.neutral800};
|
|
98
|
-
`;
|
|
99
|
-
const TierDescription = styled(Typography)`
|
|
100
|
-
color: ${(p) => p.theme.colors.neutral600};
|
|
101
|
-
margin-bottom: 24px;
|
|
102
|
-
`;
|
|
103
|
-
const LimitsBox = styled(Box)`
|
|
104
|
-
background: ${(p) => p.theme.colors.neutral100};
|
|
105
|
-
border-radius: 8px;
|
|
106
|
-
padding: 12px;
|
|
107
|
-
margin-bottom: 20px;
|
|
108
|
-
`;
|
|
109
|
-
const LimitText = styled(Typography)`
|
|
110
|
-
font-size: 13px;
|
|
111
|
-
color: ${(p) => p.theme.colors.neutral800};
|
|
112
|
-
`;
|
|
113
|
-
const PeriodText = styled(Typography)`
|
|
114
|
-
color: ${(p) => p.theme.colors.neutral600};
|
|
115
|
-
`;
|
|
116
|
-
const FeatureText = styled(Typography)`
|
|
117
|
-
font-size: 14px;
|
|
118
|
-
color: ${(p) => p.$included ? p.theme.colors.neutral800 : p.theme.colors.neutral500};
|
|
119
|
-
text-decoration: ${(p) => p.$included ? "none" : "line-through"};
|
|
120
|
-
`;
|
|
121
|
-
const FeatureList = styled(Box)`
|
|
122
|
-
margin-bottom: 24px;
|
|
123
|
-
`;
|
|
124
|
-
const Feature = styled(Flex)`
|
|
125
|
-
gap: 12px;
|
|
126
|
-
margin-bottom: 12px;
|
|
127
|
-
align-items: flex-start;
|
|
128
|
-
`;
|
|
129
|
-
const FeatureIcon = styled(Box)`
|
|
130
|
-
width: 20px;
|
|
131
|
-
height: 20px;
|
|
132
|
-
border-radius: 50%;
|
|
133
|
-
display: flex;
|
|
134
|
-
align-items: center;
|
|
135
|
-
justify-content: center;
|
|
136
|
-
flex-shrink: 0;
|
|
137
|
-
margin-top: 2px;
|
|
138
|
-
|
|
139
|
-
${(props) => props.$included ? `
|
|
140
|
-
background: rgba(34, 197, 94, 0.15);
|
|
141
|
-
svg { color: #16A34A; }
|
|
142
|
-
` : `
|
|
143
|
-
background: rgba(220, 38, 38, 0.12);
|
|
144
|
-
svg { color: #DC2626; }
|
|
145
|
-
`}
|
|
146
|
-
`;
|
|
147
|
-
const UpgradeButton = styled(Button)`
|
|
148
|
-
width: 100%;
|
|
149
|
-
height: 48px;
|
|
150
|
-
font-weight: 600;
|
|
151
|
-
font-size: 15px;
|
|
152
|
-
background: ${(props) => props.$gradient};
|
|
153
|
-
border: none;
|
|
154
|
-
color: white;
|
|
155
|
-
|
|
156
|
-
&:hover {
|
|
157
|
-
transform: translateY(-2px);
|
|
158
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
159
|
-
}
|
|
160
|
-
`;
|
|
161
|
-
const CurrentPlanBadge = styled(Badge)`
|
|
162
|
-
width: 100%;
|
|
163
|
-
height: 48px;
|
|
164
|
-
display: flex;
|
|
165
|
-
align-items: center;
|
|
166
|
-
justify-content: center;
|
|
167
|
-
background: ${(p) => p.theme.colors.neutral100};
|
|
168
|
-
color: ${(p) => p.theme.colors.neutral600};
|
|
169
|
-
font-weight: 600;
|
|
170
|
-
font-size: 15px;
|
|
171
|
-
`;
|
|
172
|
-
const LicensePage = () => {
|
|
173
|
-
const { get, post } = useFetchClient();
|
|
174
|
-
const { toggleNotification } = useNotification();
|
|
175
|
-
const [currentTier, setCurrentTier] = useState("free");
|
|
176
|
-
const [limits, setLimits] = useState(null);
|
|
177
|
-
const [loading, setLoading] = useState(true);
|
|
178
|
-
useEffect(() => {
|
|
179
|
-
fetchLicenseInfo();
|
|
180
|
-
}, []);
|
|
181
|
-
const fetchLicenseInfo = async () => {
|
|
182
|
-
try {
|
|
183
|
-
const response = await get("/magic-link/license/status");
|
|
184
|
-
const licenseData = response.data?.data || response.data;
|
|
185
|
-
let tier = "free";
|
|
186
|
-
if (licenseData.features) {
|
|
187
|
-
if (licenseData.features.enterprise) {
|
|
188
|
-
tier = "enterprise";
|
|
189
|
-
} else if (licenseData.features.advanced) {
|
|
190
|
-
tier = "advanced";
|
|
191
|
-
} else if (licenseData.features.premium) {
|
|
192
|
-
tier = "premium";
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
setCurrentTier(tier);
|
|
196
|
-
setLoading(false);
|
|
197
|
-
} catch (error) {
|
|
198
|
-
console.error("Failed to fetch license info:", error);
|
|
199
|
-
setLoading(false);
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
const getTierRank = (tierId) => {
|
|
203
|
-
const ranks = {
|
|
204
|
-
"free": 0,
|
|
205
|
-
"premium": 1,
|
|
206
|
-
"advanced": 2,
|
|
207
|
-
"enterprise": 3
|
|
208
|
-
};
|
|
209
|
-
return ranks[tierId] || 0;
|
|
210
|
-
};
|
|
211
|
-
const getButtonText = (tierId) => {
|
|
212
|
-
const currentRank = getTierRank(currentTier);
|
|
213
|
-
const targetRank = getTierRank(tierId);
|
|
214
|
-
if (currentRank === targetRank) {
|
|
215
|
-
return "Current Plan";
|
|
216
|
-
} else if (targetRank > currentRank) {
|
|
217
|
-
return "Upgrade Now";
|
|
218
|
-
} else {
|
|
219
|
-
return "Downgrade";
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
const tiers = [
|
|
223
|
-
{
|
|
224
|
-
id: "free",
|
|
225
|
-
name: "FREE",
|
|
226
|
-
price: "$0",
|
|
227
|
-
period: "forever",
|
|
228
|
-
description: "Perfect for small projects and testing",
|
|
229
|
-
icon: /* @__PURE__ */ jsx(Sparkle, {}),
|
|
230
|
-
color: "linear-gradient(135deg, #6B7280, #4B5563)",
|
|
231
|
-
features: [
|
|
232
|
-
{ name: "Magic Link Authentication", included: true },
|
|
233
|
-
{ name: "Token Management", included: true },
|
|
234
|
-
{ name: "IP Banning & Security", included: true },
|
|
235
|
-
{ name: "Rate Limiting", included: true },
|
|
236
|
-
{ name: "JWT Session Management", included: true },
|
|
237
|
-
{ name: "Email OTP (2FA)", included: false },
|
|
238
|
-
{ name: "TOTP Authenticator", included: false },
|
|
239
|
-
{ name: "Advanced Analytics", included: false }
|
|
240
|
-
],
|
|
241
|
-
limits: {
|
|
242
|
-
authentication: "Magic Link Only",
|
|
243
|
-
mfa: "Not Available",
|
|
244
|
-
support: "Community"
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
id: "premium",
|
|
249
|
-
name: "PREMIUM",
|
|
250
|
-
price: "$14.50",
|
|
251
|
-
period: "/month",
|
|
252
|
-
description: "Enhanced security with Email OTP",
|
|
253
|
-
icon: /* @__PURE__ */ jsx(Lightning, {}),
|
|
254
|
-
color: "linear-gradient(135deg, #8B5CF6, #7C3AED)",
|
|
255
|
-
featured: true,
|
|
256
|
-
features: [
|
|
257
|
-
{ name: "Magic Link Authentication", included: true },
|
|
258
|
-
{ name: "Token Management", included: true },
|
|
259
|
-
{ name: "IP Banning & Security", included: true },
|
|
260
|
-
{ name: "Rate Limiting", included: true },
|
|
261
|
-
{ name: "JWT Session Management", included: true },
|
|
262
|
-
{ name: "Email OTP (2FA)", included: true },
|
|
263
|
-
{ name: "Configurable OTP Settings", included: true },
|
|
264
|
-
{ name: "TOTP Authenticator", included: false }
|
|
265
|
-
],
|
|
266
|
-
limits: {
|
|
267
|
-
authentication: "Magic Link + Email OTP",
|
|
268
|
-
mfa: "Email OTP",
|
|
269
|
-
support: "Priority Support"
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
id: "advanced",
|
|
274
|
-
name: "ADVANCED",
|
|
275
|
-
price: "$39.50",
|
|
276
|
-
period: "/month",
|
|
277
|
-
description: "Maximum security with TOTP MFA",
|
|
278
|
-
icon: /* @__PURE__ */ jsx(Rocket, {}),
|
|
279
|
-
color: "linear-gradient(135deg, #0EA5E9, #0284C7)",
|
|
280
|
-
features: [
|
|
281
|
-
{ name: "Magic Link Authentication", included: true },
|
|
282
|
-
{ name: "Token Management", included: true },
|
|
283
|
-
{ name: "IP Banning & Security", included: true },
|
|
284
|
-
{ name: "Rate Limiting", included: true },
|
|
285
|
-
{ name: "JWT Session Management", included: true },
|
|
286
|
-
{ name: "Email OTP (2FA)", included: true },
|
|
287
|
-
{ name: "TOTP Authenticator (MFA)", included: true },
|
|
288
|
-
{ name: "TOTP-Only Login", included: true }
|
|
289
|
-
],
|
|
290
|
-
limits: {
|
|
291
|
-
authentication: "All Modes",
|
|
292
|
-
mfa: "Email OTP + TOTP",
|
|
293
|
-
support: "Priority + Phone"
|
|
294
|
-
}
|
|
295
|
-
},
|
|
296
|
-
{
|
|
297
|
-
id: "enterprise",
|
|
298
|
-
name: "ENTERPRISE",
|
|
299
|
-
price: "Custom",
|
|
300
|
-
period: "pricing",
|
|
301
|
-
description: "Tailored solutions for large organizations",
|
|
302
|
-
icon: /* @__PURE__ */ jsx(Crown, {}),
|
|
303
|
-
color: "linear-gradient(135deg, #F59E0B, #D97706)",
|
|
304
|
-
features: [
|
|
305
|
-
{ name: "All Advanced Features", included: true },
|
|
306
|
-
{ name: "White-Label Options", included: true },
|
|
307
|
-
{ name: "Custom Integrations", included: true },
|
|
308
|
-
{ name: "Dedicated Support", included: true },
|
|
309
|
-
{ name: "SLA Guarantee", included: true },
|
|
310
|
-
{ name: "On-Premise Deployment", included: true },
|
|
311
|
-
{ name: "Custom MFA Providers", included: true },
|
|
312
|
-
{ name: "Training & Onboarding", included: true }
|
|
313
|
-
],
|
|
314
|
-
limits: {
|
|
315
|
-
authentication: "Unlimited",
|
|
316
|
-
mfa: "Custom Solutions",
|
|
317
|
-
support: "Dedicated Team"
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
];
|
|
321
|
-
const handleUpgrade = (tierId) => {
|
|
322
|
-
window.open("https://store.magicdx.dev/", "_blank");
|
|
323
|
-
};
|
|
324
|
-
if (loading) {
|
|
325
|
-
return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "400px" }, children: /* @__PURE__ */ jsx(Typography, { children: "Loading license information..." }) }) });
|
|
326
|
-
}
|
|
327
|
-
return /* @__PURE__ */ jsxs(Container, { children: [
|
|
328
|
-
/* @__PURE__ */ jsxs(Header, { children: [
|
|
329
|
-
/* @__PURE__ */ jsx(Title, { variant: "alpha", children: "Choose Your Plan" }),
|
|
330
|
-
/* @__PURE__ */ jsx(Subtitle, { variant: "omega", children: "Unlock powerful authentication features for your Strapi application" })
|
|
331
|
-
] }),
|
|
332
|
-
/* @__PURE__ */ jsx(TierGrid, { children: tiers.filter((tier) => tier.id !== "enterprise").map((tier) => /* @__PURE__ */ jsx(TierWrapper, { children: /* @__PURE__ */ jsxs(TierCard, { $featured: tier.featured, children: [
|
|
333
|
-
tier.featured && /* @__PURE__ */ jsx(PopularBadge, { children: "MOST POPULAR" }),
|
|
334
|
-
/* @__PURE__ */ jsx(TierIcon, { $color: tier.color, children: tier.icon }),
|
|
335
|
-
/* @__PURE__ */ jsx(TierName, { variant: "beta", children: tier.name }),
|
|
336
|
-
/* @__PURE__ */ jsxs(Flex, { alignItems: "baseline", gap: 1, children: [
|
|
337
|
-
/* @__PURE__ */ jsx(TierPrice, { variant: "alpha", children: tier.price }),
|
|
338
|
-
/* @__PURE__ */ jsx(PeriodText, { variant: "omega", children: tier.period })
|
|
339
|
-
] }),
|
|
340
|
-
/* @__PURE__ */ jsx(TierDescription, { variant: "omega", children: tier.description }),
|
|
341
|
-
/* @__PURE__ */ jsx(LimitsBox, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
|
342
|
-
/* @__PURE__ */ jsxs(LimitText, { variant: "pi", children: [
|
|
343
|
-
/* @__PURE__ */ jsx("strong", { children: "Authentication:" }),
|
|
344
|
-
" ",
|
|
345
|
-
tier.limits.authentication
|
|
346
|
-
] }),
|
|
347
|
-
/* @__PURE__ */ jsxs(LimitText, { variant: "pi", children: [
|
|
348
|
-
/* @__PURE__ */ jsx("strong", { children: "MFA:" }),
|
|
349
|
-
" ",
|
|
350
|
-
tier.limits.mfa
|
|
351
|
-
] }),
|
|
352
|
-
/* @__PURE__ */ jsxs(LimitText, { variant: "pi", children: [
|
|
353
|
-
/* @__PURE__ */ jsx("strong", { children: "Support:" }),
|
|
354
|
-
" ",
|
|
355
|
-
tier.limits.support
|
|
356
|
-
] })
|
|
357
|
-
] }) }),
|
|
358
|
-
/* @__PURE__ */ jsx(FeatureList, { children: tier.features.map((feature, index) => /* @__PURE__ */ jsxs(Feature, { children: [
|
|
359
|
-
/* @__PURE__ */ jsx(FeatureIcon, { $included: feature.included, children: feature.included ? /* @__PURE__ */ jsx(Check, { style: { width: 14, height: 14 } }) : /* @__PURE__ */ jsx(Cross, { style: { width: 14, height: 14 } }) }),
|
|
360
|
-
/* @__PURE__ */ jsx(FeatureText, { variant: "omega", $included: feature.included, children: feature.name })
|
|
361
|
-
] }, index)) }),
|
|
362
|
-
currentTier === tier.id ? /* @__PURE__ */ jsx(CurrentPlanBadge, { children: "Current Plan" }) : /* @__PURE__ */ jsx(
|
|
363
|
-
UpgradeButton,
|
|
364
|
-
{
|
|
365
|
-
$gradient: tier.color,
|
|
366
|
-
onClick: () => handleUpgrade(tier.id),
|
|
367
|
-
children: getButtonText(tier.id)
|
|
368
|
-
}
|
|
369
|
-
)
|
|
370
|
-
] }) }, tier.id)) })
|
|
371
|
-
] });
|
|
372
|
-
};
|
|
373
|
-
export {
|
|
374
|
-
LicensePage as default
|
|
375
|
-
};
|