@djangocfg/centrifugo 2.1.18 → 2.1.19
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/centrifugo",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.19",
|
|
4
4
|
"description": "Production-ready Centrifugo WebSocket client for React with real-time subscriptions, RPC patterns, and connection state management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"centrifugo",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"centrifuge": "^5.2.2"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@djangocfg/api": "^2.1.
|
|
55
|
-
"@djangocfg/ui-nextjs": "^2.1.
|
|
56
|
-
"@djangocfg/layouts": "^2.1.
|
|
54
|
+
"@djangocfg/api": "^2.1.19",
|
|
55
|
+
"@djangocfg/ui-nextjs": "^2.1.19",
|
|
56
|
+
"@djangocfg/layouts": "^2.1.19",
|
|
57
57
|
"consola": "^3.4.2",
|
|
58
58
|
"lucide-react": "^0.545.0",
|
|
59
59
|
"moment": "^2.30.1",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"react-dom": "^19.1.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
64
|
+
"@djangocfg/typescript-config": "^2.1.19",
|
|
65
65
|
"@types/react": "^19.1.0",
|
|
66
66
|
"@types/react-dom": "^19.1.0",
|
|
67
67
|
"moment": "^2.30.1",
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel name validation utilities for Centrifugo
|
|
3
|
+
*
|
|
4
|
+
* Helps detect common mistakes with channel naming that can lead to permission errors.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface ChannelValidationResult {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
warning?: string;
|
|
10
|
+
suggestion?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validates Centrifugo channel name and detects potential issues.
|
|
15
|
+
*
|
|
16
|
+
* Common issues:
|
|
17
|
+
* - Using `#` for namespace separator (should use `:`)
|
|
18
|
+
* - User-limited channels without proper JWT token setup
|
|
19
|
+
*
|
|
20
|
+
* @param channel - Channel name to validate
|
|
21
|
+
* @returns Validation result with warnings and suggestions
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* // ❌ Bad: might be interpreted as user-limited channel
|
|
26
|
+
* validateChannelName('terminal#session#abc123')
|
|
27
|
+
* // Returns: { valid: false, warning: "...", suggestion: "Use terminal:session:abc123" }
|
|
28
|
+
*
|
|
29
|
+
* // ✅ Good: proper namespace separator
|
|
30
|
+
* validateChannelName('terminal:session:abc123')
|
|
31
|
+
* // Returns: { valid: true }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function validateChannelName(channel: string): ChannelValidationResult {
|
|
35
|
+
// Check for multiple # symbols (potential user-limited channel misuse)
|
|
36
|
+
const hashCount = (channel.match(/#/g) || []).length;
|
|
37
|
+
|
|
38
|
+
if (hashCount >= 2) {
|
|
39
|
+
// Pattern: namespace#something#something
|
|
40
|
+
// This might be interpreted as user-limited channel: namespace#user_id#channel
|
|
41
|
+
const parts = channel.split('#');
|
|
42
|
+
const [namespace, possibleUserId, ...rest] = parts;
|
|
43
|
+
|
|
44
|
+
// Check if second part looks like a user ID (numeric)
|
|
45
|
+
const isNumericUserId = /^\d+$/.test(possibleUserId);
|
|
46
|
+
|
|
47
|
+
if (!isNumericUserId && possibleUserId) {
|
|
48
|
+
// Non-numeric second part after # - likely a mistake
|
|
49
|
+
const suggestion = channel.replace(/#/g, ':');
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
valid: false,
|
|
53
|
+
warning: `Channel "${channel}" uses '#' separator which Centrifugo interprets as user-limited channel boundary. ` +
|
|
54
|
+
`The part "${possibleUserId}" will be treated as user_id, which may cause permission errors if not in JWT token.`,
|
|
55
|
+
suggestion: `Use ':' for namespace separation: "${suggestion}"`
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (isNumericUserId) {
|
|
60
|
+
return {
|
|
61
|
+
valid: true,
|
|
62
|
+
warning: `Channel "${channel}" appears to be a user-limited channel (user_id: ${possibleUserId}). ` +
|
|
63
|
+
`Make sure your JWT token's "sub" field matches "${possibleUserId}".`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Single # is okay for user-limited channels like "user#123"
|
|
69
|
+
if (hashCount === 1) {
|
|
70
|
+
const [namespace, userId] = channel.split('#');
|
|
71
|
+
if (userId && !/^\d+$/.test(userId) && userId !== '*') {
|
|
72
|
+
// Non-numeric user_id (not a wildcard) - might be a mistake
|
|
73
|
+
const suggestion = channel.replace('#', ':');
|
|
74
|
+
return {
|
|
75
|
+
valid: false,
|
|
76
|
+
warning: `Channel "${channel}" uses '#' but "${userId}" doesn't look like a user_id. ` +
|
|
77
|
+
`This might cause permission issues.`,
|
|
78
|
+
suggestion: `Consider using ':' instead: "${suggestion}"`
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { valid: true };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Log channel validation warnings to console (development only).
|
|
88
|
+
*
|
|
89
|
+
* @param channel - Channel name to validate
|
|
90
|
+
* @param logger - Logger instance (optional)
|
|
91
|
+
*/
|
|
92
|
+
export function logChannelWarnings(
|
|
93
|
+
channel: string,
|
|
94
|
+
logger?: { warning: (msg: string) => void }
|
|
95
|
+
): void {
|
|
96
|
+
if (process.env.NODE_ENV === 'production') {
|
|
97
|
+
return; // Skip in production
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const result = validateChannelName(channel);
|
|
101
|
+
|
|
102
|
+
if (!result.valid && result.warning) {
|
|
103
|
+
const message = `[Centrifugo Channel Warning]\n${result.warning}${
|
|
104
|
+
result.suggestion ? `\n💡 Suggestion: ${result.suggestion}` : ''
|
|
105
|
+
}`;
|
|
106
|
+
|
|
107
|
+
if (logger?.warning) {
|
|
108
|
+
logger.warning(message);
|
|
109
|
+
} else {
|
|
110
|
+
console.warn(message);
|
|
111
|
+
}
|
|
112
|
+
} else if (result.warning) {
|
|
113
|
+
// Valid but has informational warning
|
|
114
|
+
if (logger?.warning) {
|
|
115
|
+
logger.warning(`[Centrifugo] ${result.warning}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { useEffect, useCallback, useRef, useState } from 'react';
|
|
16
16
|
import { useCentrifugo } from '../providers/CentrifugoProvider';
|
|
17
17
|
import { createLogger } from '../core/logger';
|
|
18
|
+
import { logChannelWarnings } from '../core/utils/channelValidator';
|
|
18
19
|
|
|
19
20
|
export interface UseSubscriptionOptions<T = any> {
|
|
20
21
|
channel: string;
|
|
@@ -76,6 +77,9 @@ export function useSubscription<T = any>(
|
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
// Validate channel name and log warnings (dev only)
|
|
81
|
+
logChannelWarnings(channel, logger);
|
|
82
|
+
|
|
79
83
|
logger.info(`Subscribing to channel: ${channel}`);
|
|
80
84
|
|
|
81
85
|
try {
|