mirror of
https://github.com/bitwarden/clients.git
synced 2025-12-22 05:07:16 +00:00
[PM-28746] Item transfer event logs (#18032)
* [PM-28746] Add item organization event types and i18n strings * [PM-28746] Log event when transfer is accepted or declined
This commit is contained in:
@@ -452,6 +452,12 @@ export class EventService {
|
||||
this.getShortId(ev.organizationId),
|
||||
);
|
||||
break;
|
||||
case EventType.Organization_ItemOrganization_Accepted:
|
||||
msg = humanReadableMsg = this.i18nService.t("userAcceptedTransfer");
|
||||
break;
|
||||
case EventType.Organization_ItemOrganization_Declined:
|
||||
msg = humanReadableMsg = this.i18nService.t("userDeclinedTransfer");
|
||||
break;
|
||||
|
||||
// Policies
|
||||
case EventType.Policy_Updated: {
|
||||
|
||||
@@ -4214,6 +4214,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"userAcceptedTransfer": {
|
||||
"message": "Accepted transfer to organization ownership."
|
||||
},
|
||||
"userDeclinedTransfer": {
|
||||
"message": "Revoked for declining transfer to organization ownership."
|
||||
},
|
||||
"invitedUserId": {
|
||||
"message": "Invited user $ID$.",
|
||||
"placeholders": {
|
||||
@@ -12411,7 +12417,7 @@
|
||||
"placeholders": {
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
"example": "My Org Name"
|
||||
"example": "My Org Name"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -12420,7 +12426,7 @@
|
||||
"placeholders": {
|
||||
"organization": {
|
||||
"content": "$1",
|
||||
"example": "My Org Name"
|
||||
"example": "My Org Name"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -79,6 +79,8 @@ export enum EventType {
|
||||
Organization_CollectionManagement_LimitItemDeletionDisabled = 1615,
|
||||
Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsEnabled = 1616,
|
||||
Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsDisabled = 1617,
|
||||
Organization_ItemOrganization_Accepted = 1618,
|
||||
Organization_ItemOrganization_Declined = 1619,
|
||||
|
||||
Policy_Updated = 1700,
|
||||
|
||||
|
||||
@@ -3,11 +3,13 @@ import { firstValueFrom, of, Subject } from "rxjs";
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { CollectionService, CollectionView } from "@bitwarden/admin-console/common";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -37,6 +39,7 @@ describe("DefaultVaultItemsTransferService", () => {
|
||||
let mockI18nService: MockProxy<I18nService>;
|
||||
let mockDialogService: MockProxy<DialogService>;
|
||||
let mockToastService: MockProxy<ToastService>;
|
||||
let mockEventCollectionService: MockProxy<EventCollectionService>;
|
||||
let mockConfigService: MockProxy<ConfigService>;
|
||||
|
||||
const userId = "user-id" as UserId;
|
||||
@@ -71,6 +74,7 @@ describe("DefaultVaultItemsTransferService", () => {
|
||||
mockI18nService = mock<I18nService>();
|
||||
mockDialogService = mock<DialogService>();
|
||||
mockToastService = mock<ToastService>();
|
||||
mockEventCollectionService = mock<EventCollectionService>();
|
||||
mockConfigService = mock<ConfigService>();
|
||||
|
||||
mockI18nService.t.mockImplementation((key) => key);
|
||||
@@ -85,6 +89,7 @@ describe("DefaultVaultItemsTransferService", () => {
|
||||
mockI18nService,
|
||||
mockDialogService,
|
||||
mockToastService,
|
||||
mockEventCollectionService,
|
||||
mockConfigService,
|
||||
);
|
||||
});
|
||||
@@ -774,6 +779,63 @@ describe("DefaultVaultItemsTransferService", () => {
|
||||
expect(mockDialogService.open).toHaveBeenCalledTimes(4);
|
||||
expect(mockCipherService.shareManyWithServer).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("event logs", () => {
|
||||
it("logs accepted event when user accepts transfer", async () => {
|
||||
const personalCiphers = [{ id: "cipher-1" } as CipherView];
|
||||
setupMocksForEnforcementScenario({
|
||||
policies: [policy],
|
||||
organizations: [organization],
|
||||
ciphers: personalCiphers,
|
||||
defaultCollection: {
|
||||
id: collectionId,
|
||||
organizationId: organizationId,
|
||||
isDefaultCollection: true,
|
||||
} as CollectionView,
|
||||
});
|
||||
|
||||
mockDialogService.open.mockReturnValueOnce(
|
||||
createMockDialogRef(TransferItemsDialogResult.Accepted),
|
||||
);
|
||||
mockCipherService.shareManyWithServer.mockResolvedValue(undefined);
|
||||
|
||||
await service.enforceOrganizationDataOwnership(userId);
|
||||
|
||||
expect(mockEventCollectionService.collect).toHaveBeenCalledWith(
|
||||
EventType.Organization_ItemOrganization_Accepted,
|
||||
undefined,
|
||||
undefined,
|
||||
organizationId,
|
||||
);
|
||||
});
|
||||
|
||||
it("logs declined event when user rejects transfer", async () => {
|
||||
const personalCiphers = [{ id: "cipher-1" } as CipherView];
|
||||
setupMocksForEnforcementScenario({
|
||||
policies: [policy],
|
||||
organizations: [organization],
|
||||
ciphers: personalCiphers,
|
||||
defaultCollection: {
|
||||
id: collectionId,
|
||||
organizationId: organizationId,
|
||||
isDefaultCollection: true,
|
||||
} as CollectionView,
|
||||
});
|
||||
|
||||
mockDialogService.open
|
||||
.mockReturnValueOnce(createMockDialogRef(TransferItemsDialogResult.Declined))
|
||||
.mockReturnValueOnce(createMockDialogRef(LeaveConfirmationDialogResult.Confirmed));
|
||||
|
||||
await service.enforceOrganizationDataOwnership(userId);
|
||||
|
||||
expect(mockEventCollectionService.collect).toHaveBeenCalledWith(
|
||||
EventType.Organization_ItemOrganization_Declined,
|
||||
undefined,
|
||||
undefined,
|
||||
organizationId,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("transferInProgress$", () => {
|
||||
|
||||
@@ -11,10 +11,12 @@ import {
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -49,6 +51,7 @@ export class DefaultVaultItemsTransferService implements VaultItemsTransferServi
|
||||
private i18nService: I18nService,
|
||||
private dialogService: DialogService,
|
||||
private toastService: ToastService,
|
||||
private eventCollectionService: EventCollectionService,
|
||||
private configService: ConfigService,
|
||||
) {}
|
||||
|
||||
@@ -160,6 +163,13 @@ export class DefaultVaultItemsTransferService implements VaultItemsTransferServi
|
||||
|
||||
if (!userAcceptedTransfer) {
|
||||
// TODO: Revoke user from organization if they decline migration and show toast PM-29465
|
||||
|
||||
await this.eventCollectionService.collect(
|
||||
EventType.Organization_ItemOrganization_Declined,
|
||||
undefined,
|
||||
undefined,
|
||||
migrationInfo.enforcingOrganization.id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,6 +185,13 @@ export class DefaultVaultItemsTransferService implements VaultItemsTransferServi
|
||||
variant: "success",
|
||||
message: this.i18nService.t("itemsTransferred"),
|
||||
});
|
||||
|
||||
await this.eventCollectionService.collect(
|
||||
EventType.Organization_ItemOrganization_Accepted,
|
||||
undefined,
|
||||
undefined,
|
||||
migrationInfo.enforcingOrganization.id,
|
||||
);
|
||||
} catch (error) {
|
||||
this._transferInProgressSubject.next(false);
|
||||
this.logService.error("Error transferring personal items to organization", error);
|
||||
|
||||
Reference in New Issue
Block a user