Skip to content

[PM-18721][PM-21272] Integrate InputPasswordComponent in AccountRecoveryDialogComponent #14662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: auth/pm-18721/integrate-input-password-component-in-dialogs
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9606947
[Account Recovery][PM-18721] setup AccountRecoveryDialogComponent HTMโ€ฆ
rr-bw May 7, 2025
0c17789
[Account Recovery][PM-18721] add generatePassword() logic to InputPasโ€ฆ
rr-bw May 7, 2025
5c80984
[Account Recovery][PM-18721] add copy() logic to InputPasswordComponent
rr-bw May 7, 2025
787fddf
[Account Recovery][PM-18721] feature flag AccountRecoveryDialogComponent
rr-bw May 7, 2025
aa64267
[Account Recovery][PM-18721] convert enum to as const
rr-bw May 14, 2025
7ca7918
[Account Recovery][PM-18721] pass message as @Input
rr-bw May 14, 2025
42e56d0
[Account Recovery][PM-18721] disable button during submit process
rr-bw May 14, 2025
db7a401
[Account Recovery][PM-18721] fix type errors
rr-bw May 14, 2025
9360bb0
[Account Recovery][PM-18721] update property name/type
rr-bw May 14, 2025
9b13ff5
[Account Recovery][PM-18721] convert retreival of policy options to bโ€ฆ
rr-bw May 14, 2025
5d7ceac
[Account Recovery][PM-18721] remove unused prop
rr-bw May 28, 2025
53d4a14
[Account Recovery][PM-18721] use early return
rr-bw May 28, 2025
09128e2
[Account Recovery][PM-18721] update typing on open method
rr-bw May 28, 2025
1fccdde
[Account Recovery][PM-18721] handle cross-component submit process
rr-bw May 28, 2025
60e2bdc
[Account Recovery][PM-18721] add type check
rr-bw May 28, 2025
801f5b1
[Account Recovery][PM-18721] update as const / type
rr-bw May 29, 2025
03415ea
[Account Recovery][PM-18721] remove message Input as it's now handledโ€ฆ
rr-bw May 30, 2025
45f8c19
[Account Recovery][PM-18721] update type for organizationId
rr-bw May 30, 2025
1ae47e4
[Account Recovery][PM-18721] catch missing user details client-side
rr-bw Jun 3, 2025
d562acc
[Account Recovery][PM-18721] move error handling within flag, and revโ€ฆ
rr-bw Jun 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
protected i18nService: I18nService,
protected keyService: KeyService,
protected validationService: ValidationService,
private logService: LogService,
protected logService: LogService,

Check warning on line 89 in apps/web/src/app/admin-console/common/base-members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/common/base-members.component.ts#L89

Added line #L89 was not covered by tests
protected userNamePipe: UserNamePipe,
protected dialogService: DialogService,
protected organizationManagementPreferencesService: OrganizationManagementPreferencesService,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<bit-dialog [title]="'recoverAccount' | i18n" [subtitle]="dialogData.name">
<ng-container bitDialogContent>
<bit-callout type="warning"
>{{ "resetPasswordLoggedOutWarning" | i18n: loggedOutWarningName }}
</bit-callout>

<auth-input-password
[flow]="inputPasswordFlow"
[masterPasswordPolicyOptions]="masterPasswordPolicyOptions$ | async"
(onPasswordFormSubmit)="handlePasswordFormSubmit($event)"
(isSubmitting)="handleIsSubmittingChange($event)"
></auth-input-password>
</ng-container>

<ng-container bitDialogFooter>
<button
type="button"
bitButton
buttonType="primary"
[disabled]="submitting$ | async"
(click)="handlePrimaryButtonClick()"
>
{{ "save" | i18n }}
</button>
<button type="button" bitButton buttonType="secondary" bitDialogClose>
{{ "cancel" | i18n }}
</button>
</ng-container>
</bit-dialog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { CommonModule } from "@angular/common";
import { Component, Inject, ViewChild } from "@angular/core";
import { BehaviorSubject, combineLatest, map, switchMap } from "rxjs";

Check warning on line 3 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L1-L3

Added lines #L1 - L3 were not covered by tests

import {

Check warning on line 5 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L5

Added line #L5 was not covered by tests
InputPasswordComponent,
InputPasswordFlow,
PasswordInputResult,
} from "@bitwarden/auth/angular";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";

Check warning on line 14 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L10-L14

Added lines #L10 - L14 were not covered by tests
import { OrganizationId } from "@bitwarden/common/types/guid";
import {

Check warning on line 16 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L16

Added line #L16 was not covered by tests
ButtonModule,
CalloutModule,
DIALOG_DATA,
DialogConfig,
DialogModule,
DialogRef,
DialogService,
ToastService,
} from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";

Check warning on line 26 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L26

Added line #L26 was not covered by tests

import { OrganizationUserResetPasswordService } from "../../services/organization-user-reset-password/organization-user-reset-password.service";

Check warning on line 28 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L28

Added line #L28 was not covered by tests

/**
* Encapsulates a few key data inputs needed to initiate an account recovery
* process for the organization user in question.
*/
export type AccountRecoveryDialogData = {
/**
* The organization user's full name
*/
name: string;

/**
* The organization user's email address
*/
email: string;

/**
* The `organizationUserId` for the user
*/
organizationUserId: string;

/**
* The organization's `organizationId`
*/
organizationId: OrganizationId;
};

export const AccountRecoveryDialogResultType = {

Check warning on line 56 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L56

Added line #L56 was not covered by tests
Ok: "ok",
} as const;

export type AccountRecoveryDialogResultType =
(typeof AccountRecoveryDialogResultType)[keyof typeof AccountRecoveryDialogResultType];

/**
* Used in a dialog for initiating the account recovery process against a
* given organization user. An admin will access this form when they want to
* reset a user's password and log them out of sessions.
*/
@Component({
standalone: true,
selector: "app-account-recovery-dialog",
templateUrl: "account-recovery-dialog.component.html",
imports: [
ButtonModule,
CalloutModule,
CommonModule,
DialogModule,
I18nPipe,
InputPasswordComponent,
],
})
export class AccountRecoveryDialogComponent {

Check warning on line 81 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L81

Added line #L81 was not covered by tests
@ViewChild(InputPasswordComponent)
inputPasswordComponent: InputPasswordComponent | undefined = undefined;

Check warning on line 83 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L83

Added line #L83 was not covered by tests

private parentSubmittingBehaviorSubject = new BehaviorSubject(false);
parentSubmitting$ = this.parentSubmittingBehaviorSubject.asObservable();

Check warning on line 86 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L85-L86

Added lines #L85 - L86 were not covered by tests

private childSubmittingBehaviorSubject = new BehaviorSubject(false);
childSubmitting$ = this.childSubmittingBehaviorSubject.asObservable();

Check warning on line 89 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L88-L89

Added lines #L88 - L89 were not covered by tests

submitting$ = combineLatest([this.parentSubmitting$, this.childSubmitting$]).pipe(

Check warning on line 91 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L91

Added line #L91 was not covered by tests
map(([parentIsSubmitting, childIsSubmitting]) => parentIsSubmitting || childIsSubmitting),
);
Comment on lines +85 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've fixed the race condition, but I think this is still a lot of boilerplate just to handle a form submission. I assume this would have to be repeated in every parent component that wants to use this child component.

Does the child need to know about the form submit state at all? The submission process starts when handlePrimaryButtonClick is called, and it ends when handlePasswordFormSubmit is finished, or if the child emits an error. If that's the case, the parent should be able to handle all of that by itself, which is also better design because the parent owns the form.


๐Ÿ’ญ I also like the suggestion in Slack:

Directly referencing a component is highly discouraged. Could you instead invert the relationship so that the action happens in the parent?

It does feel a bit unusual that the child is handling the parent's submit action. There's quite a bit of logic in that child component, what if it were extracted to a service that the parent could call (thereby handling its own form submission), and the child is more presentational, simply emitting form values? That's a fairly large change so it doesn't need to be done in this PR (if at all), just mentioning it as feedback.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The submission process starts when handlePrimaryButtonClick is called, and it ends when handlePasswordFormSubmit is finished, or if the child emits an error. If that's the case, the parent should be able to handle all of that by itself

The submit process can also end if the child returns early, without emitting. That means handlePasswordFormSubmit would never get called in the parent, leaving is in a perpetual "submitting" state.

That is, if we merely set submitting to true in handlePrimaryButtonClick, and then set it to false in handlePasswordFormSubmit, then that false set would never get called in a case where InputPasswordComponent.submit() returns early without emitting. That's the case I was trying to solve in my previous implementation here (but had the race condition).

cc: @JaredSnider-Bitwarden let me know if you have any other thoughts on this.

Copy link
Contributor Author

@rr-bw rr-bw Jun 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's quite a bit of logic in that child component, what if it were extracted to a service that the parent could call (thereby handling its own form submission), and the child is more presentational, simply emitting form values? That's a fairly large change so it doesn't need to be done in this PR (if at all), just mentioning it as feedback.

Yea the InputPasswordComponent has grown in scope over time. I will do a retro soon to investigate if/how we could potentially refactor things.


masterPasswordPolicyOptions$ = this.accountService.activeAccount$.pipe(

Check warning on line 95 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L95

Added line #L95 was not covered by tests
getUserId,
switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId)),

Check warning on line 97 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L97

Added line #L97 was not covered by tests
);

inputPasswordFlow = InputPasswordFlow.ChangePasswordDelegation;

Check warning on line 100 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L100

Added line #L100 was not covered by tests

get loggedOutWarningName() {
return this.dialogData.name != null ? this.dialogData.name : this.i18nService.t("thisUser");
}

constructor(
@Inject(DIALOG_DATA) protected dialogData: AccountRecoveryDialogData,
private accountService: AccountService,
private dialogRef: DialogRef<AccountRecoveryDialogResultType>,
private i18nService: I18nService,
private logService: LogService,
private policyService: PolicyService,
private resetPasswordService: OrganizationUserResetPasswordService,
private toastService: ToastService,

Check warning on line 114 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L107-L114

Added lines #L107 - L114 were not covered by tests
) {}

handlePrimaryButtonClick = async () => {

Check warning on line 117 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L117

Added line #L117 was not covered by tests
if (!this.inputPasswordComponent) {
throw new Error("InputPasswordComponent is not initialized");

Check warning on line 119 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L119

Added line #L119 was not covered by tests
}

await this.inputPasswordComponent.submit();

Check warning on line 122 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L122

Added line #L122 was not covered by tests
};

async handlePasswordFormSubmit(passwordInputResult: PasswordInputResult) {
this.parentSubmittingBehaviorSubject.next(true);

Check warning on line 126 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L126

Added line #L126 was not covered by tests

try {
await this.resetPasswordService.resetMasterPassword(

Check warning on line 129 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L128-L129

Added lines #L128 - L129 were not covered by tests
passwordInputResult.newPassword,
this.dialogData.email,
this.dialogData.organizationUserId,
this.dialogData.organizationId,
);

this.toastService.showToast({

Check warning on line 136 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L136

Added line #L136 was not covered by tests
variant: "success",
title: "",
message: this.i18nService.t("resetPasswordSuccess"),
});
} catch (e) {
this.logService.error(e);

Check warning on line 142 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L142

Added line #L142 was not covered by tests
} finally {
this.parentSubmittingBehaviorSubject.next(false);

Check warning on line 144 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L144

Added line #L144 was not covered by tests
}

this.dialogRef.close(AccountRecoveryDialogResultType.Ok);

Check warning on line 147 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L147

Added line #L147 was not covered by tests
}

protected handleIsSubmittingChange(isSubmitting: boolean) {
this.childSubmittingBehaviorSubject.next(isSubmitting);

Check warning on line 151 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L151

Added line #L151 was not covered by tests
}

/**
* Strongly typed helper to open an `AccountRecoveryDialogComponent`
* @param dialogService Instance of the dialog service that will be used to open the dialog
* @param dialogConfig Configuration for the dialog
*/
static open = (

Check warning on line 159 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L159

Added line #L159 was not covered by tests
dialogService: DialogService,
dialogConfig: DialogConfig<
AccountRecoveryDialogData,
DialogRef<AccountRecoveryDialogResultType, unknown>
>,
) => {
return dialogService.open<AccountRecoveryDialogResultType, AccountRecoveryDialogData>(

Check warning on line 166 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/account-recovery-dialog.component.ts#L166

Added line #L166 was not covered by tests
AccountRecoveryDialogComponent,
dialogConfig,
);
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./account-recovery-dialog.component";

Check warning on line 1 in apps/web/src/app/admin-console/organizations/members/components/account-recovery/index.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/components/account-recovery/index.ts#L1

Added line #L1 was not covered by tests
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { OrganizationId } from "@bitwarden/common/types/guid";
import {
DIALOG_DATA,
DialogConfig,
Expand Down Expand Up @@ -47,7 +48,7 @@ export type ResetPasswordDialogData = {
/**
* The organization's `organizationId`
*/
organizationId: string;
organizationId: OrganizationId;
};

// FIXME: update to use a const object instead of a typescript enum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { DialogService, SimpleDialogOptions, ToastService } from "@bitwarden/components";
import { KeyService } from "@bitwarden/key-management";
Expand All @@ -66,6 +67,10 @@
import { OrganizationUserView } from "../core/views/organization-user.view";
import { openEntityEventsDialog } from "../manage/entity-events.component";

import {

Check warning on line 70 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L70

Added line #L70 was not covered by tests
AccountRecoveryDialogComponent,
AccountRecoveryDialogResultType,
} from "./components/account-recovery/account-recovery-dialog.component";
import { BulkConfirmDialogComponent } from "./components/bulk/bulk-confirm-dialog.component";
import { BulkDeleteDialogComponent } from "./components/bulk/bulk-delete-dialog.component";
import { BulkEnableSecretsManagerDialogComponent } from "./components/bulk/bulk-enable-sm-dialog.component";
Expand All @@ -90,7 +95,6 @@

@Component({
templateUrl: "members.component.html",
standalone: false,
})
export class MembersComponent extends BaseMembersComponent<OrganizationUserView> {
userType = OrganizationUserType;
Expand Down Expand Up @@ -738,11 +742,44 @@
}

async resetPassword(user: OrganizationUserView) {
const changePasswordRefactorFlag = await this.configService.getFeatureFlag(

Check warning on line 745 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L745

Added line #L745 was not covered by tests
FeatureFlag.PM16117_ChangeExistingPasswordRefactor,
);

if (changePasswordRefactorFlag) {
if (!user || !user.email || !user.id) {
this.toastService.showToast({

Check warning on line 751 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L751

Added line #L751 was not covered by tests
variant: "error",
title: this.i18nService.t("errorOccurred"),
message: this.i18nService.t("orgUserDetailsNotFound"),
});
this.logService.error("Org user details not found when attempting account recovery");

Check warning on line 756 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L756

Added line #L756 was not covered by tests

return;

Check warning on line 758 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L758

Added line #L758 was not covered by tests
}

const dialogRef = AccountRecoveryDialogComponent.open(this.dialogService, {

Check warning on line 761 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L761

Added line #L761 was not covered by tests
data: {
name: this.userNamePipe.transform(user),
email: user.email,
organizationId: this.organization.id as OrganizationId,
organizationUserId: user.id,
},
});

const result = await lastValueFrom(dialogRef.closed);

Check warning on line 770 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L770

Added line #L770 was not covered by tests
if (result === AccountRecoveryDialogResultType.Ok) {
await this.load();

Check warning on line 772 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L772

Added line #L772 was not covered by tests
}

return;

Check warning on line 775 in apps/web/src/app/admin-console/organizations/members/members.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/admin-console/organizations/members/members.component.ts#L775

Added line #L775 was not covered by tests
}

const dialogRef = ResetPasswordComponent.open(this.dialogService, {
data: {
name: this.userNamePipe.transform(user),
email: user != null ? user.email : null,
organizationId: this.organization.id,
organizationId: this.organization.id as OrganizationId,
id: user != null ? user.id : null,
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { EncryptService } from "@bitwarden/common/key-management/crypto/abstract
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { UserId } from "@bitwarden/common/types/guid";
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { UserKey } from "@bitwarden/common/types/key";
import {
Argon2KdfConfig,
Expand Down Expand Up @@ -96,7 +96,7 @@ export class OrganizationUserResetPasswordService
newMasterPassword: string,
email: string,
orgUserId: string,
orgId: string,
orgId: OrganizationId,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eliykat

When I updated the organizationId property type from string to OrganizationId in the new AccountRecoveryDialogComponent (here), it meant I have to update the param type here in the resetPassword() method as well. Since that method is also used by the old ResetPasswordComponent, it means I had to make some changes to the old code (here and here).

Since I'd rather changes not leak outside the feature flag, would it be better for me to set the param type in resetPassword() to be orgId: string | OrganizationId -- and then cleanup when the flag is removed?

): Promise<void> {
const response = await this.organizationUserApiService.getOrganizationUserResetPasswordDetails(
orgId,
Expand Down
3 changes: 3 additions & 0 deletions apps/web/src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,9 @@
"disable": {
"message": "Turn off"
},
"orgUserDetailsNotFound": {
"message": "Org user details not found"
},
"revokeAccess": {
"message": "Revoke access"
},
Expand Down
Loading