mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-19 05:31:10 +02:00
* Add helper combineOpenApiAttrs + test * hydrateModel working with upgradeModelSchema * new registerNewModelWithAttrs method for generated models * Add newFields to generated models * copyright * Glimmerize path-help service * update generated-item-list adapter and path-help usage of it * remove unused methods combineAttributes and combineFields * move expandOpenApiProps to ts helper file * fix auth test * fix bug where adding user to second userpass mount saves to first mount * Add mutableId * fix ent test * remove addressed deprecation * Address PR comments * [VAULT-31208] remove deprecation early-static from decorator tests
295 lines
8.1 KiB
JavaScript
295 lines
8.1 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { module, test } from 'qunit';
|
|
import {
|
|
_getPathParam,
|
|
combineOpenApiAttrs,
|
|
expandOpenApiProps,
|
|
getHelpUrlForModel,
|
|
pathToHelpUrlSegment,
|
|
} from 'vault/utils/openapi-helpers';
|
|
import Model, { attr } from '@ember-data/model';
|
|
import { setupTest } from 'ember-qunit';
|
|
import { camelize } from '@ember/string';
|
|
|
|
module('Unit | Utility | OpenAPI helper utils', function (hooks) {
|
|
setupTest(hooks);
|
|
|
|
test(`pathToHelpUrlSegment`, function (assert) {
|
|
[
|
|
{ path: '/auth/{username}', result: '/auth/example' },
|
|
{ path: '{username}/foo', result: 'example/foo' },
|
|
{ path: 'foo/{username}/bar', result: 'foo/example/bar' },
|
|
{ path: '', result: '' },
|
|
{ path: undefined, result: '' },
|
|
].forEach((test) => {
|
|
assert.strictEqual(pathToHelpUrlSegment(test.path), test.result, `translates ${test.path}`);
|
|
});
|
|
});
|
|
|
|
test(`_getPathParam`, function (assert) {
|
|
[
|
|
{ path: '/auth/{username}', result: 'username' },
|
|
{ path: '{unicorn}/foo', result: 'unicorn' },
|
|
{ path: 'foo/{bigfoot}/bar', result: 'bigfoot' },
|
|
{ path: '{alphabet}/bowl/{soup}', result: 'alphabet' },
|
|
{ path: 'no/params', result: false },
|
|
{ path: '', result: false },
|
|
{ path: undefined, result: false },
|
|
].forEach((test) => {
|
|
assert.strictEqual(_getPathParam(test.path), test.result, `returns first param for ${test.path}`);
|
|
});
|
|
});
|
|
|
|
test(`getHelpUrlForModel`, function (assert) {
|
|
[
|
|
{ modelType: 'kmip/config', result: '/v1/foobar/config?help=1' },
|
|
{ modelType: 'does-not-exist', result: null },
|
|
{ modelType: 4, result: null },
|
|
{ modelType: '', result: null },
|
|
{ modelType: undefined, result: null },
|
|
].forEach((test) => {
|
|
assert.strictEqual(
|
|
getHelpUrlForModel(test.modelType, 'foobar'),
|
|
test.result,
|
|
`returns first param for ${test.path}`
|
|
);
|
|
});
|
|
});
|
|
|
|
test('combineOpenApiAttrs should combine attributes correctly', async function (assert) {
|
|
class FooModel extends Model {
|
|
@attr('string', {
|
|
label: 'Foo',
|
|
subText: 'A form field',
|
|
})
|
|
foo;
|
|
@attr('boolean', {
|
|
label: 'Bar',
|
|
subText: 'Maybe a checkbox',
|
|
})
|
|
bar;
|
|
@attr('number', {
|
|
label: 'Baz',
|
|
subText: 'A number field',
|
|
})
|
|
baz;
|
|
}
|
|
this.owner.register('model:foo', FooModel);
|
|
const myModel = this.owner.lookup('service:store').modelFor('foo');
|
|
const newProps = {
|
|
foo: {
|
|
editType: 'ttl',
|
|
},
|
|
baz: {
|
|
type: 'number',
|
|
editType: 'slider',
|
|
label: 'Old label',
|
|
},
|
|
foobar: {
|
|
type: 'string',
|
|
label: 'Foo-bar',
|
|
},
|
|
};
|
|
const expected = [
|
|
{
|
|
name: 'foo',
|
|
type: 'string',
|
|
options: {
|
|
label: 'Foo',
|
|
subText: 'A form field',
|
|
editType: 'ttl',
|
|
},
|
|
},
|
|
{
|
|
name: 'bar',
|
|
type: 'boolean',
|
|
options: {
|
|
label: 'Bar',
|
|
subText: 'Maybe a checkbox',
|
|
},
|
|
},
|
|
{
|
|
name: 'baz',
|
|
type: 'number',
|
|
options: {
|
|
label: 'Baz', // uses the value we set on the model
|
|
editType: 'slider',
|
|
subText: 'A number field',
|
|
},
|
|
},
|
|
{
|
|
name: 'foobar',
|
|
type: 'string',
|
|
options: {
|
|
label: 'Foo-bar',
|
|
},
|
|
},
|
|
];
|
|
const { attrs, newFields } = combineOpenApiAttrs(myModel.attributes, newProps);
|
|
assert.deepEqual(newFields, ['foobar'], 'correct newFields added');
|
|
|
|
// When combineOpenApiAttrs
|
|
assert.strictEqual(attrs.length, 4, 'correct number of attributes returned');
|
|
expected.forEach((exp) => {
|
|
const name = exp.name;
|
|
const attr = attrs.find((a) => a.name === name);
|
|
assert.deepEqual(attr, exp, `${name} combined properly`);
|
|
});
|
|
});
|
|
|
|
module('expandopenApiProps', function () {
|
|
const OPENAPI_RESPONSE_PROPS = {
|
|
ttl: {
|
|
type: 'string',
|
|
format: 'seconds',
|
|
description: 'this is a TTL!',
|
|
'x-vault-displayAttrs': {
|
|
name: 'TTL',
|
|
},
|
|
},
|
|
'awesome-people': {
|
|
type: 'array',
|
|
items: {
|
|
type: 'string',
|
|
},
|
|
'x-vault-displayAttrs': {
|
|
value: 'Grace Hopper,Lady Ada',
|
|
},
|
|
},
|
|
'favorite-ice-cream': {
|
|
type: 'string',
|
|
enum: ['vanilla', 'chocolate', 'strawberry'],
|
|
},
|
|
'default-value': {
|
|
default: 30,
|
|
'x-vault-displayAttrs': {
|
|
value: 300,
|
|
},
|
|
type: 'integer',
|
|
},
|
|
default: {
|
|
'x-vault-displayAttrs': {
|
|
value: 30,
|
|
},
|
|
type: 'integer',
|
|
},
|
|
'super-secret': {
|
|
type: 'string',
|
|
'x-vault-displayAttrs': {
|
|
sensitive: true,
|
|
},
|
|
description: 'A really secret thing',
|
|
},
|
|
};
|
|
const EXPANDED_PROPS = {
|
|
ttl: {
|
|
helpText: 'this is a TTL!',
|
|
editType: 'ttl',
|
|
label: 'TTL',
|
|
fieldGroup: 'default',
|
|
},
|
|
awesomePeople: {
|
|
editType: 'stringArray',
|
|
defaultValue: 'Grace Hopper,Lady Ada',
|
|
fieldGroup: 'default',
|
|
},
|
|
favoriteIceCream: {
|
|
editType: 'string',
|
|
type: 'string',
|
|
possibleValues: ['vanilla', 'chocolate', 'strawberry'],
|
|
fieldGroup: 'default',
|
|
},
|
|
defaultValue: {
|
|
editType: 'number',
|
|
type: 'number',
|
|
defaultValue: 300,
|
|
fieldGroup: 'default',
|
|
},
|
|
default: {
|
|
editType: 'number',
|
|
type: 'number',
|
|
defaultValue: 30,
|
|
fieldGroup: 'default',
|
|
},
|
|
superSecret: {
|
|
type: 'string',
|
|
editType: 'string',
|
|
sensitive: true,
|
|
helpText: 'A really secret thing',
|
|
fieldGroup: 'default',
|
|
},
|
|
};
|
|
const OPENAPI_DESCRIPTIONS = {
|
|
token_bound_cidrs: {
|
|
type: 'array',
|
|
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.',
|
|
items: {
|
|
type: 'string',
|
|
},
|
|
'x-vault-displayAttrs': {
|
|
description:
|
|
'List of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.',
|
|
name: "Generated Token's Bound CIDRs",
|
|
group: 'Tokens',
|
|
},
|
|
},
|
|
blah_blah: {
|
|
type: 'array',
|
|
description: 'Comma-separated list of policies',
|
|
items: {
|
|
type: 'string',
|
|
},
|
|
'x-vault-displayAttrs': {
|
|
name: "Generated Token's Policies",
|
|
group: 'Tokens',
|
|
},
|
|
},
|
|
only_display_description: {
|
|
type: 'array',
|
|
items: {
|
|
type: 'string',
|
|
},
|
|
'x-vault-displayAttrs': {
|
|
description: 'Hello there, you look nice today',
|
|
},
|
|
},
|
|
};
|
|
|
|
const STRING_ARRAY_DESCRIPTIONS = {
|
|
token_bound_cidrs: {
|
|
helpText:
|
|
'List of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.',
|
|
},
|
|
blah_blah: {
|
|
helpText: 'Comma-separated list of policies',
|
|
},
|
|
only_display_description: {
|
|
helpText: 'Hello there, you look nice today',
|
|
},
|
|
};
|
|
test('it creates objects from OpenAPI schema props', function (assert) {
|
|
assert.expect(6);
|
|
const generatedProps = expandOpenApiProps(OPENAPI_RESPONSE_PROPS);
|
|
for (const propName in EXPANDED_PROPS) {
|
|
assert.deepEqual(EXPANDED_PROPS[propName], generatedProps[propName], `correctly expands ${propName}`);
|
|
}
|
|
});
|
|
test('it uses the description from the display attrs block if it exists', async function (assert) {
|
|
assert.expect(3);
|
|
const generatedProps = expandOpenApiProps(OPENAPI_DESCRIPTIONS);
|
|
for (const propName in STRING_ARRAY_DESCRIPTIONS) {
|
|
assert.strictEqual(
|
|
generatedProps[camelize(propName)].helpText,
|
|
STRING_ARRAY_DESCRIPTIONS[propName].helpText,
|
|
`correctly updates helpText for ${propName}`
|
|
);
|
|
}
|
|
});
|
|
});
|
|
});
|