strapi-plugin-magic-sessionmanager 2.0.1 → 2.0.3
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/admin/jsconfig.json +10 -0
- package/admin/src/components/Initializer.jsx +11 -0
- package/admin/src/components/LicenseGuard.jsx +591 -0
- package/admin/src/components/OnlineUsersWidget.jsx +208 -0
- package/admin/src/components/PluginIcon.jsx +8 -0
- package/admin/src/components/SessionDetailModal.jsx +445 -0
- package/admin/src/components/SessionInfoCard.jsx +151 -0
- package/admin/src/components/SessionInfoPanel.jsx +375 -0
- package/admin/src/components/index.jsx +5 -0
- package/admin/src/hooks/useLicense.js +103 -0
- package/admin/src/index.js +137 -0
- package/admin/src/pages/ActiveSessions.jsx +12 -0
- package/admin/src/pages/Analytics.jsx +735 -0
- package/admin/src/pages/App.jsx +12 -0
- package/admin/src/pages/HomePage.jsx +1248 -0
- package/admin/src/pages/License.jsx +603 -0
- package/admin/src/pages/Settings.jsx +1497 -0
- package/admin/src/pages/SettingsNew.jsx +1204 -0
- package/admin/src/pages/index.jsx +3 -0
- package/admin/src/pluginId.js +3 -0
- package/admin/src/translations/de.json +20 -0
- package/admin/src/translations/en.json +20 -0
- package/admin/src/utils/getTranslation.js +5 -0
- package/admin/src/utils/index.js +2 -0
- package/admin/src/utils/parseUserAgent.js +79 -0
- package/dist/server/index.js +91 -2
- package/dist/server/index.mjs +91 -2
- package/package.json +3 -1
- package/server/jsconfig.json +10 -0
- package/server/src/bootstrap.js +297 -0
- package/server/src/config/index.js +20 -0
- package/server/src/content-types/index.js +9 -0
- package/server/src/content-types/session/schema.json +76 -0
- package/server/src/controllers/controller.js +11 -0
- package/server/src/controllers/index.js +11 -0
- package/server/src/controllers/license.js +266 -0
- package/server/src/controllers/session.js +362 -0
- package/server/src/controllers/settings.js +122 -0
- package/server/src/destroy.js +18 -0
- package/server/src/index.js +23 -0
- package/server/src/middlewares/index.js +5 -0
- package/server/src/middlewares/last-seen.js +56 -0
- package/server/src/policies/index.js +3 -0
- package/server/src/register.js +32 -0
- package/server/src/routes/admin.js +149 -0
- package/server/src/routes/content-api.js +51 -0
- package/server/src/routes/index.js +9 -0
- package/server/src/services/geolocation.js +180 -0
- package/server/src/services/index.js +13 -0
- package/server/src/services/license-guard.js +308 -0
- package/server/src/services/notifications.js +319 -0
- package/server/src/services/service.js +7 -0
- package/server/src/services/session.js +345 -0
- package/server/src/utils/getClientIp.js +118 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract real client IP address from request
|
|
3
|
+
* Handles proxies, load balancers, and various header formats
|
|
4
|
+
*
|
|
5
|
+
* Priority order:
|
|
6
|
+
* 1. CF-Connecting-IP (Cloudflare)
|
|
7
|
+
* 2. True-Client-IP (Akamai, Cloudflare)
|
|
8
|
+
* 3. X-Real-IP (nginx)
|
|
9
|
+
* 4. X-Forwarded-For (standard proxy header)
|
|
10
|
+
* 5. X-Client-IP
|
|
11
|
+
* 6. X-Cluster-Client-IP
|
|
12
|
+
* 7. ctx.request.ip (Koa default)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const getClientIp = (ctx) => {
|
|
16
|
+
try {
|
|
17
|
+
const headers = ctx.request.headers || ctx.request.header || {};
|
|
18
|
+
|
|
19
|
+
// 1. Cloudflare
|
|
20
|
+
if (headers['cf-connecting-ip']) {
|
|
21
|
+
return cleanIp(headers['cf-connecting-ip']);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 2. True-Client-IP (Akamai, Cloudflare Enterprise)
|
|
25
|
+
if (headers['true-client-ip']) {
|
|
26
|
+
return cleanIp(headers['true-client-ip']);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 3. X-Real-IP (nginx proxy_pass)
|
|
30
|
+
if (headers['x-real-ip']) {
|
|
31
|
+
return cleanIp(headers['x-real-ip']);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 4. X-Forwarded-For (most common)
|
|
35
|
+
// Format: "client, proxy1, proxy2"
|
|
36
|
+
// We want the FIRST IP (the actual client)
|
|
37
|
+
if (headers['x-forwarded-for']) {
|
|
38
|
+
const forwardedIps = headers['x-forwarded-for'].split(',');
|
|
39
|
+
const clientIp = forwardedIps[0].trim();
|
|
40
|
+
if (clientIp && !isPrivateIp(clientIp)) {
|
|
41
|
+
return cleanIp(clientIp);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 5. X-Client-IP
|
|
46
|
+
if (headers['x-client-ip']) {
|
|
47
|
+
return cleanIp(headers['x-client-ip']);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 6. X-Cluster-Client-IP (Rackspace, Riverbed)
|
|
51
|
+
if (headers['x-cluster-client-ip']) {
|
|
52
|
+
return cleanIp(headers['x-cluster-client-ip']);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 7. Forwarded (RFC 7239)
|
|
56
|
+
if (headers['forwarded']) {
|
|
57
|
+
const match = headers['forwarded'].match(/for=([^;,\s]+)/);
|
|
58
|
+
if (match && match[1]) {
|
|
59
|
+
return cleanIp(match[1].replace(/"/g, ''));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 8. Fallback to Koa's ctx.request.ip
|
|
64
|
+
if (ctx.request.ip) {
|
|
65
|
+
return cleanIp(ctx.request.ip);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 9. Last resort
|
|
69
|
+
return 'unknown';
|
|
70
|
+
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error('[getClientIp] Error extracting IP:', error);
|
|
73
|
+
return 'unknown';
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Clean IP address (remove IPv6 prefix, port, etc.)
|
|
79
|
+
*/
|
|
80
|
+
const cleanIp = (ip) => {
|
|
81
|
+
if (!ip) return 'unknown';
|
|
82
|
+
|
|
83
|
+
// Remove port if present
|
|
84
|
+
ip = ip.split(':')[0];
|
|
85
|
+
|
|
86
|
+
// Remove IPv6 prefix (::ffff:)
|
|
87
|
+
if (ip.startsWith('::ffff:')) {
|
|
88
|
+
ip = ip.substring(7);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Trim whitespace
|
|
92
|
+
ip = ip.trim();
|
|
93
|
+
|
|
94
|
+
return ip || 'unknown';
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Check if IP is private/local
|
|
99
|
+
*/
|
|
100
|
+
const isPrivateIp = (ip) => {
|
|
101
|
+
if (!ip) return true;
|
|
102
|
+
|
|
103
|
+
// Private IP ranges
|
|
104
|
+
if (ip === '127.0.0.1' || ip === 'localhost' || ip === '::1') return true;
|
|
105
|
+
if (ip.startsWith('192.168.')) return true;
|
|
106
|
+
if (ip.startsWith('10.')) return true;
|
|
107
|
+
if (ip.startsWith('172.')) {
|
|
108
|
+
const second = parseInt(ip.split('.')[1]);
|
|
109
|
+
if (second >= 16 && second <= 31) return true;
|
|
110
|
+
}
|
|
111
|
+
if (ip.startsWith('fc00:') || ip.startsWith('fd00:')) return true;
|
|
112
|
+
if (ip.startsWith('fe80:')) return true;
|
|
113
|
+
|
|
114
|
+
return false;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
module.exports = getClientIp;
|
|
118
|
+
|