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

Code before:
}

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[] = '';

  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;
    const mountTypes = ALL_ENGINES.filter(
      (engine) => engine.mountType === this.args.mountType || engine.mountType === 'both'
    ).map((engine) => engine.type);

    // if the current path has not been altered by user,
    // change it here to match the new type
    if (!currentPath || mountTypes.includes(currentPath)) {
      mount.path = backendType;
    }
  }

  typeChangeSideEffect(type: string) {
    if (this.args.mountType !== 'secret') return;
    if (type === 'pki') {
      // If type PKI, set max lease to ~10years
      this.args.mountModel.config.maxLeaseTtl = '3650d';
    } else {
      // otherwise reset
      this.args.mountModel.config.maxLeaseTtl = 0;
    }
  }

  checkModelValidity(model: MountModel) {
    const { isValid, state, invalidFormMessage } = model.validate();
    this.modelValidations = state;
    this.invalidFormAlert = invalidFormMessage;

Review comment (security):
since filtering by whether it's "secret" or "auth" happens a lot, it seems like that could be useful as another util function in the `all-engines-metadata.ts` util file. 

Code after:
  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)) {
      mount.path = backendType;
    }
  }

  typeChangeSideEffect(type: string) {
    if (this.args.mountCategory !== 'secret') return;
    if (type === 'pki') {
      // If type PKI, set max lease to ~10years
      this.args.mountModel.config.maxLeaseTtl = '3650d';