UI: Ember upgrade: Handle deprecation router service from host (#28603)

* use alias for router injection

* update @router declarations in engine files

* fix remaining pki router imports

* dynamically set router based on owner

* address replication routers

* update markdown docs

* use non-deprecated import for getOwner

* revert out of scope changes

* add transition-to test
This commit is contained in:
claire bontempo
2024-10-08 09:01:46 -07:00
committed by GitHub
parent b6145bc3bb
commit 7774261c15
90 changed files with 238 additions and 116 deletions

View File

@@ -8,7 +8,6 @@ import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers';
import config from 'vault/config/environment';
// TODO: DEPRECATION https://ember-engines.com/docs/deprecations#-use-alias-for-inject-router-service-from-host-application
export default class App extends Application {
modulePrefix = config.modulePrefix;
podModulePrefix = config.podModulePrefix;
@@ -16,12 +15,20 @@ export default class App extends Application {
engines = {
'config-ui': {
dependencies: {
services: ['auth', 'flash-messages', 'namespace', 'router', 'store', 'version', 'custom-messages'],
services: [
'auth',
'flash-messages',
'namespace',
{ 'app-router': 'router' },
'store',
'version',
'custom-messages',
],
},
},
'open-api-explorer': {
dependencies: {
services: ['auth', 'flash-messages', 'namespace', 'router', 'version'],
services: ['auth', 'flash-messages', 'namespace', { 'app-router': 'router' }, 'version'],
},
},
replication: {
@@ -32,7 +39,7 @@ export default class App extends Application {
'flash-messages',
'namespace',
'replication-mode',
'router',
{ 'app-router': 'router' },
'store',
'version',
'-portal',
@@ -51,7 +58,7 @@ export default class App extends Application {
'flash-messages',
'namespace',
'path-help',
'router',
{ 'app-router': 'router' },
'store',
'version',
'secret-mount-path',
@@ -63,7 +70,7 @@ export default class App extends Application {
},
kubernetes: {
dependencies: {
services: ['router', 'store', 'secret-mount-path', 'flash-messages'],
services: [{ 'app-router': 'router' }, 'store', 'secret-mount-path', 'flash-messages'],
externalRoutes: {
secrets: 'vault.cluster.secrets.backends',
},
@@ -71,7 +78,7 @@ export default class App extends Application {
},
ldap: {
dependencies: {
services: ['router', 'store', 'secret-mount-path', 'flash-messages', 'auth'],
services: [{ 'app-router': 'router' }, 'store', 'secret-mount-path', 'flash-messages', 'auth'],
externalRoutes: {
secrets: 'vault.cluster.secrets.backends',
},
@@ -85,7 +92,7 @@ export default class App extends Application {
'download',
'flash-messages',
'namespace',
'router',
{ 'app-router': 'router' },
'secret-mount-path',
'store',
'version',
@@ -104,7 +111,7 @@ export default class App extends Application {
'flash-messages',
'namespace',
'path-help',
'router',
{ 'app-router': 'router' },
'secret-mount-path',
'store',
'version',
@@ -118,7 +125,7 @@ export default class App extends Application {
},
sync: {
dependencies: {
services: ['flash-messages', 'flags', 'router', 'store', 'version'],
services: ['flash-messages', 'flags', { 'app-router': 'router' }, 'store', 'version'],
externalRoutes: {
kvSecretOverview: 'vault.cluster.secrets.backend.kv.secret.index',
clientCountOverview: 'vault.cluster.clients',

View File

@@ -96,7 +96,7 @@ export default class <EngineName>Engine extends Engine {
modulePrefix = modulePrefix;
Resolver = Resolver;
dependencies = {
services: ['router', 'store', 'secret-mount-path', 'flash-messages'],
services: ['app-router', 'store', 'secret-mount-path', 'flash-messages'],
externalRoutes: ['secrets'],
};
}
@@ -128,7 +128,7 @@ The external route dependencies allow you to link to a route outside of your eng
## Register your engine with our main application:
In our `app/app.js` file in the engines object, add your engines name and dependencies.
In our `app/app.js` file in the engines object, add your engines name and dependencies. The `router` service must be referenced via an alias within engines. The pattern is to use `app-router` as the alias, see example below.
```js
/**
@@ -146,7 +146,7 @@ export default class App extends Application {
engines = {
<engine-name>: {
dependencies: {
services: ['router', 'store', 'secret-mount-path', 'flash-messages', <any-other-dependencies-you-have>],
services: [{ 'app-router': 'router' }, 'store', 'secret-mount-path', 'flash-messages', <any-other-dependencies-you-have>],
externalRoutes: {
secrets: 'vault.cluster.secrets.backends',
},

View File

@@ -23,7 +23,7 @@ import { isAfter } from 'date-fns';
*/
export default class MessagesList extends Component {
@service router;
@service('app-router') router;
@service store;
@service flashMessages;
@service customMessages;

View File

@@ -20,7 +20,7 @@ import errorMessage from 'vault/utils/error-message';
export default class MessageDetails extends Component {
@service store;
@service router;
@service('app-router') router;
@service flashMessages;
@service customMessages;
@service namespace;

View File

@@ -24,7 +24,7 @@ import errorMessage from 'vault/utils/error-message';
export default class MessagesList extends Component {
@service store;
@service router;
@service('app-router') router;
@service flashMessages;
@service namespace;
@service customMessages;

View File

@@ -16,7 +16,7 @@ export default class ConfigUiEngine extends Engine {
modulePrefix = modulePrefix;
Resolver = Resolver;
dependencies = {
services: ['auth', 'store', 'flash-messages', 'namespace', 'router', 'version', 'custom-messages'],
services: ['auth', 'store', 'flash-messages', 'namespace', 'app-router', 'version', 'custom-messages'],
};
}

View File

@@ -4,7 +4,7 @@
*/
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { getOwner } from '@ember/owner';
import { action } from '@ember/object';
import { encodePath } from 'vault/utils/path-encoding-helpers';
@@ -26,7 +26,14 @@ import { encodePath } from 'vault/utils/path-encoding-helpers';
*/
export default class LinkedBlockComponent extends Component {
@service router;
// We don't import the router service here because Ember Engine's use the alias 'app-router'
// Since this component is shared across engines, we look up the router dynamically using getOwner instead.
// This way we avoid throwing an error by looking up a service that doesn't exist.
// https://guides.emberjs.com/release/services/#toc_accessing-services
get router() {
const owner = getOwner(this);
return owner.lookup('service:router') || owner.lookup('service:app-router');
}
@action
onClick(event) {

View File

@@ -9,6 +9,7 @@ import { action } from '@ember/object';
import { service } from '@ember/service';
import { task } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
import { getOwner } from '@ember/owner';
/**
* @module ReplicationPage
@@ -28,9 +29,14 @@ const MODE = {
export default class ReplicationPage extends Component {
@service store;
@service router;
@tracked reindexingDetails = null;
// This component renders both within and outside the replication engine so we have to dynamically look up the router
get router() {
const owner = getOwner(this);
return owner.lookup('service:router') || owner.lookup('service:app-router');
}
@action onModeUpdate(evt, replicationMode) {
// Called on did-insert and did-update
this.getReplicationModeStatus.perform(replicationMode);

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Helper from '@ember/component/helper';
import { getOwner } from '@ember/owner';
/*
template helper that replaces ember-router-helpers https://github.com/rwjblue/ember-router-helpers
example:
<MyForm @onSave={{transition-to "vault.cluster.some.route.item" "item-id"}} />
<MyForm @onSave={{transition-to "vault.cluster.some.external.route" external=true}} />
*/
export default class TransitionTo extends Helper {
// We don't import the router service here because Ember Engine's use the alias 'app-router'
// Since this helper is shared across engines, we look up the router dynamically using getOwner instead.
// This way we avoid throwing an error by looking up a service that doesn't exist.
// https://guides.emberjs.com/release/services/#toc_accessing-services
get router() {
const owner = getOwner(this);
return owner.lookup('service:router') || owner.lookup('service:app-router');
}
compute(routeParams, { external = false }) {
if (external) {
return () => this.router.transitionToExternal(...routeParams);
}
return () => this.router.transitionTo(...routeParams);
}
}

View File

@@ -11,7 +11,6 @@ import { task } from 'ember-concurrency';
export default Mixin.create({
store: service(),
router: service(),
loading: or('save.isRunning', 'submitSuccess.isRunning'),
onDisable() {},
onPromote() {},

View File

@@ -0,0 +1,6 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
export { default } from 'core/helpers/transition-to';

View File

@@ -9,7 +9,7 @@ import { action } from '@ember/object';
export default class CredentialsShowController extends Controller {
@service flashMessages;
@service router;
@service('app-router') router;
@action
async revokeCredentials() {

View File

@@ -9,7 +9,7 @@ import { action } from '@ember/object';
export default class RoleController extends Controller {
@service flashMessages;
@service router;
@service('app-router') router;
@action
async deleteRole() {

View File

@@ -20,7 +20,7 @@ const Eng = Engine.extend({
'flash-messages',
'namespace',
'path-help',
'router',
'app-router',
'store',
'version',
'secret-mount-path',

View File

@@ -18,7 +18,7 @@ import errorMessage from 'vault/utils/error-message';
* @param {object} model - config model that contains kubernetes configuration
*/
export default class ConfigurePageComponent extends Component {
@service router;
@service('app-router') router;
@service store;
@tracked inferredState;

View File

@@ -23,7 +23,7 @@ import timestamp from 'vault/utils/timestamp';
*/
export default class CredentialsPageComponent extends Component {
@service store;
@service router;
@service('app-router') router;
@tracked ttl = '';
@tracked clusterRoleBinding = false;

View File

@@ -19,7 +19,7 @@ import { action } from '@ember/object';
*/
export default class OverviewPageComponent extends Component {
@service router;
@service('app-router') router;
@tracked selectedRole = null;
@tracked roleOptions = [];

View File

@@ -20,7 +20,7 @@ import errorMessage from 'vault/utils/error-message';
*/
export default class CreateAndEditRolePageComponent extends Component {
@service router;
@service('app-router') router;
@service flashMessages;
@tracked roleRulesTemplates;

View File

@@ -17,7 +17,7 @@ import errorMessage from 'vault/utils/error-message';
*/
export default class RoleDetailsPageComponent extends Component {
@service router;
@service('app-router') router;
@service flashMessages;
get extraFields() {

View File

@@ -23,7 +23,7 @@ import keys from 'core/utils/key-codes';
*/
export default class RolesPageComponent extends Component {
@service flashMessages;
@service router;
@service('app-router') router;
@tracked query;
@tracked roleToDelete = null;

View File

@@ -16,7 +16,7 @@ export default class KubernetesEngine extends Engine {
modulePrefix = modulePrefix;
Resolver = Resolver;
dependencies = {
services: ['router', 'store', 'secret-mount-path', 'flash-messages'],
services: ['app-router', 'store', 'secret-mount-path', 'flash-messages'],
externalRoutes: ['secrets'],
};
}

View File

@@ -7,7 +7,7 @@ import Route from '@ember/routing/route';
import { service } from '@ember/service';
export default class KubernetesRoute extends Route {
@service router;
@service('app-router') router;
redirect() {
this.router.transitionTo('vault.cluster.secrets.backend.kubernetes.overview');

View File

@@ -7,7 +7,7 @@ import Route from '@ember/routing/route';
import { service } from '@ember/service';
export default class KubernetesRoleRoute extends Route {
@service router;
@service('app-router') router;
redirect() {
this.router.transitionTo('vault.cluster.secrets.backend.kubernetes.roles.role.details');

View File

@@ -31,7 +31,7 @@ import { task, timeout } from 'ember-concurrency';
*/
export default class KvListFilterComponent extends Component {
@service router;
@service('app-router') router;
@tracked query;
constructor() {

View File

@@ -26,7 +26,7 @@ import { pathIsDirectory } from 'kv/utils/kv-breadcrumbs';
export default class KvListPageComponent extends Component {
@service flashMessages;
@service router;
@service('app-router') router;
@service store;
@tracked secretPath;

View File

@@ -41,7 +41,7 @@ import { isAdvancedSecret } from 'core/utils/advanced-secret';
export default class KvSecretDetails extends Component {
@service flashMessages;
@service router;
@service('app-router') router;
@service store;
@tracked showJsonView = false;

View File

@@ -31,7 +31,7 @@ import { isAdvancedSecret } from 'core/utils/advanced-secret';
export default class KvSecretEdit extends Component {
@service controlGroup;
@service flashMessages;
@service router;
@service('app-router') router;
@tracked showJsonView = false;
@tracked showDiff = false;

View File

@@ -37,7 +37,7 @@ import errorMessage from 'vault/utils/error-message';
export default class KvSecretMetadataDetails extends Component {
@service controlGroup;
@service flashMessages;
@service router;
@service('app-router') router;
@service store;
@tracked error = null;

View File

@@ -37,7 +37,7 @@ import errorMessage from 'vault/utils/error-message';
export default class KvSecretPatch extends Component {
@service controlGroup;
@service flashMessages;
@service router;
@service('app-router') router;
@service store;
@tracked controlGroupError;

View File

@@ -28,7 +28,7 @@ import errorMessage from 'vault/utils/error-message';
export default class KvSecretCreate extends Component {
@service controlGroup;
@service flashMessages;
@service router;
@service('app-router') router;
@service store;
@tracked showJsonView = false;

View File

@@ -22,7 +22,7 @@ export default class KvEngine extends Engine {
'download',
'flash-messages',
'namespace',
'router',
'app-router',
'secret-mount-path',
'store',
'version',

View File

@@ -7,7 +7,7 @@ import Route from '@ember/routing/route';
import { service } from '@ember/service';
export default class KvRoute extends Route {
@service router;
@service('app-router') router;
redirect() {
this.router.transitionTo('vault.cluster.secrets.backend.kv.list');

View File

@@ -12,7 +12,7 @@ import { pathIsDirectory } from 'kv/utils/kv-breadcrumbs';
export default class KvSecretsListRoute extends Route {
@service store;
@service router;
@service('app-router') router;
@service secretMountPath;
queryParams = {

View File

@@ -8,7 +8,7 @@ import { service } from '@ember/service';
import { breadcrumbsForSecret } from 'kv/utils/kv-breadcrumbs';
export default class SecretIndex extends Route {
@service router;
@service('app-router') router;
setupController(controller, resolvedModel) {
super.setupController(controller, resolvedModel);

View File

@@ -8,7 +8,7 @@ import { breadcrumbsForSecret } from 'kv/utils/kv-breadcrumbs';
import { service } from '@ember/service';
export default class SecretPatch extends Route {
@service router;
@service('app-router') router;
setupController(controller, resolvedModel) {
super.setupController(controller, resolvedModel);

View File

@@ -29,7 +29,7 @@ interface SchemaOption {
export default class LdapConfigurePageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked showRotatePrompt = false;
@tracked modelValidations: ValidationMap | null = null;

View File

@@ -23,7 +23,7 @@ interface Args {
export default class LdapCreateAndEditLibraryPageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked modelValidations: ValidationMap | null = null;
@tracked invalidFormMessage = '';

View File

@@ -20,7 +20,7 @@ interface Args {
export default class LdapLibraryDetailsPageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@action
async delete() {

View File

@@ -21,7 +21,7 @@ interface Args {
export default class LdapLibraryDetailsAccountsPageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked showCheckOutPrompt = false;
@tracked checkOutTtl: string | null = null;

View File

@@ -25,7 +25,7 @@ interface Args {
}
export default class LdapLibrariesPageComponent extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked selectedRole: LdapRoleModel | undefined;

View File

@@ -30,7 +30,7 @@ interface RoleTypeOption {
export default class LdapCreateAndEditRolePageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@tracked modelValidations: ValidationMap | null = null;

View File

@@ -23,7 +23,7 @@ interface Args {
export default class LdapRoleDetailsPageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@action

View File

@@ -27,7 +27,7 @@ interface Args {
export default class LdapRolesPageComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@tracked credsToRotate: LdapRoleModel | null = null;
@tracked roleToDelete: LdapRoleModel | null = null;

View File

@@ -14,7 +14,7 @@ export default class LdapEngine extends Engine {
modulePrefix = modulePrefix;
Resolver = Resolver;
dependencies = {
services: ['router', 'store', 'secret-mount-path', 'flash-messages', 'auth'],
services: ['app-router', 'store', 'secret-mount-path', 'flash-messages', 'auth'],
externalRoutes: ['secrets'],
};
}

View File

@@ -24,7 +24,7 @@ interface LdapLibraryCheckOutController extends Controller {
export default class LdapLibraryCheckOutRoute extends Route {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
accountsRoute = 'vault.cluster.secrets.backend.ldap.libraries.library.details.accounts';

View File

@@ -9,7 +9,7 @@ import { service } from '@ember/service';
import type RouterService from '@ember/routing/router-service';
export default class LdapLibraryRoute extends Route {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
redirect() {
this.router.transitionTo('vault.cluster.secrets.backend.ldap.libraries.library.details.accounts');

View File

@@ -9,7 +9,7 @@ import { service } from '@ember/service';
import type RouterService from '@ember/routing/router-service';
export default class LdapLibraryRoute extends Route {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
redirect() {
this.router.transitionTo('vault.cluster.secrets.backend.ldap.libraries.library.details');

View File

@@ -9,7 +9,7 @@ import { service } from '@ember/service';
import type RouterService from '@ember/routing/router-service';
export default class LdapRoleRoute extends Route {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
redirect() {
this.router.transitionTo('vault.cluster.secrets.backend.ldap.roles.role.details');

View File

@@ -14,7 +14,7 @@ const Eng = Engine.extend({
modulePrefix,
Resolver,
dependencies: {
services: ['auth', 'flash-messages', 'namespace', 'router', 'version'],
services: ['auth', 'flash-messages', 'namespace', 'app-router', 'version'],
},
});

View File

@@ -19,7 +19,7 @@ interface Args {
export default class PkiConfigurationDetails extends Component<Args> {
@service declare readonly store: Store;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly version: VersionService;
@tracked showDeleteAllIssuers = false;

View File

@@ -44,7 +44,7 @@ interface ErrorObject {
message: string;
}
export default class PkiConfigurationEditComponent extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly version: VersionService;

View File

@@ -7,7 +7,7 @@ import Component from '@glimmer/component';
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import type Store from '@ember-data/store';
import type Router from '@ember/routing/router';
import type RouterService from '@ember/routing/router';
import type FlashMessageService from 'vault/services/flash-messages';
import type PkiActionModel from 'vault/models/pki/action';
import type { Breadcrumb } from 'vault/vault/app-types';
@@ -26,9 +26,9 @@ interface Args {
* and form submission and cancel actions.
*/
export default class PkiConfigureCreate extends Component<Args> {
@service declare readonly store: Store;
@service declare readonly router: Router;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly store: Store;
@service('app-router') declare readonly router: RouterService;
@tracked title = 'Configure PKI';

View File

@@ -21,7 +21,7 @@ interface Args {
}
export default class PkiIssuerEditComponent extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly flashMessages: FlashMessageService;
@tracked usageValues: Array<string> = [];

View File

@@ -11,7 +11,7 @@ import { waitFor } from '@ember/test-waiters';
import { task } from 'ember-concurrency';
import errorMessage from 'vault/utils/error-message';
import type Store from '@ember-data/store';
import type Router from '@ember/routing/router';
import type RouterService from '@ember/routing/router';
import type FlashMessageService from 'vault/services/flash-messages';
import type SecretMountPath from 'vault/services/secret-mount-path';
import type PkiIssuerModel from 'vault/models/pki/issuer';
@@ -31,10 +31,10 @@ const RADIO_BUTTON_KEY = {
};
export default class PagePkiIssuerRotateRootComponent extends Component<Args> {
@service declare readonly store: Store;
@service declare readonly router: Router;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly secretMountPath: SecretMountPath;
@service declare readonly store: Store;
@service('app-router') declare readonly router: RouterService;
@tracked displayedForm = RADIO_BUTTON_KEY.oldSettings;
@tracked showOldSettings = false;

View File

@@ -15,7 +15,7 @@ interface Args {
}
export default class PkiKeyDetails extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly flashMessages: FlashMessageService;
@action

View File

@@ -19,7 +19,7 @@ interface Args {
}
export default class PkiOverview extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: Store;
@tracked rolesValue = '';

View File

@@ -17,7 +17,7 @@ interface Args {
}
export default class DetailsPage extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly secretMountPath: SecretMountPath;

View File

@@ -52,7 +52,7 @@ export default class PkiTidyStatusComponent extends Component<Args> {
@service declare readonly secretMountPath: SecretMountPath;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly version: VersionService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked tidyOptionsModal = false;
@tracked confirmCancelTidy = false;

View File

@@ -51,7 +51,7 @@ interface Args {
*/
export default class PkiGenerateRootComponent extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked modelValidations: ValidationMap | null = null;
@tracked errorBanner = '';

View File

@@ -9,7 +9,7 @@ import { task } from 'ember-concurrency';
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import errorMessage from 'vault/utils/error-message';
import type Router from '@ember/routing/router';
import type RouterService from '@ember/routing/router';
import type Store from '@ember-data/store';
import type FlashMessageService from 'vault/services/flash-messages';
import type DownloadService from 'vault/services/download';
@@ -23,10 +23,10 @@ interface Args {
}
export default class PkiRoleGenerate extends Component<Args> {
@service declare readonly router: Router;
@service declare readonly store: Store;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly download: DownloadService;
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly store: Store;
@service('app-router') declare readonly router: RouterService;
@tracked errorBanner = '';
@tracked invalidFormAlert = '';

View File

@@ -30,7 +30,7 @@ interface PkiTidyBooleans {
}
export default class PkiTidyForm extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked errorBanner = '';
@tracked invalidFormAlert = '';

View File

@@ -22,7 +22,7 @@ export default class PkiEngine extends Engine {
'flash-messages',
'namespace',
'path-help',
'router',
'app-router',
'secret-mount-path',
'store',
'version',

View File

@@ -7,7 +7,7 @@ import Route from '@ember/routing/route';
import { service } from '@ember/service';
export default class PkiRoute extends Route {
@service router;
@service('app-router') router;
redirect() {
this.router.transitionTo('vault.cluster.secrets.backend.pki.overview');

View File

@@ -29,7 +29,7 @@ export default Controller.extend(structuredClone(DEFAULTS), {
isModalActive: false,
isTokenCopied: false,
expirationDate: null,
router: service(),
router: service('app-router'),
store: service(),
rm: service('replication-mode'),
replicationMode: alias('rm.mode'),

View File

@@ -9,7 +9,7 @@ import Controller from '@ember/controller';
export default Controller.extend({
flashMessages: service(),
router: service(),
router: service('app-router'),
rm: service('replication-mode'),
replicationMode: alias('rm.mode'),
actions: {

View File

@@ -11,7 +11,7 @@ import { action } from '@ember/object';
export default class ReplicationModeBaseController extends Controller {
@service('replication-mode') rm;
@service router;
@service('app-router') router;
@service store;
get replicationMode() {

View File

@@ -20,7 +20,7 @@ const Eng = Engine.extend({
'flash-messages',
'namespace',
'replication-mode',
'router',
'app-router',
'store',
'version',
'-portal',

View File

@@ -12,7 +12,7 @@ export default Route.extend(ClusterRoute, {
version: service(),
store: service(),
auth: service(),
router: service(),
router: service('app-router'),
capabilities: service(),
async fetchCapabilities() {

View File

@@ -12,7 +12,7 @@ const SUPPORTED_REPLICATION_MODES = ['dr', 'performance'];
export default Route.extend({
replicationMode: service(),
router: service(),
router: service('app-router'),
store: service(),
beforeModel() {
const replicationMode = this.paramsFor(this.routeName).replication_mode;

View File

@@ -9,7 +9,7 @@ import Route from '@ember/routing/route';
import { service } from '@ember/service';
export default Route.extend({
router: service(),
router: service('app-router'),
store: service(),
model() {
const replicationMode = this.paramsFor('mode').replication_mode;

View File

@@ -20,7 +20,7 @@ const pathForAction = (action, replicationMode, clusterMode) => {
};
export default Route.extend({
router: service(),
router: service('app-router'),
store: service(),
model() {
const store = this.store;

View File

@@ -9,7 +9,7 @@ import Route from '@ember/routing/route';
import { service } from '@ember/service';
export default Route.extend({
router: service(),
router: service('app-router'),
store: service(),
model() {
const replicationMode = this.paramsFor('mode').replication_mode;

View File

@@ -9,7 +9,7 @@ import Base from '../../replication-base';
export default Base.extend({
flashMessages: service(),
router: service(),
router: service('app-router'),
modelPath: 'model.config',

View File

@@ -9,7 +9,7 @@ import Route from '@ember/routing/route';
import UnloadModelRouteMixin from 'vault/mixins/unload-model-route';
export default Route.extend(UnloadModelRouteMixin, {
router: service(),
router: service('app-router'),
store: service(),
version: service(),
rm: service('replication-mode'),

View File

@@ -18,7 +18,7 @@ interface Args {
}
export default class DestinationsTabsToolbar extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@service declare readonly flashMessages: FlashMessageService;

View File

@@ -27,7 +27,7 @@ interface Args {
}
export default class SyncSecretsDestinationsPageComponent extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@service declare readonly flashMessages: FlashMessageService;

View File

@@ -23,7 +23,7 @@ interface Args {
export default class DestinationsCreateForm extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@tracked modelValidations: ValidationMap | null = null;

View File

@@ -23,7 +23,7 @@ interface Args {
}
export default class SyncSecretsDestinationsPageComponent extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@service declare readonly flashMessages: FlashMessageService;

View File

@@ -22,7 +22,7 @@ interface Args {
}
export default class DestinationSyncPageComponent extends Component<Args> {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@service declare readonly flashMessages: FlashMessageService;

View File

@@ -24,7 +24,7 @@ interface Args {
export default class SyncActivationModal extends Component<Args> {
@service declare readonly flashMessages: FlashMessageService;
@service declare readonly store: StoreService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@tracked hasConfirmedDocs = false;

View File

@@ -14,7 +14,7 @@ export default class SyncEngine extends Engine {
modulePrefix = modulePrefix;
Resolver = Resolver;
dependencies = {
services: ['flash-messages', 'flags', 'router', 'store', 'version'],
services: ['flash-messages', 'flags', 'app-router', 'store', 'version'],
externalRoutes: ['kvSecretOverview', 'clientCountOverview'],
};
}

View File

@@ -9,7 +9,7 @@ import { service } from '@ember/service';
import type RouterService from '@ember/routing/router-service';
export default class SyncIndexRoute extends Route {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
redirect() {
this.router.transitionTo('vault.cluster.sync.secrets.overview');

View File

@@ -10,7 +10,7 @@ import type RouterService from '@ember/routing/router-service';
import type FlagService from 'vault/services/flags';
export default class SyncSecretsRoute extends Route {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly flags: FlagService;
model() {

View File

@@ -19,7 +19,7 @@ interface RouteParams {
export default class SyncSecretsDestinationsDestinationRoute extends Route {
@service declare readonly store: Store;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly flashMessages: FlashMessageService;
model(params: RouteParams) {

View File

@@ -9,7 +9,7 @@ import { service } from '@ember/service';
import type RouterService from '@ember/routing/router-service';
export default class SyncSecretsDestinationsDestinationIndexRoute extends Route {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
redirect() {
this.router.transitionTo('vault.cluster.sync.secrets.destinations.destination.details');

View File

@@ -34,7 +34,7 @@ interface SyncSecretsDestinationsController extends Controller {
export default class SyncSecretsDestinationsIndexRoute extends Route {
@service declare readonly store: StoreService;
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
queryParams = {
page: {

View File

@@ -13,7 +13,7 @@ import type StoreService from 'vault/services/store';
import type VersionService from 'vault/services/version';
export default class SyncSecretsOverviewRoute extends Route {
@service declare readonly router: RouterService;
@service('app-router') declare readonly router: RouterService;
@service declare readonly store: StoreService;
@service declare readonly flags: FlagsService;
@service declare readonly version: VersionService;

View File

@@ -136,7 +136,6 @@
"ember-qunit": "^8.0.1",
"ember-resolver": "^11.0.1",
"ember-responsive": "5.0.0",
"ember-router-helpers": "^0.4.0",
"ember-service-worker": "meirish/ember-service-worker#configurable-scope",
"ember-sinon-qunit": "^7.4.0",
"ember-source": "~5.4.0",

View File

@@ -0,0 +1,77 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'vault/tests/helpers';
import { setupEngine } from 'ember-engines/test-support';
import { click, render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import Sinon from 'sinon';
module('Integration | Helper | transition-to', function (hooks) {
setupRenderingTest(hooks);
// using 'kv' here for testing, but this could be any Ember engine in the app
// sets this.engine, which we use to set context for the component testing service:app-router
setupEngine(hooks, 'kv');
hooks.beforeEach(function () {
this.router = this.owner.lookup('service:router');
this.router.reopen({
transitionTo: Sinon.stub(),
transitionToExternal: Sinon.stub(),
});
});
test('it does not call transition on render', async function (assert) {
await render(hbs`<button data-test-btn {{on "click" (transition-to "vault.cluster")}}>Click</button>`);
assert.true(this.router.transitionTo.notCalled, 'transitionTo not called on render');
assert.true(this.router.transitionToExternal.notCalled, 'transitionToExternal not called on render');
});
test('it calls transitionTo correctly', async function (assert) {
await render(
hbs`<button data-test-btn {{on "click" (transition-to "vault.cluster" "foobar" "baz")}}>Click</button>`
);
await click('[data-test-btn]');
assert.true(this.router.transitionTo.calledOnce, 'transitionTo called once on click');
assert.deepEqual(
this.router.transitionTo.args[0],
['vault.cluster', 'foobar', 'baz'],
'transitionTo called with positional params'
);
assert.true(this.router.transitionToExternal.notCalled, 'transitionToExternal not called');
});
test('it calls transitionToExternal correctly', async function (assert) {
await render(
hbs`<button data-test-btn {{on "click" (transition-to "vault.cluster" "foobar" "baz" external=true)}}>Click</button>`
);
await click('[data-test-btn]');
assert.true(this.router.transitionToExternal.calledOnce, 'transitionToExternal called');
assert.deepEqual(
this.router.transitionToExternal.args[0],
['vault.cluster', 'foobar', 'baz'],
'transitionToExternal called with positional params'
);
assert.true(this.router.transitionTo.notCalled, 'transitionTo not called');
});
// This test is confusing (and admittedly not ideal) because stubbing routers gets strange,
// but if you go into the TransitionTo class and console.log owner.lookup('service:router') in get router()
// you'll see the getter returns 'service:app-router' (because of the context setup)
// so although we're asserting this.router, the TransitionTo helper is using "service:app-router" under the hood.
// This test passing, indirectly means the helper works as expected. Failures might be something like "global failure: TypeError: this.router is undefined"
test('it uses service:app-router when base router undefined', async function (assert) {
await render(
hbs`<button data-test-btn {{on "click" (transition-to "vault.cluster" "foobar" "baz" external=true)}}>Click</button>`,
{ owner: this.engine }
);
await click('[data-test-btn]');
assert.true(this.router.transitionToExternal.calledOnce, 'transitionToExternal called');
});
});

View File

@@ -7613,7 +7613,7 @@ __metadata:
languageName: node
linkType: hard
"ember-cli-babel@npm:^7.1.2, ember-cli-babel@npm:^7.1.3, ember-cli-babel@npm:^7.10.0, ember-cli-babel@npm:^7.13.0, ember-cli-babel@npm:^7.18.0, ember-cli-babel@npm:^7.20.0, ember-cli-babel@npm:^7.22.1, ember-cli-babel@npm:^7.23.0, ember-cli-babel@npm:^7.26.11, ember-cli-babel@npm:^7.26.3, ember-cli-babel@npm:^7.26.4, ember-cli-babel@npm:^7.26.5, ember-cli-babel@npm:^7.26.6, ember-cli-babel@npm:^7.26.8, ember-cli-babel@npm:^7.5.0, ember-cli-babel@npm:^7.7.3":
"ember-cli-babel@npm:^7.1.2, ember-cli-babel@npm:^7.1.3, ember-cli-babel@npm:^7.10.0, ember-cli-babel@npm:^7.13.0, ember-cli-babel@npm:^7.18.0, ember-cli-babel@npm:^7.22.1, ember-cli-babel@npm:^7.23.0, ember-cli-babel@npm:^7.26.11, ember-cli-babel@npm:^7.26.3, ember-cli-babel@npm:^7.26.4, ember-cli-babel@npm:^7.26.5, ember-cli-babel@npm:^7.26.6, ember-cli-babel@npm:^7.26.8, ember-cli-babel@npm:^7.5.0, ember-cli-babel@npm:^7.7.3":
version: 7.26.11
resolution: "ember-cli-babel@npm:7.26.11"
dependencies:
@@ -8652,15 +8652,6 @@ __metadata:
languageName: node
linkType: hard
"ember-router-helpers@npm:^0.4.0":
version: 0.4.0
resolution: "ember-router-helpers@npm:0.4.0"
dependencies:
ember-cli-babel: ^7.20.0
checksum: e847ceb1061f87416d6bb5d72ef539fda738a24086051bc94d740117c6353b3406c65247ac8190b8572df008a70d9f801e224d38489170129c5ca6c4ec7f206e
languageName: node
linkType: hard
"ember-service-worker@meirish/ember-service-worker#configurable-scope":
version: 9.0.1
resolution: "ember-service-worker@https://github.com/meirish/ember-service-worker.git#commit=dda14187aace0d73ecdb6a55beac2194a3aec01b"
@@ -18829,7 +18820,6 @@ __metadata:
ember-qunit: ^8.0.1
ember-resolver: ^11.0.1
ember-responsive: 5.0.0
ember-router-helpers: ^0.4.0
ember-service-worker: "meirish/ember-service-worker#configurable-scope"
ember-sinon-qunit: ^7.4.0
ember-source: ~5.4.0