diff --git a/ui/mirage/factories/login-rule.js b/ui/mirage/factories/login-rule.js new file mode 100644 index 0000000000..8d2aa55a2b --- /dev/null +++ b/ui/mirage/factories/login-rule.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { Factory } from 'miragejs'; + +export default Factory.extend({ + name: (i) => `Login rule ${i}`, + namespace: (i) => `namespace-${i}`, + default_auth_type: 'okta', + backup_auth_types: () => ['oidc', 'token'], + disable_inheritance: false, +}); diff --git a/ui/mirage/handlers/custom-login.js b/ui/mirage/handlers/custom-login.js new file mode 100644 index 0000000000..cb82141076 --- /dev/null +++ b/ui/mirage/handlers/custom-login.js @@ -0,0 +1,60 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +export default function (server) { + // LIST, READ and DELETE requests for default-auth (login customizations) + server.get('sys/config/ui/login/default-auth', (schema, req) => { + // API expects { data: { list: true } } as query params when making LIST requests + if (req.queryParams.list) { + const records = schema.db['loginRules']; + if (records) { + const keys = records.map(({ name }) => name); + const key_info = records.reduce((obj, record) => { + const { name, namespace, disable_inheritance } = record; + // TBD, but likely only limited information will be returned about the record from the LIST request + obj[name] = { namespace, disable_inheritance }; + return obj; + }, {}); + return { + data: { keys, key_info }, + }; + } + return new Response(404, {}, { errors: [] }); + } + }); + + server.get('sys/config/ui/login/default-auth/:name', (schema, req) => { + // req.params come in as: { name: "Login rule name" } + const record = schema.db['loginRules'].findBy(req.params); + if (record) { + delete record.id; // "name" is the id + return { data: record }; + } + return new Response(404, {}, { errors: [] }); + }); + + server.delete('sys/config/ui/login/default-auth/:name', (schema, req) => { + const record = schema.db['loginRules'].findBy(req.params); + if (record) { + schema.db['loginRules'].remove(record); + return new Response(204); // No content + } + return new Response(404, {}, { errors: [] }); + }); + + // UNAUTHENTICATED READ ONLY for login form display logic + server.get('sys/internal/ui/default-login-methods', (schema, req) => { + const nsHeader = req.requestHeaders['X-Vault-Namespace']; + // if no namespace is passed, assume root + const namespace = !nsHeader ? '' : nsHeader; + const nsRule = schema.db['loginRules'].findBy({ namespace }); + if (nsRule) { + // only data relevant to login form is returned + const { default_auth_type, backup_auth_types } = nsRule; + return { data: { default_auth_type, backup_auth_types } }; + } + return new Response(404, {}, { errors: [] }); + }); +} diff --git a/ui/mirage/handlers/index.js b/ui/mirage/handlers/index.js index f7c290efc1..b85ff4e99f 100644 --- a/ui/mirage/handlers/index.js +++ b/ui/mirage/handlers/index.js @@ -7,8 +7,9 @@ // individual lookup done in mirage config import base from './base'; import chrootNamespace from './chroot-namespace'; -import customMessages from './custom-messages'; import clients from './clients'; +import customMessages from './custom-messages'; +import customLogin from './custom-login'; import database from './database'; import hcpLink from './hcp-link'; import kms from './kms'; @@ -18,13 +19,15 @@ import mfaConfig from './mfa-config'; import mfaLogin from './mfa-login'; import oidcConfig from './oidc-config'; import reducedDisclosure from './reduced-disclosure'; -import sync from './sync'; import replication from './replication'; +import sync from './sync'; export { base, chrootNamespace, clients, + customLogin, + customMessages, database, hcpLink, kms, @@ -34,7 +37,6 @@ export { mfaLogin, oidcConfig, reducedDisclosure, - customMessages, - sync, replication, + sync, }; diff --git a/ui/mirage/scenarios/custom-login.js b/ui/mirage/scenarios/custom-login.js new file mode 100644 index 0000000000..44d45f7e50 --- /dev/null +++ b/ui/mirage/scenarios/custom-login.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +export default function (server) { + server.create('login-rule', { + name: 'Root namespace default', + namespace: '', + default_auth_type: 'userpass', + backup_auth_types: ['okta'], + disable_inheritance: true, + }); + server.create('login-rule', { + namespace: 'admin/', + default_auth_type: 'oidc', + backup_auth_types: ['token'], + }); + server.create('login-rule', { default_auth_type: 'jwt', backup_auth_types: [] }); + server.create('login-rule', { default_auth_type: '', backup_auth_types: ['oidc', 'jwt'] }); + server.create('login-rule', { default_auth_type: '', backup_auth_types: ['token'] }); +} diff --git a/ui/mirage/scenarios/index.js b/ui/mirage/scenarios/index.js index d2e4587c2b..20b094a576 100644 --- a/ui/mirage/scenarios/index.js +++ b/ui/mirage/scenarios/index.js @@ -6,5 +6,6 @@ import kubernetes from './kubernetes'; import ldap from './ldap'; import sync from './sync'; +import customLogin from './custom-login'; -export { kubernetes, ldap, sync }; +export { kubernetes, ldap, sync, customLogin };