Merge branch 'develop' into ICU-580-view-an-account

This commit is contained in:
Randall Morey authored and GitHub committed 2020-09-16 09:06:46 -04:00
commit b1554e96ce
16 files changed
+226 -26

No files matched your search

+24
View File
@@ -9,4 +9,28 @@ export default class AccountModel extends GeneratedAccountModel {
*/
@fragment('fragment-account-attributes', { defaultValue: {} }) attributes;
// =methods
/**
* Save account password via the `set-password` method.
* See serializer and adapter for more information.
* @param {string} password
* @param {object} options
* @param {object} options.adapterOptions
* @return {Promise}
*/
setPassword(password, options={ adapterOptions: {} }) {
const defaultAdapterOptions = {
method: 'set-password',
password
};
return this.save({
...options,
adapterOptions: {
...defaultAdapterOptions,
...options.adapterOptions
}
});
}
}
@@ -7,7 +7,4 @@ export default class FragmentAccountAttributesModel extends Fragment {
description: 'The account login name'
}) login_name;
@attr('string', {
description: 'The account password'
}) password;
}
@@ -0,0 +1,10 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
export default class FragmentTargetAttributesModel extends Fragment {
@attr('number', {
description: 'The default port a target should use if present.'
}) default_port;
}
+7 -1
View File
@@ -1,11 +1,17 @@
import GeneratedTargetModel from '../generated/models/target';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
import { computed } from '@ember/object';
export default class TargetModel extends GeneratedTargetModel {
// =attributes
/**
* Attributes of this resource, if any, represented as a JSON fragment.
* @type {FragmentTargetAttributesModel}
*/
@fragment('fragment-target-attributes', { defaultValue: {} }) attributes;
/**
* @type {[FragmentHostSetModel]}
*/
+39
View File
@@ -0,0 +1,39 @@
import ApplicationSerializer from './application';
export default class AccountSerializer extends ApplicationSerializer {
// =methods
/**
* If `adapterOptions.method` is `set-password`, the serialization should
* include only **password** and the version.
* If `adapterOptions.password` is set, the serialization should
* include **password** in it's `attributes`.
* @override
* @param {Snapshot} snapshot
* @return {object}
*/
serialize(snapshot) {
const password = snapshot?.adapterOptions?.password;
let serialized = super.serialize(...arguments);
if (password && snapshot?.record?.isNew) serialized.attributes.password = password;
if (snapshot?.adapterOptions?.method === 'set-password') {
serialized = this.serializeForSetPassword(snapshot, password);
}
return serialized;
}
/**
* Returns a payload containing only new password.
* @param {Snapshot} snapshot
* @param {string} password
* @return {object}
*/
serializeForSetPassword(snapshot, password) {
return {
version: snapshot.attr('version'),
password,
};
}
}
@@ -0,0 +1 @@
export { default } from 'api/models/fragment-target-attributes';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/serializers/account';
@@ -4,21 +4,10 @@ import { setupTest } from 'ember-qunit';
module('Unit | Model | account', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let store = this.owner.lookup('service:store');
let model = store.createRecord('account', {});
assert.ok(model);
});
test('it contains attributes', function(assert) {
let store = this.owner.lookup('service:store');
let model = store.createRecord('account', {
type: 'password',
attributes: {
login_name: 'loginname'
}
});
assert.equal(model.attributes.login_name, 'loginname');
});
});
@@ -0,0 +1,97 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Serializer | account', function(hooks) {
setupTest(hooks);
test('it serializes normally', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
const serializer = store.serializerFor('account');
const record = store.createRecord('account', {
type: 'password',
name: 'Name',
auth_method_id: '1',
description: 'Description',
attributes: {
login_name: 'Login Name',
},
version: 1
});
const snapshot = record._createSnapshot();
snapshot.adapterOptions = {};
const serializedRecord = serializer.serialize(snapshot);
assert.deepEqual(serializedRecord, {
type: 'password',
name: 'Name',
auth_method_id: '1',
description: 'Description',
attributes: {
login_name: 'Login Name'
},
version: 1
});
});
test('it serializes password attribute when `adapterOptions.password` is true', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
const serializer = store.serializerFor('account');
const record = store.createRecord('account', {
type: 'password',
name: 'Name',
auth_method_id: '1',
description: 'Description',
attributes: {
login_name: 'Login Name',
},
version: 1
});
const snapshot = record._createSnapshot();
snapshot.adapterOptions = {
password: 'Password'
};
const serializedRecord = serializer.serialize(snapshot);
assert.deepEqual(serializedRecord, {
type: 'password',
name: 'Name',
auth_method_id: '1',
description: 'Description',
attributes: {
login_name: 'Login Name',
password: 'Password'
},
version: 1
});
});
test('it does not serialize password for non-new records', function (assert) {
assert.expect(0);
});
test('it serializes only password when `adapterOptions.method` is set to `set-password`', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
const serializer = store.serializerFor('account');
const record = store.createRecord('account', {
type: 'password',
name: 'Name',
description: 'Description',
attributes: {
login_name: 'Login Name'
},
auth_method_id: '1',
version: 1
});
const snapshot = record._createSnapshot();
snapshot.adapterOptions = {
method: 'set-password',
password: 'Password'
};
const serializedRecord = serializer.serialize(snapshot);
assert.deepEqual(serializedRecord, {
password: 'Password',
version: 1
});
});
});
@@ -30,7 +30,10 @@ module('Unit | Serializer | target', function(hooks) {
description: 'Description',
version: 1,
type: 'tcp',
scope_id: 'org_1'
scope_id: 'org_1',
attributes: {
default_port: null
}
});
});
+22 -5
View File
@@ -14,11 +14,10 @@
<form.input
@name="name"
@type="name"
@type="text"
@value={{@model.name}}
@label={{t "form.label.name"}}
@error={{@model.errors.name}}
readonly={{false}}
as |field|>
{{#if @model.errors.name}}
<field.errors as |errors|>
@@ -31,12 +30,10 @@
<form.textarea
@name="description"
@type="description"
@type="text"
@value={{@model.description}}
@label={{t "form.label.description"}}
@error={{@model.errors.description}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|>
{{#if @model.errors.description}}
<field.errors as |errors|>
@@ -47,6 +44,26 @@
{{/if}}
</form.textarea>
{{!-- TODO this is a type-specific field --}}
<form.input
@name="default_port"
@type="number"
@value={{@model.attributes.default_port}}
@label={{t "form.label.default_port"}}
@error={{@model.errors.default_port}}
min="0"
step="1"
as |field|>
{{!-- TODO need to figure out how to reference `attributes.errors` here --}}
{{#if @model.errors.default_port}}
<field.errors as |errors|>
{{#each @model.errors.default_port as |error|}}
<errors.message>{{error.message}}</errors.message>
{{/each}}
</field.errors>
{{/if}}
</form.input>
<form.actions
@disabled={{if @model.cannotSave @model.cannotSave}}
@submitText={{t "actions.save"}}
+3 -2
View File
@@ -63,11 +63,12 @@ export default function() {
const method = idMethod.split(':')[1];
const account = accounts.find(id);
const updatedAttrs = {
version: attrs.version
version: attrs.version,
attributes: account.attributes
};
// Set new password
if (method === 'set-password') {
updatedAttrs.password = accounts.attributes.password;
updatedAttrs.attributes.password = attrs.password;
}
return account.update(updatedAttrs);
});
+14
View File
@@ -1,11 +1,25 @@
import factory from '../generated/factories/target';
import { trait } from 'ember-cli-mirage';
import { random } from 'faker';
const randomBoolean = (chance = 0.5) => Math.random() < chance;
const hostSetChance = 0.3;
export default factory.extend({
/**
* Generates attributes fields by type.
*/
afterCreate(target) {
if (target.type === 'tcp') {
target.update({
attributes: {
default_port: random.number()
}
});
}
},
/**
* Randomly selects existing host sets to assign to target.
*/
+2 -3
View File
@@ -1,8 +1,7 @@
import { Model, belongsTo, hasMany} from 'ember-cli-mirage';
import { Model, belongsTo } from 'ember-cli-mirage';
export default Model.extend({
scope: belongsTo(),
accounts: hasMany('account')
scope: belongsTo()
});
+1
View File
@@ -6,6 +6,7 @@ export default ApplicationSerializer.extend({
_hashForModel(model) {
const json = ApplicationSerializer.prototype._hashForModel.apply(this, arguments);
json.auth_method_id = model.authMethodId;
delete json.attributes?.password;
return json;
}
});
+1
View File
@@ -149,6 +149,7 @@ form:
address: Address
protocol: Protocol
actions: Actions
default_port: Default Port
errors:
titles:
unauthenticated-error: You are not signed in