Skip to content

Commit

Permalink
Merge branch 'main' into pm-8161-payment-optional-trial-mvp
Browse files Browse the repository at this point in the history
  • Loading branch information
cyprain-okeke committed Nov 4, 2024
2 parents 3264ceb + d669d20 commit 0783cc6
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ <h3 class="tw-mt-4">
<button
*ngIf="editMode"
type="button"
bitIconButton="bwi-close"
buttonType="danger"
bitFormButton
[appA11yTitle]="'remove' | i18n"
[bitAction]="remove"
[disabled]="loading"
></button>
<button
*ngIf="editMode && params.managedByOrganization === true"
type="button"
bitIconButton="bwi-trash"
buttonType="danger"
bitFormButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface MemberDialogParams {
isOnSecretsManagerStandalone: boolean;
initialTab?: MemberDialogTab;
numConfirmedMembers: number;
managedByOrganization?: boolean;
}

export enum MemberDialogResult {
Expand Down Expand Up @@ -464,7 +465,7 @@ export class MemberDialogComponent implements OnDestroy {
this.close(MemberDialogResult.Saved);
};

delete = async () => {
remove = async () => {
if (!this.editMode) {
return;
}
Expand Down Expand Up @@ -561,6 +562,39 @@ export class MemberDialogComponent implements OnDestroy {
this.close(MemberDialogResult.Restored);
};

delete = async () => {
if (!this.editMode) {
return;
}

const confirmed = await this.dialogService.openSimpleDialog({
title: {
key: "deleteOrganizationUser",
placeholders: [this.params.name],
},
content: { key: "deleteOrganizationUserWarning" },
type: "warning",
acceptButtonText: { key: "delete" },
cancelButtonText: { key: "cancel" },
});

if (!confirmed) {
return false;
}

await this.organizationUserApiService.deleteOrganizationUser(
this.params.organizationId,
this.params.organizationUserId,
);

this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("organizationUserDeleted", this.params.name),
});
this.close(MemberDialogResult.Deleted);
};

ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,17 @@
<i aria-hidden="true" class="bwi bwi-close"></i> {{ "remove" | i18n }}
</span>
</button>
<button
*ngIf="u.managedByOrganization === true"
type="button"
bitMenuItem
(click)="deleteUser(u)"
>
<span class="tw-text-danger">
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
{{ "delete" | i18n }}
</span>
</button>
</bit-menu>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
isOnSecretsManagerStandalone: this.orgIsOnSecretsManagerStandalone,
initialTab: initialTab,
numConfirmedMembers: this.dataSource.confirmedUserCount,
managedByOrganization: user?.managedByOrganization,
},
});

Expand Down Expand Up @@ -725,6 +726,40 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
return true;
}

async deleteUser(user: OrganizationUserView) {
const confirmed = await this.dialogService.openSimpleDialog({
title: {
key: "deleteOrganizationUser",
placeholders: [this.userNamePipe.transform(user)],
},
content: { key: "deleteOrganizationUserWarning" },
type: "warning",
acceptButtonText: { key: "delete" },
cancelButtonText: { key: "cancel" },
});

if (!confirmed) {
return false;
}

this.actionPromise = this.organizationUserApiService.deleteOrganizationUser(
this.organization.id,
user.id,
);
try {
await this.actionPromise;
this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("organizationUserDeleted", this.userNamePipe.transform(user)),
});
this.dataSource.removeUser(user);
} catch (e) {
this.validationService.showError(e);
}
this.actionPromise = null;
}

private async noMasterPasswordConfirmationDialog(user: OrganizationUserView) {
return this.dialogService.openSimpleDialog({
title: {
Expand Down
26 changes: 26 additions & 0 deletions apps/web/src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -9604,6 +9604,32 @@
"single-org-revoked-user-warning": {
"message": "Non-compliant members will be revoked. Administrators can restore members once they leave all other organizations."
},
"deleteOrganizationUser": {
"message": "Delete $NAME$",
"placeholders": {
"name": {
"content": "$1",
"example": "John Doe"
},
"description": "Title for the delete organization user dialog"
}
},
"deleteOrganizationUserWarning": {
"message": "When a member is deleted, their Bitwarden account and individual vault data will be permanently deleted. Collection data will remain in the organization. To reinstate them they must create an account and be onboarded again.",
"description": "Warning for the delete organization user dialog"
},
"organizationUserDeleted": {
"message": "Deleted $NAME$",
"placeholders": {
"name": {
"content": "$1",
"example": "John Doe"
}
}
},
"organizationUserDeletedDesc": {
"message": "The user was removed from the organization and all associated user data has been deleted."
},
"suspendedOrganizationTitle": {
"message": "The $ORGANIZATION$ is suspended",
"placeholders": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,11 @@ export abstract class OrganizationUserApiService {
organizationId: string,
ids: string[],
): Promise<ListResponse<OrganizationUserBulkResponse>>;

/**
* Remove an organization user's access to the organization and delete their account data
* @param organizationId - Identifier for the organization the user belongs to
* @param id - Organization user identifier
*/
abstract deleteOrganizationUser(organizationId: string, id: string): Promise<void>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -359,4 +359,14 @@ export class DefaultOrganizationUserApiService implements OrganizationUserApiSer
);
return new ListResponse(r, OrganizationUserBulkResponse);
}

deleteOrganizationUser(organizationId: string, id: string): Promise<void> {
return this.apiService.send(
"DELETE",
"/organizations/" + organizationId + "/users/" + id + "/delete-account",
null,
true,
false,
);
}
}

0 comments on commit 0783cc6

Please sign in to comment.