UI OpenAPI fixes: itemType pluralization, hide deprecated attrs, utilize apiPath, fix get param label (#7166)
This commit is contained in:
parent
f8cefa9b18
commit
18fa9e418c
|
@ -52,7 +52,7 @@ export default Route.extend(ListRoute, {
|
|||
setupController(controller) {
|
||||
this._super(...arguments);
|
||||
const { apiPath, method, itemType } = this.getMethodAndModelInfo();
|
||||
controller.set('itemType', singularize(itemType));
|
||||
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), []));
|
||||
|
|
|
@ -10,6 +10,7 @@ import { getOwner } from '@ember/application';
|
|||
import { capitalize } from '@ember/string';
|
||||
import { assign } from '@ember/polyfills';
|
||||
import { expandOpenApiProps, combineAttributes } from 'vault/utils/openapi-to-attrs';
|
||||
import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends';
|
||||
import fieldToAttrs from 'vault/utils/field-to-attrs';
|
||||
import { resolve } from 'rsvp';
|
||||
import { debug } from '@ember/debug';
|
||||
|
@ -55,22 +56,20 @@ export default Service.extend({
|
|||
//if we have an adapter already use that, otherwise create one
|
||||
if (!adapterFactory) {
|
||||
debug(`Creating new adapter for ${modelType}`);
|
||||
const adapter = this.getNewAdapter(backend, paths, itemType);
|
||||
const adapter = this.getNewAdapter(paths, itemType);
|
||||
owner.register(`adapter:${modelType}`, adapter);
|
||||
}
|
||||
//if we have an item we want the create info for that itemType
|
||||
let tag, path;
|
||||
let path;
|
||||
if (itemType) {
|
||||
const createPath = paths.create.find(path => path.path.includes(itemType));
|
||||
tag = createPath.tag; //tag is for type of backend, e.g. auth or secret
|
||||
path = createPath.path;
|
||||
path = path.slice(0, path.indexOf('{') - 1) + '/example';
|
||||
} else {
|
||||
//we need the mount config
|
||||
tag = paths.configPath[0].tag;
|
||||
path = paths.configPath[0].path;
|
||||
}
|
||||
helpUrl = `/v1/${tag}/${backend}${path}?help=true`;
|
||||
helpUrl = `/v1/${apiPath}${path}?help=true`;
|
||||
return this.registerNewModelWithProps(helpUrl, backend, newModel, modelName);
|
||||
});
|
||||
}
|
||||
|
@ -79,31 +78,31 @@ export default Service.extend({
|
|||
reducePaths(paths, currentPath) {
|
||||
const pathName = currentPath[0];
|
||||
const pathInfo = currentPath[1];
|
||||
|
||||
//config is a get/post endpoint that doesn't take route params
|
||||
//and isn't also a list endpoint
|
||||
//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, tag: pathInfo.get.tags[0] });
|
||||
paths.configPath.push({ path: pathName });
|
||||
return paths; //config path should only be config path
|
||||
}
|
||||
|
||||
//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, tag: pathInfo.get.tags[0] });
|
||||
paths.list.push({ path: pathName });
|
||||
}
|
||||
|
||||
if (pathInfo.delete) {
|
||||
paths.delete.push({ path: pathName, tag: pathInfo.delete.tags[0] });
|
||||
paths.delete.push({ path: pathName });
|
||||
}
|
||||
|
||||
//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,
|
||||
tag: pathInfo.post.tags[0],
|
||||
action: pathInfo['x-vault-displayAttrs'].action,
|
||||
});
|
||||
}
|
||||
|
@ -122,7 +121,7 @@ export default Service.extend({
|
|||
let paths = Object.entries(pathInfo);
|
||||
|
||||
return paths.reduce(this.reducePaths, {
|
||||
apiPath: [],
|
||||
apiPath: apiPath,
|
||||
configPath: [],
|
||||
list: [],
|
||||
create: [],
|
||||
|
@ -149,16 +148,13 @@ export default Service.extend({
|
|||
//include url params
|
||||
if (params) {
|
||||
const { name, schema, description } = params[0];
|
||||
let label = capitalize(name);
|
||||
if (label.toLowerCase() !== 'name') {
|
||||
label += ' name';
|
||||
}
|
||||
let label = name.split('_').join(' ');
|
||||
|
||||
paramProp[name] = {
|
||||
'x-vault-displayAttrs': {
|
||||
name: name,
|
||||
name: label,
|
||||
group: 'default',
|
||||
},
|
||||
label: label,
|
||||
type: schema.type,
|
||||
description: description,
|
||||
isId: true,
|
||||
|
@ -174,16 +170,16 @@ export default Service.extend({
|
|||
});
|
||||
},
|
||||
|
||||
getNewAdapter(backend, paths, itemType) {
|
||||
getNewAdapter(paths, itemType) {
|
||||
//we need list and create paths to set the correct urls for actions
|
||||
const { list, create } = paths;
|
||||
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));
|
||||
return generatedItemAdapter.extend({
|
||||
urlForItem(method, id) {
|
||||
let { tag, path } = listPath;
|
||||
let url = `${this.buildURL()}/${tag}/${backend}${path}/`;
|
||||
let { path } = listPath;
|
||||
let url = `${this.buildURL()}/${apiPath}${path}/`;
|
||||
if (id) {
|
||||
url = url + encodePath(id);
|
||||
}
|
||||
|
@ -195,22 +191,22 @@ export default Service.extend({
|
|||
},
|
||||
|
||||
urlForUpdateRecord(id) {
|
||||
let { tag, path } = createPath;
|
||||
let { path } = createPath;
|
||||
path = path.slice(0, path.indexOf('{') - 1);
|
||||
return `${this.buildURL()}/${tag}/${backend}${path}/${id}`;
|
||||
return `${this.buildURL()}/${apiPath}${path}/${id}`;
|
||||
},
|
||||
|
||||
urlForCreateRecord(modelType, snapshot) {
|
||||
const { id } = snapshot;
|
||||
let { tag, path } = createPath;
|
||||
let { path } = createPath;
|
||||
path = path.slice(0, path.indexOf('{') - 1);
|
||||
return `${this.buildURL()}/${tag}/${backend}${path}/${id}`;
|
||||
return `${this.buildURL()}/${apiPath}${path}/${id}`;
|
||||
},
|
||||
|
||||
urlForDeleteRecord(id) {
|
||||
let { tag, path } = deletePath;
|
||||
let { path } = deletePath;
|
||||
path = path.slice(0, path.indexOf('{') - 1);
|
||||
return `${this.buildURL()}/${tag}/${backend}${path}/${id}`;
|
||||
return `${this.buildURL()}/${apiPath}${path}/${id}`;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
<ToolbarActions>
|
||||
<ToolbarLink @params={{array
|
||||
"vault.cluster.access.method.item.create"
|
||||
(pluralize itemType)
|
||||
itemType
|
||||
}}>
|
||||
Create
|
||||
{{itemType}}
|
||||
{{singularize itemType}}
|
||||
</ToolbarLink>
|
||||
</ToolbarActions>
|
||||
</Toolbar>
|
||||
|
@ -35,27 +35,27 @@
|
|||
@message="A list of {{pluralize itemType}} will be listed here. Create your first {{itemType}} to get started.">
|
||||
{{#link-to
|
||||
"vault.cluster.access.method.item.create"
|
||||
(pluralize itemType)
|
||||
itemType
|
||||
class="link"
|
||||
}}
|
||||
Create {{itemType}}
|
||||
Create {{singularize itemType}}
|
||||
{{/link-to}}
|
||||
</list.empty>
|
||||
{{else if list.item}}
|
||||
<ListItem @linkParams={{array "vault.cluster.access.method.item.show"
|
||||
(pluralize itemType) list.item.id}} as |Item|>
|
||||
itemType list.item.id}} as |Item|>
|
||||
<Item.content>
|
||||
<Icon @glyph="folder-outline" class="has-text-grey-light" @size="l" />{{list.item.id}}
|
||||
</Item.content>
|
||||
<Item.menu>
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.method.item.show" list.item.id class="is-block"}}
|
||||
View {{itemType}}
|
||||
View {{singularize itemType}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.method.item.edit" list.item.id class="is-block"}}
|
||||
Edit {{itemType}}
|
||||
Edit {{singularize itemType}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
|
@ -64,14 +64,14 @@
|
|||
Item.callMethod
|
||||
"destroyRecord"
|
||||
list.item
|
||||
(concat "Successfully deleted " itemType " " list.item.id)
|
||||
(concat "There was an error deleting this " itemType)
|
||||
(concat "Successfully deleted " (singularize itemType) " " list.item.id)
|
||||
(concat "There was an error deleting this " (singularize itemType))
|
||||
(action "refreshItemList")
|
||||
)
|
||||
}} @confirmMessage={{concat "Are you sure you want to delete " list.item.id "?"}}
|
||||
@cancelButtonText="Cancel" data-test-secret-delete="true">
|
||||
Delete
|
||||
{{itemType}}
|
||||
{{singularize itemType}}
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
</Item.menu>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</span>
|
||||
{{#link-to
|
||||
"vault.cluster.access.method.item.list"
|
||||
(pluralize itemType)
|
||||
itemType
|
||||
}}
|
||||
{{pluralize itemType}}
|
||||
{{/link-to}}
|
||||
|
@ -41,9 +41,9 @@
|
|||
Delete
|
||||
{{itemType}}
|
||||
</ConfirmAction>
|
||||
<ToolbarLink @params={{array "vault.cluster.access.method.item.edit" (pluralize itemType) model.id}}
|
||||
<ToolbarLink @params={{array "vault.cluster.access.method.item.edit" itemType model.id}}
|
||||
@data-test-configure-link="true">
|
||||
Edit {{itemType}}
|
||||
Edit {{singularize itemType}}
|
||||
</ToolbarLink>
|
||||
</ToolbarActions>
|
||||
</Toolbar>
|
||||
|
|
|
@ -8,7 +8,10 @@ export const expandOpenApiProps = function(props) {
|
|||
// expand all attributes
|
||||
for (const propName in props) {
|
||||
const prop = props[propName];
|
||||
let { description, items, type, format, isId, label } = prop;
|
||||
let { description, items, type, format, isId, deprecated } = prop;
|
||||
if (deprecated === true) {
|
||||
continue;
|
||||
}
|
||||
let { name, value, group, sensitive } = prop['x-vault-displayAttrs'] || {};
|
||||
|
||||
if (type === 'integer') {
|
||||
|
@ -21,11 +24,11 @@ export const expandOpenApiProps = function(props) {
|
|||
} else if (items) {
|
||||
editType = items.type + capitalize(type);
|
||||
}
|
||||
|
||||
let attrDefn = {
|
||||
editType,
|
||||
helpText: description,
|
||||
sensitive: sensitive,
|
||||
label: name || label,
|
||||
possibleValues: prop['enum'],
|
||||
fieldValue: isId ? 'id' : null,
|
||||
fieldGroup: group || 'default',
|
||||
|
@ -33,6 +36,8 @@ export const expandOpenApiProps = function(props) {
|
|||
defaultValue: value || null,
|
||||
};
|
||||
|
||||
attrDefn.label = capitalize(name || propName);
|
||||
|
||||
// ttls write as a string and read as a number
|
||||
// so setting type on them runs the wrong transform
|
||||
if (editType !== 'ttl' && type !== 'array') {
|
||||
|
|
|
@ -58,32 +58,36 @@ 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',
|
||||
editType: 'string',
|
||||
sensitive: true,
|
||||
helpText: 'A really secret thing',
|
||||
fieldGroup: 'default',
|
||||
label: 'Super-secret',
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue