Skip to content

Commit 3d4aed9

Browse files
feat(ui): separate the namespace from the server URL
This should help prevent people from connecting to the main namespace, when they forget to include the namespace at the end of the server URL. Related: - #26 - #42
1 parent 8542601 commit 3d4aed9

File tree

5 files changed

+59
-17
lines changed

5 files changed

+59
-17
lines changed

ui/src/App.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
:initial-server-url="serverUrl"
1818
:initial-ws-only="wsOnly"
1919
:initial-path="path"
20+
:initial-namespace="namespace"
2021
:initial-parser="parser"
2122
:is-connecting="isConnecting"
2223
:error="connectionError"
@@ -70,6 +71,7 @@ export default {
7071
serverUrl: (state) => state.connection.serverUrl,
7172
wsOnly: (state) => state.connection.wsOnly,
7273
path: (state) => state.connection.path,
74+
namespace: (state) => state.connection.namespace,
7375
parser: (state) => state.connection.parser,
7476
backgroundColor: (state) =>
7577
state.config.darkTheme ? "" : "grey lighten-5",
@@ -92,15 +94,15 @@ export default {
9294
},
9395
9496
methods: {
95-
tryConnect(serverUrl, auth, wsOnly, path, parser) {
97+
tryConnect(serverUrl, namespace, auth, wsOnly, path, parser) {
9698
this.isConnecting = true;
9799
if (SocketHolder.socket) {
98100
SocketHolder.socket.disconnect();
99101
SocketHolder.socket.off("connect");
100102
SocketHolder.socket.off("connect_error");
101103
SocketHolder.socket.off("disconnect");
102104
}
103-
const socket = io(serverUrl, {
105+
const socket = io(serverUrl + namespace, {
104106
forceNew: true,
105107
reconnection: false,
106108
withCredentials: true, // needed for cookie-based sticky-sessions
@@ -119,6 +121,7 @@ export default {
119121
serverUrl,
120122
wsOnly,
121123
path,
124+
namespace,
122125
parser,
123126
});
124127
SocketHolder.socket = socket;
@@ -210,6 +213,7 @@ export default {
210213
onSubmit(form) {
211214
this.tryConnect(
212215
form.serverUrl,
216+
form.namespace,
213217
{
214218
username: form.username,
215219
password: form.password,
@@ -231,6 +235,7 @@ export default {
231235
const sessionId = this.$store.state.connection.sessionId;
232236
this.tryConnect(
233237
this.serverUrl,
238+
this.namespace,
234239
{
235240
sessionId,
236241
},

ui/src/components/ConnectionModal.vue

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<v-text-field
1313
v-model="serverUrl"
1414
:label="$t('connection.serverUrl')"
15-
placeholder="https://example.com/admin"
15+
placeholder="https://example.com"
1616
required
1717
></v-text-field>
1818
<v-text-field
@@ -26,22 +26,39 @@
2626
></v-text-field>
2727

2828
<v-switch
29-
v-model="wsOnly"
30-
:label="$t('connection.websocket-only')"
29+
v-model="showAdvancedOptions"
30+
:label="$t('connection.advanced-options')"
3131
inset
3232
dense
3333
/>
3434

35-
<v-text-field
36-
v-model="path"
37-
:label="$t('connection.path')"
38-
></v-text-field>
35+
<v-expand-transition>
36+
<div v-if="showAdvancedOptions">
37+
<v-switch
38+
v-model="wsOnly"
39+
:label="$t('connection.websocket-only')"
40+
inset
41+
dense
42+
v-show="showAdvancedOptions"
43+
/>
3944

40-
<v-select
41-
v-model="parser"
42-
:label="$t('connection.parser')"
43-
:items="parserOptions"
44-
/>
45+
<v-text-field
46+
v-model="namespace"
47+
:label="$t('connection.namespace')"
48+
></v-text-field>
49+
50+
<v-text-field
51+
v-model="path"
52+
:label="$t('connection.path')"
53+
></v-text-field>
54+
55+
<v-select
56+
v-model="parser"
57+
:label="$t('connection.parser')"
58+
:items="parserOptions"
59+
/>
60+
</div>
61+
</v-expand-transition>
4562

4663
<v-btn
4764
:loading="isConnecting"
@@ -69,15 +86,18 @@ export default {
6986
initialServerUrl: String,
7087
initialWsOnly: Boolean,
7188
initialPath: String,
89+
initialNamespace: String,
7290
initialParser: String,
7391
error: String,
7492
},
7593
7694
data() {
7795
return {
96+
showAdvancedOptions: false,
7897
serverUrl: this.initialServerUrl,
7998
wsOnly: this.initialWsOnly,
8099
path: this.initialPath,
100+
namespace: this.initialNamespace,
81101
username: "",
82102
password: "",
83103
parser: this.initialParser,
@@ -111,6 +131,7 @@ export default {
111131
serverUrl: this.serverUrl,
112132
wsOnly: this.wsOnly,
113133
path: this.path,
134+
namespace: this.namespace,
114135
username: this.username,
115136
password: this.password,
116137
parser: this.parser,

ui/src/locales/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
"path": "Path",
3030
"parser": "Parser",
3131
"default-parser": "Built-in parser",
32-
"msgpack-parser": "MessagePack parser"
32+
"msgpack-parser": "MessagePack parser",
33+
"namespace": "Admin namespace",
34+
"advanced-options": "Advanced options"
3335
},
3436
"dashboard": {
3537
"title": "Dashboard",

ui/src/locales/fr.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@
2626
"invalid-credentials": "Identifiants invalides",
2727
"error": "Erreur",
2828
"websocket-only": "WebSocket uniquement ?",
29-
"path": "Chemin HTTP"
29+
"path": "Chemin HTTP",
30+
"parser": "Encodeur",
31+
"default-parser": "Encodeur par défaut",
32+
"msgpack-parser": "Encodeur basé sur MessagePack",
33+
"namespace": "Espace de nom d'administration",
34+
"advanced-options": "Options avancées"
3035
},
3136
"dashboard": {
3237
"title": "Accueil",

ui/src/store/modules/connection.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default {
66
serverUrl: "",
77
wsOnly: false,
88
path: "/socket.io",
9+
namespace: "/admin",
910
parser: "default",
1011
sessionId: "",
1112
connected: false,
@@ -14,21 +15,29 @@ export default {
1415
init(state) {
1516
if (isLocalStorageAvailable) {
1617
state.serverUrl = localStorage.getItem("server_url");
18+
if (state.serverUrl.endsWith("/admin")) {
19+
// for backward compatibility
20+
state.serverUrl = state.serverUrl.slice(0, -6);
21+
} else {
22+
state.namespace = localStorage.getItem("namespace") || "/admin";
23+
}
1724
state.wsOnly = localStorage.getItem("ws_only") === "true";
1825
state.sessionId = localStorage.getItem("session_id");
1926
state.path = localStorage.getItem("path") || "/socket.io";
2027
state.parser = localStorage.getItem("parser") || "default";
2128
}
2229
},
23-
saveConfig(state, { serverUrl, wsOnly, path, parser }) {
30+
saveConfig(state, { serverUrl, wsOnly, path, namespace, parser }) {
2431
state.serverUrl = serverUrl;
2532
state.wsOnly = wsOnly;
2633
state.path = path;
34+
state.namespace = namespace;
2735
state.parser = parser;
2836
if (isLocalStorageAvailable) {
2937
localStorage.setItem("server_url", serverUrl);
3038
localStorage.setItem("ws_only", wsOnly);
3139
localStorage.setItem("path", path);
40+
localStorage.setItem("namespace", namespace);
3241
localStorage.setItem("parser", parser);
3342
}
3443
},

0 commit comments

Comments
 (0)