refactor: 💡 do not scope-prefix paths by default

This commit is contained in:
Randall Morey committed 2020-09-10 19:02:53 -04:00
1 parent ab608c7544
commit 795f3f5839
32 files changed
+15 -353

No files matched your search

-46
View File
@@ -58,54 +58,8 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
*/
namespace = get(config, 'api.namespace');
/**
* Whether or not to prefix the URL with the resource scope.
* @type {boolean}
*/
hasScopePrefix = true;
// =methods
/**
* Prepends a scope to the URL prefix. Precedence is given to the ID passed
* via `adapterOptions.scopeID`. If this value isn't found in
* `adapterOptions`, we look to the `scope.scope_id` field on the snapshot,
* which most resources have.
*
* Note: scopes themselves never receive a scope URL prefix.
*
* @override
* @param {string} path
* @param {string} parentURL
* @param {string} modelName
* @param {string} id
* @param {object} snapshot
* @return {string}
*/
urlPrefix(path, parentURL, modelName, id, snapshot) {
const prefix = super.urlPrefix(...arguments);
let scopePath = '';
let scopeID = '';
if (snapshot && this.hasScopePrefix) {
// Not all snapshots have `attr` (such as array snapshots),
// so we do this sort of ugly check.
if (snapshot.attr) {
const parentScope = snapshot.attr('scope');
if (parentScope) scopeID = parentScope.attr('scope_id');
}
// Attempt to get scopeID from adapterOptions and fallback on its current
// value if it wasn't passed through options.
scopeID = getWithDefault(snapshot, 'adapterOptions.scopeID', scopeID);
}
// Only non-scope resources need a scope path, since scope resources
// aren't technically "scoped" the same way.
// Ensure a slash is added between prefix + scope path if needed.
if (scopeID && prefix.charAt(prefix.length - 1) !== '/') {
scopePath = `/scopes/${scopeID}`;
}
return `${prefix}${scopePath}`;
}
/**
* Appends a custom method after a colon, if a method is passed via the
* snapshot's `adapterOptions.method` field.
-13
View File
@@ -1,13 +0,0 @@
import ApplicationAdapter from './application';
export default class AuthMethodAdapter extends ApplicationAdapter {
// =attributes
/**
* Auth methods use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-13
View File
@@ -1,13 +0,0 @@
import ApplicationAdapter from './application';
export default class GroupAdapter extends ApplicationAdapter {
// =attributes
/**
* Groups use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-13
View File
@@ -1,13 +0,0 @@
import ApplicationAdapter from './application';
export default class HostCatalogAdapter extends ApplicationAdapter {
// =attributes
/**
* Host catalogs use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-18
View File
@@ -1,18 +0,0 @@
import ApplicationAdapter from './application';
import { inject as service } from '@ember/service';
export default class HostSetAdapter extends ApplicationAdapter {
// =services
@service store;
// =attributes
/**
* Host sets use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-18
View File
@@ -1,18 +0,0 @@
import ApplicationAdapter from './application';
import { inject as service } from '@ember/service';
export default class HostAdapter extends ApplicationAdapter {
// =services
@service store;
// =attributes
/**
* Hosts use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-13
View File
@@ -1,13 +0,0 @@
import ApplicationAdapter from './application';
export default class RoleAdapter extends ApplicationAdapter {
// =attributes
/**
* Roles use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-13
View File
@@ -1,13 +0,0 @@
import ApplicationAdapter from './application';
export default class ScopeAdapter extends ApplicationAdapter {
// =attributes
/**
* Scopes do not include a scope prefix.
* @override
*/
hasScopePrefix = false;
}
-13
View File
@@ -1,13 +0,0 @@
import ApplicationAdapter from './application';
export default class TargetAdapter extends ApplicationAdapter {
// =attributes
/**
* Targets use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-13
View File
@@ -1,13 +0,0 @@
import ApplicationAdapter from './application';
export default class UserAdapter extends ApplicationAdapter {
// =attributes
/**
* Users use the new, unprefixed pathing style.
* @override
*/
hasScopePrefix = false;
}
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/auth-method';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/group';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/host-catalog';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/host-set';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/host';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/role';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/scope';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/target';
-1
View File
@@ -1 +0,0 @@
export { default } from 'api/adapters/user';
@@ -24,29 +24,6 @@ module('Unit | Adapter | application', function (hooks) {
assert.equal(adapter.urlPrefix(), config.api.namespace);
});
test('it generates URL prefixes with optional `scopeID` from adapterOptions', function (assert) {
assert.expect(2);
const scopeID = 'global';
const adapter = this.owner.lookup('adapter:application');
const prefix = adapter.urlPrefix(null, null, null, null, {
adapterOptions: { scopeID }
});
assert.ok(config.api.namespace);
assert.equal(prefix, `v1/scopes/${scopeID}`);
});
test('it does not prefix URLs with `scopeID` when hasScopePrefix is `false`', function (assert) {
assert.expect(2);
const scopeID = 'global';
const adapter = this.owner.lookup('adapter:application');
adapter.hasScopePrefix = false;
const prefix = adapter.urlPrefix(null, null, null, null, {
adapterOptions: { scopeID }
});
assert.ok(config.api.namespace);
assert.equal(prefix, 'v1');
});
test('it generates correct default URL suffixes', function (assert) {
assert.expect(1);
const adapter = this.owner.lookup('adapter:application');
@@ -77,17 +54,17 @@ module('Unit | Adapter | application', function (hooks) {
const adapter = this.owner.lookup('adapter:application');
// test URL generation for each request type...
const findRecordURL = adapter.buildURL('user', '1', mockSnapshot, 'findRecord');
assert.equal(findRecordURL, '/v1/scopes/o_1/users/1:my-custom-method');
assert.equal(findRecordURL, '/v1/users/1:my-custom-method');
const findAllURL = adapter.buildURL('user', null, mockSnapshot, 'findAll');
assert.equal(findAllURL, '/v1/scopes/o_1/users:my-custom-method');
assert.equal(findAllURL, '/v1/users:my-custom-method');
const findBelongsToURL = adapter.buildURL('user', '2', mockSnapshot, 'findBelongsTo');
assert.equal(findBelongsToURL, '/v1/scopes/o_1/users/2:my-custom-method');
assert.equal(findBelongsToURL, '/v1/users/2:my-custom-method');
const createRecordURL = adapter.buildURL('user', null, mockSnapshot, 'createRecord');
assert.equal(createRecordURL, '/v1/scopes/o_1/users:my-custom-method');
assert.equal(createRecordURL, '/v1/users:my-custom-method');
const updateRecordURL = adapter.buildURL('user', '3', mockSnapshot, 'updateRecord');
assert.equal(updateRecordURL, '/v1/scopes/o_1/users/3:my-custom-method');
assert.equal(updateRecordURL, '/v1/users/3:my-custom-method');
const deleteRecordURL = adapter.buildURL('user', '4', mockSnapshot, 'deleteRecord');
assert.equal(deleteRecordURL, '/v1/scopes/o_1/users/4:my-custom-method');
assert.equal(deleteRecordURL, '/v1/users/4:my-custom-method');
});
test('it can request records through the store from a specified scope', async function (assert) {
@@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Adapter | auth method', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let adapter = this.owner.lookup('adapter:auth-method');
assert.ok(adapter);
});
});
@@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Adapter | group', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let adapter = this.owner.lookup('adapter:group');
assert.ok(adapter);
});
});
@@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Adapter | host catalog', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let adapter = this.owner.lookup('adapter:host-catalog');
assert.ok(adapter);
});
});
@@ -1,22 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Adapter | host set', function(hooks) {
setupTest(hooks);
test('it generates correct complete URLs', function (assert) {
assert.expect(2);
const hostCatalogID = 'hc_098';
const method = 'my-custom-method';
const mockSnapshot = { adapterOptions: { method } };
const adapter = this.owner.lookup('adapter:host-set');
// Without hostCatalogID...
let url = adapter.buildURL('host-set', null, mockSnapshot, 'findAll');
assert.equal(url, '/v1/host-sets:my-custom-method');
// With hostCatalogID...
mockSnapshot.adapterOptions.hostCatalogID = hostCatalogID;
url = adapter.buildURL('host-set', null, mockSnapshot, 'findAll');
assert.equal(url, '/v1/host-sets:my-custom-method');
});
});
@@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Adapter | host', function(hooks) {
setupTest(hooks);
test('it exists', function(assert) {
let adapter = this.owner.lookup('adapter:host');
assert.ok(adapter);
});
});
@@ -1,12 +0,0 @@
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);
});
});
@@ -1,19 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
module('Unit | Adapter | scope', function(hooks) {
setupTest(hooks);
setupMirage(hooks);
test('it does not prefix URLs with `scopeID` for scope resources', function (assert) {
assert.expect(1);
const scopeID = 'global';
const adapter = this.owner.lookup('adapter:scope');
const prefix = adapter.urlPrefix(null, null, 'scope', null, {
adapterOptions: { scopeID }
});
assert.equal(prefix, `v1`);
});
});
@@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Adapter | target', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let adapter = this.owner.lookup('adapter:target');
assert.ok(adapter);
});
});
@@ -1,12 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Adapter | user', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let adapter = this.owner.lookup('adapter:user');
assert.ok(adapter);
});
});
+1 -13
View File
@@ -50,7 +50,7 @@ export default function() {
this.del('/auth-methods/:id');
// Authenticate/deauthenticate routes
this.post('/scopes/:scope_id/auth-methods/:id_method', authHandler);
this.post('/auth-methods/:id_method', authHandler);
this.post('/scopes/:id_method', deauthHandler);
// IAM : Users
@@ -250,16 +250,4 @@ export default function() {
}
return target.update(updatedAttrs);
});
// Uncomment the following line and the Response import above
// Then change the response code to simulate error responses.
// this.get('/scopes/:scope_id/projects', () => new Response(505));
// Update error payload to simulate specific error responses.
// this.get('/scopes/:scope_id/projects', () => new Response(505, {}, {
// errors: [{
// status: 505,
// message: 'HTTP version not supported.',
// }]
// }));
}
+6 -4
View File
@@ -23,16 +23,18 @@ import { Response } from 'miragejs';
// }
// }
export function authHandler({ scopes }, request) {
export function authHandler({ scopes, authMethods }, request) {
const payload = JSON.parse(request.requestBody);
if (payload.credentials.login_name === 'error') {
return new Response(400);
} else {
const id = request.params.id_method.split(':')[0];
const authMethod = authMethods.find(id);
const scope = scopes.find(authMethod.scopeId);
const scopeAttrs =
this.serialize(scopes.find(request.params.scope_id));
const scope = scopeAttrs;
this.serialize(scopes.find(scope.id));
return new Response(200, {}, {
scope,
scope: scopeAttrs,
id: 'token123',
token: 'thetokenstring',
user_id: 'user123',
@@ -34,6 +34,8 @@ module('Unit | Authenticator | password', function (hooks) {
const creds = { identification: 'foo', password: 'bar' };
const scope = { id: 'global' };
const authMethod = { id: 'paum_1234' };
this.server.create('scope', { id: 'global', type: 'global' });
this.server.create('auth-method', { id: authMethod.id, scopeId: 'global' });
await authenticator.authenticate(
creds,
null,