diff --git a/ui-v2/app/adapters/role.js b/ui-v2/app/adapters/role.js index 81128125927f..84f6d39330b7 100644 --- a/ui-v2/app/adapters/role.js +++ b/ui-v2/app/adapters/role.js @@ -1,72 +1,39 @@ -import Adapter, { - REQUEST_CREATE, - REQUEST_UPDATE, - DATACENTER_QUERY_PARAM as API_DATACENTER_KEY, -} from './application'; +import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application'; -import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/role'; +import { SLUG_KEY } from 'consul-ui/models/role'; import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc'; -import { OK as HTTP_OK } from 'consul-ui/utils/http/status'; -import { PUT as HTTP_PUT } from 'consul-ui/utils/http/method'; -import WithPolicies from 'consul-ui/mixins/policy/as-many'; +export default Adapter.extend({ + requestForQuery: function(request, { dc, index, id }) { + return request` + GET /v1/acl/roles?${{ dc }} -export default Adapter.extend(WithPolicies, { - urlForQuery: function(query, modelName) { - return this.appendURL('acl/roles', [], this.cleanQuery(query)); + ${{ index }} + `; }, - urlForQueryRecord: function(query, modelName) { - if (typeof query.id === 'undefined') { + requestForQueryRecord: function(request, { dc, index, id }) { + if (typeof id === 'undefined') { throw new Error('You must specify an id'); } - return this.appendURL('acl/role', [query.id], this.cleanQuery(query)); - }, - urlForCreateRecord: function(modelName, snapshot) { - return this.appendURL('acl/role', [], { - [API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY), - }); - }, - urlForUpdateRecord: function(id, modelName, snapshot) { - return this.appendURL('acl/role', [snapshot.attr(SLUG_KEY)], { - [API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY), - }); - }, - urlForDeleteRecord: function(id, modelName, snapshot) { - return this.appendURL('acl/role', [snapshot.attr(SLUG_KEY)], { - [API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY), - }); - }, - handleResponse: function(status, headers, payload, requestData) { - let response = payload; - if (status === HTTP_OK) { - const url = this.parseURL(requestData.url); - switch (true) { - case response === true: - response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY); - break; - case Array.isArray(response): - response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY); - break; - default: - response = this.handleSingleResponse(url, response, PRIMARY_KEY, SLUG_KEY); - } - } - return this._super(status, headers, response, requestData); - }, - methodForRequest: function(params) { - switch (params.requestType) { - case REQUEST_CREATE: - return HTTP_PUT; - } - return this._super(...arguments); - }, - dataForRequest: function(params) { - const data = this._super(...arguments); - switch (params.requestType) { - case REQUEST_UPDATE: - case REQUEST_CREATE: - return data.role; - } - return data; + return request` + GET /v1/acl/role/${id}?${{ dc }} + + ${{ index }} + `; + }, + requestForCreateRecord: function(request, data) { + return request` + PUT /v1/acl/role?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }} + `; + }, + requestForUpdateRecord: function(request, data) { + return request` + PUT /v1/acl/role/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }} + `; + }, + requestForDeleteRecord: function(request, data) { + return request` + DELETE /v1/acl/role/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }} + `; }, }); diff --git a/ui-v2/app/adapters/session.js b/ui-v2/app/adapters/session.js index e1aa6b17518f..f178fa877b48 100644 --- a/ui-v2/app/adapters/session.js +++ b/ui-v2/app/adapters/session.js @@ -28,8 +28,4 @@ export default Adapter.extend({ PUT /v1/session/destroy/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }} `; }, - // - respondForQueryRecord: function(respond, query) { - return this._super(cb => respond((headers, body) => cb(headers, body[0])), query); - }, }); diff --git a/ui-v2/app/adapters/token.js b/ui-v2/app/adapters/token.js index 4b1816293b0c..ca615cd88728 100644 --- a/ui-v2/app/adapters/token.js +++ b/ui-v2/app/adapters/token.js @@ -1,15 +1,10 @@ import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application'; import { inject as service } from '@ember/service'; +import { get } from '@ember/object'; import { SLUG_KEY } from 'consul-ui/models/token'; import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc'; -import WithPolicies from 'consul-ui/mixins/policy/as-many'; -import WithRoles from 'consul-ui/mixins/role/as-many'; - -import { get } from '@ember/object'; - - -export default Adapter.extend(WithRoles, WithPolicies, { +export default Adapter.extend({ store: service('store'), requestForQuery: function(request, { dc, index, policy }) { @@ -35,7 +30,7 @@ export default Adapter.extend(WithRoles, WithPolicies, { `; }, requestForUpdateRecord: function(request, data) { - // TODO: Serializer + // TODO: Serializer - Pretty sure this can go now // If a token has Rules, use the old API if (typeof data['Rules'] !== 'undefined') { // TODO: need to clean up vars sent diff --git a/ui-v2/app/mixins/policy/as-many.js b/ui-v2/app/mixins/policy/as-many.js index 37d07a494b62..a7e7eaac9735 100644 --- a/ui-v2/app/mixins/policy/as-many.js +++ b/ui-v2/app/mixins/policy/as-many.js @@ -1,5 +1,3 @@ -import { REQUEST_CREATE, REQUEST_UPDATE } from 'consul-ui/adapters/application'; - import Mixin from '@ember/object/mixin'; import { get } from '@ember/object'; @@ -17,6 +15,8 @@ const normalizeServiceIdentities = function(items) { return policy; }); }; +// Sometimes we get `Policies: null`, make null equal an empty array +// and add an empty template const normalizePolicies = function(items) { return (items || []).map(function(item) { return { @@ -47,24 +47,36 @@ const serializePolicies = function(items) { }; export default Mixin.create({ - handleSingleResponse: function(url, response, primary, slug) { - response.Policies = normalizePolicies(response.Policies).concat( - normalizeServiceIdentities(response.ServiceIdentities) - ); - return this._super(url, response, primary, slug); + //TODO: what about update and create? + respondForQueryRecord: function(respond, query) { + return this._super(function(cb) { + return respond((headers, body) => { + body.Policies = normalizePolicies(body.Policies).concat( + normalizeServiceIdentities(body.ServiceIdentities) + ); + return cb(headers, body); + }); + }, query); + }, + respondForQuery: function(respond, query) { + return this._super(function(cb) { + return respond(function(headers, body) { + return cb( + headers, + body.map(function(item) { + item.Policies = normalizePolicies(item.Policies).concat( + normalizeServiceIdentities(item.ServiceIdentities) + ); + return item; + }) + ); + }); + }, query); }, - dataForRequest: function(params) { + serialize: function(snapshot, options) { const data = this._super(...arguments); - const name = params.type.modelName; - switch (params.requestType) { - case REQUEST_UPDATE: - // falls through - case REQUEST_CREATE: - // ServiceIdentities serialization must happen first, or a copy taken - data[name].ServiceIdentities = serializeServiceIdentities(data[name].Policies); - data[name].Policies = minimizeModel(serializePolicies(data[name].Policies)); - break; - } + data.ServiceIdentities = serializeServiceIdentities(data.Policies); + data.Policies = minimizeModel(serializePolicies(data.Policies)); return data; }, }); diff --git a/ui-v2/app/mixins/role/as-many.js b/ui-v2/app/mixins/role/as-many.js index 8fce74eb4180..b2e77f143a15 100644 --- a/ui-v2/app/mixins/role/as-many.js +++ b/ui-v2/app/mixins/role/as-many.js @@ -1,28 +1,33 @@ -import { REQUEST_CREATE, REQUEST_UPDATE } from 'consul-ui/adapters/application'; - import Mixin from '@ember/object/mixin'; import minimizeModel from 'consul-ui/utils/minimizeModel'; export default Mixin.create({ - handleSingleResponse: function(url, response, primary, slug) { - ['Roles'].forEach(function(prop) { - if (typeof response[prop] === 'undefined' || response[prop] === null) { - response[prop] = []; - } - }); - return this._super(url, response, primary, slug); + // TODO: what about update and create? + respondForQueryRecord: function(respond, query) { + return this._super(function(cb) { + return respond((headers, body) => { + body.Roles = typeof body.Roles === 'undefined' || body.Roles === null ? [] : body.Roles; + return cb(headers, body); + }); + }, query); + }, + respondForQuery: function(respond, query) { + return this._super(function(cb) { + return respond(function(headers, body) { + return cb( + headers, + body.map(function(item) { + item.Roles = typeof item.Roles === 'undefined' || item.Roles === null ? [] : item.Roles; + return item; + }) + ); + }); + }, query); }, - dataForRequest: function(params) { - const name = params.type.modelName; + serialize: function(snapshot, options) { const data = this._super(...arguments); - switch (params.requestType) { - case REQUEST_UPDATE: - // falls through - case REQUEST_CREATE: - data[name].Roles = minimizeModel(data[name].Roles); - break; - } + data.Roles = minimizeModel(data.Roles); return data; }, }); diff --git a/ui-v2/app/serializers/role.js b/ui-v2/app/serializers/role.js index 4a43dd24f77b..7f0382599a1c 100644 --- a/ui-v2/app/serializers/role.js +++ b/ui-v2/app/serializers/role.js @@ -1,5 +1,7 @@ import Serializer from './application'; -import { PRIMARY_KEY } from 'consul-ui/models/role'; -export default Serializer.extend({ +import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/role'; +import WithPolicies from 'consul-ui/mixins/policy/as-many'; +export default Serializer.extend(WithPolicies, { primaryKey: PRIMARY_KEY, + slugKey: SLUG_KEY, }); diff --git a/ui-v2/app/serializers/token.js b/ui-v2/app/serializers/token.js index ce39e4ff6687..ef48aa072b76 100644 --- a/ui-v2/app/serializers/token.js +++ b/ui-v2/app/serializers/token.js @@ -2,7 +2,10 @@ import Serializer from './application'; import { get } from '@ember/object'; import { PRIMARY_KEY, SLUG_KEY, ATTRS } from 'consul-ui/models/token'; -export default Serializer.extend({ +import WithPolicies from 'consul-ui/mixins/policy/as-many'; +import WithRoles from 'consul-ui/mixins/role/as-many'; + +export default Serializer.extend(WithPolicies, WithRoles, { primaryKey: PRIMARY_KEY, slugKey: SLUG_KEY, attrs: ATTRS, @@ -15,20 +18,6 @@ export default Serializer.extend({ data['ID'] = data['SecretID']; data['Name'] = data['Description']; } - - if (Array.isArray(data.Policies)) { - data.Policies = data.Policies.filter(function(item) { - // Just incase, don't save any policies that aren't saved - return !get(item, 'isNew'); - }).map(function(item) { - return { - ID: get(item, 'ID'), - Name: get(item, 'Name'), - }; - }); - } else { - delete data.Policies; - } // make sure we never send the SecretID if (data && typeof data['SecretID'] !== 'undefined') { delete data['SecretID']; @@ -58,17 +47,4 @@ export default Serializer.extend({ query ); }, - respondForQueryRecord: function(respond, query) { - return this._super( - cb => - respond((headers, body) => { - // Sometimes we get `Policies: null`, make null equal an empty array - if (typeof body.Policies === 'undefined' || body.Policies === null) { - body.Policies = []; - } - return cb(headers, body); - }), - query - ); - }, }); diff --git a/ui-v2/tests/acceptance/deleting.feature b/ui-v2/tests/acceptance/deleting.feature index 31f4a83f47e6..894e78f6eac5 100644 --- a/ui-v2/tests/acceptance/deleting.feature +++ b/ui-v2/tests/acceptance/deleting.feature @@ -56,7 +56,6 @@ Feature: deleting: Deleting items with confirmations, success and error notifica | kv | DELETE | /v1/kv/key-name?dc=datacenter | kv: key-name | | intention | DELETE | /v1/connect/intentions/ee52203d-989f-4f7a-ab5a-2bef004164ca?dc=datacenter | intention: ee52203d-989f-4f7a-ab5a-2bef004164ca | | token | DELETE | /v1/acl/token/001fda31-194e-4ff1-a5ec-589abf2cafd0?dc=datacenter | token: 001fda31-194e-4ff1-a5ec-589abf2cafd0 | - | policy | DELETE | /v1/acl/policy/1981f51d-301a-497b-89a0-05112ef02b4b?dc=datacenter | policy: 1981f51d-301a-497b-89a0-05112ef02b4b | ---------------------------------------------------------------------------------------------------------------------------------------------------- @ignore Scenario: Sort out the wide tables ^ diff --git a/ui-v2/tests/integration/adapters/role/response-test.js b/ui-v2/tests/integration/adapters/role/response-test.js index 5ffde9999024..7b20b89fc328 100644 --- a/ui-v2/tests/integration/adapters/role/response-test.js +++ b/ui-v2/tests/integration/adapters/role/response-test.js @@ -8,8 +8,8 @@ module('Integration | Adapter | role | response', function(hooks) { setupTest(hooks); const dc = 'dc-1'; const id = 'role-name'; - test('handleResponse returns the correct data for list endpoint', function(assert) { - const adapter = this.owner.lookup('adapter:role'); + test('respondForQuery returns the correct data for list endpoint', function(assert) { + const serializer = this.owner.lookup('serializer:role'); const request = { url: `/v1/acl/roles?dc=${dc}`, }; @@ -17,27 +17,45 @@ module('Integration | Adapter | role | response', function(hooks) { const expected = payload.map(item => Object.assign({}, item, { Datacenter: dc, - uid: `["${dc}","${item.ID}"]`, Policies: createPolicies(item), + uid: `["${dc}","${item.ID}"]`, }) ); - const actual = adapter.handleResponse(200, {}, payload, request); + const actual = serializer.respondForQuery( + function(cb) { + const headers = {}; + const body = payload; + return cb(headers, body); + }, + { + dc: dc, + } + ); assert.deepEqual(actual, expected); }); }); - test('handleResponse returns the correct data for item endpoint', function(assert) { - const adapter = this.owner.lookup('adapter:role'); + test('respondForQueryRecord returns the correct data for item endpoint', function(assert) { + const serializer = this.owner.lookup('serializer:role'); const request = { url: `/v1/acl/role/${id}?dc=${dc}`, }; return get(request.url).then(function(payload) { const expected = Object.assign({}, payload, { Datacenter: dc, + Policies: createPolicies(payload), [META]: {}, uid: `["${dc}","${id}"]`, - Policies: createPolicies(payload), }); - const actual = adapter.handleResponse(200, {}, payload, request); + const actual = serializer.respondForQueryRecord( + function(cb) { + const headers = {}; + const body = payload; + return cb(headers, body); + }, + { + dc: dc, + } + ); assert.deepEqual(actual, expected); }); }); diff --git a/ui-v2/tests/integration/adapters/role/url-test.js b/ui-v2/tests/integration/adapters/role/url-test.js index 3b3bae452d5f..e7dab419e33e 100644 --- a/ui-v2/tests/integration/adapters/role/url-test.js +++ b/ui-v2/tests/integration/adapters/role/url-test.js @@ -1,70 +1,70 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -import makeAttrable from 'consul-ui/utils/makeAttrable'; module('Integration | Adapter | role | url', function(hooks) { setupTest(hooks); const dc = 'dc-1'; const id = 'role-name'; - test('urlForQuery returns the correct url', function(assert) { + test('requestForQuery returns the correct url', function(assert) { const adapter = this.owner.lookup('adapter:role'); - const expected = `/v1/acl/roles?dc=${dc}`; - const actual = adapter.urlForQuery({ + const client = this.owner.lookup('service:client/http'); + const expected = `GET /v1/acl/roles?dc=${dc}`; + const actual = adapter.requestForQuery(client.url, { dc: dc, }); assert.equal(actual, expected); }); - test('urlForQueryRecord returns the correct url', function(assert) { + test('requestForQueryRecord returns the correct url', function(assert) { const adapter = this.owner.lookup('adapter:role'); - const expected = `/v1/acl/role/${id}?dc=${dc}`; - const actual = adapter.urlForQueryRecord({ + const client = this.owner.lookup('service:client/http'); + const expected = `GET /v1/acl/role/${id}?dc=${dc}`; + const actual = adapter.requestForQueryRecord(client.url, { dc: dc, id: id, }); assert.equal(actual, expected); }); - test("urlForQueryRecord throws if you don't specify an id", function(assert) { + test("requestForQueryRecord throws if you don't specify an id", function(assert) { const adapter = this.owner.lookup('adapter:role'); + const client = this.owner.lookup('service:client/http'); assert.throws(function() { - adapter.urlForQueryRecord({ + adapter.requestForQueryRecord(client.url, { dc: dc, }); }); }); - test('urlForCreateRecord returns the correct url', function(assert) { + test('requestForCreateRecord returns the correct url', function(assert) { const adapter = this.owner.lookup('adapter:role'); - const expected = `/v1/acl/role?dc=${dc}`; - const actual = adapter.urlForCreateRecord( - 'role', - makeAttrable({ + const client = this.owner.lookup('service:client/http'); + const expected = `PUT /v1/acl/role?dc=${dc}`; + const actual = adapter + .requestForCreateRecord(client.url, { Datacenter: dc, }) - ); + .split('\n')[0]; assert.equal(actual, expected); }); - test('urlForUpdateRecord returns the correct url', function(assert) { + test('requestForUpdateRecord returns the correct url', function(assert) { const adapter = this.owner.lookup('adapter:role'); - const expected = `/v1/acl/role/${id}?dc=${dc}`; - const actual = adapter.urlForUpdateRecord( - id, - 'role', - makeAttrable({ + const client = this.owner.lookup('service:client/http'); + const expected = `PUT /v1/acl/role/${id}?dc=${dc}`; + const actual = adapter + .requestForUpdateRecord(client.url, { Datacenter: dc, ID: id, }) - ); + .split('\n')[0]; assert.equal(actual, expected); }); - test('urlForDeleteRecord returns the correct url', function(assert) { + test('requestForDeleteRecord returns the correct url', function(assert) { const adapter = this.owner.lookup('adapter:role'); - const expected = `/v1/acl/role/${id}?dc=${dc}`; - const actual = adapter.urlForDeleteRecord( - id, - 'role', - makeAttrable({ + const client = this.owner.lookup('service:client/http'); + const expected = `DELETE /v1/acl/role/${id}?dc=${dc}`; + const actual = adapter + .requestForDeleteRecord(client.url, { Datacenter: dc, ID: id, }) - ); + .split('\n')[0]; assert.equal(actual, expected); }); });