strapi-plugin-magic-link-v5 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.eslintignore +1 -0
  2. package/.github/workflows/semantic-release.yml +27 -0
  3. package/README.md +318 -0
  4. package/admin/jsconfig.json +10 -0
  5. package/admin/src/components/Initializer/index.jsx +20 -0
  6. package/admin/src/components/Initializer.jsx +18 -0
  7. package/admin/src/components/LazyComponentLoader.jsx +27 -0
  8. package/admin/src/components/PluginIcon/index.jsx +6 -0
  9. package/admin/src/components/PluginIcon.jsx +5 -0
  10. package/admin/src/index.js +101 -0
  11. package/admin/src/pages/App/index.jsx +50 -0
  12. package/admin/src/pages/App.jsx +15 -0
  13. package/admin/src/pages/HomePage/index.js +2 -0
  14. package/admin/src/pages/HomePage/index.jsx +228 -0
  15. package/admin/src/pages/HomePage.jsx +655 -0
  16. package/admin/src/pages/Settings/index.jsx +1289 -0
  17. package/admin/src/pages/Settings/utils/api.js +13 -0
  18. package/admin/src/pages/Settings/utils/index.js +5 -0
  19. package/admin/src/pages/Settings/utils/layout.js +100 -0
  20. package/admin/src/pages/Settings/utils/schema.js +18 -0
  21. package/admin/src/pages/Tokens/index.jsx +2250 -0
  22. package/admin/src/permissions.js +7 -0
  23. package/admin/src/pluginId.js +3 -0
  24. package/admin/src/routes.js +40 -0
  25. package/admin/src/translations/de.json +188 -0
  26. package/admin/src/translations/en.json +189 -0
  27. package/admin/src/utils/getRequestURL.js +5 -0
  28. package/admin/src/utils/getTrad.js +17 -0
  29. package/admin/src/utils/getTranslation.js +3 -0
  30. package/admin/src/utils/index.js +4 -0
  31. package/build.js +75 -0
  32. package/package.json +59 -0
  33. package/server/bootstrap.js +127 -0
  34. package/server/controllers/settings.js +122 -0
  35. package/server/jsconfig.json +10 -0
  36. package/server/services/store.js +35 -0
  37. package/server/src/bootstrap.js +110 -0
  38. package/server/src/config/index.js +6 -0
  39. package/server/src/content-types/index.js +7 -0
  40. package/server/src/content-types/token/index.js +5 -0
  41. package/server/src/content-types/token/schema.json +47 -0
  42. package/server/src/controllers/auth.js +211 -0
  43. package/server/src/controllers/controller.js +213 -0
  44. package/server/src/controllers/index.js +16 -0
  45. package/server/src/controllers/jwt.js +261 -0
  46. package/server/src/controllers/tokens.js +654 -0
  47. package/server/src/destroy.js +5 -0
  48. package/server/src/index.js +33 -0
  49. package/server/src/middlewares/index.js +3 -0
  50. package/server/src/policies/index.js +3 -0
  51. package/server/src/register.js +5 -0
  52. package/server/src/routes/admin.js +160 -0
  53. package/server/src/routes/content-api.js +27 -0
  54. package/server/src/routes/index.js +9 -0
  55. package/server/src/services/index.js +11 -0
  56. package/server/src/services/magic-link.js +356 -0
  57. package/server/src/services/service.js +13 -0
  58. package/server/utils/index.js +14 -0
  59. package/strapi-admin.js +82 -0
  60. package/strapi-server.js +4 -0
  61. package/vite.config.js +36 -0
@@ -0,0 +1,655 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import {
3
+ Box,
4
+ Typography,
5
+ Main,
6
+ Flex,
7
+ Button,
8
+ Card,
9
+ Divider,
10
+ Badge,
11
+ ProgressBar
12
+ } from '@strapi/design-system';
13
+ import {
14
+ ArrowRight,
15
+ Cog,
16
+ Key,
17
+ Shield,
18
+ Check,
19
+ PuzzlePiece,
20
+ ExternalLink,
21
+ User,
22
+ Pencil,
23
+ Information,
24
+ Calendar
25
+ } from '@strapi/icons';
26
+ import { useFetchClient } from '@strapi/helper-plugin';
27
+
28
+ const HomePage = () => {
29
+ const { get } = useFetchClient();
30
+ const [activeTab, setActiveTab] = useState('dashboard');
31
+ const [stats, setStats] = useState({
32
+ activeTokens: 0,
33
+ tokenUsage: 0,
34
+ usersUsingMagicLink: 0,
35
+ securityScore: 85,
36
+ tokenCreatedLast24h: 0,
37
+ tokenExpiresNextDays: 0
38
+ });
39
+ const [isLoading, setIsLoading] = useState(true);
40
+
41
+ // API-Anfrage, um echte Token-Daten zu laden
42
+ useEffect(() => {
43
+ const fetchTokenData = async () => {
44
+ try {
45
+ setIsLoading(true);
46
+ const response = await get('/magic-link/tokens');
47
+ const { data, meta } = response.data || { data: [], meta: {} };
48
+
49
+ if (data && Array.isArray(data)) {
50
+ // Aktive Tokens zählen
51
+ const activeTokens = data.filter(token =>
52
+ token.is_active && new Date(token.expires_at) > new Date()
53
+ ).length;
54
+
55
+ // Unique Benutzer mit Magic Link zählen
56
+ const uniqueUsers = new Set(data.map(token => token.email).filter(Boolean)).size;
57
+
58
+ // Token, die in den letzten 24 Stunden erstellt wurden
59
+ const oneDayAgo = new Date();
60
+ oneDayAgo.setDate(oneDayAgo.getDate() - 1);
61
+ const tokenCreatedLast24h = data.filter(token =>
62
+ new Date(token.createdAt) > oneDayAgo
63
+ ).length;
64
+
65
+ // Token, die in den nächsten 3 Tagen ablaufen
66
+ const threeDaysFromNow = new Date();
67
+ threeDaysFromNow.setDate(threeDaysFromNow.getDate() + 3);
68
+ const tokenExpiresNextDays = data.filter(token => {
69
+ const expiryDate = new Date(token.expires_at);
70
+ return expiryDate > new Date() && expiryDate < threeDaysFromNow;
71
+ }).length;
72
+
73
+ // Token-Nutzung berechnen (Prozentsatz der aktiven Tokens im Verhältnis zu allen)
74
+ const tokenUsage = data.length > 0
75
+ ? Math.round((activeTokens / data.length) * 100)
76
+ : 0;
77
+
78
+ // Sicherheitswert aus den Metadaten oder Fallback verwenden
79
+ const securityScore = meta?.securityScore || 85;
80
+
81
+ setStats({
82
+ activeTokens,
83
+ tokenUsage,
84
+ usersUsingMagicLink: uniqueUsers,
85
+ securityScore, // Dynamischer Wert aus der API
86
+ tokenCreatedLast24h,
87
+ tokenExpiresNextDays: tokenExpiresNextDays // Umbenennen von tokenExpiresNextHour zu tokenExpiresNextDays
88
+ });
89
+ }
90
+ } catch (error) {
91
+ console.error('Fehler beim Laden der Token-Daten:', error);
92
+ } finally {
93
+ setIsLoading(false);
94
+ }
95
+ };
96
+
97
+ fetchTokenData();
98
+
99
+ // Aktualisiere die Daten alle 30 Sekunden
100
+ const interval = setInterval(fetchTokenData, 30000);
101
+ return () => clearInterval(interval);
102
+ }, [get]);
103
+
104
+ return (
105
+ <Main>
106
+ <Box
107
+ background="neutral0"
108
+ paddingTop={6}
109
+ paddingBottom={6}
110
+ paddingLeft={7}
111
+ paddingRight={7}
112
+ hasRadius
113
+ shadow="tableShadow"
114
+ >
115
+ <Flex direction="column" gap={5}>
116
+ <Flex justifyContent="space-between" alignItems="center" gap={4}>
117
+ <Flex direction="column" alignItems="center">
118
+ <Typography variant="alpha" fontWeight="bold" textColor="neutral900">
119
+ Magic Link Verwaltung
120
+ </Typography>
121
+ <Box paddingTop={1}>
122
+ <Typography variant="zeta" textColor="neutral600" textAlign="center">
123
+ Zentrale Übersicht für Magic Links und JWT-Sessions
124
+ </Typography>
125
+ </Box>
126
+ </Flex>
127
+
128
+
129
+ </Flex>
130
+
131
+ <Divider />
132
+
133
+ {/* Tab Navigation */}
134
+ <Box padding={1} background="neutral100" hasRadius>
135
+ <Flex gap={2} justifyContent="center" padding={2}>
136
+ <Button
137
+ variant={activeTab === 'dashboard' ? "primary" : "tertiary"}
138
+ onClick={() => setActiveTab('dashboard')}
139
+ >
140
+ Dashboard
141
+ </Button>
142
+ <Button
143
+ variant={activeTab === 'features' ? "primary" : "tertiary"}
144
+ onClick={() => setActiveTab('features')}
145
+ >
146
+ Funktionen
147
+ </Button>
148
+ <Button
149
+ variant={activeTab === 'status' ? "primary" : "tertiary"}
150
+ onClick={() => setActiveTab('status')}
151
+ >
152
+ System-Status
153
+ </Button>
154
+ </Flex>
155
+ </Box>
156
+
157
+ {/* Tab Content */}
158
+ {activeTab === 'dashboard' && (
159
+ <Box paddingTop={4}>
160
+ <Flex direction="column" gap={4}>
161
+ {/* Statistik-Karten */}
162
+ <Flex gap={4} wrap="wrap" style={{ margin: '-8px' }}>
163
+ <Box padding={2} style={{ flex: '1 1 25%', minWidth: '250px' }}>
164
+ <Card shadow="tableShadow" background="neutral0" hasRadius height="100%">
165
+ <Box padding={4}>
166
+ <Flex direction="column" gap={2}>
167
+ <Box paddingBottom={1} style={{ textAlign: 'right' }}>
168
+ <Box background="primary100" padding={2} style={{ display: 'inline-block', borderRadius: '50%' }}>
169
+ <Key width="1.5rem" height="1.5rem" color="primary600" />
170
+ </Box>
171
+ <Badge active style={{ marginLeft: '0.5rem' }}>AKTIV</Badge>
172
+ </Box>
173
+ <Box>
174
+ <Flex direction="column" gap={1}>
175
+ <Typography variant="beta" fontWeight="bold" textColor="primary700">
176
+ {stats.activeTokens}
177
+ </Typography>
178
+ <Typography
179
+ variant="zeta"
180
+ textColor="neutral500"
181
+ fontWeight="medium"
182
+ textTransform="uppercase"
183
+ >
184
+ Aktive Tokens
185
+ </Typography>
186
+ </Flex>
187
+ </Box>
188
+ <Typography variant="pi" textColor="neutral500">
189
+ Letzte Aktualisierung: {new Date().toLocaleTimeString()}
190
+ </Typography>
191
+ </Flex>
192
+ </Box>
193
+ </Card>
194
+ </Box>
195
+
196
+ <Box padding={2} style={{ flex: '1 1 25%', minWidth: '250px' }}>
197
+ <Card shadow="tableShadow" background="neutral0" hasRadius height="100%">
198
+ <Box padding={4}>
199
+ <Flex direction="column" gap={2}>
200
+ <Box paddingBottom={1} style={{ textAlign: 'right' }}>
201
+ <Box background="secondary100" padding={2} style={{ display: 'inline-block', borderRadius: '50%' }}>
202
+ <User width="1.5rem" height="1.5rem" color="secondary600" />
203
+ </Box>
204
+ <Badge active style={{ marginLeft: '0.5rem' }}>AKTIV</Badge>
205
+ </Box>
206
+ <Box>
207
+ <Flex direction="column" gap={1}>
208
+ <Typography
209
+ variant="beta"
210
+ fontWeight="bold"
211
+ textColor="primary700"
212
+ >
213
+ {stats.usersUsingMagicLink}
214
+ </Typography>
215
+ <Typography
216
+ variant="zeta"
217
+ textColor="neutral500"
218
+ fontWeight="medium"
219
+ textTransform="uppercase"
220
+ >
221
+ Benutzer mit Magic Link
222
+ </Typography>
223
+ </Flex>
224
+ </Box>
225
+ <Flex justifyContent="space-between" style={{ marginTop: 'auto' }}>
226
+ <Typography variant="pi" textColor="neutral600">
227
+ Neu heute:
228
+ </Typography>
229
+ <Typography variant="pi" fontWeight="bold">
230
+ {stats.tokenCreatedLast24h}
231
+ </Typography>
232
+ </Flex>
233
+ </Flex>
234
+ </Box>
235
+ </Card>
236
+ </Box>
237
+
238
+ <Box padding={2} style={{ flex: '1 1 25%', minWidth: '250px' }}>
239
+ <Card shadow="tableShadow" background="neutral0" hasRadius height="100%">
240
+ <Box padding={4}>
241
+ <Flex direction="column" gap={2}>
242
+ <Box paddingBottom={1} style={{ textAlign: 'right' }}>
243
+ <Box background="success100" padding={2} style={{ display: 'inline-block', borderRadius: '50%' }}>
244
+ <Calendar width="1.5rem" height="1.5rem" color="success600" />
245
+ </Box>
246
+ <Badge style={{ marginLeft: '0.5rem' }}>LETZTE 24H</Badge>
247
+ </Box>
248
+ <Box>
249
+ <Flex direction="column" gap={0}>
250
+ <Typography
251
+ variant="gamma" // Changed from beta to gamma for even smaller size
252
+ fontWeight="bold"
253
+ textColor="primary700"
254
+ >
255
+ {stats.tokenUsage}%
256
+ </Typography>
257
+ <Typography
258
+ variant="zeta"
259
+ textColor="neutral500"
260
+ fontWeight="medium"
261
+ textTransform="uppercase"
262
+ style={{ fontSize: '0.75rem' }} // Added explicit smaller font size
263
+ >
264
+ Token-Nutzung
265
+ </Typography>
266
+ </Flex>
267
+ </Box>
268
+ <Box paddingTop={1}>
269
+ <ProgressBar value={stats.tokenUsage} size="S" />
270
+ <Flex justifyContent="space-between" paddingTop={1}>
271
+ <Typography variant="pi" textColor="neutral600">
272
+ Erstellt:
273
+ </Typography>
274
+ <Typography variant="pi" fontWeight="bold">
275
+ {stats.tokenCreatedLast24h}
276
+ </Typography>
277
+ </Flex>
278
+ </Box>
279
+ </Flex>
280
+ </Box>
281
+ </Card>
282
+ </Box>
283
+
284
+ <Box padding={2} style={{ flex: '1 1 25%', minWidth: '250px' }}>
285
+ <Card shadow="tableShadow" background="neutral0" hasRadius height="100%">
286
+ <Box padding={4}>
287
+ <Flex direction="column" gap={2}>
288
+ <Box paddingBottom={1} style={{ textAlign: 'right' }}>
289
+ <Box background="danger100" padding={2} style={{ display: 'inline-block', borderRadius: '50%' }}>
290
+ <Shield width="1.5rem" height="1.5rem" color="danger600" />
291
+ </Box>
292
+ <Badge style={{ marginLeft: '0.5rem' }}>SICHERHEIT</Badge>
293
+ </Box>
294
+ <Box>
295
+ <Flex direction="column" gap={1}>
296
+ <Typography
297
+ variant="beta"
298
+ fontWeight="bold"
299
+ textColor="primary700"
300
+ >
301
+ {stats.securityScore}/100
302
+ </Typography>
303
+ <Box paddingTop={1}>
304
+ <Typography
305
+ variant="zeta"
306
+ textColor="neutral600"
307
+ fontWeight="medium"
308
+ textTransform="uppercase"
309
+ style={{ fontSize: '0.75rem' }}
310
+ >
311
+ Sicherheitswert
312
+ </Typography>
313
+ </Box>
314
+ </Flex>
315
+ </Box>
316
+ <Box paddingTop={1}>
317
+ <ProgressBar value={stats.securityScore} size="S" />
318
+ <Flex justifyContent="space-between" paddingTop={1}>
319
+ <Typography variant="pi" textColor="neutral600">
320
+ Ablaufend (3 Tage):
321
+ </Typography>
322
+ <Typography variant="pi" fontWeight="bold">
323
+ {stats.tokenExpiresNextDays}
324
+ </Typography>
325
+ </Flex>
326
+ </Box>
327
+ </Flex>
328
+ </Box>
329
+ </Card>
330
+ </Box>
331
+ </Flex>
332
+
333
+ {/* Aktionsfläche */}
334
+ <Box paddingTop={4}>
335
+ <Typography variant="delta" fontWeight="bold" marginBottom={4}>
336
+ Schnellzugriff
337
+ </Typography>
338
+ <br />
339
+ <Flex gap={4} wrap="wrap" marginTop={4}>
340
+ <Box style={{ flex: '1 1 50%', minWidth: '300px' }}>
341
+ <Card shadow="tableShadow" hasRadius>
342
+ <Flex gap={3} alignItems="center" padding={4}>
343
+ <Box background="primary100" padding={3} hasRadius>
344
+ <ExternalLink width="1.5rem" height="1.5rem" color="primary600" />
345
+ </Box>
346
+ <Box style={{ flex: 1 }}>
347
+ <Typography variant="delta">Token-Verwaltung</Typography>
348
+ <br></br>
349
+ <Typography variant="pi" textColor="neutral600">
350
+ Aktive Tokens anzeigen und verwalten
351
+ </Typography>
352
+ </Box>
353
+ <Button
354
+ variant="default"
355
+ endIcon={<ArrowRight />}
356
+ onClick={() => {
357
+ window.location.href = '/admin/plugins/magic-link/tokens';
358
+ }}
359
+ >
360
+ Öffnen
361
+ </Button>
362
+ </Flex>
363
+ </Card>
364
+ </Box>
365
+
366
+ <Box style={{ flex: '1 1 50%', minWidth: '300px' }}>
367
+ <Card shadow="tableShadow" hasRadius>
368
+ <Flex gap={3} alignItems="center" padding={4}>
369
+ <Box background="secondary100" padding={3} hasRadius>
370
+ <Cog width="1.5rem" height="1.5rem" color="secondary600" />
371
+ </Box>
372
+ <Box style={{ flex: 1 }}>
373
+ <Typography variant="delta">Plugin-Einstellungen</Typography>
374
+ <br></br>
375
+ <Typography variant="pi" textColor="neutral600">
376
+ Plugin konfigurieren und anpassen
377
+ </Typography>
378
+ </Box>
379
+ <Button
380
+ variant="default"
381
+ endIcon={<ArrowRight />}
382
+ onClick={() => {
383
+ window.location.href = '/admin/settings/magic-link';
384
+ }}
385
+ >
386
+ Öffnen
387
+ </Button>
388
+ </Flex>
389
+ </Card>
390
+ </Box>
391
+ </Flex>
392
+ </Box>
393
+ </Flex>
394
+ </Box>
395
+ )}
396
+
397
+ {activeTab === 'features' && (
398
+ <Box padding={6}>
399
+ <Flex wrap="wrap" gap={4} style={{ margin: '-8px' }}>
400
+ <Box padding={2} style={{ flex: '1 1 33.33%', minWidth: '300px' }}>
401
+ <Card shadow="tableShadow" hasRadius height="100%">
402
+ <Flex direction="column" gap={4} style={{ alignItems: 'center', justifyContent: 'space-between', height: '100%' }} padding={5}>
403
+ <Box
404
+ background="primary100"
405
+ borderRadius="50%"
406
+ width={80}
407
+ height={80}
408
+ shadow="tableShadow"
409
+ style={{
410
+ display: 'flex',
411
+ justifyContent: 'center',
412
+ alignItems: 'center',
413
+ }}
414
+ >
415
+ <PuzzlePiece width="2.5rem" height="2.5rem" color="primary600" />
416
+ </Box>
417
+ <Box style={{ textAlign: 'center' }}>
418
+ <Box textAlign="center">
419
+ <Typography
420
+ variant="delta"
421
+ as="h3"
422
+ fontWeight="bold"
423
+ paddingBottom={2}
424
+ >
425
+ Magic Link Authentifizierung
426
+ </Typography>
427
+ <Typography
428
+ variant="epsilon"
429
+ textColor="neutral600"
430
+ paddingTop={2}
431
+ >
432
+ Sichere, passwortlose Authentifizierung via E-Mail-Link
433
+ </Typography>
434
+ </Box>
435
+ </Box>
436
+ <Box paddingTop={2}>
437
+ <Badge active>Aktiviert</Badge>
438
+ </Box>
439
+ </Flex>
440
+ </Card>
441
+ </Box>
442
+
443
+ <Box padding={2} style={{ flex: '1 1 33.33%', minWidth: '300px' }}>
444
+ <Card shadow="tableShadow" hasRadius height="100%">
445
+ <Flex direction="column" gap={4} style={{ alignItems: 'center', justifyContent: 'space-between', height: '100%' }} padding={5}>
446
+ <Box
447
+ background="success100"
448
+ borderRadius="50%"
449
+ width={80}
450
+ height={80}
451
+ shadow="tableShadow"
452
+ style={{
453
+ display: 'flex',
454
+ justifyContent: 'center',
455
+ alignItems: 'center',
456
+ }}
457
+ >
458
+ <Key width="2.5rem" height="2.5rem" color="success600" />
459
+ </Box>
460
+ <Box style={{ textAlign: 'center' }}>
461
+ <Typography
462
+ variant="delta"
463
+ fontWeight="bold"
464
+ textColor="neutral800"
465
+ paddingBottom={3}
466
+ >
467
+ Token-Management
468
+ </Typography>
469
+ <br />
470
+ <Typography
471
+ variant="epsilon"
472
+ textColor="neutral600"
473
+ paddingBottom={1}
474
+ >
475
+ Verwalten und überwachen Sie aktive Anmelde-Tokens
476
+ </Typography>
477
+ <Typography
478
+ variant="epsilon"
479
+ textColor="neutral600"
480
+ paddingTop={1}
481
+ >
482
+ Kontrollieren Sie die Sicherheit Ihrer Authentifizierungen
483
+ </Typography>
484
+ </Box>
485
+ <Box style={{ marginTop: 'auto', width: '100%', textAlign: 'center' }}>
486
+ <Button
487
+ variant="secondary"
488
+ startIcon={<Key />}
489
+ endIcon={<ArrowRight />}
490
+ onClick={() => {
491
+ window.location.href = '/admin/plugins/magic-link/tokens';
492
+ }}
493
+ >
494
+ Tokens verwalten
495
+ </Button>
496
+ </Box>
497
+ </Flex>
498
+ </Card>
499
+ </Box>
500
+
501
+ <Box padding={2} style={{ flex: '1 1 33.33%', minWidth: '300px' }}>
502
+ <Card shadow="tableShadow" hasRadius height="100%">
503
+ <Flex direction="column" gap={4} style={{ alignItems: 'center', justifyContent: 'space-between', height: '100%' }} padding={5}>
504
+ <Box
505
+ background="danger100"
506
+ borderRadius="50%"
507
+ width={80}
508
+ height={80}
509
+ shadow="tableShadow"
510
+ style={{
511
+ display: 'flex',
512
+ justifyContent: 'center',
513
+ alignItems: 'center',
514
+ }}
515
+ >
516
+ <Shield width="2.5rem" height="2.5rem" color="danger600" />
517
+ </Box>
518
+ <Box style={{ textAlign: 'center' }}>
519
+ <Typography variant="delta" textAlign="center" fontWeight="bold" paddingBottom={2}>
520
+ JWT-Session-Verwaltung
521
+ </Typography>
522
+ <br />
523
+ <Typography textAlign="center" variant="epsilon">
524
+ Überwachen Sie aktive JWT-Sessions und erhöhen Sie die Sicherheit Ihrer Anwendung.
525
+ </Typography>
526
+ </Box>
527
+ <Box style={{ marginTop: 'auto', width: '100%', textAlign: 'center' }}>
528
+ <Button
529
+ variant="secondary"
530
+ startIcon={<Shield />}
531
+ endIcon={<ArrowRight />}
532
+ onClick={() => {
533
+ window.location.href = '/admin/settings/magic-link';
534
+ }}
535
+ >
536
+ Einstellungen öffnen
537
+ </Button>
538
+ </Box>
539
+ </Flex>
540
+ </Card>
541
+ </Box>
542
+ </Flex>
543
+ </Box>
544
+ )}
545
+
546
+ {activeTab === 'status' && (
547
+ <Box padding={6}>
548
+ <Card shadow="tableShadow" hasRadius>
549
+ <Box padding={5}>
550
+ <Box paddingBottom={4}>
551
+ <Typography variant="delta" fontWeight="bold">
552
+ System-Status
553
+ </Typography>
554
+ </Box>
555
+ <Divider />
556
+ <Flex direction="column" alignItems="center" gap={4} padding={4}>
557
+ <Box textAlign="center" paddingBottom={3}>
558
+ <Flex gap={2} justifyContent="center" alignItems="center" paddingBottom={2}>
559
+ <Check width="1rem" color="success600" />
560
+ <Typography fontWeight="bold">Magic Link Status</Typography>
561
+ </Flex>
562
+ <Badge active>Aktiv</Badge>
563
+ </Box>
564
+
565
+ <Box textAlign="center" paddingBottom={3}>
566
+ <Flex gap={2} justifyContent="center" alignItems="center" paddingBottom={2}>
567
+ <Check width="1rem" color="success600" />
568
+ <Typography fontWeight="bold">JWT Sessions</Typography>
569
+ </Flex>
570
+ <Badge active>Funktioniert</Badge>
571
+ </Box>
572
+
573
+ <Box textAlign="center" paddingBottom={3}>
574
+ <Flex gap={2} justifyContent="center" alignItems="center" paddingBottom={2}>
575
+ <Check width="1rem" color="success600" />
576
+ <Typography fontWeight="bold">E-Mail-Versand</Typography>
577
+ </Flex>
578
+ <Badge active>Konfiguriert</Badge>
579
+ </Box>
580
+ <Divider />
581
+
582
+ <Flex direction="column" gap={1}>
583
+ <Typography variant="pi" textColor="neutral600">
584
+ Plugin Version
585
+ </Typography>
586
+ <Typography variant="pi" fontWeight="bold">1.2.0</Typography>
587
+ </Flex>
588
+ <Flex direction="column" gap={1}>
589
+ <Typography variant="pi" textColor="neutral600">
590
+ Strapi Version
591
+ </Typography>
592
+ <Typography variant="pi" fontWeight="bold">5.0.0</Typography>
593
+ </Flex>
594
+ <Flex direction="column" gap={1}>
595
+ <Typography variant="pi" textColor="neutral600">
596
+ Letzter API-Aufruf
597
+ </Typography>
598
+ <Typography variant="pi" fontWeight="bold">
599
+ {new Date().toLocaleString()}
600
+ </Typography>
601
+ </Flex>
602
+ <Flex direction="column" gap={1}>
603
+ <Typography variant="pi" textColor="neutral600">
604
+ Browser
605
+ </Typography>
606
+ <Typography variant="pi" fontWeight="bold">
607
+ {window.navigator.userAgent.includes('Chrome') ? 'Chrome' :
608
+ window.navigator.userAgent.includes('Firefox') ? 'Firefox' :
609
+ window.navigator.userAgent.includes('Safari') ? 'Safari' : 'Unbekannt'}
610
+ </Typography>
611
+ </Flex>
612
+ </Flex>
613
+ </Box>
614
+ </Card>
615
+
616
+ <Box paddingTop={4}>
617
+ <Card shadow="tableShadow" hasRadius>
618
+ <Box padding={5}>
619
+ <Box paddingBottom={2}>
620
+ <Typography variant="delta" fontWeight="bold">
621
+ Debug-Informationen
622
+ </Typography>
623
+ </Box>
624
+ <Divider />
625
+ <Box as="pre" padding={4} background="neutral100" marginTop={4} hasRadius style={{overflow: 'auto'}}>
626
+ Current Path: {window.location.pathname}<br/>
627
+ Plugin ID: magic-link<br/>
628
+ HomePage Component Status: Loaded<br/>
629
+ Session Active: Yes<br/>
630
+ Current Time: {new Date().toLocaleString()}<br/>
631
+ User Agent: {window.navigator.userAgent}
632
+ </Box>
633
+ </Box>
634
+ </Card>
635
+ </Box>
636
+ </Box>
637
+ )}
638
+ </Flex>
639
+ </Box>
640
+
641
+ <Box
642
+ background="primary100"
643
+ padding={5}
644
+ marginTop={6}
645
+ hasRadius
646
+ borderColor="primary200"
647
+ borderWidth="1px"
648
+ borderStyle="solid"
649
+ >
650
+ </Box>
651
+ </Main>
652
+ );
653
+ };
654
+
655
+ export default HomePage;