Repository: hashicorp/vault
File: ui/app/components/mount-backend-form.ts (TypeScript)

Code before:
 * @param {string} mountType=auth - The type of engine to mount, either 'secret' or 'auth'.
 *
 */

type MountModel = MountSecretBackendModel | AuthEnableModel;

interface Args {
  mountModel: MountModel;
  mountType: 'secret' | 'auth';
  onMountSuccess: (type: string, path: string, useEngineRoute: boolean) => void;
}

export default class MountBackendForm extends Component<Args> {
  @service declare readonly store: Store;
  @service declare readonly flashMessages: FlashMessageService;

  // validation related properties
  @tracked modelValidations = null;
  @tracked invalidFormAlert = null;

  @tracked errorMessage: string | string[] = '';

  constructor(owner: unknown, args: Args) {
    super(owner, args);

    if (!this.args.mountType) {
      debug(`'mountType' is required to be passed into the component. Must return "auth" or "secret".`);
    }
  }

  willDestroy() {
    // components are torn down after store is unloaded and will cause an error if attempt to unload record
    const noTeardown = this.store && !this.store.isDestroying;
    if (noTeardown && this.args?.mountModel?.isNew) {
      this.args.mountModel.unloadRecord();
    }
    super.willDestroy();
  }

  checkPathChange(backendType: string) {
    if (!backendType) return;
    const mount = this.args.mountModel;
    const currentPath = mount.path;
    // while mountType is always set to 'secret' or 'auth', there's situations where we pass in an empty string (such as on setMountType) and in this case we want to default to returning auth methods.
    const mountsByType = filterEnginesByMountType(
      this.args.mountType ? this.args.mountType : 'auth',
      true
    ).map((engine) => engine.type);

    // if the current path has not been altered by user,
    // change it here to match the new type

Review comment (security):
Love the assertion! 

The [typical pattern I've seen us do is using](https://github.com/hashicorp/vault/blob/main/ui/lib/core/addon/components/form-field.js#L83) `assert` - I'm not sure if it makes much of a difference, but it is slightly cleaner by not needing to wrap it in a conditional.

```js
assert( `@mountType is required. Must be "auth" or "secret".`', presence(this.args.mountType);



Code after:
 * @param {function} onMountSuccess - A function that transitions once the Mount has been successfully posted.
 * @param {string} mountCategory=auth - The type of engine to mount, either 'secret' or 'auth'.
 *
 */

type MountModel = MountSecretBackendModel | AuthEnableModel;

interface Args {
  mountModel: MountModel;
  mountCategory: 'secret' | 'auth';
  onMountSuccess: (type: string, path: string, useEngineRoute: boolean) => void;
}

export default class MountBackendForm extends Component<Args> {
  @service declare readonly store: Store;
  @service declare readonly flashMessages: FlashMessageService;

  // validation related properties
  @tracked modelValidations = null;
  @tracked invalidFormAlert = null;

  @tracked errorMessage: string | string[] = '';

  constructor(owner: unknown, args: Args) {
    super(owner, args);

    assert(`@mountCategory is required. Must be "auth" or "secret".`, presence(this.args.mountCategory));
  }

  willDestroy() {
    // components are torn down after store is unloaded and will cause an error if attempt to unload record
    const noTeardown = this.store && !this.store.isDestroying;
    if (noTeardown && this.args?.mountModel?.isNew) {
      this.args.mountModel.unloadRecord();
    }
    super.willDestroy();
  }

  checkPathChange(backendType: string) {
    if (!backendType) return;
    const mount = this.args.mountModel;
    const currentPath = mount.path;
    // mountCategory is usually 'secret' or 'auth', but sometimes an empty string is passed in (like when we click the cancel button).
    // In these cases, we should default to returning auth methods.
    const mountsByType = filterEnginesByMountCategory({
      mountCategory: this.args.mountCategory ?? 'auth',
      isEnterprise: true,
    }).map((engine) => engine.type);
    // if the current path has not been altered by user,
    // change it here to match the new type
    if (!currentPath || mountsByType.includes(currentPath)) {