fix: 🐛 Fix generic-vault getting extra null fields when saving (#1640)

* fix: 🐛 Fix generic-vault getting extra null fields when saving

✅ Closes: ICU-8141
This commit is contained in:
Zhihe Li authored and GitHub committed 2023-02-24 13:11:17 -05:00
1 parent 7816772ef2
commit a8bbf91a0a
3 files changed
+72 -41

No files matched your search

@@ -48,6 +48,7 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
//= attributes (vault) //= attributes (vault)
@attr('string', { @attr('string', {
for: 'vault-generic',
isNestedAttribute: true, isNestedAttribute: true,
description: description:
'The HTTP method the library uses when requesting credentials from Vault.', 'The HTTP method the library uses when requesting credentials from Vault.',
@@ -56,6 +57,7 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
http_method; http_method;
@attr('string', { @attr('string', {
for: 'vault-generic',
isNestedAttribute: true, isNestedAttribute: true,
description: description:
'The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.', 'The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.',
@@ -69,18 +71,21 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
path; path;
@attr('string', { @attr('string', {
for: 'vault-ssh-certificate',
isNestedAttribute: true, isNestedAttribute: true,
description: 'The username to use when making an SSH connection.', description: 'The username to use when making an SSH connection.',
}) })
username; username;
@attr('string', { @attr('string', {
for: 'vault-ssh-certificate',
isNestedAttribute: true, isNestedAttribute: true,
description: 'The desired key type to use when generating a private key.', description: 'The desired key type to use when generating a private key.',
}) })
key_type; key_type;
@attr('number', { @attr('number', {
for: 'vault-ssh-certificate',
isNestedAttribute: true, isNestedAttribute: true,
description: description:
'Specifies the number of bits used when generating the private key. Not used if key type is ed25519', 'Specifies the number of bits used when generating the private key. Not used if key type is ed25519',
@@ -88,12 +93,14 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
key_bits; key_bits;
@attr('string', { @attr('string', {
for: 'vault-ssh-certificate',
isNestedAttribute: true, isNestedAttribute: true,
description: 'Specifies the requested time to live for the certificate.', description: 'Specifies the requested time to live for the certificate.',
}) })
ttl; ttl;
@attr('string', { @attr('string', {
for: 'vault-ssh-certificate',
isNestedAttribute: true, isNestedAttribute: true,
description: description:
'Specifies the key id that the created certificate should have.', 'Specifies the key id that the created certificate should have.',
@@ -101,6 +108,7 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
key_id; key_id;
@attr('object-as-array', { @attr('object-as-array', {
for: 'vault-ssh-certificate',
isNestedAttribute: true, isNestedAttribute: true,
description: description:
'Specifies a map of the critical options that the certificate should be signed for.', 'Specifies a map of the critical options that the certificate should be signed for.',
@@ -108,6 +116,7 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
critical_options; critical_options;
@attr('object-as-array', { @attr('object-as-array', {
for: 'vault-ssh-certificate',
isNestedAttribute: true, isNestedAttribute: true,
description: description:
'Specifies a map of the extensions that the certificate should be signed for.', 'Specifies a map of the extensions that the certificate should be signed for.',
@@ -1,5 +1,8 @@
import ApplicationSerializer from './application'; import ApplicationSerializer from './application';
import { TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC } from '../models/credential-library'; import {
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
} from '../models/credential-library';
export default class CredentialLibrarySerializer extends ApplicationSerializer { export default class CredentialLibrarySerializer extends ApplicationSerializer {
// =properties // =properties
@@ -14,16 +17,41 @@ export default class CredentialLibrarySerializer extends ApplicationSerializer {
* @method serialize * @method serialize
* @param {Snapshot} snapshot * @param {Snapshot} snapshot
*/ */
serialize() { serialize(snapshot) {
switch (snapshot.record.type) {
case TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC:
return this.serializeVaultGeneric(...arguments);
case TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE:
default:
return super.serialize(...arguments);
}
}
serializeAttribute(snapshot, json, key, attribute) {
super.serializeAttribute(...arguments);
const { options } = attribute;
const { type } = snapshot.record;
// If an attribute has a `for` option, it must match the
// record's `type`, else the attribute is excluded
// from serialization.
if (options?.for && options.for !== type) {
if (options.isNestedAttribute) {
delete json.attributes[key];
} else {
delete json[key];
}
}
}
serializeVaultGeneric() {
const serialized = super.serialize(...arguments); const serialized = super.serialize(...arguments);
if (serialized.attributes) { if (serialized.attributes) {
if (serialized.type !== TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC) { // Set `http_request_body` only if `http_method` is POST
delete serialized.attributes.http_method; // otherwise set to null to have the field removed
if (!serialized.attributes?.http_method?.match(/post/i)) {
serialized.attributes.http_request_body = null;
} }
// Serialize `http_request_body` only if `http_method` is POST
if (!serialized.attributes?.http_method?.match(/post/i))
delete serialized.attributes.http_request_body;
} }
return serialized; return serialized;
} }
@@ -31,13 +31,7 @@ module('Unit | Serializer | credential library', function (hooks) {
attributes: { attributes: {
path: '/vault/path', path: '/vault/path',
http_method: 'GET', http_method: 'GET',
critical_options: null, http_request_body: null,
extensions: null,
key_bits: null,
key_id: null,
key_type: null,
ttl: null,
username: null,
}, },
}); });
}); });
@@ -71,41 +65,54 @@ module('Unit | Serializer | credential library', function (hooks) {
attributes: { attributes: {
path: '/vault/path', path: '/vault/path',
http_method: 'GET', http_method: 'GET',
critical_options: null, http_request_body: null,
extensions: null,
key_bits: null,
key_id: null,
key_type: null,
ttl: null,
username: null,
}, },
version: 1, version: 1,
}); });
}); });
test('it serializes empty strings to null', function (assert) { test('it serializes empty strings to null', function (assert) {
assert.expect(1); assert.expect(2);
const store = this.owner.lookup('service:store'); const store = this.owner.lookup('service:store');
const record = store.createRecord('credential-library', { const vaultGenericRecord = store.createRecord('credential-library', {
type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
http_method: '', http_method: '',
path: null, path: null,
}); });
let serializedRecord = record.serialize(); const vaultSSHCertificateRecord = store.createRecord('credential-library', {
assert.deepEqual(serializedRecord, { type: TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
http_method: '',
path: null,
});
let serializedVaultGenericRecord = vaultGenericRecord.serialize();
let serializedVaultSSHCertificateRecord =
vaultSSHCertificateRecord.serialize();
assert.deepEqual(serializedVaultGenericRecord, {
attributes: { attributes: {
path: null, path: null,
http_method: null,
http_request_body: null,
},
credential_store_id: null,
description: null,
name: null,
type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
});
assert.deepEqual(serializedVaultSSHCertificateRecord, {
attributes: {
critical_options: null, critical_options: null,
extensions: null, extensions: null,
key_bits: null, key_bits: null,
key_id: null, key_id: null,
key_type: null, key_type: null,
path: null,
ttl: null, ttl: null,
username: null, username: null,
}, },
credential_store_id: null, credential_store_id: null,
description: null, description: null,
name: null, name: null,
type: null, type: TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
}); });
}); });
@@ -123,14 +130,8 @@ module('Unit | Serializer | credential library', function (hooks) {
{ {
attributes: { attributes: {
http_method: 'GET', http_method: 'GET',
http_request_body: null,
path: null, path: null,
critical_options: null,
extensions: null,
key_bits: null,
key_id: null,
key_type: null,
ttl: null,
username: null,
}, },
credential_store_id: null, credential_store_id: null,
description: null, description: null,
@@ -149,13 +150,6 @@ module('Unit | Serializer | credential library', function (hooks) {
http_method: 'POST', http_method: 'POST',
http_request_body: 'body', http_request_body: 'body',
path: null, path: null,
critical_options: null,
extensions: null,
key_bits: null,
key_id: null,
key_type: null,
ttl: null,
username: null,
}, },
credential_store_id: null, credential_store_id: null,
description: null, description: null,