@moontra/moonui-pro 2.37.1 → 2.37.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/dist/index.mjs CHANGED
@@ -2353,7 +2353,27 @@ function useSubscription() {
2353
2353
  }
2354
2354
  return null;
2355
2355
  }, []);
2356
- const validateWithInternalAPI = useCallback(async () => {
2356
+ const validateWithAuthServer = useCallback(async () => {
2357
+ try {
2358
+ const authServerUrl = process.env.NEXT_PUBLIC_MOONUI_AUTH_SERVER || "http://localhost:7878";
2359
+ console.log("[Client Auth] Checking CLI auth server...");
2360
+ const authServerResponse = await fetch(`${authServerUrl}/validate`, {
2361
+ method: "GET",
2362
+ headers: {
2363
+ "X-Component": "useSubscription",
2364
+ "X-Timestamp": Date.now().toString()
2365
+ },
2366
+ credentials: "include"
2367
+ }).catch(() => null);
2368
+ if (authServerResponse && authServerResponse.ok) {
2369
+ const data = await authServerResponse.json();
2370
+ console.log("[Client Auth] CLI auth server response:", data);
2371
+ return data;
2372
+ }
2373
+ console.log("[Client Auth] CLI auth server not available, falling back...");
2374
+ } catch (error) {
2375
+ console.log("[Client Auth] CLI auth server error:", error);
2376
+ }
2357
2377
  try {
2358
2378
  console.log("[Client Auth] Validating with internal API...");
2359
2379
  const response = await fetch(AUTH_CONFIG.internalEndpoint, {
@@ -2416,23 +2436,23 @@ function useSubscription() {
2416
2436
  });
2417
2437
  if (age > maxAge * AUTH_CONFIG.cache.refreshThreshold) {
2418
2438
  console.log("[Client Auth] Refreshing validation in background...");
2419
- validateWithInternalAPI();
2439
+ validateWithAuthServer();
2420
2440
  }
2421
2441
  return;
2422
2442
  }
2423
2443
  }
2424
- validateWithInternalAPI();
2425
- }, [readValidationFromCookie, validateWithInternalAPI]);
2444
+ validateWithAuthServer();
2445
+ }, [readValidationFromCookie, validateWithAuthServer]);
2426
2446
  useEffect(() => {
2427
2447
  const handleStorageChange = (e) => {
2428
2448
  if (e.key === "moonui_pro_refresh") {
2429
2449
  console.log("[Client Auth] Refresh signal from another tab");
2430
- validateWithInternalAPI();
2450
+ validateWithAuthServer();
2431
2451
  }
2432
2452
  };
2433
2453
  window.addEventListener("storage", handleStorageChange);
2434
2454
  return () => window.removeEventListener("storage", handleStorageChange);
2435
- }, [validateWithInternalAPI]);
2455
+ }, [validateWithAuthServer]);
2436
2456
  useEffect(() => {
2437
2457
  let lastCheck = Date.now();
2438
2458
  const handleFocus = () => {
@@ -2441,12 +2461,12 @@ function useSubscription() {
2441
2461
  if (timeSinceLastCheck > 5 * 60 * 1e3) {
2442
2462
  console.log("[Client Auth] Window focused, checking validation...");
2443
2463
  lastCheck = now;
2444
- validateWithInternalAPI();
2464
+ validateWithAuthServer();
2445
2465
  }
2446
2466
  };
2447
2467
  window.addEventListener("focus", handleFocus);
2448
2468
  return () => window.removeEventListener("focus", handleFocus);
2449
- }, [validateWithInternalAPI]);
2469
+ }, [validateWithAuthServer]);
2450
2470
  return state;
2451
2471
  }
2452
2472
  async function forceRefresh() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moontra/moonui-pro",
3
- "version": "2.37.1",
3
+ "version": "2.37.3",
4
4
  "description": "Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -17,6 +17,8 @@
17
17
  import { NextRequest, NextResponse } from 'next/server';
18
18
  import { cookies, headers } from 'next/headers';
19
19
  import crypto from 'crypto';
20
+ import os from 'os';
21
+ import { execSync } from 'child_process';
20
22
 
21
23
  // Security checksum - DO NOT MODIFY
22
24
  const SECURITY_CHECKSUM = process.env.MOONUI_SECURITY_HASH ||
@@ -40,21 +42,107 @@ const validationCache = new Map<string, {
40
42
  expiresAt: number;
41
43
  }>();
42
44
 
45
+ /**
46
+ * Get MAC address for hardware fingerprinting
47
+ */
48
+ function getMacAddress(): string {
49
+ try {
50
+ const platform = os.platform();
51
+ let command: string;
52
+
53
+ switch (platform) {
54
+ case 'darwin':
55
+ command = "ifconfig | grep ether | head -1 | awk '{print $2}'";
56
+ break;
57
+ case 'linux':
58
+ command = "ip link show | grep ether | head -1 | awk '{print $2}'";
59
+ break;
60
+ case 'win32':
61
+ command = 'getmac /NH /FO csv | findstr /r "^"';
62
+ break;
63
+ default:
64
+ return 'unknown-mac';
65
+ }
66
+
67
+ const result = execSync(command, { encoding: 'utf8' }).trim();
68
+ const match = result.match(/([a-f0-9:]+)/i);
69
+
70
+ if (match && match[1]) {
71
+ return match[1].replace(/[:-]/g, '').toLowerCase();
72
+ }
73
+
74
+ // Fallback to network interfaces
75
+ const interfaces = os.networkInterfaces();
76
+ for (const name in interfaces) {
77
+ const iface = interfaces[name];
78
+ if (iface) {
79
+ for (const entry of iface) {
80
+ if (entry.mac && entry.mac !== '00:00:00:00:00:00') {
81
+ return entry.mac.replace(/[:-]/g, '').toLowerCase();
82
+ }
83
+ }
84
+ }
85
+ }
86
+ return 'fallback-mac';
87
+ } catch (error) {
88
+ console.error('[Hardware] Error getting MAC:', error);
89
+ return 'error-mac';
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Generate hardware-based device fingerprint
95
+ * Format: hw-{platform}-{macHash}-{cpuHash}
96
+ */
97
+ function generateHardwareFingerprint(): string {
98
+ const platform = os.platform();
99
+ const macAddress = getMacAddress();
100
+ const cpuCount = os.cpus().length;
101
+ const totalMem = Math.round(os.totalmem() / (1024 * 1024 * 1024)); // GB
102
+ const hostname = os.hostname();
103
+
104
+ // Create hashes
105
+ const macHash = crypto.createHash('sha256')
106
+ .update(macAddress)
107
+ .digest('hex')
108
+ .substring(0, 8);
109
+
110
+ const systemHash = crypto.createHash('sha256')
111
+ .update(`${cpuCount}:${totalMem}:${hostname}`)
112
+ .digest('hex')
113
+ .substring(0, 6);
114
+
115
+ return `hw-${platform}-${macHash}-${systemHash}`;
116
+ }
117
+
43
118
  /**
44
119
  * Generate a device fingerprint from request headers
120
+ * Combines hardware fingerprint with browser characteristics
45
121
  */
46
122
  async function getDeviceFingerprint(request: NextRequest): Promise<string> {
47
- const headersList = await headers();
48
- const ua = headersList.get('user-agent') || 'unknown';
49
- const lang = headersList.get('accept-language') || 'unknown';
50
- const ip = headersList.get('x-forwarded-for') ||
51
- headersList.get('x-real-ip') ||
52
- 'unknown';
123
+ // In development with CLI auth, generate hardware-based fingerprint
124
+ if (process.env.NODE_ENV === 'development') {
125
+ // Use hardware fingerprint for maximum security
126
+ const hardwareId = generateHardwareFingerprint();
127
+
128
+ // If CLI device ID is set, validate it matches hardware
129
+ if (process.env.NEXT_PUBLIC_MOONUI_DEVICE_ID) {
130
+ const cliDeviceId = process.env.NEXT_PUBLIC_MOONUI_DEVICE_ID;
131
+
132
+ // For backward compatibility, accept both old and new format
133
+ if (cliDeviceId.startsWith('hw-')) {
134
+ return cliDeviceId; // New hardware-based format
135
+ } else {
136
+ console.log('[MoonUI] Migrating to hardware-based device ID');
137
+ return hardwareId; // Use new hardware ID
138
+ }
139
+ }
53
140
 
54
- return crypto
55
- .createHash('sha256')
56
- .update(`${ua}|${lang}|${ip}`)
57
- .digest('hex');
141
+ return hardwareId;
142
+ }
143
+
144
+ // In production, use hardware fingerprint
145
+ return generateHardwareFingerprint();
58
146
  }
59
147
 
60
148
  /**
@@ -93,20 +181,56 @@ async function validateWithMoonUIServer(
93
181
  const devToken = process.env.NEXT_PUBLIC_MOONUI_DEV_TOKEN;
94
182
  const devDeviceId = process.env.NEXT_PUBLIC_MOONUI_DEVICE_ID;
95
183
 
96
- if (devToken && devDeviceId === deviceId) {
184
+ console.log('[MoonUI Dev Auth] Checking CLI authentication:');
185
+ console.log('[MoonUI Dev Auth] Device IDs match:', devDeviceId === deviceId);
186
+
187
+ // STRICT DEVICE ID VALIDATION - Prevent token sharing
188
+ if (devToken && devDeviceId && devDeviceId === deviceId) {
97
189
  try {
98
190
  // Decode the dev token
99
191
  const decoded = JSON.parse(Buffer.from(devToken, 'base64').toString());
192
+
193
+ // Verify token structure and session
194
+ if (!decoded.deviceId || !decoded.session || !decoded.security) {
195
+ console.error('[MoonUI Security] Invalid token structure');
196
+ return { valid: false, hasProAccess: false };
197
+ }
198
+
199
+ // Verify device ID in token matches
200
+ if (decoded.deviceId !== devDeviceId) {
201
+ console.error('[MoonUI Security] Token device ID mismatch');
202
+ return { valid: false, hasProAccess: false };
203
+ }
204
+
205
+ // Verify session hasn't expired
206
+ if (decoded.session?.expiresAt && decoded.session.expiresAt < Date.now()) {
207
+ console.error('[MoonUI Security] Token session expired');
208
+ return { valid: false, hasProAccess: false };
209
+ }
210
+
211
+ console.log('[MoonUI Dev Auth] Token validated successfully');
212
+ console.log('[MoonUI Dev Auth] User plan:', decoded.user?.plan);
213
+
100
214
  if (decoded.user?.plan === 'pro_lifetime' || decoded.user?.hasProAccess) {
215
+ console.log('[MoonUI Dev Auth] Pro access granted via CLI token');
101
216
  return {
102
217
  valid: true,
103
218
  hasProAccess: true,
104
- plan: 'lifetime'
219
+ plan: decoded.user?.plan || 'lifetime'
105
220
  };
106
221
  }
107
222
  } catch (e) {
108
- console.error('[MoonUI] Error parsing dev token:', e);
223
+ console.error('[MoonUI Security] Error parsing dev token:', e);
224
+ return { valid: false, hasProAccess: false };
109
225
  }
226
+ } else if (devToken && !devDeviceId) {
227
+ console.warn('[MoonUI Security] Token found but no device ID - possible token sharing attempt');
228
+ return { valid: false, hasProAccess: false };
229
+ } else if (devDeviceId !== deviceId) {
230
+ console.warn('[MoonUI Security] Device ID mismatch - token not valid for this device');
231
+ console.warn('[MoonUI Security] This token is locked to device:', devDeviceId);
232
+ console.warn('[MoonUI Security] Current device:', deviceId);
233
+ return { valid: false, hasProAccess: false };
110
234
  }
111
235
  }
112
236
 
@@ -178,7 +302,9 @@ function verifyRequestIntegrity(request: NextRequest): boolean {
178
302
  const suspiciousHeaders = [
179
303
  'x-moonui-bypass',
180
304
  'x-force-pro',
181
- 'x-admin-override'
305
+ 'x-admin-override',
306
+ 'x-moonui-device-override',
307
+ 'x-moonui-token-override'
182
308
  ];
183
309
 
184
310
  for (const header of suspiciousHeaders) {
@@ -188,6 +314,19 @@ function verifyRequestIntegrity(request: NextRequest): boolean {
188
314
  }
189
315
  }
190
316
 
317
+ // Check for proxy/VPN indicators
318
+ const proxyHeaders = [
319
+ 'x-proxy-connection',
320
+ 'x-forwarded-server',
321
+ 'x-originating-ip',
322
+ 'x-remote-ip'
323
+ ];
324
+
325
+ const hasProxy = proxyHeaders.some(header => request.headers.has(header));
326
+ if (hasProxy) {
327
+ console.warn('[MoonUI Security] Proxy/VPN detected - additional validation required');
328
+ }
329
+
191
330
  return true;
192
331
  }
193
332