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:
parent
91481143af
commit
b743ada5ab
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
ui: Fix secret render when path includes %. Resolves #11616.
|
||||||
|
```
|
|
@ -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 };
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue