UI: fix secret with % in path (#20430)

* Use encode/decode uri component instead of route-recognizer. Fixes #11616

* Remove route-recognizer explicit dependency

* Add changelog
This commit is contained in:
Chelsea Shaw 2023-05-01 09:18:45 -05:00 committed by GitHub
parent 91481143af
commit b743ada5ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 11 deletions

3
changelog/20430.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
ui: Fix secret render when path includes %. Resolves #11616.
```

View File

@ -3,14 +3,25 @@
* SPDX-License-Identifier: MPL-2.0 * SPDX-License-Identifier: MPL-2.0
*/ */
import RouteRecognizer from 'route-recognizer'; function encodePath(path) {
return path
const { ? path
Normalizer: { normalizePath, encodePathSegment }, .split('/')
} = RouteRecognizer; .map((segment) => encodeURIComponent(segment))
.join('/')
export function encodePath(path) { : path;
return path ? path.split('/').map(encodePathSegment).join('/') : path;
} }
export { normalizePath, encodePathSegment }; function normalizePath(path) {
// Unlike normalizePath from route-recognizer, this method assumes
// we do not have percent-encoded data octets as defined in
// https://datatracker.ietf.org/doc/html/rfc3986
return path
? path
.split('/')
.map((segment) => decodeURIComponent(segment))
.join('/')
: '';
}
export { normalizePath, encodePath };

View File

@ -83,7 +83,7 @@ export default class KeyValueHeader extends Component {
label: parts[index], label: parts[index],
text: this.stripTrailingSlash(parts[index]), text: this.stripTrailingSlash(parts[index]),
path: path, path: path,
model: ancestor, model: encodePath(ancestor),
}); });
}); });

View File

@ -187,7 +187,6 @@
"pvutils": "^1.0.17", "pvutils": "^1.0.17",
"qunit": "^2.19.1", "qunit": "^2.19.1",
"qunit-dom": "^2.0.0", "qunit-dom": "^2.0.0",
"route-recognizer": "^0.3.4",
"sass-svg-uri": "^1.0.0", "sass-svg-uri": "^1.0.0",
"shell-quote": "^1.6.1", "shell-quote": "^1.6.1",
"string.prototype.endswith": "^0.2.0", "string.prototype.endswith": "^0.2.0",

View File

@ -515,6 +515,37 @@ module('Acceptance | secrets/secret/create, read, delete', function (hooks) {
assert.strictEqual(currentURL(), `/vault/secrets/${enginePath}/show/${encodedSecretPath}?version=1`); assert.strictEqual(currentURL(), `/vault/secrets/${enginePath}/show/${encodedSecretPath}?version=1`);
}); });
test('UI handles secret with % in path correctly', async function (assert) {
const enginePath = `kv-engine-${this.uid}`;
const secretPath = 'per%cent/%fu ll';
const [firstPath, secondPath] = secretPath.split('/');
const commands = [`write sys/mounts/${enginePath} type=kv`, `write '${enginePath}/${secretPath}' 3=4`];
await consoleComponent.runCommands(commands);
await listPage.visitRoot({ backend: enginePath });
assert.dom(`[data-test-secret-link="${firstPath}/"]`).exists('First section item exists');
await click(`[data-test-secret-link="${firstPath}/"]`);
assert.strictEqual(
currentURL(),
`/vault/secrets/${enginePath}/list/${encodeURIComponent(firstPath)}/`,
'First part of path is encoded in URL'
);
assert.dom(`[data-test-secret-link="${secretPath}"]`).exists('Link to secret exists');
await click(`[data-test-secret-link="${secretPath}"]`);
assert.strictEqual(
currentURL(),
`/vault/secrets/${enginePath}/show/${encodeURIComponent(firstPath)}/${encodeURIComponent(secondPath)}`,
'secret path is encoded in URL'
);
assert.dom('h1').hasText(secretPath, 'Path renders correctly on show page');
await click(`[data-test-secret-breadcrumb="${firstPath}"]`);
assert.strictEqual(
currentURL(),
`/vault/secrets/${enginePath}/list/${encodeURIComponent(firstPath)}/`,
'Breadcrumb link encodes correctly'
);
});
// the web cli does not handle a quote as part of a path, so we test it here via the UI // the web cli does not handle a quote as part of a path, so we test it here via the UI
test('creating a secret with a single or double quote works properly', async function (assert) { test('creating a secret with a single or double quote works properly', async function (assert) {
assert.expect(4); assert.expect(4);