UI: Add Typescript for PKI engine (#17927)
This commit is contained in:
parent
de70878e16
commit
0fb4e422be
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
ui: Enable typescript for future development
|
||||
```
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Type declarations for
|
||||
* import config from 'my-app/config/environment'
|
||||
*/
|
||||
declare const config: {
|
||||
environment: string;
|
||||
modulePrefix: string;
|
||||
podModulePrefix: string;
|
||||
locationType: 'history' | 'hash' | 'none' | 'auto';
|
||||
rootURL: string;
|
||||
APP: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -10,6 +10,14 @@ const validations = {
|
|||
|
||||
@withModelValidations(validations)
|
||||
export default class PkiRoleModel extends Model {
|
||||
get useOpenAPI() {
|
||||
// must be a getter so it can be accessed in path-help.js
|
||||
return true;
|
||||
}
|
||||
getHelpUrl(backend) {
|
||||
return `/v1/${backend}/roles/example?help=1`;
|
||||
}
|
||||
|
||||
@attr('string', { readOnly: true }) backend;
|
||||
|
||||
/* Overriding OpenApi default options */
|
||||
|
@ -219,6 +227,20 @@ export default class PkiRoleModel extends Model {
|
|||
})
|
||||
ou;
|
||||
|
||||
@attr('array', {
|
||||
defaultValue() {
|
||||
return ['DigitalSignature', 'KeyAgreement', 'KeyEncipherment'];
|
||||
},
|
||||
})
|
||||
keyUsage;
|
||||
|
||||
@attr('array', {
|
||||
defaultValue() {
|
||||
return [];
|
||||
},
|
||||
})
|
||||
extKeyUsage;
|
||||
|
||||
@attr({ hideFormSection: true }) organization;
|
||||
@attr({ hideFormSection: true }) country;
|
||||
@attr({ hideFormSection: true }) locality;
|
||||
|
@ -227,14 +249,7 @@ export default class PkiRoleModel extends Model {
|
|||
@attr({ hideFormSection: true }) postalCode;
|
||||
/* End of overriding Additional subject field options */
|
||||
|
||||
// must be a getter so it can be added to the prototype needed in the pathHelp service on the line here: if (newModel.merged || modelProto.useOpenAPI !== true) {
|
||||
get useOpenAPI() {
|
||||
return true;
|
||||
}
|
||||
getHelpUrl(backend) {
|
||||
return `/v1/${backend}/roles/example?help=1`;
|
||||
}
|
||||
|
||||
/* CAPABILITIES */
|
||||
@lazyCapabilities(apiPath`${'backend'}/roles/${'id'}`, 'backend', 'id') updatePath;
|
||||
get canDelete() {
|
||||
return this.updatePath.get('canCreate');
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<div data-test-checkbox-grid ...attributes>
|
||||
<FormFieldLabel for={{@name}} @label={{@label}} @subText={{@subText}} />
|
||||
<div class="is-grid is-grid-3-columns is-medium-height">
|
||||
{{#each this.checkboxes as |checkbox|}}
|
||||
<div class="field">
|
||||
<div class="b-checkbox">
|
||||
<Input
|
||||
@type="checkbox"
|
||||
id={{checkbox.key}}
|
||||
name={{checkbox.key}}
|
||||
class="styled"
|
||||
@checked={{checkbox.value}}
|
||||
{{on "change" this.checkboxChange}}
|
||||
data-test-checkbox={{checkbox.key}}
|
||||
/>
|
||||
<label for={{checkbox.key}} class="is-label">
|
||||
{{checkbox.label}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,55 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { action } from '@ember/object';
|
||||
import { HTMLElementEvent } from 'forms';
|
||||
|
||||
interface CheckboxGridArgs {
|
||||
name: string;
|
||||
label: string;
|
||||
subText?: string;
|
||||
fields: Field[];
|
||||
value: string[] | undefined;
|
||||
onChange: (name: string, value: string[]) => void;
|
||||
}
|
||||
interface Field {
|
||||
key: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @module CheckboxGrid
|
||||
* CheckboxGrid components are used to allow users to select any
|
||||
* number of predetermined options, aligned in a 3-column grid.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* <CheckboxGrid
|
||||
* @name="modelKey"
|
||||
* @label="Model Attribute Label"
|
||||
* @fields={{options}}
|
||||
* @value={{['Hello', 'Yes']}}
|
||||
* />
|
||||
* ```
|
||||
*/
|
||||
|
||||
export default class CheckboxGrid extends Component<CheckboxGridArgs> {
|
||||
get checkboxes() {
|
||||
const list = this.args.value || [];
|
||||
return this.args.fields.map((field) => ({
|
||||
...field,
|
||||
value: list.includes(field.key),
|
||||
}));
|
||||
}
|
||||
|
||||
@action checkboxChange(event: HTMLElementEvent<HTMLInputElement>) {
|
||||
const list = this.args.value || [];
|
||||
const checkboxName = event.target.id;
|
||||
const checkboxVal = event.target.checked;
|
||||
const idx = list.indexOf(checkboxName);
|
||||
if (checkboxVal === true && idx < 0) {
|
||||
list.push(checkboxName);
|
||||
} else if (checkboxVal === false && idx >= 0) {
|
||||
list.splice(idx, 1);
|
||||
}
|
||||
this.args.onChange(this.args.name, list);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export { default } from 'core/components/checkbox-grid';
|
|
@ -14,6 +14,7 @@
|
|||
"ember-cli-clipboard": "*",
|
||||
"ember-cli-htmlbars": "*",
|
||||
"ember-cli-string-helpers": "*",
|
||||
"ember-cli-typescript": "*",
|
||||
"ember-composable-helpers": "*",
|
||||
"ember-concurrency": "*",
|
||||
"ember-maybe-in-element": "*",
|
||||
|
|
|
@ -9,58 +9,25 @@
|
|||
/>
|
||||
{{#if (get @model prop)}}
|
||||
<div class="box is-tall is-marginless" data-test-surrounding-div={{@group}}>
|
||||
<FormFieldLabel
|
||||
for="keyUsageLabel"
|
||||
<CheckboxGrid
|
||||
@name="keyUsage"
|
||||
@label="Key usage"
|
||||
@subText="Specifies the default key usage constraint on the issued certificate. To specify no default key_usage constraints, uncheck every item in this list."
|
||||
@fields={{this.keyUsageFields}}
|
||||
@value={{@model.keyUsage}}
|
||||
@onChange={{this.checkboxChange}}
|
||||
data-test-key-usage-key-usage-checkboxes
|
||||
/>
|
||||
<CheckboxGrid
|
||||
@name="extKeyUsage"
|
||||
@label="Extended key usage"
|
||||
@subText="Specifies the default key usage constraint on the issued certificate. To specify no default ext_key_usage constraints, uncheck every item in this list."
|
||||
@fields={{this.extKeyUsageFields}}
|
||||
@value={{@model.extKeyUsage}}
|
||||
@onChange={{this.checkboxChange}}
|
||||
class="has-top-margin-s"
|
||||
data-test-key-usage-ext-key-usage-checkboxes
|
||||
/>
|
||||
<div class="is-grid is-grid-3-columns is-medium-height">
|
||||
{{! KEY USAGE SECTION }}
|
||||
{{#each-in this.keyUsageFields as |name attr|}}
|
||||
<div class="field">
|
||||
<div class="b-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={{name}}
|
||||
class="styled"
|
||||
checked={{attr.value}}
|
||||
onchange={{fn this.checkboxChange "keyUsage"}}
|
||||
data-test-input={{name}}
|
||||
/>
|
||||
<label for={{name}} class="is-label">
|
||||
{{attr.label}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/each-in}}
|
||||
</div>
|
||||
<div class="has-top-margin-s">
|
||||
<FormFieldLabel
|
||||
for="ExtKeyUsageLabel"
|
||||
@label="Extended key usage"
|
||||
@subText="Specifies the default key usage constraint on the issued certificate. To specify no default ext_key_usage constraints, uncheck every item in this list."
|
||||
/>
|
||||
</div>
|
||||
{{! EXT KEY USAGE SECTION }}
|
||||
<div class="is-grid is-grid-3-columns is-medium-height">
|
||||
{{#each-in this.extKeyUsageFields as |name attr|}}
|
||||
<div class="field">
|
||||
<div class="b-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={{name}}
|
||||
class="styled"
|
||||
checked={{attr.value}}
|
||||
onchange={{fn this.checkboxChange "extKeyUsage"}}
|
||||
data-test-input={{name}}
|
||||
/>
|
||||
<label for={{name}} class="is-label">
|
||||
{{attr.label}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/each-in}}
|
||||
</div>
|
||||
<div class="has-top-margin-xxl">
|
||||
<StringList
|
||||
data-test-input="extKeyUsageOids"
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
/**
|
||||
* @module KeyUsage
|
||||
* KeyUsage components are used to build out the toggle options for PKI's role create/update key_usage, ext_key_usage and ext_key_usage_oids model params.
|
||||
* Instead of having the user search on the following goLang pages for these options we present them in checkbox form and manually add them to the params as an array of strings.
|
||||
* key_usage options: https://pkg.go.dev/crypto/x509#KeyUsage
|
||||
* ext_key_usage options (not all are include on purpose): https://pkg.go.dev/crypto/x509#ExtKeyUsage
|
||||
* @example
|
||||
* ```js
|
||||
* <KeyUsage @model={@model} @group={group}/>
|
||||
* ```
|
||||
* @param {class} model - The pki/role model.
|
||||
* @param {string} group - The name of the group created in the model. In this case, it's the "Key usage" group.
|
||||
*/
|
||||
|
||||
const KEY_USAGE_FIELDS = {
|
||||
DigitalSignature: {
|
||||
label: 'Digital Signature',
|
||||
value: true,
|
||||
},
|
||||
ContentCommitment: { label: 'Content Commitment' },
|
||||
CrlSign: { label: 'CRL Sign' },
|
||||
KeyAgreement: {
|
||||
label: 'Key Agreement',
|
||||
value: true,
|
||||
},
|
||||
DataEncipherment: { label: 'Data Encipherment' },
|
||||
EncipherOnly: { label: 'Encipher Only' },
|
||||
KeyEncipherment: {
|
||||
label: 'Key Encipherment',
|
||||
value: true,
|
||||
},
|
||||
CertSign: { label: 'Cert Sign' },
|
||||
DecipherOnly: { label: 'Decipher Only' },
|
||||
};
|
||||
|
||||
const EXT_KEY_USAGE_FIELDS = {
|
||||
Any: { label: 'Any' },
|
||||
EmailProtection: { label: 'Email Protection' },
|
||||
TimeStamping: { label: 'Time Stamping' },
|
||||
ServerAuth: { label: 'Server Auth' },
|
||||
IpsecEndSystem: { label: 'IPSEC End System' },
|
||||
OcspSigning: { label: 'OCSP Signing' },
|
||||
ClientAuth: { label: 'Client Auth' },
|
||||
IpsecTunnel: { label: 'IPSEC Tunnel' },
|
||||
IpsecUser: { label: 'IPSEC User' },
|
||||
CodeSigning: { label: 'Code Signing' },
|
||||
};
|
||||
|
||||
export default class KeyUsage extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.keyUsageFields = {};
|
||||
this.extKeyUsageFields = {};
|
||||
Object.assign(this.keyUsageFields, KEY_USAGE_FIELDS);
|
||||
Object.assign(this.extKeyUsageFields, EXT_KEY_USAGE_FIELDS);
|
||||
// set default of key_usage to the three params that are true by default.
|
||||
this.args.model.set('keyUsage', ['DigitalSignature', 'KeyAgreement', 'KeyEncipherment']);
|
||||
}
|
||||
|
||||
@action onStringListChange(value) {
|
||||
this.args.model.set('extKeyUsageOids', value);
|
||||
}
|
||||
|
||||
_amendList(checkboxName, value, type) {
|
||||
const keyUsageList = this.args.model.keyUsage;
|
||||
const extKeyUsageList = this.args.model.extKeyUsage;
|
||||
|
||||
/* Process:
|
||||
1. We first check if the checkbox change is coming from the checkbox options of key_usage or ext_key_usage.
|
||||
// Param key_usage || ext_key_usage accept a comma separated string and an array of strings. E.g. "DigitalSignature,KeyAgreement,KeyEncipherment" || [“DigitalSignature”,“KeyAgreement”,“KeyEncipherment”]
|
||||
2. Then we convert the string to an array if it's not already an array (e.g. it's already been converted). This makes it easier to add or remove items.
|
||||
3. Then if the value of checkbox is "true" we add it to the arrayList, otherwise remove it.
|
||||
*/
|
||||
if (type === 'keyUsage') {
|
||||
const keyUsageListArray = Array.isArray(keyUsageList) ? keyUsageList : keyUsageList.split(',');
|
||||
|
||||
return value ? keyUsageListArray.addObject(checkboxName) : keyUsageListArray.removeObject(checkboxName);
|
||||
} else {
|
||||
// because there is no default on init for ext_key_usage property (set normally by OpenAPI) we define it as an empty array if it is undefined.
|
||||
const extKeyUsageListArray = !extKeyUsageList ? [] : extKeyUsageList;
|
||||
|
||||
return value
|
||||
? extKeyUsageListArray.addObject(checkboxName)
|
||||
: extKeyUsageListArray.removeObject(checkboxName);
|
||||
}
|
||||
}
|
||||
@action checkboxChange(type) {
|
||||
const checkboxName = event.target.id;
|
||||
const value = event.target['checked'];
|
||||
this.args.model.set(type, this._amendList(checkboxName, value, type));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
/**
|
||||
* @module PkiKeyUsage
|
||||
* PkiKeyUsage components are used to build out the toggle options for PKI's role create/update key_usage, ext_key_usage and ext_key_usage_oids model params.
|
||||
* Instead of having the user search on the following goLang pages for these options we present them in checkbox form and manually add them to the params as an array of strings.
|
||||
* key_usage options: https://pkg.go.dev/crypto/x509#KeyUsage
|
||||
* ext_key_usage options (not all are include on purpose): https://pkg.go.dev/crypto/x509#ExtKeyUsage
|
||||
* @example
|
||||
* ```js
|
||||
* <PkiKeyUsage @model={@model} @group={group}/>
|
||||
* ```
|
||||
* @param {class} model - The pki/pki-role-engine model.
|
||||
* @param {string} group - The name of the group created in the model. In this case, it's the "Key usage" group.
|
||||
*/
|
||||
|
||||
interface Field {
|
||||
key: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const KEY_USAGE_FIELDS: Field[] = [
|
||||
{ key: 'DigitalSignature', label: 'Digital Signature' },
|
||||
{ key: 'ContentCommitment', label: 'Content Commitment' },
|
||||
{ key: 'CrlSign', label: 'CRL Sign' },
|
||||
{ key: 'KeyAgreement', label: 'Key Agreement' },
|
||||
{ key: 'DataEncipherment', label: 'Data Encipherment' },
|
||||
{ key: 'EncipherOnly', label: 'Encipher Only' },
|
||||
{ key: 'KeyEncipherment', label: 'Key Encipherment' },
|
||||
{ key: 'CertSign', label: 'Cert Sign' },
|
||||
{ key: 'DecipherOnly', label: 'Decipher Only' },
|
||||
];
|
||||
|
||||
const EXT_KEY_USAGE_FIELDS: Field[] = [
|
||||
{ key: 'Any', label: 'Any' },
|
||||
{ key: 'EmailProtection', label: 'Email Protection' },
|
||||
{ key: 'TimeStamping', label: 'Time Stamping' },
|
||||
{ key: 'ServerAuth', label: 'Server Auth' },
|
||||
{ key: 'IpsecEndSystem', label: 'IPSEC End System' },
|
||||
{ key: 'OcspSigning', label: 'OCSP Signing' },
|
||||
{ key: 'ClientAuth', label: 'Client Auth' },
|
||||
{ key: 'IpsecTunnel', label: 'IPSEC Tunnel' },
|
||||
{ key: 'IpsecUser', label: 'IPSEC User' },
|
||||
{ key: 'CodeSigning', label: 'Code Signing' },
|
||||
];
|
||||
|
||||
interface PkiKeyUsageArgs {
|
||||
group: string;
|
||||
model: {
|
||||
keyUsage: string[];
|
||||
extKeyUsageOids: string[];
|
||||
extKeyUsage: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export default class PkiKeyUsage extends Component<PkiKeyUsageArgs> {
|
||||
keyUsageFields = KEY_USAGE_FIELDS;
|
||||
extKeyUsageFields = EXT_KEY_USAGE_FIELDS;
|
||||
|
||||
@action onStringListChange(value: string[]) {
|
||||
this.args.model.extKeyUsageOids = value;
|
||||
}
|
||||
|
||||
_amendList(checkboxName: string, value: boolean, type: string): string[] {
|
||||
const list = type === 'keyUsage' ? this.args.model.keyUsage : this.args.model.extKeyUsage;
|
||||
const idx = list.indexOf(checkboxName);
|
||||
if (value === true && idx < 0) {
|
||||
list.push(checkboxName);
|
||||
} else if (value === false && idx >= 0) {
|
||||
list.splice(idx, 1);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@action checkboxChange(name: string, value: string[]) {
|
||||
// Make sure we can set this value type to this model key
|
||||
if (name === 'keyUsage' || name === 'extKeyUsage') {
|
||||
this.args.model[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,9 @@
|
|||
"ember-engine"
|
||||
],
|
||||
"dependencies": {
|
||||
"ember-cli-babel": "*",
|
||||
"ember-cli-htmlbars": "*",
|
||||
"ember-cli-babel": "*"
|
||||
"ember-cli-typescript": "*"
|
||||
},
|
||||
"ember-addon": {
|
||||
"paths": [
|
||||
|
|
|
@ -62,6 +62,35 @@
|
|||
"@hashicorp/ember-flight-icons": "2.0.3",
|
||||
"@hashicorp/structure-icons": "^1.3.0",
|
||||
"@icholy/duration": "^5.1.0",
|
||||
"@tsconfig/ember": "^1.0.1",
|
||||
"@types/ember": "^4.0.2",
|
||||
"@types/ember-data": "^4.4.6",
|
||||
"@types/ember-data__adapter": "^4.0.1",
|
||||
"@types/ember-data__model": "^4.0.0",
|
||||
"@types/ember-data__serializer": "^4.0.1",
|
||||
"@types/ember-data__store": "^4.0.2",
|
||||
"@types/ember-qunit": "^5.0.2",
|
||||
"@types/ember-resolver": "^5.0.13",
|
||||
"@types/ember__application": "^4.0.4",
|
||||
"@types/ember__array": "^4.0.3",
|
||||
"@types/ember__component": "^4.0.11",
|
||||
"@types/ember__controller": "^4.0.3",
|
||||
"@types/ember__debug": "^4.0.3",
|
||||
"@types/ember__destroyable": "^4.0.1",
|
||||
"@types/ember__engine": "^4.0.4",
|
||||
"@types/ember__error": "^4.0.1",
|
||||
"@types/ember__object": "^4.0.5",
|
||||
"@types/ember__polyfills": "^4.0.1",
|
||||
"@types/ember__routing": "^4.0.12",
|
||||
"@types/ember__runloop": "^4.0.2",
|
||||
"@types/ember__service": "^4.0.1",
|
||||
"@types/ember__string": "^3.0.10",
|
||||
"@types/ember__template": "^4.0.1",
|
||||
"@types/ember__test": "^4.0.1",
|
||||
"@types/ember__test-helpers": "^2.8.2",
|
||||
"@types/ember__utils": "^4.0.2",
|
||||
"@types/qunit": "^2.19.3",
|
||||
"@types/rsvp": "^4.0.4",
|
||||
"asn1js": "^2.2.0",
|
||||
"autosize": "^4.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
|
@ -103,6 +132,7 @@
|
|||
"ember-cli-sri": "meirish/ember-cli-sri#rooturl",
|
||||
"ember-cli-string-helpers": "6.1.0",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-cli-typescript": "^5.2.1",
|
||||
"ember-composable-helpers": "5.0.0",
|
||||
"ember-concurrency": "2.3.4",
|
||||
"ember-copy": "2.0.1",
|
||||
|
@ -152,7 +182,7 @@
|
|||
"pkijs": "^2.2.2",
|
||||
"pretender": "^3.4.3",
|
||||
"prettier": "2.6.2",
|
||||
"prettier-eslint-cli": "^5.0.0",
|
||||
"prettier-eslint-cli": "^7.1.0",
|
||||
"pvutils": "^1.0.17",
|
||||
"qunit": "^2.19.1",
|
||||
"qunit-dom": "^2.0.0",
|
||||
|
@ -163,6 +193,7 @@
|
|||
"string.prototype.startswith": "^0.2.0",
|
||||
"swagger-ui-dist": "^3.36.2",
|
||||
"text-encoder-lite": "2.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"walk-sync": "^2.0.2",
|
||||
"webpack": "5.73.0",
|
||||
"xstate": "^3.3.3"
|
||||
|
|
|
@ -17,11 +17,11 @@ export const SELECTORS = {
|
|||
signatureBits: '[data-test-input="signatureBits"]',
|
||||
keyUsage: '[data-test-toggle-group="Key usage"]',
|
||||
extKeyUsageOids: '[data-test-input="extKeyUsageOids"]',
|
||||
digitalSignature: '[data-test-input="DigitalSignature"]',
|
||||
keyAgreement: '[data-test-input="KeyAgreement"]',
|
||||
keyEncipherment: '[data-test-input="KeyEncipherment"]',
|
||||
any: '[data-test-input="Any"]',
|
||||
serverAuth: '[data-test-input="ServerAuth"]',
|
||||
digitalSignature: '[data-test-checkbox="DigitalSignature"]',
|
||||
keyAgreement: '[data-test-checkbox="KeyAgreement"]',
|
||||
keyEncipherment: '[data-test-checkbox="KeyEncipherment"]',
|
||||
any: '[data-test-checkbox="Any"]',
|
||||
serverAuth: '[data-test-checkbox="ServerAuth"]',
|
||||
policyIdentifiers: '[data-test-toggle-group="Policy identifiers"]',
|
||||
san: '[data-test-toggle-group="Subject Alternative Name (SAN) Options"]',
|
||||
additionalSubjectFields: '[data-test-toggle-group="Additional subject fields"]',
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, click } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import Sinon from 'sinon';
|
||||
|
||||
module('Integration | Component | checkbox-grid', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.name = 'fooBar';
|
||||
this.label = 'Foo bar';
|
||||
this.fields = [
|
||||
{ key: 'abc', label: 'All Bears Cry' },
|
||||
{ key: 'def', label: 'Dark Eel Feelings' },
|
||||
];
|
||||
|
||||
this.onChange = Sinon.spy();
|
||||
});
|
||||
|
||||
test('it renders with minimum inputs', async function (assert) {
|
||||
const changeSpy = Sinon.spy();
|
||||
this.set('onChange', changeSpy);
|
||||
await render(
|
||||
hbs`<CheckboxGrid @name={{this.name}} @label={{this.label}} @fields={{this.fields}} @onChange={{this.onChange}} />`
|
||||
);
|
||||
|
||||
assert.dom('[data-test-checkbox]').exists({ count: 2 }, 'One checkbox is rendered for each field');
|
||||
assert.dom('[data-test-checkbox]').isNotChecked('no fields are checked by default');
|
||||
await click('[data-test-checkbox="abc"]');
|
||||
assert.ok(changeSpy.calledOnceWithExactly('fooBar', ['abc']));
|
||||
});
|
||||
|
||||
test('it renders with values set', async function (assert) {
|
||||
const changeSpy = Sinon.spy();
|
||||
this.set('onChange', changeSpy);
|
||||
this.set('currentValue', ['abc']);
|
||||
await render(
|
||||
hbs`<CheckboxGrid @name={{this.name}} @label={{this.label}} @fields={{this.fields}} @onChange={{this.onChange}} @value={{this.currentValue}} />`
|
||||
);
|
||||
|
||||
assert.dom('[data-test-checkbox]').exists({ count: 2 }, 'One checkbox is rendered for each field');
|
||||
assert.dom('[data-test-checkbox="abc"]').isChecked('abc field is checked on load');
|
||||
assert.dom('[data-test-checkbox="def"]').isNotChecked('def field is unchecked on load');
|
||||
await click('[data-test-checkbox="abc"]');
|
||||
assert.ok(changeSpy.calledOnceWithExactly('fooBar', []), 'Sends correct payload when unchecking');
|
||||
await click('[data-test-checkbox="def"]');
|
||||
await click('[data-test-checkbox="abc"]');
|
||||
assert.ok(
|
||||
changeSpy.calledWithExactly('fooBar', ['def', 'abc']),
|
||||
'sends correct payload with multiple checked'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -46,7 +46,7 @@ module('Integration | Component | pki/key-usage', function (hooks) {
|
|||
});
|
||||
|
||||
test('it should set the model properties of key_usage and ext_key_usage based on the checkbox selections', async function (assert) {
|
||||
assert.expect(4);
|
||||
assert.expect(2);
|
||||
await render(
|
||||
hbs`
|
||||
<div class="has-top-margin-xxl">
|
||||
|
@ -58,17 +58,6 @@ module('Integration | Component | pki/key-usage', function (hooks) {
|
|||
`,
|
||||
{ owner: this.engine }
|
||||
);
|
||||
// See PKI API docs https://developer.hashicorp.com/vault/api-docs/secret/pki#key_usage
|
||||
assert.deepEqual(
|
||||
this.model.keyUsage,
|
||||
['DigitalSignature', 'KeyAgreement', 'KeyEncipherment'],
|
||||
'sets the default values for key_usage on the model.'
|
||||
);
|
||||
assert.strictEqual(
|
||||
this.model.extKeyUsage,
|
||||
undefined,
|
||||
'sets no default value set for ext_key_usage on load.'
|
||||
);
|
||||
|
||||
await click(SELECTORS.keyUsage);
|
||||
await click(SELECTORS.digitalSignature);
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"extends": "@tsconfig/ember/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
// The combination of `baseUrl` with `paths` allows Ember's classic package
|
||||
// layout, which is not resolvable with the Node resolution algorithm, to
|
||||
// work with TypeScript.
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"vault/tests/*": ["tests/*"],
|
||||
"vault/mirage/*": ["mirage/*"],
|
||||
"vault/*": [
|
||||
"app/*",
|
||||
"lib/core/app/*",
|
||||
"lib/css/app/*",
|
||||
"lib/kmip/app/*",
|
||||
"lib/open-api-explorer/app/*",
|
||||
"lib/pki/app/*",
|
||||
"lib/replication/app/*",
|
||||
"lib/service-worker-authenticated-download/app/*"
|
||||
],
|
||||
"core": ["lib/core/addon"],
|
||||
"core/*": ["lib/core/addon/*"],
|
||||
"core/test-support": ["lib/core/addon-test-support"],
|
||||
"core/test-support/*": ["lib/core/addon-test-support/*"],
|
||||
"css": ["lib/css/addon"],
|
||||
"css/*": ["lib/css/addon/*"],
|
||||
"css/test-support": ["lib/css/addon-test-support"],
|
||||
"css/test-support/*": ["lib/css/addon-test-support/*"],
|
||||
"kmip": ["lib/kmip/addon"],
|
||||
"kmip/*": ["lib/kmip/addon/*"],
|
||||
"kmip/test-support": ["lib/kmip/addon-test-support"],
|
||||
"kmip/test-support/*": ["lib/kmip/addon-test-support/*"],
|
||||
"open-api-explorer": ["lib/open-api-explorer/addon"],
|
||||
"open-api-explorer/*": ["lib/open-api-explorer/addon/*"],
|
||||
"open-api-explorer/test-support": ["lib/open-api-explorer/addon-test-support"],
|
||||
"open-api-explorer/test-support/*": ["lib/open-api-explorer/addon-test-support/*"],
|
||||
"pki": ["lib/pki/addon"],
|
||||
"pki/*": ["lib/pki/addon/*"],
|
||||
"pki/test-support": ["lib/pki/addon-test-support"],
|
||||
"pki/test-support/*": ["lib/pki/addon-test-support/*"],
|
||||
"replication": ["lib/replication/addon"],
|
||||
"replication/*": ["lib/replication/addon/*"],
|
||||
"replication/test-support": ["lib/replication/addon-test-support"],
|
||||
"replication/test-support/*": ["lib/replication/addon-test-support/*"],
|
||||
"service-worker-authenticated-download": ["lib/service-worker-authenticated-download/addon"],
|
||||
"service-worker-authenticated-download/*": ["lib/service-worker-authenticated-download/addon/*"],
|
||||
"service-worker-authenticated-download/test-support": [
|
||||
"lib/service-worker-authenticated-download/addon-test-support"
|
||||
],
|
||||
"service-worker-authenticated-download/test-support/*": [
|
||||
"lib/service-worker-authenticated-download/addon-test-support/*"
|
||||
],
|
||||
"*": ["types/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"app/**/*",
|
||||
"tests/**/*",
|
||||
"types/**/*",
|
||||
"lib/core/**/*",
|
||||
"lib/css/**/*",
|
||||
"lib/kmip/**/*",
|
||||
"lib/open-api-explorer/**/*",
|
||||
"lib/pki/**/*",
|
||||
"lib/replication/**/*",
|
||||
"lib/service-worker-authenticated-download/**/*",
|
||||
"mirage/**/*"
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* Catch-all for ember-data.
|
||||
*/
|
||||
export default interface ModelRegistry {
|
||||
[key: string]: any;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export type HTMLElementEvent<T extends HTMLElement> = Event & {
|
||||
target: T;
|
||||
currentTarget: T;
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
// Types for compiled templates
|
||||
declare module 'vault/templates/*' {
|
||||
import { TemplateFactory } from 'ember-cli-htmlbars';
|
||||
|
||||
const tmpl: TemplateFactory;
|
||||
export default tmpl;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
declare global {
|
||||
// Prevents ESLint from "fixing" this via its auto-fix to turn it into a type
|
||||
// alias (e.g. after running any Ember CLI generator)
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
interface Array<T> extends Ember.ArrayPrototypeExtensions<T> {}
|
||||
// interface Function extends Ember.FunctionPrototypeExtensions {}
|
||||
}
|
||||
|
||||
export {};
|
1032
ui/yarn.lock
1032
ui/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue