strapi-plugin-magic-sessionmanager 4.2.4 → 4.2.6

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 (62) hide show
  1. package/README.md +0 -2
  2. package/dist/server/index.js +1 -1
  3. package/dist/server/index.mjs +1 -1
  4. package/package.json +1 -3
  5. package/admin/jsconfig.json +0 -10
  6. package/admin/src/components/Initializer.jsx +0 -11
  7. package/admin/src/components/LicenseGuard.jsx +0 -591
  8. package/admin/src/components/OnlineUsersWidget.jsx +0 -212
  9. package/admin/src/components/PluginIcon.jsx +0 -8
  10. package/admin/src/components/SessionDetailModal.jsx +0 -449
  11. package/admin/src/components/SessionInfoCard.jsx +0 -151
  12. package/admin/src/components/SessionInfoPanel.jsx +0 -385
  13. package/admin/src/components/index.jsx +0 -5
  14. package/admin/src/hooks/useLicense.js +0 -103
  15. package/admin/src/index.js +0 -149
  16. package/admin/src/pages/ActiveSessions.jsx +0 -12
  17. package/admin/src/pages/Analytics.jsx +0 -735
  18. package/admin/src/pages/App.jsx +0 -12
  19. package/admin/src/pages/HomePage.jsx +0 -1212
  20. package/admin/src/pages/License.jsx +0 -603
  21. package/admin/src/pages/Settings.jsx +0 -1646
  22. package/admin/src/pages/SettingsNew.jsx +0 -1204
  23. package/admin/src/pages/UpgradePage.jsx +0 -448
  24. package/admin/src/pages/index.jsx +0 -3
  25. package/admin/src/pluginId.js +0 -4
  26. package/admin/src/translations/de.json +0 -299
  27. package/admin/src/translations/en.json +0 -299
  28. package/admin/src/translations/es.json +0 -287
  29. package/admin/src/translations/fr.json +0 -287
  30. package/admin/src/translations/pt.json +0 -287
  31. package/admin/src/utils/getTranslation.js +0 -5
  32. package/admin/src/utils/index.js +0 -2
  33. package/admin/src/utils/parseUserAgent.js +0 -79
  34. package/admin/src/utils/theme.js +0 -85
  35. package/server/jsconfig.json +0 -10
  36. package/server/src/bootstrap.js +0 -492
  37. package/server/src/config/index.js +0 -23
  38. package/server/src/content-types/index.js +0 -9
  39. package/server/src/content-types/session/schema.json +0 -84
  40. package/server/src/controllers/controller.js +0 -11
  41. package/server/src/controllers/index.js +0 -11
  42. package/server/src/controllers/license.js +0 -266
  43. package/server/src/controllers/session.js +0 -433
  44. package/server/src/controllers/settings.js +0 -122
  45. package/server/src/destroy.js +0 -22
  46. package/server/src/index.js +0 -23
  47. package/server/src/middlewares/index.js +0 -5
  48. package/server/src/middlewares/last-seen.js +0 -62
  49. package/server/src/policies/index.js +0 -3
  50. package/server/src/register.js +0 -36
  51. package/server/src/routes/admin.js +0 -149
  52. package/server/src/routes/content-api.js +0 -60
  53. package/server/src/routes/index.js +0 -9
  54. package/server/src/services/geolocation.js +0 -182
  55. package/server/src/services/index.js +0 -13
  56. package/server/src/services/license-guard.js +0 -316
  57. package/server/src/services/notifications.js +0 -319
  58. package/server/src/services/service.js +0 -7
  59. package/server/src/services/session.js +0 -393
  60. package/server/src/utils/encryption.js +0 -121
  61. package/server/src/utils/getClientIp.js +0 -118
  62. package/server/src/utils/logger.js +0 -84
package/README.md CHANGED
@@ -7,8 +7,6 @@ Track logins, monitor active users, and secure your app with one simple plugin.
7
7
  [![NPM](https://img.shields.io/npm/v/strapi-plugin-magic-sessionmanager.svg)](https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager)
8
8
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
9
 
10
- > 💡 **Tip:** Set `debug: true` in plugin config to enable detailed logging
11
-
12
10
  ---
13
11
 
14
12
  ## 📸 What It Looks Like
@@ -1862,7 +1862,7 @@ var session$1 = ({ strapi: strapi2 }) => {
1862
1862
  }
1863
1863
  };
1864
1864
  };
1865
- const version = "4.2.3";
1865
+ const version = "4.2.5";
1866
1866
  const require$$2 = {
1867
1867
  version
1868
1868
  };
@@ -1858,7 +1858,7 @@ var session$1 = ({ strapi: strapi2 }) => {
1858
1858
  }
1859
1859
  };
1860
1860
  };
1861
- const version = "4.2.3";
1861
+ const version = "4.2.5";
1862
1862
  const require$$2 = {
1863
1863
  version
1864
1864
  };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.2.4",
2
+ "version": "4.2.6",
3
3
  "keywords": [
4
4
  "strapi",
5
5
  "strapi-plugin",
@@ -27,8 +27,6 @@
27
27
  },
28
28
  "files": [
29
29
  "dist",
30
- "server",
31
- "admin",
32
30
  "strapi-admin.js",
33
31
  "strapi-server.js",
34
32
  "README.md",
@@ -1,10 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es6",
4
- "jsx": "react",
5
- "module": "esnext",
6
- "allowSyntheticDefaultImports": true,
7
- "esModuleInterop": true
8
- },
9
- "include": ["./src/**/*.js", "./src/**/*.jsx"]
10
- }
@@ -1,11 +0,0 @@
1
- import { useEffect } from 'react';
2
-
3
- const Initializer = () => {
4
- useEffect(() => {
5
- console.log('[magic-sessionmanager] Plugin initialized');
6
- }, []);
7
-
8
- return null;
9
- };
10
-
11
- export default Initializer;
@@ -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
-