mirror of
https://github.com/hashicorp/vault.git
synced 2026-02-03 20:40:45 -05:00
* override auth form with direct link * add changelog Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
This commit is contained in:
parent
caf642b7d2
commit
4e78a0bfc5
4 changed files with 30 additions and 16 deletions
3
changelog/_12142.txt
Normal file
3
changelog/_12142.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:bug
|
||||
ui: Fixes login form so `?with=<path>` query param correctly displays only the specified mount when multiple mounts of the same auth type are configured with `listing_visibility="unauth"`
|
||||
```
|
||||
|
|
@ -58,17 +58,6 @@ import type { Task } from 'ember-concurrency';
|
|||
* 🔀 Multiple visible mounts:
|
||||
* ▸ Path dropdown is shown.
|
||||
*
|
||||
* @example
|
||||
* <Auth::Page
|
||||
* @cluster={{this.model.clusterModel}}
|
||||
* @directLinkData={{this.model.directLinkData}}
|
||||
* @loginSettings={{this.model.loginSettings}}
|
||||
* @namespaceQueryParam={{this.namespaceQueryParam}}
|
||||
* @oidcProviderQueryParam={{this.oidcProvider}}
|
||||
* @loginAndTransition={{this.loginAndTransition}}
|
||||
* @onNamespaceUpdate={{perform this.updateNamespace}}
|
||||
* @visibleAuthMounts={{this.model.visibleAuthMounts}}
|
||||
* />
|
||||
*
|
||||
* @param {object} cluster - the ember data cluster model. contains information such as cluster id, name and boolean for if the cluster is in standby
|
||||
* @param {object} directLinkData - mount data built from the "with" query param. If param is a mount path and maps to a visible mount, the login form defaults to this mount. Otherwise the form preselects the passed auth type.
|
||||
|
|
@ -161,10 +150,14 @@ export default class AuthPage extends Component<Args> {
|
|||
get directLinkViews() {
|
||||
const { directLinkData } = this.args;
|
||||
|
||||
// If "path" key exists we know the "with" query param references a mount with listing_visibility="unauth"
|
||||
// Treat it as a preferred method and hide all other tabs.
|
||||
// If "path" key exists then the "with" query param references a specific mount with listing_visibility="unauth".
|
||||
// Show only this mount and hide any others for this auth type as well as any tabs for different auth types.
|
||||
if (directLinkData?.path) {
|
||||
const tabData = this.filterVisibleMountsByType([directLinkData.type]);
|
||||
const mounts = this.mountsByType(directLinkData.type);
|
||||
const selectedMount = mounts?.find((m) => m.path === directLinkData?.path);
|
||||
const tabData: UnauthMountsByType = {
|
||||
[directLinkData.type]: selectedMount ? [selectedMount] : null,
|
||||
};
|
||||
const defaultView = this.constructViews(FormView.TABS, tabData);
|
||||
const alternateView = this.constructViews(FormView.DROPDOWN, null);
|
||||
|
||||
|
|
@ -263,11 +256,16 @@ export default class AuthPage extends Component<Args> {
|
|||
const tabs: UnauthMountsByType = {};
|
||||
for (const type of authTypes) {
|
||||
// adds visible mounts for each type, if they exist
|
||||
tabs[type] = this.visibleMountsByType?.[type] || null;
|
||||
tabs[type] = this.mountsByType(type);
|
||||
}
|
||||
return tabs;
|
||||
}
|
||||
|
||||
private mountsByType(type: string) {
|
||||
// Return null and not an empty array to distinguish between "dropdown mode" and "tabs with no mounts" in downstream components
|
||||
return this.visibleMountsByType?.[type] || null;
|
||||
}
|
||||
|
||||
private constructViews(view: FormView, tabData: UnauthMountsByType | null) {
|
||||
return { view, tabData };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ export default class AuthRoute extends Route {
|
|||
const { default_auth_type, backup_auth_types } = response.data;
|
||||
return {
|
||||
defaultType: default_auth_type,
|
||||
// TODO WIP backend PR consistently return empty array when no backup_auth_types
|
||||
backupTypes: backup_auth_types?.length ? backup_auth_types : null,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,20 @@ module('Integration | Component | auth | page | listing visibility', function (h
|
|||
assert.dom(GENERAL.backButton).doesNotExist();
|
||||
});
|
||||
|
||||
test('it treats direct link as only mount when multiple mounts are tuned with listing_visibility="unauth"', async function (assert) {
|
||||
this.directLinkData = { path: 'userpass2/', type: 'userpass' };
|
||||
await this.renderComponent();
|
||||
assert.dom(AUTH_FORM.authForm('userpass')).exists;
|
||||
assert.dom(AUTH_FORM.tabBtn('userpass')).hasText('Userpass', 'it renders tab for type');
|
||||
assert.dom(AUTH_FORM.tabs).exists({ count: 1 }, 'only one tab renders');
|
||||
assert.dom(GENERAL.inputByAttr('path')).hasAttribute('type', 'hidden');
|
||||
assert.dom(GENERAL.inputByAttr('path')).hasValue('userpass2/');
|
||||
assert.dom(GENERAL.button('Sign in with other methods')).exists('"Sign in with other methods" renders');
|
||||
assert.dom(GENERAL.selectByAttr('auth type')).doesNotExist();
|
||||
assert.dom(AUTH_FORM.advancedSettings).doesNotExist();
|
||||
assert.dom(GENERAL.backButton).doesNotExist();
|
||||
});
|
||||
|
||||
test('it prioritizes auth type from canceled mfa instead of direct link for path', async function (assert) {
|
||||
assert.expect(1);
|
||||
this.directLinkData = this.directLinkIsVisibleMount; // type is "oidc"
|
||||
|
|
|
|||
Loading…
Reference in a new issue