Skip to content

Commit da2b940

Browse files
authored
Properly url encode/decode branch names + object names whenever they're used in url paths (#353)
1 parent 27fb1ca commit da2b940

8 files changed

Lines changed: 28 additions & 13 deletions

File tree

shared/studio/state/connection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class Connection extends Model({
9191
conn = AdminUIFetchConnection.create(
9292
{
9393
address: this.config.serverUrl,
94-
database: this.config.database,
94+
database: encodeURIComponent(this.config.database),
9595
user: this.config.user,
9696
token: this.config.authToken,
9797
},

shared/studio/tabs/ai/state/rag.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ export async function runRAGQuery(
6464
abortController: AbortController
6565
): Promise<SSEStream> {
6666
const response = await fetch(
67-
`${connectConfig.serverUrl}/branch/${connectConfig.database}/ext/ai/rag`,
67+
`${connectConfig.serverUrl}/branch/${encodeURIComponent(
68+
connectConfig.database
69+
)}/ext/ai/rag`,
6870
{
6971
method: "POST",
7072
headers: {

shared/studio/tabs/auth/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const AuthUrls = observer(function AuthUrls({
142142
const databaseState = useDatabaseState();
143143

144144
const url = new URL(instanceState.serverUrl);
145-
url.pathname = `db/${databaseState.name}/ext/auth`;
145+
url.pathname = `db/${encodeURIComponent(databaseState.name)}/ext/auth`;
146146

147147
const baseUrl = url.toString();
148148

shared/studio/tabs/dataview/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ export const DataView = observer(function DataView() {
5353
} else if (dbState.schemaData) {
5454
const updatedPath = state.updateFromPath(path ?? "");
5555
if (updatedPath !== null) {
56-
navigate(`${basePath}/${updatedPath}`, true);
56+
navigate(
57+
`${basePath}/${updatedPath
58+
.map((part) => encodeURIComponent(part).replace(/%3A/g, ":"))
59+
.join("/")}`,
60+
true
61+
);
5762
}
5863
}
5964
}, [currentPath, dbState.schemaData]);

shared/studio/tabs/dataview/state/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ export class DataView extends Model({
118118
}
119119

120120
@modelAction
121-
updateFromPath(path: string): string | null {
121+
updateFromPath(path: string): string[] | null {
122122
this.lastSelectedPath = path;
123-
const [rootObjectTypeName, ...nestedParts] = path.split("/");
123+
const [rootObjectTypeName, ...nestedParts] = path
124+
.split("/")
125+
.map(decodeURIComponent);
124126
if (rootObjectTypeName !== this.inspectorStack[0]?.objectType?.name) {
125127
const objTypeId = this.objectTypes.find(
126128
(obj) => obj.name === rootObjectTypeName
@@ -129,7 +131,7 @@ export class DataView extends Model({
129131
this.selectObject(objTypeId);
130132
} else {
131133
this.selectObject(this.objectTypes[0]?.id);
132-
return this.objectTypes[0]?.name ?? "";
134+
return [this.objectTypes[0]?.name ?? ""];
133135
}
134136
}
135137
let i = 0;
@@ -162,7 +164,7 @@ export class DataView extends Model({
162164
(typeof objId === "number" && !this.edits.insertEdits.has(objId))
163165
) {
164166
this.inspectorStack = this.inspectorStack.slice(0, i + 1);
165-
return [rootObjectTypeName, ...nestedParts.slice(0, i * 2)].join("/");
167+
return [rootObjectTypeName, ...nestedParts.slice(0, i * 2)];
166168
} else {
167169
if (
168170
objId !== stackItem?.parentObject!.id ||

shared/studio/tabs/repl/state/commands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export async function handleSlashCommand(
7777

7878
if (instanceState.databases!.includes(dbName)) {
7979
item.setCommandResult({kind: CommandOutputKind.none});
80-
repl.navigation?.(`${dbName}/repl`);
80+
repl.navigation?.(`${encodeURIComponent(dbName)}/repl`);
8181
} else {
8282
item.setCommandResult({
8383
kind: CommandOutputKind.error,

web/src/components/databasePage/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function HeaderNavMenu({
101101
label: db,
102102
selected: selectedDB === db,
103103
checked: currentDB === db,
104-
linkProps: {to: `/${db}`},
104+
linkProps: {to: `/${encodeURIComponent(db)}`},
105105
onHover: () => setSelectedDB(db),
106106
})) ?? null,
107107
},
@@ -113,7 +113,9 @@ function HeaderNavMenu({
113113
<CreateBranchModal
114114
fromBranch={currentDB}
115115
instanceState={instanceState}
116-
navigateToDB={(dbName) => navigate(`/${dbName}`)}
116+
navigateToDB={(dbName) =>
117+
navigate(`/${encodeURIComponent(dbName)}`)
118+
}
117119
/>
118120
),
119121
}}

web/src/components/instancePage/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ export default observer(function InstancePage() {
2121
<div className={styles.instanceName}>{instanceState.instanceName}</div>
2222
<div className={styles.databases}>
2323
{instanceState.databases?.map((db) => (
24-
<Link key={db} className={styles.databaseCard} to={db}>
24+
<Link
25+
key={db}
26+
className={styles.databaseCard}
27+
to={encodeURIComponent(db)}
28+
>
2529
<HeaderDatabaseIcon />
2630
<span>{db}</span>
2731
</Link>
@@ -59,7 +63,7 @@ export default observer(function InstancePage() {
5963
<CreateBranchModal
6064
instanceState={instanceState}
6165
navigateToDB={(branchName) => {
62-
navigate(`/${branchName}`);
66+
navigate(`/${encodeURIComponent(branchName)}`);
6367
}}
6468
/>
6569
);

0 commit comments

Comments
 (0)