strapi-plugin-magic-sessionmanager 4.2.3 → 4.2.5
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/dist/server/index.js +1 -1
- package/dist/server/index.mjs +1 -1
- package/package.json +1 -3
- package/admin/jsconfig.json +0 -10
- package/admin/src/components/Initializer.jsx +0 -11
- package/admin/src/components/LicenseGuard.jsx +0 -591
- package/admin/src/components/OnlineUsersWidget.jsx +0 -212
- package/admin/src/components/PluginIcon.jsx +0 -8
- package/admin/src/components/SessionDetailModal.jsx +0 -449
- package/admin/src/components/SessionInfoCard.jsx +0 -151
- package/admin/src/components/SessionInfoPanel.jsx +0 -385
- package/admin/src/components/index.jsx +0 -5
- package/admin/src/hooks/useLicense.js +0 -103
- package/admin/src/index.js +0 -149
- package/admin/src/pages/ActiveSessions.jsx +0 -12
- package/admin/src/pages/Analytics.jsx +0 -735
- package/admin/src/pages/App.jsx +0 -12
- package/admin/src/pages/HomePage.jsx +0 -1212
- package/admin/src/pages/License.jsx +0 -603
- package/admin/src/pages/Settings.jsx +0 -1646
- package/admin/src/pages/SettingsNew.jsx +0 -1204
- package/admin/src/pages/UpgradePage.jsx +0 -448
- package/admin/src/pages/index.jsx +0 -3
- package/admin/src/pluginId.js +0 -4
- package/admin/src/translations/de.json +0 -299
- package/admin/src/translations/en.json +0 -299
- package/admin/src/translations/es.json +0 -287
- package/admin/src/translations/fr.json +0 -287
- package/admin/src/translations/pt.json +0 -287
- package/admin/src/utils/getTranslation.js +0 -5
- package/admin/src/utils/index.js +0 -2
- package/admin/src/utils/parseUserAgent.js +0 -79
- package/admin/src/utils/theme.js +0 -85
- package/server/jsconfig.json +0 -10
- package/server/src/bootstrap.js +0 -492
- package/server/src/config/index.js +0 -23
- package/server/src/content-types/index.js +0 -9
- package/server/src/content-types/session/schema.json +0 -84
- package/server/src/controllers/controller.js +0 -11
- package/server/src/controllers/index.js +0 -11
- package/server/src/controllers/license.js +0 -266
- package/server/src/controllers/session.js +0 -433
- package/server/src/controllers/settings.js +0 -122
- package/server/src/destroy.js +0 -22
- package/server/src/index.js +0 -23
- package/server/src/middlewares/index.js +0 -5
- package/server/src/middlewares/last-seen.js +0 -62
- package/server/src/policies/index.js +0 -3
- package/server/src/register.js +0 -36
- package/server/src/routes/admin.js +0 -149
- package/server/src/routes/content-api.js +0 -60
- package/server/src/routes/index.js +0 -9
- package/server/src/services/geolocation.js +0 -182
- package/server/src/services/index.js +0 -13
- package/server/src/services/license-guard.js +0 -316
- package/server/src/services/notifications.js +0 -319
- package/server/src/services/service.js +0 -7
- package/server/src/services/session.js +0 -393
- package/server/src/utils/encryption.js +0 -121
- package/server/src/utils/getClientIp.js +0 -118
- package/server/src/utils/logger.js +0 -84
package/dist/server/index.js
CHANGED
package/dist/server/index.mjs
CHANGED
package/package.json
CHANGED
package/admin/jsconfig.json
DELETED
|
@@ -1,591 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import styled, { keyframes } from 'styled-components';
|
|
3
|
-
import {
|
|
4
|
-
Typography,
|
|
5
|
-
Box,
|
|
6
|
-
Flex,
|
|
7
|
-
Button,
|
|
8
|
-
TextInput,
|
|
9
|
-
Loader,
|
|
10
|
-
} from '@strapi/design-system';
|
|
11
|
-
import { useFetchClient, useNotification } from '@strapi/strapi/admin';
|
|
12
|
-
import { Check, Key, Cross } from '@strapi/icons';
|
|
13
|
-
import { useNavigate } from 'react-router-dom';
|
|
14
|
-
import pluginId from '../pluginId';
|
|
15
|
-
|
|
16
|
-
// Animations
|
|
17
|
-
const fadeIn = keyframes`
|
|
18
|
-
from { opacity: 0; }
|
|
19
|
-
to { opacity: 1; }
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
const slideUp = keyframes`
|
|
23
|
-
from {
|
|
24
|
-
opacity: 0;
|
|
25
|
-
transform: translateY(30px);
|
|
26
|
-
}
|
|
27
|
-
to {
|
|
28
|
-
opacity: 1;
|
|
29
|
-
transform: translateY(0);
|
|
30
|
-
}
|
|
31
|
-
`;
|
|
32
|
-
|
|
33
|
-
// Styled Components
|
|
34
|
-
const ModalOverlay = styled.div`
|
|
35
|
-
position: fixed;
|
|
36
|
-
top: 0;
|
|
37
|
-
left: 0;
|
|
38
|
-
right: 0;
|
|
39
|
-
bottom: 0;
|
|
40
|
-
background: rgba(4, 28, 47, 0.85);
|
|
41
|
-
backdrop-filter: blur(8px);
|
|
42
|
-
z-index: 9999;
|
|
43
|
-
display: flex;
|
|
44
|
-
align-items: center;
|
|
45
|
-
justify-content: center;
|
|
46
|
-
animation: ${fadeIn} 0.3s ease-out;
|
|
47
|
-
padding: 20px;
|
|
48
|
-
`;
|
|
49
|
-
|
|
50
|
-
const ModalContent = styled(Box)`
|
|
51
|
-
background: white;
|
|
52
|
-
border-radius: 16px;
|
|
53
|
-
width: 100%;
|
|
54
|
-
max-width: 580px;
|
|
55
|
-
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
|
|
56
|
-
animation: ${slideUp} 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
|
57
|
-
overflow: hidden;
|
|
58
|
-
`;
|
|
59
|
-
|
|
60
|
-
const GradientHeader = styled(Box)`
|
|
61
|
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
62
|
-
padding: 32px 40px;
|
|
63
|
-
position: relative;
|
|
64
|
-
overflow: hidden;
|
|
65
|
-
|
|
66
|
-
&::before {
|
|
67
|
-
content: '';
|
|
68
|
-
position: absolute;
|
|
69
|
-
top: -50%;
|
|
70
|
-
right: -50%;
|
|
71
|
-
width: 200%;
|
|
72
|
-
height: 200%;
|
|
73
|
-
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
|
|
74
|
-
}
|
|
75
|
-
`;
|
|
76
|
-
|
|
77
|
-
const IconWrapper = styled.div`
|
|
78
|
-
width: 72px;
|
|
79
|
-
height: 72px;
|
|
80
|
-
border-radius: 50%;
|
|
81
|
-
background: rgba(255, 255, 255, 0.2);
|
|
82
|
-
display: flex;
|
|
83
|
-
align-items: center;
|
|
84
|
-
justify-content: center;
|
|
85
|
-
margin: 0 auto 16px;
|
|
86
|
-
backdrop-filter: blur(10px);
|
|
87
|
-
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
88
|
-
|
|
89
|
-
svg {
|
|
90
|
-
width: 36px;
|
|
91
|
-
height: 36px;
|
|
92
|
-
color: white;
|
|
93
|
-
}
|
|
94
|
-
`;
|
|
95
|
-
|
|
96
|
-
const CloseButton = styled.button`
|
|
97
|
-
position: absolute;
|
|
98
|
-
top: 16px;
|
|
99
|
-
right: 16px;
|
|
100
|
-
background: rgba(255, 255, 255, 0.2);
|
|
101
|
-
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
102
|
-
border-radius: 50%;
|
|
103
|
-
width: 36px;
|
|
104
|
-
height: 36px;
|
|
105
|
-
display: flex;
|
|
106
|
-
align-items: center;
|
|
107
|
-
justify-content: center;
|
|
108
|
-
cursor: pointer;
|
|
109
|
-
transition: all 0.2s;
|
|
110
|
-
z-index: 10;
|
|
111
|
-
|
|
112
|
-
svg {
|
|
113
|
-
width: 20px;
|
|
114
|
-
height: 20px;
|
|
115
|
-
color: white;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
&:hover {
|
|
119
|
-
background: rgba(255, 255, 255, 0.3);
|
|
120
|
-
transform: scale(1.1);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
&:active {
|
|
124
|
-
transform: scale(0.95);
|
|
125
|
-
}
|
|
126
|
-
`;
|
|
127
|
-
|
|
128
|
-
const ToggleButton = styled.button`
|
|
129
|
-
background: none;
|
|
130
|
-
border: none;
|
|
131
|
-
color: #667eea;
|
|
132
|
-
font-size: 13px;
|
|
133
|
-
font-weight: 600;
|
|
134
|
-
cursor: pointer;
|
|
135
|
-
padding: 8px 0;
|
|
136
|
-
text-decoration: underline;
|
|
137
|
-
transition: color 0.2s;
|
|
138
|
-
|
|
139
|
-
&:hover {
|
|
140
|
-
color: #764ba2;
|
|
141
|
-
}
|
|
142
|
-
`;
|
|
143
|
-
|
|
144
|
-
const LicenseGuard = ({ children }) => {
|
|
145
|
-
const { get, post } = useFetchClient();
|
|
146
|
-
const { toggleNotification } = useNotification();
|
|
147
|
-
const navigate = useNavigate();
|
|
148
|
-
|
|
149
|
-
const [isChecking, setIsChecking] = useState(true);
|
|
150
|
-
const [needsLicense, setNeedsLicense] = useState(false);
|
|
151
|
-
const [isCreating, setIsCreating] = useState(false);
|
|
152
|
-
const [useExistingKey, setUseExistingKey] = useState(false);
|
|
153
|
-
const [useAutoCreate, setUseAutoCreate] = useState(true);
|
|
154
|
-
const [existingLicenseKey, setExistingLicenseKey] = useState('');
|
|
155
|
-
const [existingEmail, setExistingEmail] = useState('');
|
|
156
|
-
const [adminUser, setAdminUser] = useState(null);
|
|
157
|
-
|
|
158
|
-
const [formData, setFormData] = useState({
|
|
159
|
-
email: '',
|
|
160
|
-
firstName: '',
|
|
161
|
-
lastName: '',
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
useEffect(() => {
|
|
165
|
-
checkLicenseStatus();
|
|
166
|
-
fetchAdminUser();
|
|
167
|
-
}, []);
|
|
168
|
-
|
|
169
|
-
const fetchAdminUser = async () => {
|
|
170
|
-
try {
|
|
171
|
-
const response = await get('/admin/users/me');
|
|
172
|
-
const userData = response.data?.data || response.data;
|
|
173
|
-
if (userData) {
|
|
174
|
-
setAdminUser(userData);
|
|
175
|
-
setFormData({
|
|
176
|
-
email: userData.email || '',
|
|
177
|
-
firstName: userData.firstname || '',
|
|
178
|
-
lastName: userData.lastname || '',
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
} catch (error) {
|
|
182
|
-
// Silently fail - user might not be authenticated yet
|
|
183
|
-
console.debug('[LicenseGuard] Could not fetch admin user (not logged in yet)');
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
const checkLicenseStatus = async () => {
|
|
188
|
-
setIsChecking(true);
|
|
189
|
-
try {
|
|
190
|
-
const response = await get(`/${pluginId}/license/status`);
|
|
191
|
-
|
|
192
|
-
if (response.data.valid) {
|
|
193
|
-
setNeedsLicense(false);
|
|
194
|
-
} else {
|
|
195
|
-
setNeedsLicense(true);
|
|
196
|
-
}
|
|
197
|
-
} catch (error) {
|
|
198
|
-
console.error('[LicenseGuard] Error checking license:', error);
|
|
199
|
-
setNeedsLicense(true);
|
|
200
|
-
} finally {
|
|
201
|
-
setIsChecking(false);
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const handleAutoCreateLicense = async (e) => {
|
|
206
|
-
e.preventDefault();
|
|
207
|
-
setIsCreating(true);
|
|
208
|
-
|
|
209
|
-
try {
|
|
210
|
-
const response = await post(`/${pluginId}/license/auto-create`, {});
|
|
211
|
-
|
|
212
|
-
if (response.data && response.data.success) {
|
|
213
|
-
toggleNotification({
|
|
214
|
-
type: 'success',
|
|
215
|
-
message: 'License automatically created! Reloading...',
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
setNeedsLicense(false);
|
|
219
|
-
|
|
220
|
-
setTimeout(() => {
|
|
221
|
-
window.location.reload();
|
|
222
|
-
}, 500);
|
|
223
|
-
} else {
|
|
224
|
-
throw new Error('Failed to auto-create license');
|
|
225
|
-
}
|
|
226
|
-
} catch (error) {
|
|
227
|
-
console.error('[LicenseGuard] Error auto-creating license:', error);
|
|
228
|
-
toggleNotification({
|
|
229
|
-
type: 'danger',
|
|
230
|
-
message: error?.response?.data?.error?.message || 'Failed to auto-create license. Try manual creation.',
|
|
231
|
-
});
|
|
232
|
-
setIsCreating(false);
|
|
233
|
-
setUseAutoCreate(false);
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const handleCreateLicense = async (e) => {
|
|
238
|
-
e.preventDefault();
|
|
239
|
-
|
|
240
|
-
if (!formData.email || !formData.firstName || !formData.lastName) {
|
|
241
|
-
toggleNotification({
|
|
242
|
-
type: 'warning',
|
|
243
|
-
message: 'Please fill in all fields',
|
|
244
|
-
});
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
setIsCreating(true);
|
|
249
|
-
|
|
250
|
-
try {
|
|
251
|
-
const response = await post(`/${pluginId}/license/create`, formData);
|
|
252
|
-
|
|
253
|
-
if (response.data && response.data.success) {
|
|
254
|
-
toggleNotification({
|
|
255
|
-
type: 'success',
|
|
256
|
-
message: 'License created successfully! Reloading...',
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
setNeedsLicense(false);
|
|
260
|
-
|
|
261
|
-
setTimeout(() => {
|
|
262
|
-
window.location.reload();
|
|
263
|
-
}, 500);
|
|
264
|
-
} else {
|
|
265
|
-
throw new Error('Failed to create license');
|
|
266
|
-
}
|
|
267
|
-
} catch (error) {
|
|
268
|
-
console.error('[LicenseGuard] Error creating license:', error);
|
|
269
|
-
toggleNotification({
|
|
270
|
-
type: 'danger',
|
|
271
|
-
message: error?.response?.data?.error?.message || 'Failed to create license. Please try again.',
|
|
272
|
-
});
|
|
273
|
-
setIsCreating(false);
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const handleValidateExistingKey = async (e) => {
|
|
278
|
-
e.preventDefault();
|
|
279
|
-
|
|
280
|
-
if (!existingLicenseKey.trim() || !existingEmail.trim()) {
|
|
281
|
-
toggleNotification({
|
|
282
|
-
type: 'warning',
|
|
283
|
-
message: 'Please enter both license key and email address',
|
|
284
|
-
});
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
setIsCreating(true);
|
|
289
|
-
|
|
290
|
-
try {
|
|
291
|
-
const response = await post(`/${pluginId}/license/store-key`, {
|
|
292
|
-
licenseKey: existingLicenseKey.trim(),
|
|
293
|
-
email: existingEmail.trim(),
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
if (response.data && response.data.success) {
|
|
297
|
-
toggleNotification({
|
|
298
|
-
type: 'success',
|
|
299
|
-
message: 'License key validated successfully! Reloading...',
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
setNeedsLicense(false);
|
|
303
|
-
|
|
304
|
-
setTimeout(() => {
|
|
305
|
-
window.location.reload();
|
|
306
|
-
}, 500);
|
|
307
|
-
} else {
|
|
308
|
-
throw new Error('Invalid license key or email');
|
|
309
|
-
}
|
|
310
|
-
} catch (error) {
|
|
311
|
-
console.error('[LicenseGuard] Error validating license key:', error);
|
|
312
|
-
toggleNotification({
|
|
313
|
-
type: 'danger',
|
|
314
|
-
message: error?.response?.data?.error?.message || 'Invalid license key or email address. Please check and try again.',
|
|
315
|
-
});
|
|
316
|
-
setIsCreating(false);
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
const handleClose = () => {
|
|
321
|
-
navigate('/content-manager');
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
if (isChecking) {
|
|
325
|
-
return (
|
|
326
|
-
<Box padding={8} style={{ textAlign: 'center' }}>
|
|
327
|
-
<Loader>Checking license...</Loader>
|
|
328
|
-
</Box>
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
if (needsLicense) {
|
|
333
|
-
return (
|
|
334
|
-
<ModalOverlay>
|
|
335
|
-
<ModalContent>
|
|
336
|
-
<GradientHeader>
|
|
337
|
-
<CloseButton onClick={handleClose} type="button">
|
|
338
|
-
<Cross />
|
|
339
|
-
</CloseButton>
|
|
340
|
-
<IconWrapper>
|
|
341
|
-
<Key />
|
|
342
|
-
</IconWrapper>
|
|
343
|
-
<Box style={{ textAlign: 'center', position: 'relative' }}>
|
|
344
|
-
<Typography
|
|
345
|
-
variant="alpha"
|
|
346
|
-
style={{
|
|
347
|
-
color: 'white',
|
|
348
|
-
fontSize: '24px',
|
|
349
|
-
fontWeight: '700',
|
|
350
|
-
marginBottom: '12px',
|
|
351
|
-
display: 'block',
|
|
352
|
-
}}
|
|
353
|
-
>
|
|
354
|
-
🔐 Activate Session Manager
|
|
355
|
-
</Typography>
|
|
356
|
-
<Typography
|
|
357
|
-
variant="epsilon"
|
|
358
|
-
style={{
|
|
359
|
-
color: 'rgba(255, 255, 255, 0.9)',
|
|
360
|
-
fontSize: '14px',
|
|
361
|
-
display: 'block',
|
|
362
|
-
}}
|
|
363
|
-
>
|
|
364
|
-
{useExistingKey ? 'Enter your existing license key' : 'Create a license to start using the plugin'}
|
|
365
|
-
</Typography>
|
|
366
|
-
</Box>
|
|
367
|
-
</GradientHeader>
|
|
368
|
-
|
|
369
|
-
<form onSubmit={useExistingKey ? handleValidateExistingKey : (useAutoCreate ? handleAutoCreateLicense : handleCreateLicense)}>
|
|
370
|
-
<Box
|
|
371
|
-
padding={6}
|
|
372
|
-
paddingLeft={8}
|
|
373
|
-
paddingRight={8}
|
|
374
|
-
>
|
|
375
|
-
<Flex direction="column" gap={5} style={{ width: '100%' }}>
|
|
376
|
-
<Box style={{ textAlign: 'center', width: '100%' }}>
|
|
377
|
-
{!useExistingKey && (
|
|
378
|
-
<ToggleButton
|
|
379
|
-
type="button"
|
|
380
|
-
onClick={() => setUseAutoCreate(!useAutoCreate)}
|
|
381
|
-
disabled={isCreating}
|
|
382
|
-
style={{ marginBottom: '8px', display: 'block', margin: '0 auto' }}
|
|
383
|
-
>
|
|
384
|
-
{useAutoCreate ? '→ Manual entry' : '← Auto-create with my account'}
|
|
385
|
-
</ToggleButton>
|
|
386
|
-
)}
|
|
387
|
-
<ToggleButton
|
|
388
|
-
type="button"
|
|
389
|
-
onClick={() => {
|
|
390
|
-
setUseExistingKey(!useExistingKey);
|
|
391
|
-
if (!useExistingKey) setUseAutoCreate(false);
|
|
392
|
-
}}
|
|
393
|
-
disabled={isCreating}
|
|
394
|
-
>
|
|
395
|
-
{useExistingKey ? '← Create new license' : 'Have a license key? →'}
|
|
396
|
-
</ToggleButton>
|
|
397
|
-
</Box>
|
|
398
|
-
|
|
399
|
-
<Box
|
|
400
|
-
background="primary100"
|
|
401
|
-
padding={4}
|
|
402
|
-
style={{
|
|
403
|
-
borderRadius: '8px',
|
|
404
|
-
border: '2px solid #BAE6FD',
|
|
405
|
-
width: '100%',
|
|
406
|
-
}}
|
|
407
|
-
>
|
|
408
|
-
<Typography variant="omega" style={{ fontSize: '13px', lineHeight: '1.6' }}>
|
|
409
|
-
{useExistingKey
|
|
410
|
-
? 'Enter your email and license key to activate.'
|
|
411
|
-
: useAutoCreate && adminUser && adminUser.email
|
|
412
|
-
? `Click "Activate" to auto-create a license with your account (${adminUser.email})`
|
|
413
|
-
: useAutoCreate
|
|
414
|
-
? 'Click "Activate" to auto-create a license with your admin account'
|
|
415
|
-
: 'A license will be created with the details below.'
|
|
416
|
-
}
|
|
417
|
-
</Typography>
|
|
418
|
-
</Box>
|
|
419
|
-
|
|
420
|
-
{useExistingKey ? (
|
|
421
|
-
// Existing License Key Input
|
|
422
|
-
<>
|
|
423
|
-
<Box style={{ width: '100%' }}>
|
|
424
|
-
<Typography
|
|
425
|
-
variant="pi"
|
|
426
|
-
fontWeight="bold"
|
|
427
|
-
style={{ marginBottom: '8px', display: 'block' }}
|
|
428
|
-
>
|
|
429
|
-
Email Address *
|
|
430
|
-
</Typography>
|
|
431
|
-
<TextInput
|
|
432
|
-
placeholder="admin@example.com"
|
|
433
|
-
type="email"
|
|
434
|
-
value={existingEmail}
|
|
435
|
-
onChange={(e) => setExistingEmail(e.target.value)}
|
|
436
|
-
required
|
|
437
|
-
disabled={isCreating}
|
|
438
|
-
/>
|
|
439
|
-
<Typography variant="omega" textColor="neutral600" style={{ fontSize: '11px', marginTop: '4px' }}>
|
|
440
|
-
Enter the email address associated with this license
|
|
441
|
-
</Typography>
|
|
442
|
-
</Box>
|
|
443
|
-
|
|
444
|
-
<Box style={{ width: '100%' }}>
|
|
445
|
-
<Typography
|
|
446
|
-
variant="pi"
|
|
447
|
-
fontWeight="bold"
|
|
448
|
-
style={{ marginBottom: '8px', display: 'block' }}
|
|
449
|
-
>
|
|
450
|
-
License Key *
|
|
451
|
-
</Typography>
|
|
452
|
-
<TextInput
|
|
453
|
-
placeholder="67C5-40D2-7695-718C"
|
|
454
|
-
value={existingLicenseKey}
|
|
455
|
-
onChange={(e) => setExistingLicenseKey(e.target.value)}
|
|
456
|
-
required
|
|
457
|
-
disabled={isCreating}
|
|
458
|
-
/>
|
|
459
|
-
<Typography variant="omega" textColor="neutral600" style={{ fontSize: '11px', marginTop: '4px' }}>
|
|
460
|
-
Enter the license key in the format: XXXX-XXXX-XXXX-XXXX
|
|
461
|
-
</Typography>
|
|
462
|
-
</Box>
|
|
463
|
-
</>
|
|
464
|
-
) : useAutoCreate && adminUser ? (
|
|
465
|
-
// Auto-create mode - Show user info
|
|
466
|
-
<Box
|
|
467
|
-
background="success100"
|
|
468
|
-
padding={5}
|
|
469
|
-
style={{
|
|
470
|
-
borderRadius: '8px',
|
|
471
|
-
border: '2px solid #DCFCE7',
|
|
472
|
-
textAlign: 'center',
|
|
473
|
-
}}
|
|
474
|
-
>
|
|
475
|
-
<Typography variant="omega" fontWeight="bold" style={{ marginBottom: '12px', display: 'block' }}>
|
|
476
|
-
Ready to activate with your account:
|
|
477
|
-
</Typography>
|
|
478
|
-
<Typography variant="pi" style={{ marginBottom: '4px', display: 'block' }}>
|
|
479
|
-
{adminUser.firstname || 'Admin'} {adminUser.lastname || 'User'}
|
|
480
|
-
</Typography>
|
|
481
|
-
<Typography variant="pi" textColor="neutral600">
|
|
482
|
-
{adminUser.email || 'Loading...'}
|
|
483
|
-
</Typography>
|
|
484
|
-
</Box>
|
|
485
|
-
) : (
|
|
486
|
-
// Manual Create License Fields
|
|
487
|
-
<>
|
|
488
|
-
<Box style={{ width: '100%' }}>
|
|
489
|
-
<Typography
|
|
490
|
-
variant="pi"
|
|
491
|
-
fontWeight="bold"
|
|
492
|
-
style={{ marginBottom: '8px', display: 'block' }}
|
|
493
|
-
>
|
|
494
|
-
Email Address *
|
|
495
|
-
</Typography>
|
|
496
|
-
<TextInput
|
|
497
|
-
placeholder="admin@example.com"
|
|
498
|
-
type="email"
|
|
499
|
-
value={formData.email}
|
|
500
|
-
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
501
|
-
required
|
|
502
|
-
disabled={isCreating}
|
|
503
|
-
/>
|
|
504
|
-
</Box>
|
|
505
|
-
|
|
506
|
-
<Box style={{ width: '100%' }}>
|
|
507
|
-
<Typography
|
|
508
|
-
variant="pi"
|
|
509
|
-
fontWeight="bold"
|
|
510
|
-
style={{ marginBottom: '8px', display: 'block' }}
|
|
511
|
-
>
|
|
512
|
-
First Name *
|
|
513
|
-
</Typography>
|
|
514
|
-
<TextInput
|
|
515
|
-
placeholder="John"
|
|
516
|
-
value={formData.firstName}
|
|
517
|
-
onChange={(e) => setFormData({ ...formData, firstName: e.target.value })}
|
|
518
|
-
required
|
|
519
|
-
disabled={isCreating}
|
|
520
|
-
/>
|
|
521
|
-
</Box>
|
|
522
|
-
|
|
523
|
-
<Box style={{ width: '100%' }}>
|
|
524
|
-
<Typography
|
|
525
|
-
variant="pi"
|
|
526
|
-
fontWeight="bold"
|
|
527
|
-
style={{ marginBottom: '8px', display: 'block' }}
|
|
528
|
-
>
|
|
529
|
-
Last Name *
|
|
530
|
-
</Typography>
|
|
531
|
-
<TextInput
|
|
532
|
-
placeholder="Doe"
|
|
533
|
-
value={formData.lastName}
|
|
534
|
-
onChange={(e) => setFormData({ ...formData, lastName: e.target.value })}
|
|
535
|
-
required
|
|
536
|
-
disabled={isCreating}
|
|
537
|
-
/>
|
|
538
|
-
</Box>
|
|
539
|
-
</>
|
|
540
|
-
)}
|
|
541
|
-
|
|
542
|
-
<Flex gap={3} justifyContent="center" style={{ marginTop: '16px' }}>
|
|
543
|
-
{useExistingKey ? (
|
|
544
|
-
<Button
|
|
545
|
-
type="submit"
|
|
546
|
-
size="L"
|
|
547
|
-
startIcon={<Check />}
|
|
548
|
-
loading={isCreating}
|
|
549
|
-
disabled={isCreating || !existingLicenseKey.trim() || !existingEmail.trim()}
|
|
550
|
-
style={{
|
|
551
|
-
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
552
|
-
color: 'white',
|
|
553
|
-
fontWeight: '600',
|
|
554
|
-
border: 'none',
|
|
555
|
-
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)',
|
|
556
|
-
}}
|
|
557
|
-
>
|
|
558
|
-
Validate License
|
|
559
|
-
</Button>
|
|
560
|
-
) : (
|
|
561
|
-
<Button
|
|
562
|
-
type="submit"
|
|
563
|
-
size="L"
|
|
564
|
-
startIcon={<Check />}
|
|
565
|
-
loading={isCreating}
|
|
566
|
-
disabled={isCreating || (!useAutoCreate && (!formData.email || !formData.firstName || !formData.lastName))}
|
|
567
|
-
style={{
|
|
568
|
-
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
569
|
-
color: 'white',
|
|
570
|
-
fontWeight: '600',
|
|
571
|
-
border: 'none',
|
|
572
|
-
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.4)',
|
|
573
|
-
}}
|
|
574
|
-
>
|
|
575
|
-
{useAutoCreate ? 'Activate License' : 'Create License'}
|
|
576
|
-
</Button>
|
|
577
|
-
)}
|
|
578
|
-
</Flex>
|
|
579
|
-
</Flex>
|
|
580
|
-
</Box>
|
|
581
|
-
</form>
|
|
582
|
-
</ModalContent>
|
|
583
|
-
</ModalOverlay>
|
|
584
|
-
);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
return <>{children}</>;
|
|
588
|
-
};
|
|
589
|
-
|
|
590
|
-
export default LicenseGuard;
|
|
591
|
-
|