From 3b362cfd8b85019370dab39e08ce1762c0628c3f Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Wed, 25 Sep 2019 15:06:28 -0400 Subject: [PATCH 01/63] enable auth method item configuration in go code --- builtin/credential/cert/path_certs.go | 17 +++++++++++++++++ builtin/credential/ldap/path_groups.go | 4 +++- builtin/credential/ldap/path_users.go | 4 +++- builtin/credential/okta/path_config.go | 3 +++ builtin/credential/okta/path_groups.go | 8 ++++++++ builtin/credential/okta/path_users.go | 8 ++++++++ builtin/credential/radius/path_config.go | 3 +++ builtin/credential/radius/path_users.go | 8 ++++++++ builtin/credential/userpass/path_users.go | 8 ++++++++ sdk/framework/path.go | 3 +++ 10 files changed, 64 insertions(+), 2 deletions(-) diff --git a/builtin/credential/cert/path_certs.go b/builtin/credential/cert/path_certs.go index 0a57f347be8e..806922d4421b 100644 --- a/builtin/credential/cert/path_certs.go +++ b/builtin/credential/cert/path_certs.go @@ -23,6 +23,10 @@ func pathListCerts(b *backend) *framework.Path { HelpSynopsis: pathCertHelpSyn, HelpDescription: pathCertHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Navigation: true, + ItemType: "Certificate", + }, } } @@ -59,18 +63,27 @@ At least one must exist in the Common Name. Supports globbing.`, Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of DNS names. At least one must exist in the SANs. Supports globbing.`, + DisplayAttrs: &framework.DisplayAttributes{ + Name: "Allowed DNS SANs", + }, }, "allowed_email_sans": &framework.FieldSchema{ Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of Email Addresses. At least one must exist in the SANs. Supports globbing.`, + DisplayAttrs: &framework.DisplayAttributes{ + Name: "Allowed Email SANs", + }, }, "allowed_uri_sans": &framework.FieldSchema{ Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of URIs. At least one must exist in the SANs. Supports globbing.`, + DisplayAttrs: &framework.DisplayAttributes{ + Name: "Allowed URI SANs", + }, }, "allowed_organizational_units": &framework.FieldSchema{ @@ -137,6 +150,10 @@ certificate.`, HelpSynopsis: pathCertHelpSyn, HelpDescription: pathCertHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Create", + ItemType: "Certificate", + }, } tokenutil.AddTokenFields(p.Fields) diff --git a/builtin/credential/ldap/path_groups.go b/builtin/credential/ldap/path_groups.go index 76e64c4505a0..b39691cf8174 100644 --- a/builtin/credential/ldap/path_groups.go +++ b/builtin/credential/ldap/path_groups.go @@ -21,6 +21,7 @@ func pathGroupsList(b *backend) *framework.Path { HelpDescription: pathGroupHelpDesc, DisplayAttrs: &framework.DisplayAttributes{ Navigation: true, + ItemType: "Group", }, } } @@ -49,7 +50,8 @@ func pathGroups(b *backend) *framework.Path { HelpSynopsis: pathGroupHelpSyn, HelpDescription: pathGroupHelpDesc, DisplayAttrs: &framework.DisplayAttributes{ - Action: "Create", + Action: "Create", + ItemType: "Group", }, } } diff --git a/builtin/credential/ldap/path_users.go b/builtin/credential/ldap/path_users.go index 60276cf64e5e..af2f2cb5da40 100644 --- a/builtin/credential/ldap/path_users.go +++ b/builtin/credential/ldap/path_users.go @@ -23,6 +23,7 @@ func pathUsersList(b *backend) *framework.Path { DisplayAttrs: &framework.DisplayAttributes{ Navigation: true, Action: "Create", + ItemType: "User", }, } } @@ -56,7 +57,8 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, DisplayAttrs: &framework.DisplayAttributes{ - Action: "Create", + Action: "Create", + ItemType: "User", }, } } diff --git a/builtin/credential/okta/path_config.go b/builtin/credential/okta/path_config.go index 3cbf1041e2ba..5c5dd3a68cf5 100644 --- a/builtin/credential/okta/path_config.go +++ b/builtin/credential/okta/path_config.go @@ -87,6 +87,9 @@ func pathConfig(b *backend) *framework.Path { ExistenceCheck: b.pathConfigExistenceCheck, HelpSynopsis: pathConfigHelp, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Configure", + }, } tokenutil.AddTokenFields(p.Fields) diff --git a/builtin/credential/okta/path_groups.go b/builtin/credential/okta/path_groups.go index 83742035035f..9ba36b282af8 100644 --- a/builtin/credential/okta/path_groups.go +++ b/builtin/credential/okta/path_groups.go @@ -19,6 +19,10 @@ func pathGroupsList(b *backend) *framework.Path { HelpSynopsis: pathGroupHelpSyn, HelpDescription: pathGroupHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Navigation: true, + ItemType: "Group", + }, } } @@ -45,6 +49,10 @@ func pathGroups(b *backend) *framework.Path { HelpSynopsis: pathGroupHelpSyn, HelpDescription: pathGroupHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Create", + ItemType: "Group", + }, } } diff --git a/builtin/credential/okta/path_users.go b/builtin/credential/okta/path_users.go index d928b56e72b7..d3408ee42f97 100644 --- a/builtin/credential/okta/path_users.go +++ b/builtin/credential/okta/path_users.go @@ -17,6 +17,10 @@ func pathUsersList(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Navigation: true, + ItemType: "User", + }, } } @@ -48,6 +52,10 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Create", + ItemType: "User", + }, } } diff --git a/builtin/credential/radius/path_config.go b/builtin/credential/radius/path_config.go index 28476e337a2f..aa0e730486c3 100644 --- a/builtin/credential/radius/path_config.go +++ b/builtin/credential/radius/path_config.go @@ -85,6 +85,9 @@ func pathConfig(b *backend) *framework.Path { HelpSynopsis: pathConfigHelpSyn, HelpDescription: pathConfigHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Configure", + }, } tokenutil.AddTokenFields(p.Fields) diff --git a/builtin/credential/radius/path_users.go b/builtin/credential/radius/path_users.go index 3a48788cb8b6..470513f4db41 100644 --- a/builtin/credential/radius/path_users.go +++ b/builtin/credential/radius/path_users.go @@ -20,6 +20,10 @@ func pathUsersList(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Navigation: true, + ItemType: "User", + }, } } @@ -49,6 +53,10 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Create", + ItemType: "User", + }, } } diff --git a/builtin/credential/userpass/path_users.go b/builtin/credential/userpass/path_users.go index 140025acc8e3..125332088148 100644 --- a/builtin/credential/userpass/path_users.go +++ b/builtin/credential/userpass/path_users.go @@ -22,6 +22,10 @@ func pathUsersList(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Navigation: true, + ItemType: "User", + }, } } @@ -75,6 +79,10 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Create", + ItemType: "User", + }, } tokenutil.AddTokenFields(p.Fields) diff --git a/sdk/framework/path.go b/sdk/framework/path.go index a8e5f56ffffb..bf2bbdb574a6 100644 --- a/sdk/framework/path.go +++ b/sdk/framework/path.go @@ -173,6 +173,9 @@ type DisplayAttributes struct { // Navigation indicates that the path should be available as a navigation tab Navigation bool `json:"navigation,omitempty"` + // ItemType is the type of item this path operates on + ItemType string `json:"itemType,omitempty"` + // Group is the suggested UI group to place this field in. Group string `json:"group,omitempty"` From c1674de7eedf3253363e260588024b777743c843 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Wed, 25 Sep 2019 15:06:57 -0400 Subject: [PATCH 02/63] properly parse and list generated items --- ui/app/helpers/tabs-for-auth-section.js | 22 ++- .../vault/cluster/access/method/item.js | 7 +- .../vault/cluster/access/method/item/list.js | 4 +- .../vault/cluster/access/method/section.js | 3 +- ui/app/services/path-help.js | 171 +++++++++++------- 5 files changed, 129 insertions(+), 78 deletions(-) diff --git a/ui/app/helpers/tabs-for-auth-section.js b/ui/app/helpers/tabs-for-auth-section.js index c66ed62220d6..f5a0c18faba8 100644 --- a/ui/app/helpers/tabs-for-auth-section.js +++ b/ui/app/helpers/tabs-for-auth-section.js @@ -77,6 +77,7 @@ const TABS_FOR_SHOW = {}; export function tabsForAuthSection([model, sectionType = 'authSettings', paths]) { let tabs; + debugger; if (sectionType === 'authSettings') { tabs = (TABS_FOR_SETTINGS[model.type] || []).slice(); tabs.push({ @@ -85,14 +86,19 @@ export function tabsForAuthSection([model, sectionType = 'authSettings', paths]) }); return tabs; } - if (paths) { - tabs = paths.map(path => { - let itemName = path.slice(1); //get rid of leading slash - return { - label: capitalize(pluralize(itemName)), - routeParams: ['vault.cluster.access.method.item.list', itemName], - }; - }); + if (paths || model.paths) { + if (model.paths) { + paths = model.paths.paths.filter(path => path.navigation); + } + + tabs = paths + .map(path => { + return { + label: capitalize(pluralize(path.itemName)), + routeParams: ['vault.cluster.access.method.item.list', path.itemType], + }; + }) + .compact(); } else { tabs = (TABS_FOR_SHOW[model.type] || []).slice(); } diff --git a/ui/app/routes/vault/cluster/access/method/item.js b/ui/app/routes/vault/cluster/access/method/item.js index 45b52698d7a9..3b54e4fef40f 100644 --- a/ui/app/routes/vault/cluster/access/method/item.js +++ b/ui/app/routes/vault/cluster/access/method/item.js @@ -13,6 +13,7 @@ export default Route.extend({ }, getMethodAndModelInfo() { + debugger; const { item_type: itemType } = this.paramsFor(this.routeName); const { path: method } = this.paramsFor('vault.cluster.access.method'); const methodModel = this.modelFor('vault.cluster.access.method'); @@ -26,7 +27,11 @@ export default Route.extend({ controller.set('itemType', itemType); controller.set('method', method); this.pathHelp.getPaths(apiPath, method, itemType).then(paths => { - controller.set('paths', Array.from(paths.list, pathInfo => pathInfo.path)); + let navigationPaths = paths.paths.filter(path => path.navigation); + controller.set( + 'paths', + navigationPaths.filter(path => path.itemType.includes(itemType)).map(path => path.path) + ); }); }, }); diff --git a/ui/app/routes/vault/cluster/access/method/item/list.js b/ui/app/routes/vault/cluster/access/method/item/list.js index bbb732dbcf83..2d019b31df97 100644 --- a/ui/app/routes/vault/cluster/access/method/item/list.js +++ b/ui/app/routes/vault/cluster/access/method/item/list.js @@ -52,10 +52,12 @@ export default Route.extend(ListRoute, { setupController(controller) { this._super(...arguments); const { apiPath, method, itemType } = this.getMethodAndModelInfo(); + debugger; controller.set('itemType', itemType); controller.set('method', method); this.pathHelp.getPaths(apiPath, method, itemType).then(paths => { - controller.set('paths', paths.navPaths.reduce((acc, cur) => acc.concat(cur.path), [])); + let navigationPaths = paths.paths.filter(path => path.navigation); + controller.set('paths', navigationPaths.filter(path => path.itemType.includes(itemType))); }); }, }); diff --git a/ui/app/routes/vault/cluster/access/method/section.js b/ui/app/routes/vault/cluster/access/method/section.js index ee58779d6ecc..30346bb18de7 100644 --- a/ui/app/routes/vault/cluster/access/method/section.js +++ b/ui/app/routes/vault/cluster/access/method/section.js @@ -24,7 +24,6 @@ export default Route.extend({ this._super(...arguments); controller.set('section', section); let method = this.modelFor('vault.cluster.access.method'); - let paths = method.paths.navPaths.map(pathInfo => pathInfo.path); - controller.set('paths', paths); + controller.set('paths', method.paths.paths.filter(path => path.navigation)); }, }); diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 60a8b6883f65..870b3dcb0ef2 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -10,8 +10,10 @@ import { getOwner } from '@ember/application'; import { assign } from '@ember/polyfills'; import { expandOpenApiProps, combineAttributes } from 'vault/utils/openapi-to-attrs'; import fieldToAttrs from 'vault/utils/field-to-attrs'; -import { resolve } from 'rsvp'; +import { resolve, reject } from 'rsvp'; import { debug } from '@ember/debug'; +import { dasherize } from '@ember/string'; +import { singularize } from 'ember-inflector'; import generatedItemAdapter from 'vault/adapters/generated-item-list'; export function sanitizePath(path) { @@ -42,89 +44,123 @@ export default Service.extend({ if (newModel.merged || modelProto.useOpenAPI !== true) { return resolve(); } - helpUrl = modelProto.getHelpUrl(backend); - return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); + // helpUrl = modelProto.getHelpUrl(backend); + // return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); } else { debug(`Creating new Model for ${modelType}`); newModel = DS.Model.extend({}); - //use paths to dynamically create our openapi help url - //if we have a brand new model - return this.getPaths(apiPath, backend, itemType).then(paths => { + } + + //use paths to dynamically create our openapi help url + //if we have a brand new model + return this.getPaths(apiPath, backend, itemType) + .then(pathInfo => { const adapterFactory = owner.factoryFor(`adapter:${modelType}`); //if we have an adapter already use that, otherwise create one if (!adapterFactory) { debug(`Creating new adapter for ${modelType}`); - const adapter = this.getNewAdapter(paths, itemType); + const adapter = this.getNewAdapter(pathInfo, itemType); owner.register(`adapter:${modelType}`, adapter); } + let path, paths; //if we have an item we want the create info for that itemType - let path; - if (itemType) { - const createPath = paths.create.find(path => path.path.includes(itemType)); - path = createPath.path; - path = path.slice(0, path.indexOf('{') - 1) + '/example'; - } else { - //we need the mount config - path = paths.configPath[0].path; + paths = itemType ? this.filterPathsByItemType(pathInfo, itemType) : pathInfo.paths; + const createPath = paths.find(path => path.operations.includes('post') && path.action !== 'Delete'); + path = createPath.path; + path = path.includes('{') ? path.slice(0, path.indexOf('{') - 1) + '/example' : path; + if (!path) { + return reject(); } - helpUrl = `/v1/${apiPath}${path.slice(1)}?help=true`; + + helpUrl = `/v1/${apiPath}${path.slice(1)}?help=true` || newModel.proto().getHelpUrl(backend); + pathInfo.paths = paths; + newModel = newModel.extend({ paths: pathInfo }); return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); + }) + .catch(err => { + debugger; }); - } }, - reducePaths(paths, currentPath) { + reducePathsByPathName(pathInfo, currentPath) { const pathName = currentPath[0]; - const pathInfo = currentPath[1]; + const pathDetails = currentPath[1]; + const displayAttrs = pathDetails['x-vault-displayAttrs']; - //config is a get/post endpoint that doesn't take route params - //and isn't also a list endpoint and has an Action of Configure - if ( - pathInfo.post && - pathInfo.get && - (pathInfo['x-vault-displayAttrs'] && pathInfo['x-vault-displayAttrs'].action === 'Configure') - ) { - paths.configPath.push({ path: pathName }); - return paths; //config path should only be config path + if (!displayAttrs) { + return pathInfo; } - //list endpoints all have { name: "list" } in their get parameters - if (pathInfo.get && pathInfo.get.parameters && pathInfo.get.parameters[0].name === 'list') { - paths.list.push({ path: pathName }); + if (pathName.includes('{')) { + //we need to know if there are url params + pathName.split('{')[1].split('}')[0]; } - if (pathInfo.delete) { - paths.delete.push({ path: pathName }); + let itemType, itemName; + if (displayAttrs.itemType) { + itemType = displayAttrs.itemType; + let items = itemType.split(':'); + itemName = items[items.length - 1]; + items = items.map(item => dasherize(singularize(item.toLowerCase()))); + itemType = items.join('~*'); } - //create endpoints have path an action (e.g. "Create" or "Generate") - if (pathInfo.post && pathInfo['x-vault-displayAttrs'] && pathInfo['x-vault-displayAttrs'].action) { - paths.create.push({ - path: pathName, - action: pathInfo['x-vault-displayAttrs'].action, - }); + if (itemType && !pathInfo.itemTypes.includes(itemType)) { + pathInfo.itemTypes.push(itemType); } - if (pathInfo['x-vault-displayAttrs'] && pathInfo['x-vault-displayAttrs'].navigation) { - paths.navPaths.push({ path: pathName }); + let operations = []; + if (pathDetails.get) { + operations.push('get'); + } + if (pathDetails.post) { + operations.push('post'); + } + if (pathDetails.delete) { + operations.push('delete'); + } + if (pathDetails.get && pathDetails.get.parameters && pathDetails.get.parameters[0].name === 'list') { + operations.push('list'); } - return paths; + pathInfo.paths.push({ + path: pathName, + itemType: itemType || displayAttrs.itemType, + itemName: itemName || pathInfo.itemType || displayAttrs.itemType, + operations, + action: displayAttrs.action, + navigation: displayAttrs.navigation === true, + param: pathName.includes('{') ? pathName.split('{')[1].split('}')[0] : false, + }); + + return pathInfo; + }, + + filterPathsByItemType(pathInfo, itemType) { + if (!itemType) { + return pathInfo.paths; + } + return pathInfo.paths.filter(path => { + return itemType === path.itemType; + }); }, - getPaths(apiPath, backend) { - debug(`Fetching relevant paths for ${backend} from ${apiPath}`); + getPaths(apiPath, backend, itemType, itemID) { + let debugString = + itemID && itemType + ? `Fetching relevant paths for ${backend} ${itemType} ${itemID} from ${apiPath}` + : `Fetching relevant paths for ${backend} ${itemType} from ${apiPath}`; + debug(debugString); return this.ajax(`/v1/${apiPath}?help=1`, backend).then(help => { const pathInfo = help.openapi.paths; let paths = Object.entries(pathInfo); - return paths.reduce(this.reducePaths, { - apiPath: apiPath, - configPath: [], - list: [], - create: [], - delete: [], - navPaths: [], + return paths.reduce(this.reducePathsByPathName, { + apiPath, + itemType, + itemTypes: [], + paths: [], + itemID, }); }); }, @@ -168,42 +204,45 @@ export default Service.extend({ }); }, - getNewAdapter(paths, itemType) { + getNewAdapter(pathInfo, itemType) { //we need list and create paths to set the correct urls for actions - const { list, create, apiPath } = paths; - const createPath = create.find(path => path.path.includes(itemType)); - const listPath = list.find(pathInfo => pathInfo.path.includes(itemType)); - const deletePath = paths.delete.find(path => path.path.includes(itemType)); + let paths = this.filterPathsByItemType(pathInfo, itemType); + let { apiPath } = pathInfo; + const getPath = paths.find(path => path.operations.includes('get')); + + //the action might be "Generate" or something like that so we'll grab the first post endpoint if there + //isn't one with "Create" + //TODO: look into a more sophisticated way to determine the create endpoint + const createPath = paths.find(path => path.action === 'Create' || path.operations.includes('post')); + const deletePath = paths.find(path => path.operations.includes('delete')); + return generatedItemAdapter.extend({ urlForItem(method, id) { - let { path } = listPath; - let url = `${this.buildURL()}/${apiPath}${path.slice(1)}/`; + let url = `${this.buildURL()}/${apiPath}${getPath.path.slice(1)}/`; if (id) { url = url + encodePath(id); } return url; }, - urlForFindRecord(id, modelName, snapshot) { - return this.urlForItem(modelName, id, snapshot); + urlForFindRecord(id, modelName) { + return this.urlForItem(modelName, id); }, + //urlForQuery if there is an id and we are listing, use the id to construct the path urlForUpdateRecord(id) { - let { path } = createPath; - path = path.slice(1, path.indexOf('{') - 1); + let path = createPath.path.slice(1, createPath.path.indexOf('{') - 1); return `${this.buildURL()}/${apiPath}${path}/${id}`; }, urlForCreateRecord(modelType, snapshot) { const { id } = snapshot; - let { path } = createPath; - path = path.slice(1, path.indexOf('{') - 1); + let path = createPath.path.slice(1, createPath.path.indexOf('{') - 1); return `${this.buildURL()}/${apiPath}${path}/${id}`; }, urlForDeleteRecord(id) { - let { path } = deletePath; - path = path.slice(1, path.indexOf('{') - 1); + let path = deletePath.path.slice(1, deletePath.path.indexOf('{') - 1); return `${this.buildURL()}/${apiPath}${path}/${id}`; }, }); From a0186696809c60bdf9eab2f189257e2be91543f9 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Wed, 25 Sep 2019 16:13:56 -0400 Subject: [PATCH 03/63] make sure we only set name on attrs if a label comes from openAPI --- ui/app/services/path-help.js | 4 ++-- ui/app/utils/openapi-to-attrs.js | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 870b3dcb0ef2..348e70e4231a 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -12,7 +12,7 @@ import { expandOpenApiProps, combineAttributes } from 'vault/utils/openapi-to-at import fieldToAttrs from 'vault/utils/field-to-attrs'; import { resolve, reject } from 'rsvp'; import { debug } from '@ember/debug'; -import { dasherize } from '@ember/string'; +import { dasherize, capitalize } from '@ember/string'; import { singularize } from 'ember-inflector'; import generatedItemAdapter from 'vault/adapters/generated-item-list'; @@ -182,7 +182,7 @@ export default Service.extend({ //include url params if (params) { const { name, schema, description } = params[0]; - let label = name.split('_').join(' '); + let label = capitalize(name.split('_').join(' ')); paramProp[name] = { 'x-vault-displayAttrs': { diff --git a/ui/app/utils/openapi-to-attrs.js b/ui/app/utils/openapi-to-attrs.js index cbd1d6e574ea..3de3b20254cb 100644 --- a/ui/app/utils/openapi-to-attrs.js +++ b/ui/app/utils/openapi-to-attrs.js @@ -36,13 +36,18 @@ export const expandOpenApiProps = function(props) { defaultValue: value || null, }; - attrDefn.label = capitalize(name || propName); + //only set a label if we have one from OpenAPI + //otherwise the propName will be humanized by the form-field component + if (name) { + attrDefn.label = name; + } // ttls write as a string and read as a number // so setting type on them runs the wrong transform if (editType !== 'ttl' && type !== 'array') { attrDefn.type = type; } + // loop to remove empty vals for (let attrProp in attrDefn) { if (attrDefn[attrProp] == null) { From ff3053507ae0d546298bba4bcaa43a30f405dd28 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Wed, 25 Sep 2019 16:15:00 -0400 Subject: [PATCH 04/63] correctly construct paths object for method index route --- ui/app/routes/vault/cluster/access/method/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/routes/vault/cluster/access/method/index.js b/ui/app/routes/vault/cluster/access/method/index.js index a3bff252cb83..b97b96de37aa 100644 --- a/ui/app/routes/vault/cluster/access/method/index.js +++ b/ui/app/routes/vault/cluster/access/method/index.js @@ -3,7 +3,7 @@ import { tabsForAuthSection } from 'vault/helpers/tabs-for-auth-section'; export default Route.extend({ beforeModel() { let { methodType, paths } = this.modelFor('vault.cluster.access.method'); - paths = paths ? paths.navPaths.reduce((acc, cur) => acc.concat(cur.path), []) : null; + paths = paths ? paths.paths.filter(path => path.navigation === true) : null; const activeTab = tabsForAuthSection([methodType, 'authConfig', paths])[0].routeParams; return this.transitionTo(...activeTab); }, From f6c5d8370c56ad1342cd4042da99ca02e66beb56 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Wed, 25 Sep 2019 16:32:37 -0400 Subject: [PATCH 05/63] set sensitive property on password for userpass --- builtin/credential/userpass/path_users.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/builtin/credential/userpass/path_users.go b/builtin/credential/userpass/path_users.go index 125332088148..1c43e97d2d7f 100644 --- a/builtin/credential/userpass/path_users.go +++ b/builtin/credential/userpass/path_users.go @@ -41,6 +41,9 @@ func pathUsers(b *backend) *framework.Path { "password": &framework.FieldSchema{ Type: framework.TypeString, Description: "Password for this user.", + DisplayAttrs: &framework.DisplayAttributes{ + Sensitive: true, + }, }, "policies": &framework.FieldSchema{ @@ -80,8 +83,8 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, DisplayAttrs: &framework.DisplayAttributes{ - Action: "Create", - ItemType: "User", + Action: "Create", + ItemType: "User", }, } From af7639e8650feb1db755ad2de78871fafb8e9eb9 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Wed, 25 Sep 2019 16:33:53 -0400 Subject: [PATCH 06/63] remove debugger statements --- ui/app/helpers/tabs-for-auth-section.js | 1 - ui/app/routes/vault/cluster/access/method/item.js | 1 - ui/app/routes/vault/cluster/access/method/item/list.js | 1 - ui/app/utils/openapi-to-attrs.js | 5 ++++- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/app/helpers/tabs-for-auth-section.js b/ui/app/helpers/tabs-for-auth-section.js index f5a0c18faba8..159954a0297d 100644 --- a/ui/app/helpers/tabs-for-auth-section.js +++ b/ui/app/helpers/tabs-for-auth-section.js @@ -77,7 +77,6 @@ const TABS_FOR_SHOW = {}; export function tabsForAuthSection([model, sectionType = 'authSettings', paths]) { let tabs; - debugger; if (sectionType === 'authSettings') { tabs = (TABS_FOR_SETTINGS[model.type] || []).slice(); tabs.push({ diff --git a/ui/app/routes/vault/cluster/access/method/item.js b/ui/app/routes/vault/cluster/access/method/item.js index 3b54e4fef40f..55950cc8d868 100644 --- a/ui/app/routes/vault/cluster/access/method/item.js +++ b/ui/app/routes/vault/cluster/access/method/item.js @@ -13,7 +13,6 @@ export default Route.extend({ }, getMethodAndModelInfo() { - debugger; const { item_type: itemType } = this.paramsFor(this.routeName); const { path: method } = this.paramsFor('vault.cluster.access.method'); const methodModel = this.modelFor('vault.cluster.access.method'); diff --git a/ui/app/routes/vault/cluster/access/method/item/list.js b/ui/app/routes/vault/cluster/access/method/item/list.js index 2d019b31df97..5aff3174b67a 100644 --- a/ui/app/routes/vault/cluster/access/method/item/list.js +++ b/ui/app/routes/vault/cluster/access/method/item/list.js @@ -52,7 +52,6 @@ export default Route.extend(ListRoute, { setupController(controller) { this._super(...arguments); const { apiPath, method, itemType } = this.getMethodAndModelInfo(); - debugger; controller.set('itemType', itemType); controller.set('method', method); this.pathHelp.getPaths(apiPath, method, itemType).then(paths => { diff --git a/ui/app/utils/openapi-to-attrs.js b/ui/app/utils/openapi-to-attrs.js index 3de3b20254cb..5d5a53efacd7 100644 --- a/ui/app/utils/openapi-to-attrs.js +++ b/ui/app/utils/openapi-to-attrs.js @@ -28,7 +28,6 @@ export const expandOpenApiProps = function(props) { let attrDefn = { editType, helpText: description, - sensitive: sensitive, possibleValues: prop['enum'], fieldValue: isId ? 'id' : null, fieldGroup: group || 'default', @@ -36,6 +35,10 @@ export const expandOpenApiProps = function(props) { defaultValue: value || null, }; + if (sensitive) { + attrDefn.sensitive = true; + } + //only set a label if we have one from OpenAPI //otherwise the propName will be humanized by the form-field component if (name) { From 6fbc18b13f780c7f7ed9de623a90405672e005d2 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Wed, 25 Sep 2019 22:32:15 -0400 Subject: [PATCH 07/63] pass method model to list route template to use paths on model for tabs --- .../vault/cluster/access/method/item/list.js | 5 ++-- .../components/generated-item-list.hbs | 23 ++++++++++++++++++- .../vault/cluster/access/method/item/list.hbs | 2 +- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ui/app/routes/vault/cluster/access/method/item/list.js b/ui/app/routes/vault/cluster/access/method/item/list.js index 5aff3174b67a..dd335568d465 100644 --- a/ui/app/routes/vault/cluster/access/method/item/list.js +++ b/ui/app/routes/vault/cluster/access/method/item/list.js @@ -12,7 +12,7 @@ export default Route.extend(ListRoute, { const { path: method } = this.paramsFor('vault.cluster.access.method'); const methodModel = this.modelFor('vault.cluster.access.method'); const { apiPath, type } = methodModel; - return { apiPath, type, method, itemType }; + return { apiPath, type, method, itemType, methodModel }; }, model() { @@ -51,9 +51,10 @@ export default Route.extend(ListRoute, { }, setupController(controller) { this._super(...arguments); - const { apiPath, method, itemType } = this.getMethodAndModelInfo(); + const { apiPath, method, itemType, methodModel } = this.getMethodAndModelInfo(); controller.set('itemType', itemType); controller.set('method', method); + controller.set('methodModel', methodModel); this.pathHelp.getPaths(apiPath, method, itemType).then(paths => { let navigationPaths = paths.paths.filter(path => path.navigation); controller.set('paths', navigationPaths.filter(path => path.itemType.includes(itemType))); diff --git a/ui/app/templates/components/generated-item-list.hbs b/ui/app/templates/components/generated-item-list.hbs index bbdedac69aa5..6c9ab8127f81 100644 --- a/ui/app/templates/components/generated-item-list.hbs +++ b/ui/app/templates/components/generated-item-list.hbs @@ -17,7 +17,28 @@ -{{section-tabs model "authShow" paths}} +{{debugger}} +{{#with (tabs-for-auth-section methodModel 'authConfig' paths) as |tabs|}} + {{#if tabs.length}} +
+ +
+ {{/if}} +{{/with}} \ No newline at end of file + \ No newline at end of file From 69be01cb87a3cff49b412a75c8d1547c4be197a4 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Thu, 26 Sep 2019 13:45:58 -0400 Subject: [PATCH 08/63] update tab generation in generated item list, undo enabling userpass users --- builtin/credential/cert/path_certs.go | 15 +++++++++++++++ builtin/credential/userpass/path_users.go | 13 +------------ .../templates/components/generated-item-list.hbs | 1 - 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/builtin/credential/cert/path_certs.go b/builtin/credential/cert/path_certs.go index 806922d4421b..0220c01d08b5 100644 --- a/builtin/credential/cert/path_certs.go +++ b/builtin/credential/cert/path_certs.go @@ -51,12 +51,18 @@ Must be x509 PEM encoded.`, At least one must exist in either the Common Name or SANs. Supports globbing. This parameter is deprecated, please use allowed_common_names, allowed_dns_sans, allowed_email_sans, allowed_uri_sans.`, + DisplayAttrs: &framework.DisplayAttributes{ + Group: "Certificate Options", + }, }, "allowed_common_names": &framework.FieldSchema{ Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of names. At least one must exist in the Common Name. Supports globbing.`, + DisplayAttrs: &framework.DisplayAttributes{ + Group: "Certificate Options", + }, }, "allowed_dns_sans": &framework.FieldSchema{ @@ -65,6 +71,7 @@ At least one must exist in the Common Name. Supports globbing.`, At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Allowed DNS SANs", + Group: "Certificate Options", }, }, @@ -74,6 +81,7 @@ At least one must exist in the SANs. Supports globbing.`, At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Allowed Email SANs", + Group: "Certificate Options", }, }, @@ -83,6 +91,7 @@ At least one must exist in the SANs. Supports globbing.`, At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Allowed URI SANs", + Group: "Certificate Options", }, }, @@ -90,6 +99,9 @@ At least one must exist in the SANs. Supports globbing.`, Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of Organizational Units names. At least one must exist in the OU field.`, + DisplayAttrs: &framework.DisplayAttributes{ + Group: "Certificate Options", + }, }, "required_extensions": &framework.FieldSchema{ @@ -97,6 +109,9 @@ At least one must exist in the OU field.`, Description: `A comma-separated string or array of extensions formatted as "oid:value". Expects the extension value to be some type of ASN1 encoded string. All values much match. Supports globbing on "value".`, + DisplayAttrs: &framework.DisplayAttributes{ + Group: "Certificate Options", + }, }, "display_name": &framework.FieldSchema{ diff --git a/builtin/credential/userpass/path_users.go b/builtin/credential/userpass/path_users.go index 1c43e97d2d7f..ae9af65b80c4 100644 --- a/builtin/credential/userpass/path_users.go +++ b/builtin/credential/userpass/path_users.go @@ -22,10 +22,6 @@ func pathUsersList(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, - DisplayAttrs: &framework.DisplayAttributes{ - Navigation: true, - ItemType: "User", - }, } } @@ -41,9 +37,6 @@ func pathUsers(b *backend) *framework.Path { "password": &framework.FieldSchema{ Type: framework.TypeString, Description: "Password for this user.", - DisplayAttrs: &framework.DisplayAttributes{ - Sensitive: true, - }, }, "policies": &framework.FieldSchema{ @@ -82,10 +75,6 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, - DisplayAttrs: &framework.DisplayAttributes{ - Action: "Create", - ItemType: "User", - }, } tokenutil.AddTokenFields(p.Fields) @@ -210,7 +199,7 @@ func (b *backend) userCreateUpdate(ctx context.Context, req *logical.Request, d if _, ok := d.GetOk("password"); ok { userErr, intErr := b.updateUserPassword(req, d, userEntry) if intErr != nil { - return nil, intErr + return nil, err } if userErr != nil { return logical.ErrorResponse(userErr.Error()), logical.ErrInvalidRequest diff --git a/ui/app/templates/components/generated-item-list.hbs b/ui/app/templates/components/generated-item-list.hbs index 6c9ab8127f81..2b2768851006 100644 --- a/ui/app/templates/components/generated-item-list.hbs +++ b/ui/app/templates/components/generated-item-list.hbs @@ -17,7 +17,6 @@ -{{debugger}} {{#with (tabs-for-auth-section methodModel 'authConfig' paths) as |tabs|}} {{#if tabs.length}}
From 5078fd8704780b6989ba280b6e3f6ed6bc14f39a Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Fri, 27 Sep 2019 15:22:18 -0400 Subject: [PATCH 09/63] enable openapi generated itams for certs and userpass, update ldap to no longer have action on list endpoint --- builtin/credential/cert/path_certs.go | 18 +++++++++--------- builtin/credential/ldap/path_users.go | 1 - builtin/credential/userpass/path_users.go | 11 +++++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/builtin/credential/cert/path_certs.go b/builtin/credential/cert/path_certs.go index 0220c01d08b5..fc1876632339 100644 --- a/builtin/credential/cert/path_certs.go +++ b/builtin/credential/cert/path_certs.go @@ -43,6 +43,9 @@ func pathCerts(b *backend) *framework.Path { Type: framework.TypeString, Description: `The public certificate that should be trusted. Must be x509 PEM encoded.`, + DisplayAttrs: &framework.DisplayAttributes{ + EditType: "file", + }, }, "allowed_names": &framework.FieldSchema{ @@ -52,7 +55,7 @@ At least one must exist in either the Common Name or SANs. Supports globbing. This parameter is deprecated, please use allowed_common_names, allowed_dns_sans, allowed_email_sans, allowed_uri_sans.`, DisplayAttrs: &framework.DisplayAttributes{ - Group: "Certificate Options", + Group: "Constraints", }, }, @@ -61,7 +64,7 @@ allowed_email_sans, allowed_uri_sans.`, Description: `A comma-separated list of names. At least one must exist in the Common Name. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ - Group: "Certificate Options", + Group: "Constraints", }, }, @@ -71,7 +74,7 @@ At least one must exist in the Common Name. Supports globbing.`, At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Allowed DNS SANs", - Group: "Certificate Options", + Group: "Constraints", }, }, @@ -81,7 +84,7 @@ At least one must exist in the SANs. Supports globbing.`, At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Allowed Email SANs", - Group: "Certificate Options", + Group: "Constraints", }, }, @@ -91,7 +94,7 @@ At least one must exist in the SANs. Supports globbing.`, At least one must exist in the SANs. Supports globbing.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Allowed URI SANs", - Group: "Certificate Options", + Group: "Constraints", }, }, @@ -100,7 +103,7 @@ At least one must exist in the SANs. Supports globbing.`, Description: `A comma-separated list of Organizational Units names. At least one must exist in the OU field.`, DisplayAttrs: &framework.DisplayAttributes{ - Group: "Certificate Options", + Group: "Constraints", }, }, @@ -109,9 +112,6 @@ At least one must exist in the OU field.`, Description: `A comma-separated string or array of extensions formatted as "oid:value". Expects the extension value to be some type of ASN1 encoded string. All values much match. Supports globbing on "value".`, - DisplayAttrs: &framework.DisplayAttributes{ - Group: "Certificate Options", - }, }, "display_name": &framework.FieldSchema{ diff --git a/builtin/credential/ldap/path_users.go b/builtin/credential/ldap/path_users.go index af2f2cb5da40..2cfd34d267a1 100644 --- a/builtin/credential/ldap/path_users.go +++ b/builtin/credential/ldap/path_users.go @@ -22,7 +22,6 @@ func pathUsersList(b *backend) *framework.Path { HelpDescription: pathUserHelpDesc, DisplayAttrs: &framework.DisplayAttributes{ Navigation: true, - Action: "Create", ItemType: "User", }, } diff --git a/builtin/credential/userpass/path_users.go b/builtin/credential/userpass/path_users.go index ae9af65b80c4..0085445d6df2 100644 --- a/builtin/credential/userpass/path_users.go +++ b/builtin/credential/userpass/path_users.go @@ -22,6 +22,10 @@ func pathUsersList(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Navigation: true, + ItemType: "User", + }, } } @@ -37,6 +41,9 @@ func pathUsers(b *backend) *framework.Path { "password": &framework.FieldSchema{ Type: framework.TypeString, Description: "Password for this user.", + DisplayAttrs: &framework.DisplayAttributes{ + Sensitive: true, + }, }, "policies": &framework.FieldSchema{ @@ -75,6 +82,10 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, + DisplayAttrs: &framework.DisplayAttributes{ + Action: "Create", + ItemType: "User", + }, } tokenutil.AddTokenFields(p.Fields) From 200210e958f73e5cbfdd6ee2d0cd8f539d8221cc Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Fri, 27 Sep 2019 15:22:54 -0400 Subject: [PATCH 10/63] add editType to DisplayAttributes, pull tokenutil fields into field group --- sdk/framework/path.go | 4 ++++ sdk/helper/tokenutil/tokenutil.go | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/sdk/framework/path.go b/sdk/framework/path.go index bf2bbdb574a6..ab3c866260fa 100644 --- a/sdk/framework/path.go +++ b/sdk/framework/path.go @@ -181,6 +181,10 @@ type DisplayAttributes struct { // Action is the verb to use for the operation. Action string `json:"action,omitempty"` + + //EditType is the type of form field needed for a property + //e.g. "textarea" or "file" + EditType string `json:"editType,omitempty"` } // RequestExample is example of request data. diff --git a/sdk/helper/tokenutil/tokenutil.go b/sdk/helper/tokenutil/tokenutil.go index e225f866192d..67fcba2bcd67 100644 --- a/sdk/helper/tokenutil/tokenutil.go +++ b/sdk/helper/tokenutil/tokenutil.go @@ -76,6 +76,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: `Comma separated string or JSON list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.`, DisplayAttrs: &framework.DisplayAttributes{ Name: "Generated Token's Bound CIDRs", + Group: "Tokens", }, }, @@ -84,6 +85,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: tokenExplicitMaxTTLHelp, DisplayAttrs: &framework.DisplayAttributes{ Name: "Generated Token's Explicit Maximum TTL", + Group: "Tokens", }, }, @@ -92,6 +94,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: "The maximum lifetime of the generated token", DisplayAttrs: &framework.DisplayAttributes{ Name: "Generated Token's Maximum TTL", + Group: "Tokens", }, }, @@ -100,6 +103,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: "If true, the 'default' policy will not automatically be added to generated tokens", DisplayAttrs: &framework.DisplayAttributes{ Name: "Do Not Attach 'default' Policy To Generated Tokens", + Group: "Tokens", }, }, @@ -108,6 +112,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: tokenPeriodHelp, DisplayAttrs: &framework.DisplayAttributes{ Name: "Generated Token's Period", + Group: "Tokens", }, }, @@ -116,6 +121,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: "Comma-separated list of policies", DisplayAttrs: &framework.DisplayAttributes{ Name: "Generated Token's Policies", + Group: "Tokens", }, }, @@ -125,6 +131,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: "The type of token to generate, service or batch", DisplayAttrs: &framework.DisplayAttributes{ Name: "Generated Token's Type", + Group: "Tokens", }, }, @@ -133,6 +140,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: "The initial ttl of the token to generate", DisplayAttrs: &framework.DisplayAttributes{ Name: "Generated Token's Initial TTL", + Group: "Tokens", }, }, @@ -141,6 +149,7 @@ func TokenFields() map[string]*framework.FieldSchema { Description: "The maximum number of times a token may be used, a value of zero means unlimited", DisplayAttrs: &framework.DisplayAttributes{ Name: "Maximum Uses of Generated Tokens", + Group: "Tokens", }, }, } From 9e503d0e1b5644a069f4ee3920a89c3085028366 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Fri, 27 Sep 2019 15:23:22 -0400 Subject: [PATCH 11/63] show sensitive message for sensitive fields displayed in fieldGroupShow component --- .../templates/components/field-group-show.hbs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ui/lib/core/addon/templates/components/field-group-show.hbs b/ui/lib/core/addon/templates/components/field-group-show.hbs index 04e3b843402e..2ef71b9c8688 100644 --- a/ui/lib/core/addon/templates/components/field-group-show.hbs +++ b/ui/lib/core/addon/templates/components/field-group-show.hbs @@ -5,8 +5,13 @@ {{#each fields as |attr|}} {{#if (not-eq attr.options.fieldValue "id")}} + @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}> + {{#if attr.options.sensitive}} + this value is sensitive and cannot be shown + {{else}} + {{get @model attr.name}} + {{/if}} + {{/if}} {{/each}} {{else}} @@ -16,8 +21,13 @@ {{#each fields as |attr|}} + @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}> + {{#if attr.options.sensitive}} + this value is sensitive and cannot be shown + {{else}} + {{get @model attr.name}} + {{/if}} + {{/each}}
{{/if}} From b80d10ef6d27d816edc4981b4c5e1b7f25787d44 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Fri, 27 Sep 2019 15:24:43 -0400 Subject: [PATCH 12/63] grab sensitive and editType fields from displayAttrs in openapi-to-attrs util --- ui/app/utils/openapi-to-attrs.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/app/utils/openapi-to-attrs.js b/ui/app/utils/openapi-to-attrs.js index 5d5a53efacd7..28c2bc50218c 100644 --- a/ui/app/utils/openapi-to-attrs.js +++ b/ui/app/utils/openapi-to-attrs.js @@ -12,12 +12,13 @@ export const expandOpenApiProps = function(props) { if (deprecated === true) { continue; } - let { name, value, group, sensitive } = prop['x-vault-displayAttrs'] || {}; + let { name, value, group, sensitive, editType } = prop['x-vault-displayAttrs'] || {}; if (type === 'integer') { type = 'number'; } - let editType = type; + + editType = editType || type; if (format === 'seconds') { editType = 'ttl'; From 54f8568cc8cd17849a9eafe31e1a47ba240c69b9 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Fri, 27 Sep 2019 15:25:34 -0400 Subject: [PATCH 13/63] make sure we don't ask for paths for secret backends since that isn't setup yet --- ui/app/services/path-help.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 348e70e4231a..d75b9f7a0034 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -51,6 +51,13 @@ export default Service.extend({ newModel = DS.Model.extend({}); } + //we don't have an apiPath for dynamic secrets + //and we don't need paths for them yet + if (!apiPath) { + helpUrl = newModel.proto().getHelpUrl(backend); + return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); + } + //use paths to dynamically create our openapi help url //if we have a brand new model return this.getPaths(apiPath, backend, itemType) From bbc482473524d073b9e9d976c18fa2a89dd28597 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Fri, 27 Sep 2019 15:39:04 -0400 Subject: [PATCH 14/63] fix styling of sensitive text for fieldGroupShow component --- ui/lib/core/addon/templates/components/field-group-show.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lib/core/addon/templates/components/field-group-show.hbs b/ui/lib/core/addon/templates/components/field-group-show.hbs index 2ef71b9c8688..6747cd3158b0 100644 --- a/ui/lib/core/addon/templates/components/field-group-show.hbs +++ b/ui/lib/core/addon/templates/components/field-group-show.hbs @@ -7,7 +7,7 @@ {{#if attr.options.sensitive}} - this value is sensitive and cannot be shown + this value is sensitive and cannot be shown {{else}} {{get @model attr.name}} {{/if}} @@ -23,7 +23,7 @@ {{#if attr.options.sensitive}} - this value is sensitive and cannot be shown + this value is sensitive and cannot be shown {{else}} {{get @model attr.name}} {{/if}} From f7caf20bbea41cef6d4d1f1dd30087c77fc8af71 Mon Sep 17 00:00:00 2001 From: Madalyn Parker Date: Fri, 27 Sep 2019 16:33:03 -0400 Subject: [PATCH 15/63] update openapi-to-attrs util test to no longer include label by default, change debugger to console.err in path-help, remove dynamic ui auth methods from tab count test --- ui/app/services/path-help.js | 2 +- ui/tests/acceptance/settings/auth/configure/section-test.js | 2 +- ui/tests/unit/utils/openapi-to-attrs-test.js | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index d75b9f7a0034..e269adf53524 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -85,7 +85,7 @@ export default Service.extend({ return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); }) .catch(err => { - debugger; + console.err(err); }); }, diff --git a/ui/tests/acceptance/settings/auth/configure/section-test.js b/ui/tests/acceptance/settings/auth/configure/section-test.js index b36ae3549c8c..faa632603a70 100644 --- a/ui/tests/acceptance/settings/auth/configure/section-test.js +++ b/ui/tests/acceptance/settings/auth/configure/section-test.js @@ -41,7 +41,7 @@ module('Acceptance | settings/auth/configure/section', function(hooks) { assert.ok(keys.includes('max_lease_ttl'), 'passes max_lease_ttl on tune'); }); - for (let type of ['aws', 'azure', 'gcp', 'github', 'kubernetes', 'ldap', 'okta', 'radius']) { + for (let type of ['aws', 'azure', 'gcp', 'github', 'kubernetes']) { test(`it shows tabs for auth method: ${type}`, async assert => { let path = `${type}-${Date.now()}`; await cli.consoleInput(`write sys/auth/${path} type=${type}`); diff --git a/ui/tests/unit/utils/openapi-to-attrs-test.js b/ui/tests/unit/utils/openapi-to-attrs-test.js index 00a2e97ec4d3..b0bdfd9ab9dd 100644 --- a/ui/tests/unit/utils/openapi-to-attrs-test.js +++ b/ui/tests/unit/utils/openapi-to-attrs-test.js @@ -58,28 +58,24 @@ module('Unit | Util | OpenAPI Data Utilities', function() { editType: 'stringArray', defaultValue: 'Grace Hopper,Lady Ada', fieldGroup: 'default', - label: 'Awesome-people', }, favoriteIceCream: { editType: 'string', type: 'string', possibleValues: ['vanilla', 'chocolate', 'strawberry'], fieldGroup: 'default', - label: 'Favorite-ice-cream', }, defaultValue: { editType: 'number', type: 'number', defaultValue: 300, fieldGroup: 'default', - label: 'Default-value', }, default: { editType: 'number', type: 'number', defaultValue: 30, fieldGroup: 'default', - label: 'Default', }, superSecret: { type: 'string', @@ -87,7 +83,6 @@ module('Unit | Util | OpenAPI Data Utilities', function() { sensitive: true, helpText: 'A really secret thing', fieldGroup: 'default', - label: 'Super-secret', }, }; From c8dbec2e593f12bd898f62353b4441d69ca49037 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Tue, 8 Oct 2019 08:46:00 -0700 Subject: [PATCH 16/63] properly log errors to the console --- ui/app/services/path-help.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index e269adf53524..33499608ffa7 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -85,7 +85,7 @@ export default Service.extend({ return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); }) .catch(err => { - console.err(err); + console.error(err); }); }, From b1803edba03b4cfa8f60a19852c68489fb586f20 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Tue, 8 Oct 2019 08:55:55 -0700 Subject: [PATCH 17/63] capitalize This value is sensitive... --- ui/lib/core/addon/templates/components/field-group-show.hbs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/lib/core/addon/templates/components/field-group-show.hbs b/ui/lib/core/addon/templates/components/field-group-show.hbs index 6747cd3158b0..854cdd2ec470 100644 --- a/ui/lib/core/addon/templates/components/field-group-show.hbs +++ b/ui/lib/core/addon/templates/components/field-group-show.hbs @@ -7,7 +7,7 @@ {{#if attr.options.sensitive}} - this value is sensitive and cannot be shown + This value is sensitive and cannot be shown. {{else}} {{get @model attr.name}} {{/if}} @@ -23,7 +23,7 @@ {{#if attr.options.sensitive}} - this value is sensitive and cannot be shown + This value is sensitive and cannot be shown. {{else}} {{get @model attr.name}} {{/if}} @@ -33,4 +33,4 @@ {{/if}} {{/each-in}} {{/each}} - \ No newline at end of file + From 1666872196d150cbd59b6e595e621294793a4122 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Tue, 8 Oct 2019 09:10:24 -0700 Subject: [PATCH 18/63] get rid of extra padding on bottom of fieldgroupshow --- ui/lib/core/addon/templates/components/field-group-show.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lib/core/addon/templates/components/field-group-show.hbs b/ui/lib/core/addon/templates/components/field-group-show.hbs index 854cdd2ec470..91f3392f8d82 100644 --- a/ui/lib/core/addon/templates/components/field-group-show.hbs +++ b/ui/lib/core/addon/templates/components/field-group-show.hbs @@ -1,4 +1,4 @@ -
+
{{#each @model.fieldGroups as |fieldGroup|}} {{#each-in fieldGroup as |group fields|}} {{#if (or (eq group "default") (eq group "Options"))}} @@ -15,7 +15,7 @@ {{/if}} {{/each}} {{else}} -
+

{{group}}

From 3e468e47c64f7ebbaf4d7c5f0e6ec402a8c53185 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Tue, 8 Oct 2019 14:34:46 -0700 Subject: [PATCH 19/63] make auth methods clickable and use new confirm ux --- .../vault/cluster/access/methods.hbs | 187 ++++++------------ 1 file changed, 62 insertions(+), 125 deletions(-) diff --git a/ui/app/templates/vault/cluster/access/methods.hbs b/ui/app/templates/vault/cluster/access/methods.hbs index fe0938bc6675..0d2f151cf30e 100644 --- a/ui/app/templates/vault/cluster/access/methods.hbs +++ b/ui/app/templates/vault/cluster/access/methods.hbs @@ -15,137 +15,74 @@ {{#each (sort-by "path" model) as |method|}} - {{#if (eq method.methodType "ldap")}} - -
-
-
- - - - - -
- {{method.methodType}} -
-
-
- - {{method.path}} - -
- - {{method.accessor}} - -
-
-
-
- {{#popup-menu name="auth-backend-nav"}} - - {{/popup-menu}} -
+ +
+
+
+ + + + + +
+ {{method.methodType}} +
+
+
+ + {{method.path}} + +
+ + {{method.accessor}} +
- - {{else}} -
-
-
-
- - - - - -
- {{method.methodType}} -
-
-
- - {{method.path}} - -
- - {{method.accessor}} - -
-
-
-
- {{#popup-menu name="auth-backend-nav"}} - + + {{/popup-menu}}
- {{/if}} -{{/each}} \ No newline at end of file + +{{/each}} From 4851bb5cef51614a3c10b52668486ddee02647ed Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 14:23:01 -0700 Subject: [PATCH 20/63] Update sdk/framework/path.go Co-Authored-By: Jim Kalafut --- sdk/framework/path.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/framework/path.go b/sdk/framework/path.go index ab3c866260fa..0c8c51cf0eb7 100644 --- a/sdk/framework/path.go +++ b/sdk/framework/path.go @@ -182,7 +182,7 @@ type DisplayAttributes struct { // Action is the verb to use for the operation. Action string `json:"action,omitempty"` - //EditType is the type of form field needed for a property + // EditType is the type of form field needed for a property //e.g. "textarea" or "file" EditType string `json:"editType,omitempty"` } From 0791598d4f08a37d80e3540e236943a0de2b4cbb Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 14:23:14 -0700 Subject: [PATCH 21/63] Update sdk/framework/path.go Co-Authored-By: Jim Kalafut --- sdk/framework/path.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/framework/path.go b/sdk/framework/path.go index 0c8c51cf0eb7..d6fc6e935732 100644 --- a/sdk/framework/path.go +++ b/sdk/framework/path.go @@ -183,7 +183,7 @@ type DisplayAttributes struct { Action string `json:"action,omitempty"` // EditType is the type of form field needed for a property - //e.g. "textarea" or "file" + // e.g. "textarea" or "file" EditType string `json:"editType,omitempty"` } From f8fc76838daf1b75c99609d10362cacf60a04ecc Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 16:46:41 -0700 Subject: [PATCH 22/63] add whitespace --- builtin/credential/userpass/path_users.go | 4 ++-- ui/.storybook/preview-head.html | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/builtin/credential/userpass/path_users.go b/builtin/credential/userpass/path_users.go index 0085445d6df2..9b206f3171df 100644 --- a/builtin/credential/userpass/path_users.go +++ b/builtin/credential/userpass/path_users.go @@ -83,8 +83,8 @@ func pathUsers(b *backend) *framework.Path { HelpSynopsis: pathUserHelpSyn, HelpDescription: pathUserHelpDesc, DisplayAttrs: &framework.DisplayAttributes{ - Action: "Create", - ItemType: "User", + Action: "Create", + ItemType: "User", }, } diff --git a/ui/.storybook/preview-head.html b/ui/.storybook/preview-head.html index 1fbfe45032c4..1dd12fbf8c92 100644 --- a/ui/.storybook/preview-head.html +++ b/ui/.storybook/preview-head.html @@ -2,7 +2,6 @@ - From 9d05de0fa92d4c92e35001405b160280f72a7057 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 16:48:31 -0700 Subject: [PATCH 23/63] return intErr instead of err --- builtin/credential/userpass/path_users.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/credential/userpass/path_users.go b/builtin/credential/userpass/path_users.go index 9b206f3171df..1c43e97d2d7f 100644 --- a/builtin/credential/userpass/path_users.go +++ b/builtin/credential/userpass/path_users.go @@ -210,7 +210,7 @@ func (b *backend) userCreateUpdate(ctx context.Context, req *logical.Request, d if _, ok := d.GetOk("password"); ok { userErr, intErr := b.updateUserPassword(req, d, userEntry) if intErr != nil { - return nil, err + return nil, intErr } if userErr != nil { return logical.ErrorResponse(userErr.Error()), logical.ErrInvalidRequest From 4555e6692bc36f516ff756bab07446516785d9ba Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 17:09:26 -0700 Subject: [PATCH 24/63] uncomment out helpUrl because we need it --- ui/app/services/path-help.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 33499608ffa7..c9f9e34c942f 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -44,8 +44,9 @@ export default Service.extend({ if (newModel.merged || modelProto.useOpenAPI !== true) { return resolve(); } - // helpUrl = modelProto.getHelpUrl(backend); - // return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); + + helpUrl = modelProto.getHelpUrl(backend); + return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName); } else { debug(`Creating new Model for ${modelType}`); newModel = DS.Model.extend({}); From 80eff2ddec0208032cb4c5ad972d2512d7476704 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 17:10:44 -0700 Subject: [PATCH 25/63] remove extra box class --- ui/lib/core/addon/templates/components/field-group-show.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/lib/core/addon/templates/components/field-group-show.hbs b/ui/lib/core/addon/templates/components/field-group-show.hbs index 91f3392f8d82..f05d75dc7c63 100644 --- a/ui/lib/core/addon/templates/components/field-group-show.hbs +++ b/ui/lib/core/addon/templates/components/field-group-show.hbs @@ -15,7 +15,7 @@ {{/if}} {{/each}} {{else}} -
+

{{group}}

From 254d495ede582e8fba871bae8f84f2b8e2fca133 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 17:13:37 -0700 Subject: [PATCH 26/63] use const instead of let --- ui/app/services/path-help.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index c9f9e34c942f..064a41f43859 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -239,18 +239,18 @@ export default Service.extend({ //urlForQuery if there is an id and we are listing, use the id to construct the path urlForUpdateRecord(id) { - let path = createPath.path.slice(1, createPath.path.indexOf('{') - 1); + const path = createPath.path.slice(1, createPath.path.indexOf('{') - 1); return `${this.buildURL()}/${apiPath}${path}/${id}`; }, urlForCreateRecord(modelType, snapshot) { const { id } = snapshot; - let path = createPath.path.slice(1, createPath.path.indexOf('{') - 1); + const path = createPath.path.slice(1, createPath.path.indexOf('{') - 1); return `${this.buildURL()}/${apiPath}${path}/${id}`; }, urlForDeleteRecord(id) { - let path = deletePath.path.slice(1, deletePath.path.indexOf('{') - 1); + const path = deletePath.path.slice(1, deletePath.path.indexOf('{') - 1); return `${this.buildURL()}/${apiPath}${path}/${id}`; }, }); From 66b8f9f73df98e70dbbba97e96720398e525de5b Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Wed, 9 Oct 2019 17:19:07 -0700 Subject: [PATCH 27/63] remove extra conditional since we already split the pathName later on --- ui/app/services/path-help.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 064a41f43859..5fb17233bd4f 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -99,11 +99,6 @@ export default Service.extend({ return pathInfo; } - if (pathName.includes('{')) { - //we need to know if there are url params - pathName.split('{')[1].split('}')[0]; - } - let itemType, itemName; if (displayAttrs.itemType) { itemType = displayAttrs.itemType; From 6ce2e043da56fa9a016daa2e42bf6fff9ef9ae5c Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Thu, 10 Oct 2019 13:51:53 -0700 Subject: [PATCH 28/63] ensure we request the correct url when listing generated items --- ui/app/services/path-help.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 5fb17233bd4f..d03a964567e6 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -220,8 +220,10 @@ export default Service.extend({ const deletePath = paths.find(path => path.operations.includes('delete')); return generatedItemAdapter.extend({ - urlForItem(method, id) { - let url = `${this.buildURL()}/${apiPath}${getPath.path.slice(1)}/`; + urlForItem(mountPath, id) { + const mountType = apiPath.split('/')[0]; + let url = `${this.buildURL()}/${mountType}/${mountPath}/${getPath.path.slice(1)}/`; + if (id) { url = url + encodePath(id); } From 4a096aed9cab719c3744528ae5da6c948a9d38df Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Thu, 10 Oct 2019 16:57:33 -0700 Subject: [PATCH 29/63] use const --- ui/app/services/path-help.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index d03a964567e6..4d3cd8f65efc 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -112,7 +112,7 @@ export default Service.extend({ pathInfo.itemTypes.push(itemType); } - let operations = []; + const operations = []; if (pathDetails.get) { operations.push('get'); } From 68ba6e991a2873874a3938a8ec7b443b06a431ed Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 11 Oct 2019 11:42:39 -0700 Subject: [PATCH 30/63] link to list and show pages --- ui/app/adapters/generated-item-list.js | 16 ++++++++-------- .../vault/cluster/access/method/item/list.js | 8 ++++---- .../vault/cluster/access/method/item/show.js | 3 ++- ui/app/services/path-help.js | 18 ++++++++++++------ 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/ui/app/adapters/generated-item-list.js b/ui/app/adapters/generated-item-list.js index 313985be9d78..3b6e13ac0e93 100644 --- a/ui/app/adapters/generated-item-list.js +++ b/ui/app/adapters/generated-item-list.js @@ -5,20 +5,20 @@ export default ApplicationAdapter.extend({ namespace: 'v1', urlForItem() {}, optionsForQuery(id) { - let data = {}; - if (!id) { - data['list'] = true; - } - return { data }; + return { + data: { + list: true, + }, + }; }, fetchByQuery(store, query) { - const { id, method, type } = query; - return this.ajax(this.urlForItem(method, id, type), 'GET', this.optionsForQuery(id)).then(resp => { + const { id, type, list } = query; + return this.ajax(this.urlForItem(id, type), 'GET', this.optionsForQuery(id)).then(resp => { const data = { id, name: id, - method, + method: id, }; return assign({}, resp, data); diff --git a/ui/app/routes/vault/cluster/access/method/item/list.js b/ui/app/routes/vault/cluster/access/method/item/list.js index dd335568d465..f238036cf3cd 100644 --- a/ui/app/routes/vault/cluster/access/method/item/list.js +++ b/ui/app/routes/vault/cluster/access/method/item/list.js @@ -9,14 +9,14 @@ export default Route.extend(ListRoute, { getMethodAndModelInfo() { const { item_type: itemType } = this.paramsFor('vault.cluster.access.method.item'); - const { path: method } = this.paramsFor('vault.cluster.access.method'); + const { path: id } = this.paramsFor('vault.cluster.access.method'); const methodModel = this.modelFor('vault.cluster.access.method'); const { apiPath, type } = methodModel; - return { apiPath, type, method, itemType, methodModel }; + return { apiPath, type, id, itemType, methodModel }; }, model() { - const { type, method, itemType } = this.getMethodAndModelInfo(); + const { type, id, itemType } = this.getMethodAndModelInfo(); const { page, pageFilter } = this.paramsFor(this.routeName); let modelType = `generated-${singularize(itemType)}-${type}`; @@ -26,7 +26,7 @@ export default Route.extend(ListRoute, { page: page, pageFilter: pageFilter, type: itemType, - method: method, + id: id, }) .catch(err => { if (err.httpStatus === 404) { diff --git a/ui/app/routes/vault/cluster/access/method/item/show.js b/ui/app/routes/vault/cluster/access/method/item/show.js index a80bc2e9af49..f78ee061bd3e 100644 --- a/ui/app/routes/vault/cluster/access/method/item/show.js +++ b/ui/app/routes/vault/cluster/access/method/item/show.js @@ -11,7 +11,8 @@ export default Route.extend({ const methodModel = this.modelFor('vault.cluster.access.method'); const { type } = methodModel; const modelType = `generated-${singularize(itemType)}-${type}`; - return this.store.findRecord(modelType, itemName, { + const id = `${method}/${itemName}`; + return this.store.findRecord(modelType, id, { adapterOptions: { path: `${method}/${itemType}` }, }); }, diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 4d3cd8f65efc..62e6af649b7c 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -220,18 +220,24 @@ export default Service.extend({ const deletePath = paths.find(path => path.operations.includes('delete')); return generatedItemAdapter.extend({ - urlForItem(mountPath, id) { - const mountType = apiPath.split('/')[0]; - let url = `${this.buildURL()}/${mountType}/${mountPath}/${getPath.path.slice(1)}/`; + urlForItem(id, modelName) { + // this is used for listing and showing - if (id) { - url = url + encodePath(id); + let url; + id = encodePath(id); + const mountType = apiPath.split('/')[0]; + if (id.indexOf('/') !== -1) { + id = id.split('/').join(`/${getPath.path.slice(1)}/`); + url = `${this.buildURL()}/${mountType}/${id}`; + } else { + url = `${this.buildURL()}/${mountType}/${id}/${getPath.path.slice(1)}/`; } + return url; }, urlForFindRecord(id, modelName) { - return this.urlForItem(modelName, id); + return this.urlForItem(id, modelName); }, //urlForQuery if there is an id and we are listing, use the id to construct the path From ed6a07a18195112b62a732190adf33c240e93730 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 11 Oct 2019 11:43:40 -0700 Subject: [PATCH 31/63] remove dead code --- ui/app/adapters/generated-item-list.js | 2 +- ui/app/routes/vault/cluster/access/method/item/show.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/ui/app/adapters/generated-item-list.js b/ui/app/adapters/generated-item-list.js index 3b6e13ac0e93..34c238a8ba6f 100644 --- a/ui/app/adapters/generated-item-list.js +++ b/ui/app/adapters/generated-item-list.js @@ -13,7 +13,7 @@ export default ApplicationAdapter.extend({ }, fetchByQuery(store, query) { - const { id, type, list } = query; + const { id, type } = query; return this.ajax(this.urlForItem(id, type), 'GET', this.optionsForQuery(id)).then(resp => { const data = { id, diff --git a/ui/app/routes/vault/cluster/access/method/item/show.js b/ui/app/routes/vault/cluster/access/method/item/show.js index f78ee061bd3e..74a89a0481d4 100644 --- a/ui/app/routes/vault/cluster/access/method/item/show.js +++ b/ui/app/routes/vault/cluster/access/method/item/show.js @@ -12,9 +12,7 @@ export default Route.extend({ const { type } = methodModel; const modelType = `generated-${singularize(itemType)}-${type}`; const id = `${method}/${itemName}`; - return this.store.findRecord(modelType, id, { - adapterOptions: { path: `${method}/${itemType}` }, - }); + return this.store.findRecord(modelType, id); }, setupController(controller) { From 3984b6620afa2ed25cb19102221a61a69ee99f7b Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 11 Oct 2019 11:57:39 -0700 Subject: [PATCH 32/63] show nested item name instead of id --- ui/app/components/generated-item.js | 3 +++ ui/app/templates/components/generated-item.hbs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/app/components/generated-item.js b/ui/app/components/generated-item.js index ccf815c8806d..915ed797f14c 100644 --- a/ui/app/components/generated-item.js +++ b/ui/app/components/generated-item.js @@ -21,6 +21,9 @@ import DS from 'ember-data'; export default Component.extend({ model: null, + name: computed('model', function() { + return this.model.id.split('/').pop(); + }), itemType: null, flashMessages: service(), router: service(), diff --git a/ui/app/templates/components/generated-item.hbs b/ui/app/templates/components/generated-item.hbs index 4793827e6554..bdcc686cf59e 100644 --- a/ui/app/templates/components/generated-item.hbs +++ b/ui/app/templates/components/generated-item.hbs @@ -19,7 +19,7 @@ {{#if (eq mode "show")}}

- {{model.id}} + {{name}}

{{else}}

@@ -75,4 +75,4 @@

-{{/if}} \ No newline at end of file +{{/if}} From 2efd7dddbb266a27cc79dbfc6df29f00c6a246ff Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 11 Oct 2019 12:03:53 -0700 Subject: [PATCH 33/63] add comments --- ui/app/services/path-help.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/app/services/path-help.js b/ui/app/services/path-help.js index 62e6af649b7c..cb786c103e20 100644 --- a/ui/app/services/path-help.js +++ b/ui/app/services/path-help.js @@ -221,15 +221,18 @@ export default Service.extend({ return generatedItemAdapter.extend({ urlForItem(id, modelName) { - // this is used for listing and showing - let url; id = encodePath(id); const mountType = apiPath.split('/')[0]; + + // if the id has a '/', we are getting the show page of a nested item + // e.g. userpass users or groups if (id.indexOf('/') !== -1) { id = id.split('/').join(`/${getPath.path.slice(1)}/`); url = `${this.buildURL()}/${mountType}/${id}`; } else { + // build the url for the list page of a top-level item + // e.g. userpass url = `${this.buildURL()}/${mountType}/${id}/${getPath.path.slice(1)}/`; } From 8c58198306d47feec1dbfc1202ee319559b78a47 Mon Sep 17 00:00:00 2001 From: Noelle Daley Date: Fri, 11 Oct 2019 12:19:43 -0700 Subject: [PATCH 34/63] show tooltip for text-file inputs --- ui/app/templates/components/text-file.hbs | 5 +++++ ui/lib/core/addon/templates/components/form-field.hbs | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/app/templates/components/text-file.hbs b/ui/app/templates/components/text-file.hbs index c76526c34ead..177eaa390092 100644 --- a/ui/app/templates/components/text-file.hbs +++ b/ui/app/templates/components/text-file.hbs @@ -4,6 +4,11 @@