fix url when user tries to access resource with incorrect url (#1958)
* refactor: 💡 auth-method, account, & managed abilities & routes * refactor: 💡 credential store resources abilities & routes * refactor: 💡 group abilities & routes * refactor: 💡 host-catalog resources abilities & routes * refactor: 💡 role abilities & routes * test: 💍 fix route-info-test * test: 💍 fix host serializer tests * test: 💍 fix create-test for host-sets * refactor: 💡 session recording resources abilities & routes * refactor: 💡 storage bucket abilities & routes * refactor: 💡 target abilities & routes * refactor: 💡 user abilities & routes * refactor: 💡 worker abilities & routes * refactor: 💡 remove ability changes and add comments * Update ui/admin/app/utils/route-info.js Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com> * test: 💍 add test cases and rename util file * refactor: 💡 remove dup file and update imports ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-11282 * docs: ✏️ update comments & remove console.log ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-11282 * Update ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js Co-authored-by: Dharini Jeeva <dharini@hashicorp.com> --------- Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com> Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
This commit is contained in:
80 files changed
+1333
-81
No files matched your search
@@ -54,4 +54,10 @@ export default class GeneratedHostModel extends BaseModel {
|
||||
readOnly: true,
|
||||
})
|
||||
plugin;
|
||||
|
||||
@attr({
|
||||
emptyArrayIfMissing: true,
|
||||
readOnly: true,
|
||||
})
|
||||
host_set_ids;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
import {
|
||||
TYPE_AUTH_METHOD_PASSWORD,
|
||||
TYPE_AUTH_METHOD_OIDC,
|
||||
TYPE_AUTH_METHOD_LDAP,
|
||||
TYPES_AUTH_METHOD,
|
||||
@@ -23,11 +24,17 @@ export default factory.extend({
|
||||
'delete',
|
||||
'authenticate',
|
||||
],
|
||||
authorized_collection_actions: () => {
|
||||
return {
|
||||
accounts: ['create', 'list'],
|
||||
'managed-groups': ['create', 'list'],
|
||||
};
|
||||
authorized_collection_actions() {
|
||||
switch (this.type) {
|
||||
case TYPE_AUTH_METHOD_PASSWORD:
|
||||
return { accounts: ['create', 'list'] };
|
||||
case TYPE_AUTH_METHOD_LDAP:
|
||||
case TYPE_AUTH_METHOD_OIDC:
|
||||
return {
|
||||
accounts: ['create', 'list'],
|
||||
'managed-groups': ['create', 'list'],
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
id: () => generateId('am_'),
|
||||
|
||||
@@ -85,7 +85,16 @@ export default factory.extend({
|
||||
afterCreate(hostCatalog, server) {
|
||||
const { scope, type } = hostCatalog;
|
||||
const hosts = server.createList('host', 10, { scope, hostCatalog, type });
|
||||
server.createList('host-set', 3, { scope, hostCatalog, hosts, type });
|
||||
const hostSets = server.createList('host-set', 3, {
|
||||
scope,
|
||||
hostCatalog,
|
||||
hosts,
|
||||
type,
|
||||
});
|
||||
const hostSetIds = hostSets.map((hostSet) => hostSet.id);
|
||||
hosts.forEach((host) => {
|
||||
host.update({ hostSetIds });
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
@@ -22,14 +22,8 @@ export default factory.extend({
|
||||
authorized_collection_actions() {
|
||||
const collectionActions = {
|
||||
scopes: ['create', 'list'],
|
||||
users: ['create', 'list'],
|
||||
sessions: ['list'],
|
||||
groups: ['create', 'list'],
|
||||
roles: ['create', 'list'],
|
||||
targets: ['create', 'list'],
|
||||
'credential-stores': ['create', 'list'],
|
||||
'auth-methods': ['create', 'list'],
|
||||
'host-catalogs': ['create', 'list'],
|
||||
};
|
||||
|
||||
// Worker permissions only available on the global scope
|
||||
@@ -41,6 +35,15 @@ export default factory.extend({
|
||||
if (this.type === 'global' || this.type === 'org') {
|
||||
collectionActions['storage-buckets'] = ['create', 'list'];
|
||||
collectionActions['session-recordings'] = ['list'];
|
||||
collectionActions.users = ['create', 'list'];
|
||||
collectionActions['auth-methods'] = ['create', 'list'];
|
||||
}
|
||||
|
||||
if (this.type === 'project') {
|
||||
collectionActions['credential-stores'] = ['create', 'list'];
|
||||
collectionActions['host-catalogs'] = ['create', 'list'];
|
||||
collectionActions.sessions = ['list'];
|
||||
collectionActions.targets = ['create', 'list'];
|
||||
}
|
||||
|
||||
return collectionActions;
|
||||
|
||||
@@ -7,4 +7,13 @@ import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
modelName: 'host',
|
||||
|
||||
_hashForModel(model) {
|
||||
const json = ApplicationSerializer.prototype._hashForModel.apply(
|
||||
this,
|
||||
arguments
|
||||
);
|
||||
json.host_catalog_id = model.hostCatalogId;
|
||||
return json;
|
||||
},
|
||||
});
|
||||
@@ -57,6 +57,7 @@ module('Unit | Serializer | host', function (hooks) {
|
||||
address: '10.0.0.1',
|
||||
dns_names: [],
|
||||
ip_addresses: [],
|
||||
host_set_ids: [],
|
||||
},
|
||||
relationships: {},
|
||||
},
|
||||
@@ -78,6 +79,7 @@ module('Unit | Serializer | host', function (hooks) {
|
||||
authorized_actions: ['no-op', 'read'],
|
||||
ip_addresses: ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
|
||||
dns_names: ['test.example.internal', 'test.example.external'],
|
||||
host_set_ids: ['hst_12345'],
|
||||
};
|
||||
const normalized = serializer.normalizeSingleResponse(store, host, payload);
|
||||
assert.deepEqual(normalized, {
|
||||
@@ -92,6 +94,7 @@ module('Unit | Serializer | host', function (hooks) {
|
||||
ip_addresses: ['10.0.0.1', '10.0.0.2', '10.0.0.3'],
|
||||
dns_names: ['test.example.internal', 'test.example.external'],
|
||||
plugin: { name: 'aws' },
|
||||
host_set_ids: ['hst_12345'],
|
||||
},
|
||||
relationships: {},
|
||||
},
|
||||
|
||||
@@ -7,10 +7,14 @@ import Route from '@ember/routing/route';
|
||||
import { action } from '@ember/object';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { paramValueFinder } from 'admin/utils/param-value-finder';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -18,10 +22,30 @@ export default class ScopesScopeAuthMethodsAuthMethodRoute extends Route {
|
||||
* Load an auth method by ID.
|
||||
* @param {object} params
|
||||
* @param {string} params.auth_method_id
|
||||
* @return {authMethodModel}
|
||||
* @return {Promise{AuthMethodModel}}
|
||||
*/
|
||||
async model({ auth_method_id }) {
|
||||
return this.store.findRecord('auth-method', auth_method_id);
|
||||
return this.store.findRecord('auth-method', auth_method_id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {AuthMethodModel} authMethod
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(authMethod, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (authMethod.scopeID !== scope.id) {
|
||||
let paramValues = paramValueFinder('auth-method', transition.to.parent);
|
||||
this.router.replaceWith(
|
||||
transition.to.name,
|
||||
authMethod.scopeID,
|
||||
authMethod.id,
|
||||
...paramValues
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeAuthMethodsAuthMethodAccountsAccountRoute extend
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,22 @@ export default class ScopesScopeAuthMethodsAuthMethodAccountsAccountRoute extend
|
||||
* Load an account by ID.
|
||||
* @param {object} params
|
||||
* @param {string} params.account_id
|
||||
* @return {AccountModel}
|
||||
* @return {Promise{AccountModel}}
|
||||
*/
|
||||
model({ account_id }) {
|
||||
async model({ account_id }) {
|
||||
return this.store.findRecord('account', account_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct auth-method id if incorrect.
|
||||
* @param {AccountModel} account
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(account, transition) {
|
||||
const authMethod = this.modelFor('scopes.scope.auth-methods.auth-method');
|
||||
const { auth_method_id } = account;
|
||||
if (auth_method_id !== authMethod.id) {
|
||||
this.router.replaceWith(transition.to.name, auth_method_id, account.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,23 @@ export default class ScopesScopeAuthMethodsAuthMethodAccountsNewRoute extends Ro
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when auth-method does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const authMethod = this.modelFor('scopes.scope.auth-methods.auth-method');
|
||||
if (
|
||||
this.can.cannot('create model', authMethod, { collection: 'accounts' })
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.auth-methods.auth-method.accounts');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved account in current scope.
|
||||
* @return {AccountModel}
|
||||
|
||||
+21
-2
@@ -11,6 +11,8 @@ export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsManagedGroupRo
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -18,14 +20,31 @@ export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsManagedGroupRo
|
||||
* Load managed group by ID.
|
||||
* @param {object} params
|
||||
* @param {string} params.managed_group_id
|
||||
* @returns {ManagedGroupModel}
|
||||
* @returns {Promise{ManagedGroupModel}}
|
||||
*/
|
||||
model({ managed_group_id }) {
|
||||
async model({ managed_group_id }) {
|
||||
return this.store.findRecord('managed-group', managed_group_id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct auth-method id if incorrect.
|
||||
* @param {ManagedGroupModel} managedGroup
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(managedGroup, transition) {
|
||||
const authMethod = this.modelFor('scopes.scope.auth-methods.auth-method');
|
||||
const { auth_method_id } = managedGroup;
|
||||
if (auth_method_id !== authMethod.id) {
|
||||
this.router.replaceWith(
|
||||
transition.to.name,
|
||||
auth_method_id,
|
||||
managedGroup.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of string array fields in order to force the instance
|
||||
* into a dirty state. This ensures that `model.rollbackAttributes()` reverts
|
||||
|
||||
@@ -10,8 +10,27 @@ export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsNewRoute exten
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when auth-method does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const authMethod = this.modelFor('scopes.scope.auth-methods.auth-method');
|
||||
if (
|
||||
this.can.cannot('create model', authMethod, {
|
||||
collection: 'managed-groups',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.auth-methods.auth-method.managed-groups'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
model() {
|
||||
const { id: auth_method_id, type } = this.modelFor(
|
||||
'scopes.scope.auth-methods.auth-method'
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeAuthMethodsNewRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -21,6 +23,20 @@ export default class ScopesScopeAuthMethodsNewRoute extends Route {
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (
|
||||
this.can.cannot('create model', scopeModel, {
|
||||
collection: 'auth-methods',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.auth-methods');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new unsaved auth-method.
|
||||
* @return {AuthMethodModel}
|
||||
|
||||
@@ -5,17 +5,43 @@
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { paramValueFinder } from 'admin/utils/param-value-finder';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
/**
|
||||
* Load a specific credential store in current scope
|
||||
* @return {Promise[CredentialStoreModel]}
|
||||
* @return {Promise{CredentialStoreModel}}
|
||||
*/
|
||||
async model({ credential_store_id }) {
|
||||
return this.store.findRecord('credential-store', credential_store_id);
|
||||
return this.store.findRecord('credential-store', credential_store_id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {CredentialStoreModel} credentialStore
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(credentialStore, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (credentialStore.scopeID !== scope.id) {
|
||||
let paramValues = paramValueFinder(
|
||||
'credential-store',
|
||||
transition.to.parent
|
||||
);
|
||||
this.router.replaceWith(
|
||||
transition.to.name,
|
||||
credentialStore.scopeID,
|
||||
credentialStore.id,
|
||||
...paramValues
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-1
@@ -11,6 +11,8 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrari
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -18,7 +20,7 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrari
|
||||
* Load a credential-library using current credential store and its parent scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.credential_library_id
|
||||
* @return {CredentialLibraryModel}
|
||||
* @return {Promise{CredentialLibraryModel}}
|
||||
*/
|
||||
async model({ credential_library_id }) {
|
||||
return this.store.findRecord('credential-library', credential_library_id, {
|
||||
@@ -26,6 +28,24 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrari
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct credential-store id if incorrect.
|
||||
* @param {CredentialLibraryModel} credentialLibrary
|
||||
*/
|
||||
redirect(credentialLibrary) {
|
||||
const credentialStore = this.modelFor(
|
||||
'scopes.scope.credential-stores.credential-store'
|
||||
);
|
||||
const { credential_store_id } = credentialLibrary;
|
||||
if (credential_store_id !== credentialStore.id) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.credential-stores.credential-store.credential-libraries.credential-library',
|
||||
credential_store_id,
|
||||
credentialLibrary.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of array fields in order to force the instance
|
||||
* into a dirty state. This ensures that `model.rollbackAttributes()` reverts
|
||||
|
||||
+19
@@ -14,6 +14,7 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrari
|
||||
@service store;
|
||||
@service router;
|
||||
@service features;
|
||||
@service can;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -25,6 +26,24 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrari
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when credential-store does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const credentialStore = this.modelFor(
|
||||
'scopes.scope.credential-stores.credential-store'
|
||||
);
|
||||
if (
|
||||
this.can.cannot('create model', credentialStore, {
|
||||
collection: 'credential-libraries',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.credential-stores.credential-store.credential-libraries'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved credential library in current credential store.
|
||||
* @return {CredentialLibraryModel}
|
||||
|
||||
+21
-1
@@ -10,6 +10,8 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialsCreden
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,11 +19,29 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialsCreden
|
||||
* Load a credential using current credential store and its parent scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.credential_id
|
||||
* @return {CredentialModel}
|
||||
* @return {Promise{CredentialModel}}
|
||||
*/
|
||||
async model({ credential_id }) {
|
||||
return this.store.findRecord('credential', credential_id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct credential-store id if incorrect.
|
||||
* @param {CredentialModel} credential
|
||||
*/
|
||||
redirect(credential) {
|
||||
const credentialStore = this.modelFor(
|
||||
'scopes.scope.credential-stores.credential-store'
|
||||
);
|
||||
const { credential_store_id } = credential;
|
||||
if (credential_store_id !== credentialStore.id) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.credential-stores.credential-store.credentials.credential',
|
||||
credential_store_id,
|
||||
credential.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -12,6 +12,7 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialsNewRou
|
||||
|
||||
@service store;
|
||||
@service router;
|
||||
@service can;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -23,6 +24,24 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialsNewRou
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when credential-store does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const credentialStore = this.modelFor(
|
||||
'scopes.scope.credential-stores.credential-store'
|
||||
);
|
||||
if (
|
||||
this.can.cannot('create model', credentialStore, {
|
||||
collection: 'credentials',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.credential-stores.credential-store.credentials'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved credential in current credential store.
|
||||
* Also rollback/destroy any new, unsaved instances from this route before
|
||||
|
||||
@@ -13,6 +13,7 @@ export default class ScopesScopeCredentialStoresNewRoute extends Route {
|
||||
@service store;
|
||||
@service router;
|
||||
@service features;
|
||||
@service can;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -23,6 +24,21 @@ export default class ScopesScopeCredentialStoresNewRoute extends Route {
|
||||
};
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (
|
||||
this.can.cannot('create model', scopeModel, {
|
||||
collection: 'credential-stores',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.credential-stores');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved credential-store
|
||||
* Also rollback/destroy any new, unsaved instances from this route before
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeGroupsGroupRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,21 @@ export default class ScopesScopeGroupsGroupRoute extends Route {
|
||||
* Load a group in current scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.group_id
|
||||
* @return {groupModel}
|
||||
* @return {Promise{GroupModel}}
|
||||
*/
|
||||
model({ group_id }) {
|
||||
async model({ group_id }) {
|
||||
return this.store.findRecord('group', group_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {GroupModel} credentialStore
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(group, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (group.scopeID !== scope.id) {
|
||||
this.router.replaceWith(transition.to.name, group.scopeID, group.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,21 @@ export default class ScopesScopeGroupsNewRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (this.can.cannot('create model', scopeModel, { collection: 'groups' })) {
|
||||
this.router.replaceWith('scopes.scope.groups');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved group.
|
||||
* @return {GroupModel}
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { paramValueFinder } from 'admin/utils/param-value-finder';
|
||||
|
||||
export default class ScopesScopeHostCatalogsHostCatalogRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +20,29 @@ export default class ScopesScopeHostCatalogsHostCatalogRoute extends Route {
|
||||
* Load a host catalog.
|
||||
* @param {object} params
|
||||
* @param {string} params.host_catalog_id
|
||||
* @return {HostCatalogModel}
|
||||
* @return {Promise{HostCatalogModel}}
|
||||
*/
|
||||
async model({ host_catalog_id }) {
|
||||
return this.store.findRecord('host-catalog', host_catalog_id);
|
||||
return this.store.findRecord('host-catalog', host_catalog_id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {HostCatalogModel} hostCatalog
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(hostCatalog, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (hostCatalog.scopeID !== scope.id) {
|
||||
let paramValues = paramValueFinder('host-catalog', transition.to.parent);
|
||||
this.router.replaceWith(
|
||||
transition.to.name,
|
||||
hostCatalog.scopeID,
|
||||
hostCatalog.id,
|
||||
...paramValues
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,14 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import { action } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { paramValueFinder } from 'admin/utils/param-value-finder';
|
||||
|
||||
export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,12 +21,33 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetRoute exte
|
||||
* Load a host-set using current host-catalog and its parent scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.host_set_id
|
||||
* @return {HostSetModel}
|
||||
* @return {Promise{HostSetModel}}
|
||||
*/
|
||||
async model({ host_set_id }) {
|
||||
return this.store.findRecord('host-set', host_set_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct host-catalog id if incorrect.
|
||||
* @param {HostSetModel} hostSet
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(hostSet, transition) {
|
||||
const hostCatalog = this.modelFor(
|
||||
'scopes.scope.host-catalogs.host-catalog'
|
||||
);
|
||||
const { host_catalog_id } = hostSet;
|
||||
if (host_catalog_id !== hostCatalog.id) {
|
||||
let paramValues = paramValueFinder('host-set', transition.to.parent);
|
||||
this.router.replaceWith(
|
||||
transition.to.name,
|
||||
host_catalog_id,
|
||||
hostSet.id,
|
||||
...paramValues
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of string array fields in order to force the instance
|
||||
* into a dirty state. This ensures that `model.rollbackAttributes()` reverts
|
||||
|
||||
+15
@@ -15,9 +15,24 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetCreateAndA
|
||||
@service store;
|
||||
@service intl;
|
||||
@service router;
|
||||
@service can;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when host-catalog does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const hostCatalog = this.modelFor(
|
||||
'scopes.scope.host-catalogs.host-catalog'
|
||||
);
|
||||
if (this.can.cannot('create model', hostCatalog, { collection: 'hosts' })) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.host-catalogs.host-catalog.host-sets.host-set.hosts'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved host in current host catalog scope.
|
||||
* @return {Promise{HostSetModel,HostModel}}
|
||||
|
||||
+20
-1
@@ -10,6 +10,8 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetHostsHostR
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,26 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsHostSetHostsHostR
|
||||
* Load a host in current scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.host_id
|
||||
* @return {HostModel}
|
||||
* @return {Promise{HostModel}}
|
||||
*/
|
||||
async model({ host_id }) {
|
||||
return this.store.findRecord('host', host_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct host-catalog id if incorrect.
|
||||
* @param {HostModel} host
|
||||
*/
|
||||
redirect(host) {
|
||||
const hostSet = this.modelFor(
|
||||
'scopes.scope.host-catalogs.host-catalog.host-sets.host-set'
|
||||
);
|
||||
if (host.host_set_ids !== hostSet.id) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.host-catalogs.host-catalog.host-sets.host-set.hosts.host',
|
||||
host.host_set_ids[0],
|
||||
host.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,26 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsNewRoute extends
|
||||
|
||||
@service store;
|
||||
@service router;
|
||||
@service can;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when host-catalog does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const hostCatalog = this.modelFor(
|
||||
'scopes.scope.host-catalogs.host-catalog'
|
||||
);
|
||||
if (
|
||||
this.can.cannot('create model', hostCatalog, { collection: 'host-sets' })
|
||||
) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.host-catalogs.host-catalog.host-sets'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved host set in current host catalog scope.
|
||||
* @return {HostSetModel}
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeHostCatalogsHostCatalogHostsHostRoute extends Ro
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,27 @@ export default class ScopesScopeHostCatalogsHostCatalogHostsHostRoute extends Ro
|
||||
* Load a host using current host-catalog and it's parent scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.host_id
|
||||
* @return {HostModel}
|
||||
* @return {Promise{HostModel}}
|
||||
*/
|
||||
async model({ host_id }) {
|
||||
return this.store.findRecord('host', host_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct host-catalog id if incorrect.
|
||||
* @param {HostModel} host
|
||||
*/
|
||||
redirect(host) {
|
||||
const hostCatalog = this.modelFor(
|
||||
'scopes.scope.host-catalogs.host-catalog'
|
||||
);
|
||||
const { host_catalog_id } = host;
|
||||
if (host_catalog_id !== hostCatalog.id) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.host-catalogs.host-catalog.hosts.host',
|
||||
host_catalog_id,
|
||||
host.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,23 @@ export default class ScopesScopeHostCatalogsHostCatalogHostsNewRoute extends Rou
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when host-catalog does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const hostCatalog = this.modelFor(
|
||||
'scopes.scope.host-catalogs.host-catalog'
|
||||
);
|
||||
if (this.can.cannot('create model', hostCatalog, { collection: 'hosts' })) {
|
||||
this.router.replaceWith('scopes.scope.host-catalogs.host-catalog.hosts');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved host in current host catalog scope.
|
||||
* @return {HostModel}
|
||||
|
||||
@@ -12,6 +12,7 @@ export default class ScopesScopeHostCatalogsNewRoute extends Route {
|
||||
|
||||
@service store;
|
||||
@service router;
|
||||
@service can;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -23,6 +24,20 @@ export default class ScopesScopeHostCatalogsNewRoute extends Route {
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (
|
||||
this.can.cannot('create model', scopeModel, {
|
||||
collection: 'host-catalogs',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.host-catalogs');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved host catalog belonging to the current scope.
|
||||
* Also rollback/destroy any new, unsaved instances from this route before
|
||||
|
||||
@@ -10,9 +10,21 @@ export default class ScopesScopeRolesNewRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (this.can.cannot('create model', scopeModel, { collection: 'roles' })) {
|
||||
this.router.replaceWith('scopes.scope.roles');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved role.
|
||||
* @return {RoleModel}
|
||||
|
||||
@@ -11,6 +11,8 @@ export default class ScopesScopeRolesRoleRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -18,9 +20,9 @@ export default class ScopesScopeRolesRoleRoute extends Route {
|
||||
* Load a role in current scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.role_id
|
||||
* @return {RoleModel}
|
||||
* @return {Promise{RoleModel}}
|
||||
*/
|
||||
model({ role_id }) {
|
||||
async model({ role_id }) {
|
||||
const { id: scopeID } = this.modelFor('scopes.scope');
|
||||
return this.store.findRecord('role', role_id, {
|
||||
reload: true,
|
||||
@@ -28,6 +30,18 @@ export default class ScopesScopeRolesRoleRoute extends Route {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {RoleModel} role
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(role, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (role.scopeID !== scope.id) {
|
||||
this.router.replaceWith(transition.to.name, role.scopeID, role.id);
|
||||
}
|
||||
}
|
||||
|
||||
// =actions
|
||||
/**
|
||||
* Rollback changes on a role.
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { paramValueFinder } from 'admin/utils/param-value-finder';
|
||||
|
||||
export default class ScopesScopeSessionRecordingsSessionRecordingRoute extends Route {
|
||||
// =services
|
||||
@service store;
|
||||
@service session;
|
||||
@service router;
|
||||
@service can;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -36,4 +38,25 @@ export default class ScopesScopeSessionRecordingsSessionRecordingRoute extends R
|
||||
|
||||
return sessionRecording;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {SessionRecordingModel} sessionRecording
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(sessionRecording, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (sessionRecording.scopeID !== scope.id) {
|
||||
const paramValues = paramValueFinder(
|
||||
'session-recording',
|
||||
transition.to.parent
|
||||
);
|
||||
this.router.replaceWith(
|
||||
transition.to.name,
|
||||
sessionRecording.scopeID,
|
||||
sessionRecording.id,
|
||||
...paramValues
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -9,6 +9,8 @@ import { inject as service } from '@ember/service';
|
||||
export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConnectionChannelRoute extends Route {
|
||||
// =services
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
/**
|
||||
@@ -31,4 +33,21 @@ export default class ScopesScopeSessionRecordingsSessionRecordingChannelsByConne
|
||||
storageBucket,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct session-recording id if incorrect.
|
||||
* @param {channelRecording: Object, sessionRecording: Object, storageBucket: Object} model
|
||||
*/
|
||||
redirect(model) {
|
||||
const { channelRecording, sessionRecording } = model;
|
||||
const session_recording_id =
|
||||
channelRecording.connection_recording.session_recording.id;
|
||||
if (session_recording_id !== sessionRecording.id) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.session-recordings.session-recording.channels-by-connection.channel',
|
||||
session_recording_id,
|
||||
channelRecording.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,25 @@ export default class ScopesScopeStorageBucketsNewRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (
|
||||
this.can.cannot('create scope', scopeModel, {
|
||||
collection: 'storage-buckets',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.storage-buckets');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved storage bucket.
|
||||
* Also rollback/destroy any new, unsaved instances from this route before
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeStorageBucketsStorageBucketRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,26 @@ export default class ScopesScopeStorageBucketsStorageBucketRoute extends Route {
|
||||
* Load a storage bucket in current scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.storage_bucket_id
|
||||
* @return {StorageBucketModel}
|
||||
* @return {Promise{StorageBucketModel}}
|
||||
*/
|
||||
model({ storage_bucket_id }) {
|
||||
return this.store.findRecord('storage-bucket', storage_bucket_id);
|
||||
async model({ storage_bucket_id }) {
|
||||
return this.store.findRecord('storage-bucket', storage_bucket_id, {
|
||||
reload: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {StorageBucketModel} storageBucket
|
||||
*/
|
||||
redirect(storageBucket) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (storageBucket.scopeID !== scope.id) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.storage-buckets.storage-bucket',
|
||||
storageBucket.scopeID,
|
||||
storageBucket.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,7 @@ export default class ScopesScopeTargetsNewRoute extends Route {
|
||||
@service store;
|
||||
@service router;
|
||||
@service features;
|
||||
|
||||
// =methods
|
||||
@service can;
|
||||
|
||||
// =attributes
|
||||
queryParams = {
|
||||
@@ -23,6 +22,21 @@ export default class ScopesScopeTargetsNewRoute extends Route {
|
||||
refreshModel: true,
|
||||
},
|
||||
};
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (
|
||||
this.can.cannot('create model', scopeModel, { collection: 'targets' })
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.targets');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved target in current scope.
|
||||
* Also rollback/destroy any new, unsaved instances from this route before
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeTargetsTargetRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,21 @@ export default class ScopesScopeTargetsTargetRoute extends Route {
|
||||
* Load a target.
|
||||
* @param {object} params
|
||||
* @param {string} params.target_id
|
||||
* @return {TargetModel}
|
||||
* @return {Promise{TargetModel}}
|
||||
*/
|
||||
async model({ target_id }) {
|
||||
return this.store.findRecord('target', target_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {TargetModel} target
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(target, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (target.scopeID !== scope.id) {
|
||||
this.router.replaceWith(transition.to.name, target.scopeID, target.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,21 @@ export default class ScopesScopeUsersNewRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (this.can.cannot('create model', scopeModel, { collection: 'users' })) {
|
||||
this.router.replaceWith('scopes.scope.users');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved user.
|
||||
* @return {UserModel}
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeUsersUserRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,21 @@ export default class ScopesScopeUsersUserRoute extends Route {
|
||||
* Load a user in current scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.user_id
|
||||
* @return {UserModel}
|
||||
* @return {Promise{UserModel}}
|
||||
*/
|
||||
model({ user_id }) {
|
||||
return this.store.findRecord('user', user_id);
|
||||
async model({ user_id }) {
|
||||
return this.store.findRecord('user', user_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {UserModel} user
|
||||
* @param {object} transition
|
||||
*/
|
||||
redirect(user, transition) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (user.scopeID !== scope.id) {
|
||||
this.router.replaceWith(transition.to.name, user.scopeID, user.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,25 @@ export default class ScopesScopeWorkersNewRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Redirect to parent route when scope does not have create authorized action.
|
||||
*/
|
||||
beforeModel() {
|
||||
const scopeModel = this.modelFor('scopes.scope');
|
||||
if (
|
||||
this.can.cannot('create worker led worker', scopeModel, {
|
||||
collection: 'workers',
|
||||
})
|
||||
) {
|
||||
this.router.replaceWith('scopes.scope.workers');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new unsaved worker.
|
||||
* @return {WorkerModel}
|
||||
|
||||
@@ -10,6 +10,8 @@ export default class ScopesScopeWorkersWorkerRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -17,9 +19,24 @@ export default class ScopesScopeWorkersWorkerRoute extends Route {
|
||||
* Load a worker in current scope.
|
||||
* @param {object} params
|
||||
* @param {string} params.worker_id
|
||||
* @return {WorkerModel}
|
||||
* @return {Promise{WorkerModel}}
|
||||
*/
|
||||
model({ worker_id }) {
|
||||
return this.store.findRecord('worker', worker_id);
|
||||
async model({ worker_id }) {
|
||||
return this.store.findRecord('worker', worker_id, { reload: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to route with correct scope id if incorrect.
|
||||
* @param {WorkerModel} worker
|
||||
*/
|
||||
redirect(worker) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
if (worker.scopeID !== scope.id) {
|
||||
this.router.replaceWith(
|
||||
'scopes.scope.workers.worker',
|
||||
worker.scopeID,
|
||||
worker.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Traverses through a RouteInfo object in order to find
|
||||
// the dynamic segments of a route and stops traversing when
|
||||
// the route name of the caller is reached. In the RouteInfo
|
||||
// object the params object contains the dynamic segment of
|
||||
// a particular route.
|
||||
|
||||
export function paramValueFinder(routeName, parentInfo) {
|
||||
if (!parentInfo?.params || parentInfo.localName === routeName) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let otherParam = Object.values(parentInfo.params);
|
||||
return [...paramValueFinder(routeName, parentInfo.parent), ...otherParam];
|
||||
}
|
||||
@@ -26,11 +26,13 @@ module('Acceptance | accounts | create', function (hooks) {
|
||||
org: null,
|
||||
},
|
||||
authMethods: null,
|
||||
authMethod: null,
|
||||
account: null,
|
||||
};
|
||||
const urls = {
|
||||
orgScope: null,
|
||||
authMethods: null,
|
||||
authMethod: null,
|
||||
accounts: null,
|
||||
newAccount: null,
|
||||
account: null,
|
||||
@@ -190,4 +192,21 @@ module('Acceptance | accounts | create', function (hooks) {
|
||||
'Displays field-level errors.'
|
||||
);
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new account route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.authMethod.authorized_collection_actions.accounts =
|
||||
instances.authMethod.authorized_collection_actions.accounts.filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newAccount);
|
||||
|
||||
assert.false(
|
||||
instances.authMethod.authorized_collection_actions.accounts.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.accounts);
|
||||
});
|
||||
});
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
module('Acceptance | accounts | read', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
const ACCOUNT_SELECTOR = 'main tbody .hds-table__td:nth-child(1) a';
|
||||
|
||||
const instances = {
|
||||
@@ -26,11 +27,13 @@ module('Acceptance | accounts | read', function (hooks) {
|
||||
org: null,
|
||||
},
|
||||
authMethods: null,
|
||||
authMethod: null,
|
||||
account: null,
|
||||
};
|
||||
const urls = {
|
||||
orgScope: null,
|
||||
authMethods: null,
|
||||
authMethod: null,
|
||||
accounts: null,
|
||||
account: null,
|
||||
};
|
||||
@@ -80,4 +83,22 @@ module('Acceptance | accounts | read', function (hooks) {
|
||||
await visit(urls.accounts);
|
||||
assert.dom(ACCOUNT_SELECTOR).doesNotExist();
|
||||
});
|
||||
|
||||
test('user can navigate to account and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const authMethod = this.server.create('auth-method', {
|
||||
scope: instances.scopes.org,
|
||||
});
|
||||
const account = this.server.create('account', {
|
||||
scope: instances.scopes.org,
|
||||
authMethod,
|
||||
});
|
||||
const incorrectUrl = `${urls.accounts}/${account.id}`;
|
||||
const correctUrl = `${urls.orgScope}/auth-methods/${authMethod.id}/accounts/${account.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -444,4 +444,18 @@ module('Acceptance | auth-methods | create', function (hooks) {
|
||||
.dom(FIELD_ERROR_TEXT_SELECTOR)
|
||||
.hasText('At least one URL is required.');
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new auth method route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.orgScope.authorized_collection_actions['auth-methods'] = ['list'];
|
||||
|
||||
await visit(urls.newAuthMethod);
|
||||
|
||||
assert.false(
|
||||
instances.orgScope.authorized_collection_actions['auth-methods'].includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.authMethods);
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from 'ember-simple-auth/test-support';
|
||||
import { TYPE_AUTH_METHOD_LDAP } from 'api/models/auth-method';
|
||||
|
||||
module('Acceptance | auth methods | delete', function (hooks) {
|
||||
module('Acceptance | auth-methods | delete', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
|
||||
import { TYPE_AUTH_METHOD_OIDC } from 'api/models/auth-method';
|
||||
|
||||
module('Acceptance | auth methods | oidc', function (hooks) {
|
||||
module('Acceptance | auth-methods | oidc', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
TYPE_AUTH_METHOD_PASSWORD,
|
||||
} from 'api/models/auth-method';
|
||||
|
||||
module('Acceptance | auth methods | read', function (hooks) {
|
||||
module('Acceptance | auth-methods | read', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
const AUTH_LINK_SELECTOR = 'main tbody .hds-table__td:nth-child(1) a';
|
||||
@@ -183,4 +183,22 @@ module('Acceptance | auth methods | read', function (hooks) {
|
||||
assert.dom(LDAP_AUTH_TYPE_SELECTOR).hasText('LDAP');
|
||||
assert.dom(LDAP_AUTH_ACTIONS_SELECTOR).doesNotExist();
|
||||
});
|
||||
|
||||
test('users can navigate to auth method and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const orgScope = this.server.create('scope', {
|
||||
type: 'org',
|
||||
scope: { id: 'global', type: 'global' },
|
||||
});
|
||||
const authMethod = this.server.create('auth-method', {
|
||||
scope: orgScope,
|
||||
});
|
||||
const incorrectUrl = `${urls.globalAuthMethods}/${authMethod.id}/accounts`;
|
||||
const correctUrl = `/scopes/${orgScope.id}/auth-methods/${authMethod.id}/accounts`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
TYPE_AUTH_METHOD_LDAP,
|
||||
} from 'api/models/auth-method';
|
||||
|
||||
module('Acceptance | auth methods | update', function (hooks) {
|
||||
module('Acceptance | auth-methods | update', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
|
||||
@@ -233,4 +233,22 @@ module('Acceptance | credential-libraries | create', function (hooks) {
|
||||
assert.false(featuresService.isEnabled('ssh-target'));
|
||||
assert.dom('[value="vault-ssh-certificate"]').doesNotExist();
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new credential library route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.credentialStore.authorized_collection_actions[
|
||||
'credential-libraries'
|
||||
] = instances.credentialStore.authorized_collection_actions[
|
||||
'credential-libraries'
|
||||
].filter((item) => item !== 'create');
|
||||
|
||||
await visit(urls.newCredentialLibrary);
|
||||
|
||||
assert.false(
|
||||
instances.credentialStore.authorized_collection_actions[
|
||||
'credential-libraries'
|
||||
].includes('create')
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.credentialLibraries);
|
||||
});
|
||||
});
|
||||
@@ -106,4 +106,22 @@ module('Acceptance | credential-libraries | read', function (hooks) {
|
||||
await a11yAudit();
|
||||
assert.ok(find('.rose-message-subtitle').textContent.trim(), 'Error 404');
|
||||
});
|
||||
|
||||
test('users can navigate to credential library and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const credentialStore = this.server.create('credential-store', {
|
||||
scope: instances.scopes.project,
|
||||
});
|
||||
const credentialLibrary = this.server.create('credential-library', {
|
||||
scope: instances.scopes.project,
|
||||
credentialStore,
|
||||
});
|
||||
const incorrectUrl = `${urls.credentialLibraries}/${credentialLibrary.id}`;
|
||||
const correctUrl = `${urls.projectScope}/credential-stores/${credentialStore.id}/credential-libraries/${credentialLibrary.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -153,4 +153,22 @@ module('Acceptance | credential-stores | create', function (hooks) {
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new credential store route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.scopes.project.authorized_collection_actions[
|
||||
'credential-stores'
|
||||
] = instances.scopes.project.authorized_collection_actions[
|
||||
'credential-stores'
|
||||
].filter((item) => item !== 'create');
|
||||
|
||||
await visit(urls.newCredentialStore);
|
||||
|
||||
assert.false(
|
||||
instances.scopes.project.authorized_collection_actions[
|
||||
'credential-stores'
|
||||
].includes('create')
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.credentialStores);
|
||||
});
|
||||
});
|
||||
@@ -336,5 +336,22 @@ module(
|
||||
.dom('.hds-form-radio-card:nth-child(2) input')
|
||||
.hasAttribute('value', 'ssh_private_key');
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new credential route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.staticCredentialStore.authorized_collection_actions.credentials =
|
||||
instances.staticCredentialStore.authorized_collection_actions.credentials.filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newCredential);
|
||||
|
||||
assert.false(
|
||||
instances.staticCredentialStore.authorized_collection_actions.credentials.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.credentials);
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -165,4 +165,22 @@ module('Acceptance | credential-stores | credentials | read', function (hooks) {
|
||||
find(`[href="https://boundaryproject.io/help/admin-ui/credentials"]`)
|
||||
);
|
||||
});
|
||||
|
||||
test('users can navigate to credential and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const credentialStore = this.server.create('credential-store', {
|
||||
scope: instances.scopes.project,
|
||||
});
|
||||
const credential = this.server.create('credential', {
|
||||
scope: instances.scopes.project,
|
||||
credentialStore,
|
||||
});
|
||||
const incorrectUrl = `${urls.credentials}/${credential.id}`;
|
||||
const correctUrl = `${urls.projectScope}/credential-stores/${credentialStore.id}/credentials/${credential.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -142,4 +142,22 @@ module('Acceptance | credential-stores | read', function (hooks) {
|
||||
)
|
||||
.exists();
|
||||
});
|
||||
|
||||
test('users can navigate to credential store and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const projectScope = this.server.create('scope', {
|
||||
type: 'project',
|
||||
scope: { id: instances.scopes.org.id, type: 'org' },
|
||||
});
|
||||
const credentialStore = this.server.create('credential-store', {
|
||||
scope: projectScope,
|
||||
});
|
||||
const incorrectUrl = `${urls.credentialStores}/${credentialStore.id}/credentials`;
|
||||
const correctUrl = `/scopes/${projectScope.id}/credential-stores/${credentialStore.id}/credentials`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -21,11 +21,9 @@ module('Acceptance | groups | create', function (hooks) {
|
||||
|
||||
const instances = {
|
||||
scopes: {
|
||||
global: null,
|
||||
org: null,
|
||||
},
|
||||
group: null,
|
||||
orgScope: null,
|
||||
};
|
||||
const urls = {
|
||||
groups: null,
|
||||
@@ -35,7 +33,7 @@ module('Acceptance | groups | create', function (hooks) {
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
authenticateSession({});
|
||||
instances.orgScope = this.server.create(
|
||||
instances.scopes.org = this.server.create(
|
||||
'scope',
|
||||
{
|
||||
type: 'org',
|
||||
@@ -44,9 +42,9 @@ module('Acceptance | groups | create', function (hooks) {
|
||||
'withChildren'
|
||||
);
|
||||
instances.group = this.server.create('group', {
|
||||
scope: instances.orgScope,
|
||||
scope: instances.scopes.org,
|
||||
});
|
||||
urls.groups = `/scopes/${instances.orgScope.id}/groups`;
|
||||
urls.groups = `/scopes/${instances.scopes.org.id}/groups`;
|
||||
urls.group = `${urls.groups}/${instances.group.id}`;
|
||||
urls.newGroup = `${urls.groups}/new`;
|
||||
});
|
||||
@@ -64,17 +62,21 @@ module('Acceptance | groups | create', function (hooks) {
|
||||
assert.expect(2);
|
||||
await visit(urls.groups);
|
||||
assert.ok(
|
||||
instances.orgScope.authorized_collection_actions.groups.includes('create')
|
||||
instances.scopes.org.authorized_collection_actions.groups.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.ok(find(`[href="${urls.newGroup}"]`));
|
||||
});
|
||||
|
||||
test('cannot navigate to new groups route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.orgScope.authorized_collection_actions.groups = [];
|
||||
instances.scopes.org.authorized_collection_actions.groups = [];
|
||||
await visit(urls.groups);
|
||||
assert.notOk(
|
||||
instances.orgScope.authorized_collection_actions.groups.includes('create')
|
||||
assert.false(
|
||||
instances.scopes.org.authorized_collection_actions.groups.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.notOk(find(`[href="${urls.newGroup}"]`));
|
||||
});
|
||||
@@ -123,4 +125,21 @@ module('Acceptance | groups | create', function (hooks) {
|
||||
'Displays field-level errors.'
|
||||
);
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new group route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.scopes.org.authorized_collection_actions.groups =
|
||||
instances.scopes.org.authorized_collection_actions.groups.filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newGroup);
|
||||
|
||||
assert.false(
|
||||
instances.scopes.org.authorized_collection_actions.groups.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.groups);
|
||||
});
|
||||
});
|
||||
@@ -62,4 +62,22 @@ module('Acceptance | groups | read', function (hooks) {
|
||||
await visit(urls.group);
|
||||
assert.notOk(find('main tbody .rose-table-header-cell:nth-child(1) a'));
|
||||
});
|
||||
|
||||
test('users can navigate to group and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const orgScope = this.server.create('scope', {
|
||||
type: 'org',
|
||||
scope: { id: 'global', type: 'global' },
|
||||
});
|
||||
const group = this.server.create('group', {
|
||||
scope: orgScope,
|
||||
});
|
||||
const incorrectUrl = `${urls.groups}/${group.id}/members`;
|
||||
const correctUrl = `/scopes/${orgScope.id}/groups/${group.id}/members`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -201,4 +201,21 @@ module('Acceptance | host-catalogs | create', function (hooks) {
|
||||
'Name is required.'
|
||||
);
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new host catalog route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.scopes.project.authorized_collection_actions['host-catalogs'] =
|
||||
instances.scopes.project.authorized_collection_actions[
|
||||
'host-catalogs'
|
||||
].filter((item) => item !== 'create');
|
||||
|
||||
await visit(urls.newHostCatalog);
|
||||
|
||||
assert.false(
|
||||
instances.scopes.project.authorized_collection_actions[
|
||||
'host-catalogs'
|
||||
].includes('create')
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.hostCatalogs);
|
||||
});
|
||||
});
|
||||
@@ -224,4 +224,21 @@ module('Acceptance | host-catalogs | host sets | create', function (hooks) {
|
||||
'Name is required.'
|
||||
);
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new host set route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.hostCatalog.authorized_collection_actions['host-sets'] =
|
||||
instances.hostCatalog.authorized_collection_actions['host-sets'].filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newHostSet);
|
||||
|
||||
assert.false(
|
||||
instances.hostCatalog.authorized_collection_actions['host-sets'].includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.hostSets);
|
||||
});
|
||||
});
|
||||
@@ -278,4 +278,29 @@ module('Acceptance | host-catalogs | host-sets | hosts', function (hooks) {
|
||||
await click('form [type="submit"]');
|
||||
assert.ok(find('[role="alert"]'));
|
||||
});
|
||||
|
||||
test('users can navigate to host and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const hostCatalog = this.server.create('host-catalog', {
|
||||
scope: instances.scopes.project,
|
||||
type: 'plugin',
|
||||
plugin: { name: 'aws' },
|
||||
});
|
||||
const hostSet = this.server.create('host-set', {
|
||||
scope: instances.scopes.project,
|
||||
hostCatalog,
|
||||
});
|
||||
const host = this.server.create('host', {
|
||||
scope: instances.scopes.project,
|
||||
hostCatalog,
|
||||
hostSetIds: [hostSet.id],
|
||||
});
|
||||
const incorrectUrl = `${urls.hostCatalogs}/${hostCatalog.id}/host-sets/${instances.hostSet.id}/hosts/${host.id}`;
|
||||
const correctUrl = `${urls.hostCatalogs}/${hostCatalog.id}/host-sets/${hostSet.id}/hosts/${host.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
//invalidateSession,
|
||||
} from 'ember-simple-auth/test-support';
|
||||
|
||||
module('Acceptance | host-catalogs | host sets | read', function (hooks) {
|
||||
module('Acceptance | host-catalogs | host-sets | read', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
@@ -113,4 +113,23 @@ module('Acceptance | host-catalogs | host sets | read', function (hooks) {
|
||||
.dom(`[href="https://boundaryproject.io/help/admin-ui/host-sets"]`)
|
||||
.exists();
|
||||
});
|
||||
|
||||
test('users can navigate to host set and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const hostCatalog = this.server.create('host-catalog', {
|
||||
scope: instances.scopes.project,
|
||||
type: 'static',
|
||||
});
|
||||
const hostSet = this.server.create('host-set', {
|
||||
scope: instances.scopes.project,
|
||||
hostCatalog,
|
||||
});
|
||||
const incorrectUrl = `${urls.hostSets}/${hostSet.id}`;
|
||||
const correctUrl = `${urls.hostCatalogs}/${hostCatalog.id}/host-sets/${hostSet.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -54,6 +54,7 @@ module('Acceptance | host-catalogs | hosts | create', function (hooks) {
|
||||
scope: { id: instances.scopes.org.id, type: 'org' },
|
||||
});
|
||||
instances.hostCatalog = this.server.create('host-catalog', {
|
||||
type: 'static',
|
||||
scope: instances.scopes.project,
|
||||
});
|
||||
instances.host = this.server.create('host', {
|
||||
@@ -160,4 +161,21 @@ module('Acceptance | host-catalogs | hosts | create', function (hooks) {
|
||||
'Name is required.'
|
||||
);
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new host route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.hostCatalog.authorized_collection_actions.hosts =
|
||||
instances.hostCatalog.authorized_collection_actions.hosts.filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newHost);
|
||||
|
||||
assert.false(
|
||||
instances.hostCatalog.authorized_collection_actions.hosts.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.hosts);
|
||||
});
|
||||
});
|
||||
@@ -113,4 +113,23 @@ module('Acceptance | host-catalogs | hosts | read', function (hooks) {
|
||||
.dom(`[href="https://boundaryproject.io/help/admin-ui/hosts"]`)
|
||||
.exists();
|
||||
});
|
||||
|
||||
test('users can navigate to host and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const hostCatalog = this.server.create('host-catalog', {
|
||||
scope: instances.scopes.project,
|
||||
type: 'static',
|
||||
});
|
||||
const host = this.server.create('host', {
|
||||
scope: instances.scopes.project,
|
||||
hostCatalog,
|
||||
});
|
||||
const incorrectUrl = `${urls.hosts}/${host.id}`;
|
||||
const correctUrl = `${urls.hostCatalogs}/${hostCatalog.id}/hosts/${host.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -105,4 +105,22 @@ module('Acceptance | host-catalogs | read', function (hooks) {
|
||||
.dom(`[href="https://boundaryproject.io/help/admin-ui/host-catalogs"]`)
|
||||
.exists();
|
||||
});
|
||||
|
||||
test('users can navigate to host catalog and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const projectScope = this.server.create('scope', {
|
||||
type: 'project',
|
||||
scope: { id: instances.scopes.org.id, type: 'org' },
|
||||
});
|
||||
const hostCatalog = this.server.create('host-catalog', {
|
||||
scope: projectScope,
|
||||
});
|
||||
const incorrectUrl = `${urls.hostCatalogs}/${hostCatalog.id}/host-sets`;
|
||||
const correctUrl = `/scopes/${projectScope.id}/host-catalogs/${hostCatalog.id}/host-sets`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -242,4 +242,21 @@ module('Acceptance | managed-groups | create', function (hooks) {
|
||||
assert.dom(ERROR_MSG_SELECTOR).hasText('The request was invalid.');
|
||||
assert.dom(FIELD_ERROR_TEXT_SELECTOR).hasText('Name is required.');
|
||||
});
|
||||
|
||||
test('Users cannot directly navigate to a new managed group route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.authMethod.authorized_collection_actions['managed-groups'] =
|
||||
instances.authMethod.authorized_collection_actions[
|
||||
'managed-groups'
|
||||
].filter((item) => item !== 'create');
|
||||
|
||||
await visit(urls.newManagedGroup);
|
||||
|
||||
assert.false(
|
||||
instances.authMethod.authorized_collection_actions[
|
||||
'managed-groups'
|
||||
].includes('create')
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.managedGroups);
|
||||
});
|
||||
});
|
||||
@@ -118,4 +118,23 @@ module('Acceptance | managed-groups | read', function (hooks) {
|
||||
|
||||
assert.dom(`[href="${urls.ldapManagedGroup}"]`).doesNotExist();
|
||||
});
|
||||
|
||||
test('User can navigate to managed group and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const authMethod = this.server.create('auth-method', {
|
||||
scope: instances.scopes.org,
|
||||
type: TYPE_AUTH_METHOD_LDAP,
|
||||
});
|
||||
const managedGroup = this.server.create('managed-group', {
|
||||
scope: instances.scopes.org,
|
||||
authMethod,
|
||||
});
|
||||
const incorrectUrl = `${urls.managedGroups}/${managedGroup.id}`;
|
||||
const correctUrl = `${urls.orgScope}/auth-methods/${authMethod.id}/managed-groups/${managedGroup.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -27,7 +27,6 @@ module('Acceptance | roles | create', function (hooks) {
|
||||
project: null,
|
||||
},
|
||||
role: null,
|
||||
orgScope: null,
|
||||
};
|
||||
const urls = {
|
||||
roles: null,
|
||||
@@ -38,7 +37,7 @@ module('Acceptance | roles | create', function (hooks) {
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
authenticateSession({});
|
||||
instances.orgScope = this.server.create(
|
||||
instances.scopes.org = this.server.create(
|
||||
'scope',
|
||||
{
|
||||
type: 'org',
|
||||
@@ -52,19 +51,19 @@ module('Acceptance | roles | create', function (hooks) {
|
||||
// mechanism.
|
||||
instances.scopes.project = this.server.create('scope', {
|
||||
type: 'project',
|
||||
scope: { id: instances.orgScope.id, type: instances.orgScope.type },
|
||||
scope: { id: instances.scopes.org.id, type: instances.scopes.org.type },
|
||||
});
|
||||
instances.role = this.server.create(
|
||||
'role',
|
||||
{
|
||||
scope: instances.orgScope,
|
||||
scope: instances.scopes.org,
|
||||
},
|
||||
'withPrincipals'
|
||||
);
|
||||
urls.roles = `/scopes/${instances.orgScope.id}/roles`;
|
||||
urls.roles = `/scopes/${instances.scopes.org.id}/roles`;
|
||||
urls.role = `${urls.roles}/${instances.role.id}`;
|
||||
urls.newRole = `${urls.roles}/new`;
|
||||
urls.orgScope = `/scopes/${instances.orgScope.id}`;
|
||||
urls.orgScope = `/scopes/${instances.scopes.org.id}`;
|
||||
});
|
||||
|
||||
test('can create new role', async function (assert) {
|
||||
@@ -80,17 +79,21 @@ module('Acceptance | roles | create', function (hooks) {
|
||||
assert.expect(2);
|
||||
await visit(urls.roles);
|
||||
assert.ok(
|
||||
instances.orgScope.authorized_collection_actions.roles.includes('create')
|
||||
instances.scopes.org.authorized_collection_actions.roles.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.ok(find(`[href="${urls.newRole}"]`));
|
||||
});
|
||||
|
||||
test('Users cannot navigate to new roles route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.orgScope.authorized_collection_actions.roles = [];
|
||||
instances.scopes.org.authorized_collection_actions.roles = [];
|
||||
await visit(urls.roles);
|
||||
assert.notOk(
|
||||
instances.orgScope.authorized_collection_actions.roles.includes('create')
|
||||
instances.scopes.org.authorized_collection_actions.roles.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.notOk(find(`[href="${urls.newRole}"]`));
|
||||
});
|
||||
@@ -133,4 +136,21 @@ module('Acceptance | roles | create', function (hooks) {
|
||||
assert.ok(find('[role="alert"]'));
|
||||
assert.ok(find('.hds-form-error__message'));
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new role route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.scopes.org.authorized_collection_actions.roles =
|
||||
instances.scopes.org.authorized_collection_actions.roles.filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newRole);
|
||||
|
||||
assert.false(
|
||||
instances.scopes.org.authorized_collection_actions.roles.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.roles);
|
||||
});
|
||||
});
|
||||
@@ -96,4 +96,22 @@ module('Acceptance | roles | read', function (hooks) {
|
||||
await a11yAudit();
|
||||
assert.strictEqual(currentURL(), urls.role);
|
||||
});
|
||||
|
||||
test('users can navigate to role and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const orgScope = this.server.create('scope', {
|
||||
type: 'org',
|
||||
scope: { id: 'global', type: 'global' },
|
||||
});
|
||||
const role = this.server.create('role', {
|
||||
scope: orgScope,
|
||||
});
|
||||
const incorrectUrl = `${urls.roles}/${role.id}/grants`;
|
||||
const correctUrl = `/scopes/${orgScope.id}/roles/${role.id}/grants`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), correctUrl);
|
||||
});
|
||||
});
|
||||
@@ -10,7 +10,7 @@ import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||
import a11yAudit from 'ember-a11y-testing/test-support/audit';
|
||||
import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
|
||||
module('Acceptance | session recordings | read', function (hooks) {
|
||||
module('Acceptance | session-recordings | read', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
@@ -113,4 +113,15 @@ module('Acceptance | session recordings | read', function (hooks) {
|
||||
await click(LIST_CHANNEL_RECORDING_BUTTON);
|
||||
assert.strictEqual(currentURL(), urls.channelRecording);
|
||||
});
|
||||
|
||||
test('users can navigate to session recording and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
featuresService.enable('ssh-session-recording');
|
||||
const incorrectUrl = `/scopes/${instances.scopes.org.id}/session-recordings/${instances.sessionRecording.id}/channels-by-connection`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), urls.sessionRecording);
|
||||
});
|
||||
});
|
||||
+27
-9
@@ -11,11 +11,13 @@ import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
import { Response } from 'miragejs';
|
||||
|
||||
module(
|
||||
'Acceptance | session recordings | session recording | channels by connection | channel',
|
||||
'Acceptance | session-recordings | session-recording | channels-by-connection | channel',
|
||||
function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
let featuresService;
|
||||
|
||||
// Instances
|
||||
const instances = {
|
||||
scopes: {
|
||||
@@ -32,6 +34,7 @@ module(
|
||||
globalScope: null,
|
||||
sessionRecordings: null,
|
||||
sessionRecording: null,
|
||||
channelRecording: null,
|
||||
};
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
@@ -55,22 +58,23 @@ module(
|
||||
urls.globalScope = `/scopes/global`;
|
||||
urls.sessionRecordings = `${urls.globalScope}/session-recordings`;
|
||||
urls.sessionRecording = `${urls.sessionRecordings}/${instances.sessionRecording.id}/channels-by-connection`;
|
||||
urls.connectionRecording = `${urls.sessionRecording}/${instances.channelRecording.id}`;
|
||||
urls.channelRecording = `${urls.sessionRecording}/${instances.channelRecording.id}`;
|
||||
featuresService = this.owner.lookup('service:features');
|
||||
authenticateSession({});
|
||||
});
|
||||
|
||||
test('user can navigate to a channel', async function (assert) {
|
||||
assert.expect(1);
|
||||
// Visit channel
|
||||
await visit(urls.connectionRecording);
|
||||
assert.strictEqual(currentURL(), urls.connectionRecording);
|
||||
await visit(urls.channelRecording);
|
||||
assert.strictEqual(currentURL(), urls.channelRecording);
|
||||
});
|
||||
|
||||
test('user can view recording with proper authorization', async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
// Visit channel
|
||||
await visit(urls.connectionRecording);
|
||||
await visit(urls.channelRecording);
|
||||
|
||||
// if authorized player will render
|
||||
assert.dom('.session-recording-player').exists();
|
||||
@@ -81,7 +85,7 @@ module(
|
||||
instances.channelRecording.mime_types = [];
|
||||
|
||||
// Visit channel
|
||||
await visit(urls.connectionRecording);
|
||||
await visit(urls.channelRecording);
|
||||
|
||||
// if unauthorized player will not render
|
||||
assert.dom('.session-recording-player').doesNotExist();
|
||||
@@ -95,7 +99,7 @@ module(
|
||||
);
|
||||
|
||||
// Visit channel
|
||||
await visit(urls.connectionRecording);
|
||||
await visit(urls.channelRecording);
|
||||
|
||||
// if unauthorized player will not render
|
||||
assert.dom('.session-recording-player').doesNotExist();
|
||||
@@ -118,7 +122,7 @@ module(
|
||||
);
|
||||
|
||||
// Visit channel
|
||||
await visit(urls.connectionRecording);
|
||||
await visit(urls.channelRecording);
|
||||
|
||||
// if there was an error player will not render
|
||||
assert.dom('.session-recording-player').doesNotExist();
|
||||
@@ -130,11 +134,25 @@ module(
|
||||
test('user can navigate back to session recording screen', async function (assert) {
|
||||
assert.expect(1);
|
||||
// Visit channel
|
||||
await visit(urls.connectionRecording);
|
||||
await visit(urls.channelRecording);
|
||||
// click "Back to channels" link in player header
|
||||
await click('.session-recording-player-header > a');
|
||||
|
||||
assert.strictEqual(currentURL(), urls.sessionRecording);
|
||||
});
|
||||
|
||||
test('users can navigate to channel recording and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
featuresService.enable('ssh-session-recording');
|
||||
const sessionRecording = this.server.create('session-recording', {
|
||||
scope: instances.scopes.global,
|
||||
});
|
||||
const incorrectUrl = `${urls.sessionRecordings}/${sessionRecording.id}/channels-by-connection/${instances.channelRecording.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), urls.channelRecording);
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -200,4 +200,21 @@ module('Acceptance | storage-buckets | create', function (hooks) {
|
||||
assert.dom(ALERT_TEXT_SELECTOR).hasText('The request was invalid.');
|
||||
assert.dom(FIELD_ERROR_TEXT_SELECTOR).hasText('Name is required.');
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new storage bucket route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.scopes.global.authorized_collection_actions['storage-buckets'] =
|
||||
instances.scopes.global.authorized_collection_actions[
|
||||
'storage-buckets'
|
||||
].filter((item) => item !== 'create');
|
||||
|
||||
await visit(urls.newStorageBucket);
|
||||
|
||||
assert.false(
|
||||
instances.scopes.global.authorized_collection_actions[
|
||||
'storage-buckets'
|
||||
].includes('create')
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.storageBuckets);
|
||||
});
|
||||
});
|
||||
@@ -87,4 +87,14 @@ module('Acceptance | storage-buckets | read', function (hooks) {
|
||||
|
||||
assert.dom(MESSAGE_SELECTOR).hasText('Error 404');
|
||||
});
|
||||
|
||||
test('users can navigate to storage bucket and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const incorrectUrl = `/scopes/${instances.scopes.org.id}/storage-buckets/${instances.storageBucket.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), urls.storageBucket);
|
||||
});
|
||||
});
|
||||
@@ -443,4 +443,21 @@ module('Acceptance | targets | create', function (hooks) {
|
||||
assert.false(featuresService.isEnabled('target-network-address'));
|
||||
assert.dom('[name="address"]').doesNotExist();
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new storage bucket route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.scopes.project.authorized_collection_actions.targets =
|
||||
instances.scopes.project.authorized_collection_actions.targets.filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newSSHTarget);
|
||||
|
||||
assert.false(
|
||||
instances.scopes.project.authorized_collection_actions.targets.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.targets);
|
||||
});
|
||||
});
|
||||
@@ -49,6 +49,7 @@ module('Acceptance | targets | enable session recording', function (hooks) {
|
||||
target: null,
|
||||
enableSessionRecording: null,
|
||||
storageBuckets: null,
|
||||
storageBucket: null,
|
||||
newStorageBucket: null,
|
||||
};
|
||||
|
||||
@@ -78,13 +79,13 @@ module('Acceptance | targets | enable session recording', function (hooks) {
|
||||
storageBucketTwo = instances.storageBucket[1];
|
||||
|
||||
// Generate route URLs for resources
|
||||
urls.globalScope = `/scopes/global/scopes`;
|
||||
urls.globalScope = `/scopes/global`;
|
||||
urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`;
|
||||
urls.projectScope = `/scopes/${instances.scopes.project.id}`;
|
||||
urls.targets = `${urls.projectScope}/targets`;
|
||||
urls.target = `${urls.targets}/${instances.target.id}`;
|
||||
urls.enableSessionRecording = `${urls.target}/enable-session-recording`;
|
||||
urls.storageBuckets = `${urls.projectScope}/storage-buckets`;
|
||||
urls.storageBuckets = `${urls.globalScope}/storage-buckets`;
|
||||
urls.newStorageBucket = `${urls.enableSessionRecording}/create-storage-bucket`;
|
||||
urls.storageBucket = `${urls.storageBuckets}/${storageBucketOne.id}`;
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ module('Acceptance | targets | enable session recording', function (hooks) {
|
||||
target: null,
|
||||
enableSessionRecording: null,
|
||||
storageBuckets: null,
|
||||
storageBucket: null,
|
||||
newStorageBucket: null,
|
||||
};
|
||||
|
||||
@@ -78,13 +79,13 @@ module('Acceptance | targets | enable session recording', function (hooks) {
|
||||
storageBucketTwo = instances.storageBucket[1];
|
||||
|
||||
// Generate route URLs for resources
|
||||
urls.globalScope = `/scopes/global/scopes`;
|
||||
urls.globalScope = `/scopes/global`;
|
||||
urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`;
|
||||
urls.projectScope = `/scopes/${instances.scopes.project.id}`;
|
||||
urls.targets = `${urls.projectScope}/targets`;
|
||||
urls.target = `${urls.targets}/${instances.target.id}`;
|
||||
urls.enableSessionRecording = `${urls.target}/enable-session-recording`;
|
||||
urls.storageBuckets = `${urls.projectScope}/storage-buckets`;
|
||||
urls.storageBuckets = `${urls.globalScope}/storage-buckets`;
|
||||
urls.newStorageBucket = `${urls.enableSessionRecording}/create-storage-bucket`;
|
||||
urls.storageBucket = `${urls.storageBuckets}/${storageBucketOne.id}`;
|
||||
|
||||
|
||||
@@ -193,4 +193,14 @@ module('Acceptance | targets | read', function (hooks) {
|
||||
.dom(`[href="https://boundaryproject.io/help/admin-ui/targets"]`)
|
||||
.exists();
|
||||
});
|
||||
|
||||
test('users can navigate to target and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const incorrectUrl = `/scopes/${instances.scopes.org.id}/targets/${instances.sshTarget.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), urls.sshTarget);
|
||||
});
|
||||
});
|
||||
@@ -145,4 +145,21 @@ module('Acceptance | users | create', function (hooks) {
|
||||
assert.dom('.rose-notification-body').hasText('The request was invalid.');
|
||||
assert.dom('.rose-form-error-message').hasText('Name is required.');
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new user route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
instances.scopes.org.authorized_collection_actions.users =
|
||||
instances.scopes.org.authorized_collection_actions.users.filter(
|
||||
(item) => item !== 'create'
|
||||
);
|
||||
|
||||
await visit(urls.newUser);
|
||||
|
||||
assert.false(
|
||||
instances.scopes.org.authorized_collection_actions.users.includes(
|
||||
'create'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), urls.users);
|
||||
});
|
||||
});
|
||||
@@ -90,4 +90,14 @@ module('Acceptance | users | read', function (hooks) {
|
||||
.dom(`[href="https://boundaryproject.io/help/admin-ui/users"]`)
|
||||
.exists();
|
||||
});
|
||||
|
||||
test('users can navigate to user and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const incorrectUrl = `/scopes/global/users/${instances.user.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), urls.user);
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,14 @@
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { visit, fillIn, click, find, findAll } from '@ember/test-helpers';
|
||||
import {
|
||||
visit,
|
||||
fillIn,
|
||||
click,
|
||||
find,
|
||||
findAll,
|
||||
currentURL,
|
||||
} from '@ember/test-helpers';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||
import { Response } from 'miragejs';
|
||||
@@ -144,4 +151,21 @@ module('Acceptance | workers | create', function (hooks) {
|
||||
'Displays primary error message.'
|
||||
);
|
||||
});
|
||||
|
||||
test('users cannot directly navigate to new worker route without proper authorization', async function (assert) {
|
||||
assert.expect(2);
|
||||
globalScope.authorized_collection_actions.workers =
|
||||
globalScope.authorized_collection_actions.workers.filter(
|
||||
(item) => item !== 'create:worker-led'
|
||||
);
|
||||
|
||||
await visit(newWorkerURL);
|
||||
|
||||
assert.false(
|
||||
globalScope.authorized_collection_actions.workers.includes(
|
||||
'create:worker-led'
|
||||
)
|
||||
);
|
||||
assert.strictEqual(currentURL(), workersURL);
|
||||
});
|
||||
});
|
||||
@@ -86,4 +86,18 @@ module('Acceptance | workers | read', function (hooks) {
|
||||
|
||||
assert.dom('main tbody .rose-table-header-cell:nth-child(1) a').isVisible();
|
||||
});
|
||||
|
||||
test('users can navigate to worker and incorrect url autocorrects', async function (assert) {
|
||||
assert.expect(2);
|
||||
const orgScope = this.server.create('scope', {
|
||||
type: 'org',
|
||||
scope: { id: 'global', type: 'global' },
|
||||
});
|
||||
const incorrectUrl = `/scopes/${orgScope.id}/workers/${instances.worker.id}`;
|
||||
|
||||
await visit(incorrectUrl);
|
||||
|
||||
assert.notEqual(currentURL(), incorrectUrl);
|
||||
assert.strictEqual(currentURL(), urls.worker);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { paramValueFinder } from 'admin/utils/param-value-finder';
|
||||
|
||||
module('Unit | Utility | param-value-finder', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
let router;
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
router = this.owner.lookup('service:router');
|
||||
});
|
||||
|
||||
test('returns empty array when null or empty routeInfo object is used', function (assert) {
|
||||
assert.expect(2);
|
||||
let result = paramValueFinder('scopes', null);
|
||||
|
||||
assert.deepEqual(result, []);
|
||||
|
||||
result = paramValueFinder('scopes', {});
|
||||
|
||||
assert.deepEqual(result, []);
|
||||
});
|
||||
|
||||
test('returns correct array when routeInfo object is used', function (assert) {
|
||||
assert.expect(2);
|
||||
let routeInfo = router.recognize('/scopes');
|
||||
let result = paramValueFinder('scopes', routeInfo.parent);
|
||||
|
||||
assert.deepEqual(result, []);
|
||||
|
||||
routeInfo = router.recognize('/scopes/global/auth-methods');
|
||||
result = paramValueFinder('scopes', routeInfo.parent);
|
||||
assert.deepEqual(result, ['global']);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user