diff --git a/addons/api/addon/adapters/role.js b/addons/api/addon/adapters/role.js new file mode 100644 index 000000000..036466645 --- /dev/null +++ b/addons/api/addon/adapters/role.js @@ -0,0 +1,13 @@ +import ApplicationAdapter from './application'; + +export default class RoleAdapter extends ApplicationAdapter { + + // =attributes + + /** + * Roles use the new, unprefixed pathing style. + * @override + */ + hasScopePrefix = false; + +} diff --git a/addons/api/addon/serializers/role.js b/addons/api/addon/serializers/role.js index 89d10353d..5c858bc1f 100644 --- a/addons/api/addon/serializers/role.js +++ b/addons/api/addon/serializers/role.js @@ -3,6 +3,14 @@ import { get } from '@ember/object'; export default class RoleSerializer extends ApplicationSerializer { + // =attributes + + /** + * Serialized the scope ID into the `scope_id` field. + * @type {boolean} + */ + serializeScopeID = true; + // =methods /** diff --git a/addons/api/app/adapters/role.js b/addons/api/app/adapters/role.js new file mode 100644 index 000000000..f12325923 --- /dev/null +++ b/addons/api/app/adapters/role.js @@ -0,0 +1 @@ +export { default } from 'api/adapters/role'; diff --git a/addons/api/tests/unit/adapters/role-test.js b/addons/api/tests/unit/adapters/role-test.js new file mode 100644 index 000000000..3d847ae20 --- /dev/null +++ b/addons/api/tests/unit/adapters/role-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Adapter | role', function(hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function(assert) { + let adapter = this.owner.lookup('adapter:role'); + assert.ok(adapter); + }); +}); diff --git a/addons/api/tests/unit/models/role-test.js b/addons/api/tests/unit/models/role-test.js index 50a0fdb2d..42aefae25 100644 --- a/addons/api/tests/unit/models/role-test.js +++ b/addons/api/tests/unit/models/role-test.js @@ -14,7 +14,7 @@ module('Unit | Model | role', function (hooks) { test('it has a `saveGrants` method that targets a specific POST API endpoint and serialization', async function (assert) { assert.expect(1); - this.server.post('/v1/scopes/o_1/roles/123abc:set-grants', (schema, request) => { + this.server.post('/v1/roles/123abc:set-grants', (schema, request) => { const body = JSON.parse(request.requestBody); assert.deepEqual(body, { grant_strings: ['grant1', 'grant2'], @@ -44,7 +44,7 @@ module('Unit | Model | role', function (hooks) { test('it has an `addPrincipals` method that targets a specific POST API endpoint and serialization', async function (assert) { assert.expect(1); - this.server.post('/v1/scopes/o_1/roles/123abc:add-principals', (schema, request) => { + this.server.post('/v1/roles/123abc:add-principals', (schema, request) => { const body = JSON.parse(request.requestBody); assert.deepEqual(body, { principal_ids: ['123_abc', 'foobar'], @@ -77,7 +77,7 @@ module('Unit | Model | role', function (hooks) { test('it has a `removePrincipals` method that targets a specific POST API endpoint and serialization', async function (assert) { assert.expect(1); - this.server.post('/v1/scopes/o_1/roles/123abc:remove-principals', (schema, request) => { + this.server.post('/v1/roles/123abc:remove-principals', (schema, request) => { const body = JSON.parse(request.requestBody); assert.deepEqual(body, { principal_ids: ['1', '3'], @@ -110,7 +110,7 @@ module('Unit | Model | role', function (hooks) { test('it has a `removePrincipal` method that deletes a single principal using `removePrincipals` method', async function (assert) { assert.expect(1); - this.server.post('/v1/scopes/o_1/roles/123abc:remove-principals', (schema, request) => { + this.server.post('/v1/roles/123abc:remove-principals', (schema, request) => { const body = JSON.parse(request.requestBody); assert.deepEqual(body, { principal_ids: ['3'], diff --git a/ui/core/app/routes/scopes/scope/roles.js b/ui/core/app/routes/scopes/scope/roles.js index b0418e399..00c4fc383 100644 --- a/ui/core/app/routes/scopes/scope/roles.js +++ b/ui/core/app/routes/scopes/scope/roles.js @@ -23,8 +23,8 @@ export default class ScopesScopeRolesRoute extends Route { * @return {Promise{[RoleModel]}} */ async model() { - const { id: scopeID } = this.modelFor('scopes.scope'); - return this.store.findAll('role', { adapterOptions: { scopeID } }); + const { id: scope_id } = this.modelFor('scopes.scope'); + return this.store.query('role', { scope_id }); } // =actions diff --git a/ui/core/mirage/config.js b/ui/core/mirage/config.js index f3d185893..11c78a555 100644 --- a/ui/core/mirage/config.js +++ b/ui/core/mirage/config.js @@ -97,12 +97,14 @@ export default function() { }); // IAM: Roles - this.get('/scopes/:scope_id/roles'); - this.post('/scopes/:scope_id/roles'); - this.get('/scopes/:scope_id/roles/:id'); - this.patch('/scopes/:scope_id/roles/:id'); - this.del('/scopes/:scope_id/roles/:id'); - this.post('/scopes/:scope_id/roles/:idMethod', function ({ roles, users, groups }, { params: { idMethod } }) { + this.get('/roles', ({ roles }, { queryParams: { scope_id: scopeId } }) => { + return roles.where({ scopeId }); + }); + this.post('/roles'); + this.get('/roles/:id'); + this.patch('/roles/:id'); + this.del('/roles/:id'); + this.post('/roles/:idMethod', function ({ roles, users, groups }, { params: { idMethod } }) { const attrs = this.normalizedRequestAttrs(); const id = idMethod.split(':')[0]; const method = idMethod.split(':')[1]; diff --git a/ui/core/mirage/factories/group.js b/ui/core/mirage/factories/group.js index e52d8bb82..9531de4f8 100644 --- a/ui/core/mirage/factories/group.js +++ b/ui/core/mirage/factories/group.js @@ -11,8 +11,7 @@ export default factory.extend({ withMembers: trait({ afterCreate(group, server) { const scope = group.scope; - const scopePojo = { id: scope.id, type: scope.type }; - const members = server.createList('user', 2, { scope: scopePojo }); + const members = server.createList('user', 2, { scope }); group.update({ members }); } }) diff --git a/ui/core/mirage/factories/role.js b/ui/core/mirage/factories/role.js index adebbbc12..ea5734835 100644 --- a/ui/core/mirage/factories/role.js +++ b/ui/core/mirage/factories/role.js @@ -14,8 +14,9 @@ export default factory.extend({ */ withPrincipals: trait({ afterCreate(role, server) { - const users = server.createList('user', 2); - const groups = server.createList('group', 2); + const { scope } = role; + const users = server.createList('user', 2, { scope }); + const groups = server.createList('group', 2, { scope }); role.update({ users, groups }); } }) diff --git a/ui/core/mirage/models/role.js b/ui/core/mirage/models/role.js index 6c2517f3b..744d1025a 100644 --- a/ui/core/mirage/models/role.js +++ b/ui/core/mirage/models/role.js @@ -1,7 +1,8 @@ -import { Model, hasMany } from 'ember-cli-mirage'; +import { Model, belongsTo, hasMany } from 'ember-cli-mirage'; export default Model.extend({ + scope: belongsTo(), users: hasMany(), groups: hasMany() diff --git a/ui/core/mirage/scenarios/default.js b/ui/core/mirage/scenarios/default.js index b42e7ca5f..c878699ef 100644 --- a/ui/core/mirage/scenarios/default.js +++ b/ui/core/mirage/scenarios/default.js @@ -12,7 +12,6 @@ export default function(server) { type: 'org', scope: { id: globalScope.id, type: globalScope.type } }, 'withChildren')[0]; - const scopePojo = { id: orgScope.id, type: orgScope.type }; // Auth server.createList('auth-method', 3, { scope: globalScope }); @@ -21,7 +20,7 @@ export default function(server) { // Groups and Users server.createList('group', 5, { scope: orgScope }, 'withMembers'); // Role - server.createList('role', 5, { scope: scopePojo }, 'withPrincipals'); + server.createList('role', 5, { scope: orgScope }, 'withPrincipals'); // Other resources server.schema.scopes.where({type: 'project'}).models.forEach(scope => { diff --git a/ui/core/mirage/serializers/role.js b/ui/core/mirage/serializers/role.js index 56f3d0195..47623471d 100644 --- a/ui/core/mirage/serializers/role.js +++ b/ui/core/mirage/serializers/role.js @@ -1,24 +1,35 @@ import ApplicationSerializer from './application'; +import { underscore } from '@ember/string'; export default ApplicationSerializer.extend({ modelName: 'role', + keyForRelationshipId(relationshipName) { + return `${this._container.inflector.singularize( + underscore(relationshipName) + )}_id`; + }, + _hashForModel(model) { const json = ApplicationSerializer.prototype._hashForModel.apply(this, arguments); - + const serializedUsers = model.users.models.map(user => ({ scope_id: model.scope.id, id: user.id, type: 'user' })); - const serializedGroups = model.groups.models.map(group => ({ scope_id: model.scope.id, id: group.id, type: 'group' })); - json.principals = [ ...serializedUsers, ...serializedGroups ]; + + json.scope = { + id: model.scope.id, + type: model.scope.type + }; + return json; } }); diff --git a/ui/core/tests/acceptance/bread-crumbs-test.js b/ui/core/tests/acceptance/bread-crumbs-test.js index 32382e582..9400e9dbe 100644 --- a/ui/core/tests/acceptance/bread-crumbs-test.js +++ b/ui/core/tests/acceptance/bread-crumbs-test.js @@ -43,7 +43,7 @@ module('Acceptance | breadcrumbs', function (hooks) { project = getProjectScope(); user = this.server.create('user', { scope: orgScope }); - role = this.server.create('role'); + role = this.server.create('role', { scope: orgScope }); group = this.server.create('group', { scope: orgScope }); hostCatalog = this.server.create('host-catalog', { scope: { diff --git a/ui/core/tests/acceptance/roles-test.js b/ui/core/tests/acceptance/roles-test.js index 07f55d080..e1b1b3538 100644 --- a/ui/core/tests/acceptance/roles-test.js +++ b/ui/core/tests/acceptance/roles-test.js @@ -30,10 +30,7 @@ module('Acceptance | roles', function (hooks) { ); const role = this.server.create('role', { - scope: { - id: orgScope.id, - type: orgScope.type, - }, + scope: orgScope }); rolesURL = `/scopes/${orgScope.id}/roles`; @@ -78,7 +75,7 @@ module('Acceptance | roles', function (hooks) { test('saving a new role with invalid fields displays error messages', async function (assert) { assert.expect(2); - this.server.post('/scopes/:scope_id/roles', () => { + this.server.post('/roles', () => { return new Response( 400, {}, @@ -139,7 +136,7 @@ module('Acceptance | roles', function (hooks) { test('saving an existing role with invalid fields displays error messages', async function (assert) { assert.expect(2); - this.server.patch('/scopes/:scope_id/roles/:id', () => { + this.server.patch('/roles/:id', () => { return new Response( 400, {}, @@ -175,7 +172,7 @@ module('Acceptance | roles', function (hooks) { test('errors are displayed when save project fails', async function (assert) { assert.expect(1); - this.server.patch('/scopes/:scope_id/roles/:id', () => { + this.server.patch('/roles/:id', () => { return new Response( 490, {}, @@ -198,7 +195,7 @@ module('Acceptance | roles', function (hooks) { test('errors are displayed when delete project fails', async function (assert) { assert.expect(1); - this.server.del('/scopes/:scope_id/roles/:id', () => { + this.server.del('/roles/:id', () => { return new Response( 490, {},