chore: add initial scopes routes with scope optional scope loading

This commit is contained in:
Randall Morey committed 2020-07-22 17:16:20 -04:00
1 parent df3cd1e72c
commit 857c26272d
13 files changed
+150 -46

No files matched your search

+6 -1
View File
@@ -7,6 +7,11 @@ export default class Router extends EmberRouter {
}
Router.map(function () {
this.route('scopes', function() {
this.route('scope', { path: ':scope_id' });
});
this.route('orgs', function () {
this.route('org', { path: ':org_id' }, function () {
this.route('projects', function () {
@@ -23,7 +28,7 @@ Router.map(function () {
this.route('user', { path: ':user_id' }, function() {});
this.route('new');
});
this.route('roles', function() {
this.route('role', { path: ':role_id' }, function() {});
this.route('new');
+4
View File
@@ -0,0 +1,4 @@
import Route from '@ember/routing/route';
export default class ScopesRoute extends Route {
}
+26
View File
@@ -0,0 +1,26 @@
import Route from '@ember/routing/route';
export default class ScopesScopeRoute extends Route {
/**
* Attempts to load the specified scope from the API. This is allowed
* to fail, since in some cases the user may not have permission to read a
* scope directly, but may have permission to read its resources.
* If the scope fails to load, we still proceed using a temporary scope object
* consisting of only the specified ID.
* @param {object} params
* @param {string} params.scope_id
* @return {Promise{ScopeModel}}
*/
async model({ scope_id: id }) {
try {
return await this.store.findRecord('scope', id);
} catch {
const maybeExisting = this.store.peekRecord('scope', id);
// TODO it's unclear if this is reliable...
// we may need to revert to a POJO.
return maybeExisting || this.store.createRecord('scope', { id });
}
}
}
+1
View File
@@ -0,0 +1 @@
{{outlet}}
+1
View File
@@ -0,0 +1 @@
{{outlet}}
+43 -43
View File
@@ -1,5 +1,5 @@
import config from '../config/environment';
// import { Response } from 'miragejs';
import { Response } from 'miragejs';
export default function() {
@@ -16,66 +16,66 @@ export default function() {
this.passthrough();
// Scope resources
// org
this.get('/orgs');
this.post('/orgs');
this.get('/orgs/:id');
this.patch('/orgs/:id');
this.del('/orgs/:id');
// project
this.get('/orgs/:org_id/projects');
this.post('/orgs/:org_id/projects');
this.get('/orgs/:org_id/projects/:id');
this.patch('/orgs/:org_id/projects/:id');
this.del('/orgs/:org_id/projects/:id');
this.post('/scopes');
// To simulate a possible real-world case, org scopes are not returned,
// but project scopes are.
// TODO this should be expanded to support other scenarios.
this.get('/scopes/:id', ({ scopes }, { params: { id: scopeID } }) => {
const scope = scopes.find(scopeID);
if (scope.type !== 'project') {
return new Response(404, {}, {});
} else {
return scope;
}
});
this.patch('/scopes/:id');
this.del('/scopes/:id');
// Auth & IAM resources
this.get('/orgs/:org_id/auth-methods');
this.post('/orgs/:org_id/auth-methods');
this.get('/orgs/:org_id/auth-methods/:id');
this.patch('/orgs/:org_id/auth-methods/:id');
this.del('/orgs/:org_id/auth-methods/:id');
this.get('/scopes/:scope_id/auth-methods');
this.post('/scopes/:scope_id/auth-methods');
this.get('/scopes/:scope_id/auth-methods/:id');
this.patch('/scopes/:scope_id/auth-methods/:id');
this.del('/scopes/:scope_id/auth-methods/:id');
// IAM : Users
this.get('/orgs/:org_id/users');
this.post('/orgs/:org_id/users');
this.get('/orgs/:org_id/users/:id');
this.patch('/orgs/:org_id/users/:id');
this.del('/orgs/:org_id/users/:id');
this.get('/scopes/:scope_id/users');
this.post('/scopes/:scope_id/users');
this.get('/scopes/:scope_id/users/:id');
this.patch('/scopes/:scope_id/users/:id');
this.del('/scopes/:scope_id/users/:id');
// IAM: Roles
this.get('/orgs/:org_id/roles');
this.post('/orgs/:org_id/roles');
this.get('/orgs/:org_id/roles/:id');
this.patch('/orgs/:org_id/roles/:id');
this.del('/orgs/:org_id/roles/:id');
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');
// group
this.get('/orgs/:org_id/groups');
this.post('/orgs/:org_id/groups');
this.get('/orgs/:org_id/groups/:id');
this.patch('/orgs/:org_id/groups/:id');
this.del('/orgs/:org_id/groups/:id');
this.get('/scopes/:scope_id/groups');
this.post('/scopes/:scope_id/groups');
this.get('/scopes/:scope_id/groups/:id');
this.patch('/scopes/:scope_id/groups/:id');
this.del('/scopes/:scope_id/groups/:id');
// Other resources
// host-catalog
this.get('/orgs/:org_id/projects/:project_id/host-catalogs');
this.post('/orgs/:org_id/projects/:project_id/host-catalogs');
this.get('/orgs/:org_id/projects/:project_id/host-catalogs/:id');
this.patch('/orgs/:org_id/projects/:project_id/host-catalogs/:id');
this.del('/orgs/:org_id/projects/:project_id/host-catalogs/:id');
this.get('/scopes/:scope_id/host-catalogs');
this.post('/scopes/:scope_id/host-catalogs');
this.get('/scopes/:scope_id/host-catalogs/:id');
this.patch('/scopes/:scope_id/host-catalogs/:id');
this.del('/scopes/:scope_id/host-catalogs/:id');
// Uncomment the following line and the Response import above
// Then change the response code to simulate error responses.
// this.get('/orgs/:org_id/projects', () => new Response(505));
// this.get('/scopes/:scope_id/projects', () => new Response(505));
// Update error payload to simulate specific error responses.
// this.get('/orgs/:org_id/projects', () => new Response(505, {}, {
// this.get('/scopes/:scope_id/projects', () => new Response(505, {}, {
// errors: [{
// status: 505,
// message: 'HTTP version not supported.',
+25
View File
@@ -0,0 +1,25 @@
import factory from '../generated/factories/scope';
import { trait } from 'ember-cli-mirage';
export default factory.extend({
type: 'global',
withChildren: trait({
afterCreate(record, server) {
if (record.type === 'global') {
server.createList('scope', 1, {
type: 'org',
scope: { id: record.id, type: record.type }
}, 'withChildren');
}
if (record.type === 'org') {
server.createList('scope', 5, {
type: 'project',
scope: { id: record.id, type: record.type }
});
}
}
})
});
@@ -0,0 +1,15 @@
import { Factory } from 'ember-cli-mirage';
import { random, date } from 'faker';
/**
* GeneratedScopeModelFactory
*/
export default Factory.extend({
name: () => random.words(),
description: () => random.words(),
created_time: () => date.recent(),
updated_time: () => date.recent(),
disabled: () => random.boolean(),
});
+1 -2
View File
@@ -2,8 +2,7 @@ export default function(server) {
// Scope resources
server.createList('org', 3);
server.createList('project', 6);
server.create('scope', null, 'withChildren');
// Auth
+5
View File
@@ -0,0 +1,5 @@
import ApplicationSerializer from './application';
export default ApplicationSerializer.extend({
modelName: 'scope'
});
+1
View File
@@ -54,6 +54,7 @@
"ember-cli-template-lint": "^1.0.0-beta.3",
"ember-cli-uglify": "^3.0.0",
"ember-data": "~3.16.0",
"ember-data-model-fragments": "5.0.0-beta.0",
"ember-exam": "^5.0.1",
"ember-export-application-global": "^2.0.1",
"ember-fetch": "^7.0.0",
+11
View File
@@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Route | scopes', function(hooks) {
setupTest(hooks);
test('it exists', function(assert) {
let route = this.owner.lookup('route:scopes');
assert.ok(route);
});
});
@@ -0,0 +1,11 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Route | scopes/scope', function(hooks) {
setupTest(hooks);
test('it exists', function(assert) {
let route = this.owner.lookup('route:scopes/scope');
assert.ok(route);
});
});