Icu 6794 refactor attributes using the newer is nested attribute annotation (#1481)

This commit is contained in:
Zhihe Li authored and GitHub committed 2022-11-23 14:40:07 -05:00
1 parent ff6e2bb4cf
commit ff7a1fedea
15 files changed
+325 -259

No files matched your search

@@ -49,4 +49,26 @@ export default class GeneratedAuthMethodModel extends BaseModel {
description: 'Current version number of this resource.',
})
version;
@attr('string', { readOnly: true, isNestedAttribute: true }) state;
@attr('string', { isNestedAttribute: true }) issuer;
@attr('string', { isNestedAttribute: true }) client_id;
@attr('string', { isNestedAttribute: true }) client_secret;
@attr('string', { readOnly: true, isNestedAttribute: true })
client_secret_hmac;
@attr('number', { isNestedAttribute: true }) max_age;
@attr('string', { isNestedAttribute: true }) api_url_prefix;
@attr('string', { readOnly: true, isNestedAttribute: true }) callback_url;
@attr('boolean', { isNestedAttribute: true })
disable_discovered_config_validation;
@attr('boolean', { isNestedAttribute: true }) dry_run;
}
+33 -30
View File
@@ -1,6 +1,5 @@
import GeneratedAuthMethodModel from '../generated/models/auth-method';
import { attr } from '@ember-data/model';
import { fragment } from 'ember-data-model-fragments/attributes';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
import { equal } from '@ember/object/computed';
/**
@@ -28,33 +27,37 @@ export const options = {
};
export default class AuthMethodModel extends GeneratedAuthMethodModel {
// =error attributes
// These attributes exist solely to capture errors on nested fields.
// See the application adapter's error normalization method for
// more information.
@attr('string', { readOnly: true }) attributes_state;
@attr('string', { readOnly: true }) attributes_issuer;
@attr('string', { readOnly: true }) attributes_client_id;
@attr('string', { readOnly: true }) attributes_client_secret;
@attr('string', { readOnly: true }) attributes_max_age;
@attr('string', { readOnly: true }) attributes_api_url_prefix;
@attr('string', { readOnly: true })
attributes_disable_discovered_config_validation;
@attr('string', { readOnly: true }) attributes_dry_run;
@attr('string', { readOnly: true }) attributes_account_claim_maps;
@attr('string', { readOnly: true }) attributes_claims_scopes;
@attr('string', { readOnly: true }) attributes_signing_algorithms;
@attr('string', { readOnly: true }) attributes_allowed_audiences;
@attr('string', { readOnly: true }) attributes_idp_ca_certs;
// =attributes
/**
* Attributes of this resource, if any, represented as a JSON fragment.
* @type {FragmentAuthMethodAttributesModel}
*/
@fragment('fragment-auth-method-attributes', { defaultValue: {} }) attributes;
@fragmentArray('fragment-auth-method-attributes-account-claim-map', {
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
account_claim_maps;
@fragmentArray('fragment-string', {
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
claims_scopes;
@fragmentArray('fragment-string', {
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
signing_algorithms;
@fragmentArray('fragment-string', {
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
allowed_audiences;
@fragmentArray('fragment-string', {
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
idp_ca_certs;
/**
* @type {boolean}
@@ -81,21 +84,21 @@ export default class AuthMethodModel extends GeneratedAuthMethodModel {
* @type {boolean}
*/
get isInactive() {
return this.attributes.state === 'inactive';
return this.state === 'inactive';
}
/**
* @type {boolean}
*/
get isPrivate() {
return this.attributes.state === 'active-private';
return this.state === 'active-private';
}
/**
* @type {boolean}
*/
get isPublic() {
return this.attributes.state === 'active-public';
return this.state === 'active-public';
}
// =methods
@@ -1,40 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
export default class FragmentAuthMethodAttributesModel extends Fragment {
// =attributes (OIDC)
@attr('string', { readOnly: true }) state;
@attr('string') issuer;
@attr('string') client_id;
@attr('string') client_secret;
@attr('string', { readOnly: true }) client_secret_hmac;
@attr('number') max_age;
@attr('string') api_url_prefix;
@attr('string', { readOnly: true }) callback_url;
@attr('boolean') disable_discovered_config_validation;
@attr('boolean') dry_run;
@fragmentArray('fragment-auth-method-attributes-account-claim-map', {
emptyArrayIfMissing: true,
})
account_claim_maps;
@fragmentArray('fragment-string', {
emptyArrayIfMissing: true,
})
claims_scopes;
@fragmentArray('fragment-string', {
emptyArrayIfMissing: true,
})
signing_algorithms;
@fragmentArray('fragment-string', {
emptyArrayIfMissing: true,
})
allowed_audiences;
@fragmentArray('fragment-string', { emptyArrayIfMissing: true }) idp_ca_certs;
}
@@ -1,26 +0,0 @@
import JSONSerializer from '@ember-data/serializer/json';
export default class FragmentAuthMethodAttributesSerializer extends JSONSerializer {
/**
* If an attribute is annotated as readOnly in the model, don't serialize it.
* Otherwise delegate to default attribute serializer.
*
* @override
* @method serializeAttribute
* @param {Snapshot} snapshot
* @param {Object} json
* @param {String} key
* @param {Object} attribute
*/
serializeAttribute(snapshot, json, key, attribute) {
const { type, options } = attribute;
let value = super.serializeAttribute(...arguments);
// Convert empty strings to null.
if (type === 'string' && json[key] === '') json[key] = null;
// Do not serialize read-only attributes.
if (options.readOnly) delete json[key];
// Client secret cannot be unset. If it's falsy, it must be removed.
if (key === 'client_secret' && !json[key]) delete json[key];
return value;
}
}
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-auth-method-attributes';
@@ -1 +0,0 @@
export { default } from 'api/serializers/fragment-auth-method-attributes';
@@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Model | fragment auth method attributes', function (hooks) {
setupTest(hooks);
test('it exists', function (assert) {
let store = this.owner.lookup('service:store');
let model = store.createRecord('fragment-auth-method-attributes', {});
assert.ok(model);
});
});
@@ -33,27 +33,25 @@ module('Unit | Serializer | auth method', function (hooks) {
let record = store.createRecord('auth-method', {
type: 'oidc',
name: 'OIDC Auth Method',
attributes: {
state: 'foo',
account_claim_maps: [{ from: 'foo', to: 'bar' }],
claims_scopes: [{ value: 'profile' }, { value: 'email' }],
signing_algorithms: [{ value: 'RS256' }, { value: 'RS384' }],
allowed_audiences: [
{ value: 'www.alice.com' },
{ value: 'www.alice.com/admin' },
],
idp_ca_certs: [
{ value: 'certificate-1234' },
{ value: 'certificate-5678' },
],
api_url_prefix: 'protocol://host:port/foo',
client_id: 'id123',
client_secret: 'secret456',
disable_discovered_config_validation: true,
dry_run: true,
issuer: 'http://www.example.net',
max_age: 500,
},
state: 'foo',
account_claim_maps: [{ from: 'foo', to: 'bar' }],
claims_scopes: [{ value: 'profile' }, { value: 'email' }],
signing_algorithms: [{ value: 'RS256' }, { value: 'RS384' }],
allowed_audiences: [
{ value: 'www.alice.com' },
{ value: 'www.alice.com/admin' },
],
idp_ca_certs: [
{ value: 'certificate-1234' },
{ value: 'certificate-5678' },
],
api_url_prefix: 'protocol://host:port/foo',
client_id: 'id123',
client_secret: 'secret456',
disable_discovered_config_validation: true,
dry_run: true,
issuer: 'http://www.example.net',
max_age: 500,
});
let serializedRecord = record.serialize();
@@ -148,19 +146,56 @@ module('Unit | Serializer | auth method', function (hooks) {
test('it normalizes OIDC records', async function (assert) {
const store = this.owner.lookup('service:store');
const apiUrlPrefix = 'protocol://host:port/foo';
const clientId = 'id123';
const clientSecret = 'secret456';
const disableDiscoveredConfigValidation = true;
const dryRun = true;
const issuer = 'http://www.example.net';
const maxAge = 500;
this.server.get('/v1/auth-methods/oidc123', () => ({
attributes: {
account_claim_maps: ['from=to', 'foo=bar'],
claims_scopes: [{ value: 'profile' }, { value: 'email' }],
signing_algorithms: [{ value: 'RS256' }, { value: 'RS384' }],
allowed_audiences: [
{ value: 'www.alice.com' },
{ value: 'www.alice.com/admin' },
],
idp_ca_certs: [
{ value: 'certificate-1234' },
{ value: 'certificate-5678' },
],
api_url_prefix: apiUrlPrefix,
client_id: clientId,
client_secret: clientSecret,
disable_discovered_config_validation: disableDiscoveredConfigValidation,
dry_run: dryRun,
issuer: issuer,
max_age: maxAge,
},
version: 1,
type: 'oidc',
id: 'oidc123',
}));
const record = await store.findRecord('auth-method', 'oidc123');
const { account_claim_maps } = record.attributes;
const { account_claim_maps } = record;
assert.strictEqual(account_claim_maps.firstObject.from, 'from');
assert.strictEqual(account_claim_maps.firstObject.to, 'to');
assert.strictEqual(account_claim_maps.lastObject.from, 'foo');
assert.strictEqual(account_claim_maps.lastObject.to, 'bar');
assert.strictEqual(record.api_url_prefix, apiUrlPrefix);
assert.strictEqual(record.client_id, clientId);
assert.strictEqual(record.client_secret, clientSecret);
assert.strictEqual(
record.disable_discovered_config_validation,
disableDiscoveredConfigValidation
);
assert.strictEqual(record.dry_run, dryRun);
assert.strictEqual(record.issuer, issuer);
assert.strictEqual(record.max_age, maxAge);
});
});
@@ -1,37 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Serializer | fragment auth method attributes', function (hooks) {
setupTest(hooks);
test('it serializes empty strings to null', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
const record = store.createRecord('user', {
name: '',
description: '',
version: null,
});
let serializedRecord = record.serialize();
assert.deepEqual(serializedRecord, {
name: null,
description: null,
});
});
test('it does not serialize client_secret if present but falsy', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
const record = store.createRecord('user', {
name: '',
description: '',
version: null,
client_secret: false,
});
let serializedRecord = record.serialize();
assert.deepEqual(serializedRecord, {
name: null,
description: null,
});
});
});