1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-07 04:03:29 +00:00

PM-23603 group names in event logs

This commit is contained in:
voommen-livefront
2025-07-11 09:18:23 -05:00
parent f79a522791
commit fe00892b4c
2 changed files with 54 additions and 1 deletions

View File

@@ -17,6 +17,8 @@ import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { GroupApiService, GroupView } from "../admin-console/organizations/core";
import { EventService } from "./event.service";
describe("EventService", () => {
@@ -27,10 +29,12 @@ describe("EventService", () => {
let mockCipherService = mock<CipherService>();
let mockOrgUserApiService = mock<OrganizationUserApiService>();
let mockCollectionService = mock<CollectionService>();
let mockGroupApiService = mock<GroupApiService>();
const userId = Utils.newGuid() as UserId;
const orgId = Utils.newGuid() as OrganizationId;
const collectionId = Utils.newGuid() as string;
const groupId = Utils.newGuid() as string;
const orgUserMiniResponse: ListResponse<OrganizationUserUserMiniResponse> = {
continuationToken: null,
@@ -50,6 +54,13 @@ describe("EventService", () => {
} as CollectionView,
];
const groupViews = [
{
id: groupId,
name: "Test Group",
} as GroupView,
];
const baseEvent = {
type: EventType.Cipher_Created,
cipherId: "abcdef1234567890",
@@ -57,6 +68,7 @@ describe("EventService", () => {
organizationUserId: userId,
userId: userId,
collectionId: collectionId,
groupId: groupId,
deviceType: 0, // Android
} as any;
@@ -67,6 +79,7 @@ describe("EventService", () => {
mockCipherService = mock<CipherService>();
mockOrgUserApiService = mock<OrganizationUserApiService>();
mockCollectionService = mock<CollectionService>();
mockGroupApiService = mock<GroupApiService>();
eventService = new EventService(
mocki18nService,
mockPolicyService,
@@ -74,6 +87,7 @@ describe("EventService", () => {
mockCipherService,
mockOrgUserApiService,
mockCollectionService,
mockGroupApiService,
);
// reset mocks
@@ -92,6 +106,7 @@ describe("EventService", () => {
]);
mockOrgUserApiService.getAllMiniUserDetails.mockResolvedValue(orgUserMiniResponse);
mockCollectionService.getAllDecrypted.mockResolvedValue(collectionViews);
mockGroupApiService.getAll.mockResolvedValue(groupViews);
// this method will use the mocks defined above
await eventService.loadAllOrganizationInfo(orgId, userId);
@@ -280,4 +295,27 @@ describe("EventService", () => {
});
});
});
describe("getEventInfo for Groups", () => {
const testCases = [
{ type: EventType.Group_Created, eventName: "createdGroupId" },
{ type: EventType.Group_Updated, eventName: "editedGroupId" },
{ type: EventType.Group_Deleted, eventName: "deletedGroupId" },
];
testCases.forEach(({ type, eventName }) => {
it(`should return correct info for group event type ${type}`, async () => {
const event = { ...baseEvent, type, groupId };
const info = await eventService.getEventInfo(event);
expect(info.message).toContain("Test Group");
expect(info.humanReadableMessage).toContain(eventName);
expect(info.appIcon).toBe("bwi-mobile");
expect(info.appName).toBe("mobile - Android");
expect(info.eventName).toBe(eventName);
expect(info.eventLink).toContain("<code>Test Group</code>");
});
});
});
});

View File

@@ -14,12 +14,15 @@ import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { GroupApiService } from "../admin-console/organizations/core";
@Injectable()
export class EventService {
private policies: Policy[] = [];
private ciphers: CipherView[] = [];
private organizationUserIdMap: Map<string, { name: string; email: string }> = new Map();
private collections: Map<string, { name: string }> = new Map();
private groupIdMap: Map<string, { name: string }> = new Map();
constructor(
private i18nService: I18nService,
@@ -28,6 +31,7 @@ export class EventService {
private cipherService: CipherService,
private organizationUserApiService: OrganizationUserApiService,
private collectionService: CollectionService,
private groupApiService: GroupApiService,
) {
accountService.activeAccount$
.pipe(
@@ -66,6 +70,10 @@ export class EventService {
(await this.collectionService.getAllDecrypted()).map((c) => {
this.collections.set(c.id, { name: c.name });
});
(await this.groupApiService.getAll(organizationId)).map((g) => {
this.groupIdMap.set(g.id, { name: g.name });
});
}
async getEventInfo(ev: EventResponse, options = new EventOptions()): Promise<EventInfo> {
@@ -300,14 +308,20 @@ export class EventService {
case EventType.Group_Created:
msg = this.i18nService.t("createdGroupId", this.formatGroupId(ev));
humanReadableMsg = this.i18nService.t("createdGroupId", this.getShortId(ev.groupId));
eventName = this.i18nService.t("createdGroupId", "");
eventLink = this.formatGroupId(ev);
break;
case EventType.Group_Updated:
msg = this.i18nService.t("editedGroupId", this.formatGroupId(ev));
humanReadableMsg = this.i18nService.t("editedGroupId", this.getShortId(ev.groupId));
eventName = this.i18nService.t("editedGroupId", "");
eventLink = this.formatGroupId(ev);
break;
case EventType.Group_Deleted:
msg = this.i18nService.t("deletedGroupId", this.formatGroupId(ev));
humanReadableMsg = this.i18nService.t("deletedGroupId", this.getShortId(ev.groupId));
eventName = this.i18nService.t("deletedGroupId", "");
eventLink = this.formatGroupId(ev);
break;
// Org user
case EventType.OrganizationUser_Invited:
@@ -683,7 +697,8 @@ export class EventService {
private formatGroupId(ev: EventResponse) {
const shortId = this.getShortId(ev.groupId);
const a = this.makeAnchor(shortId);
const anchorName = this.groupIdMap.get(ev.groupId)?.name ?? shortId;
const a = this.makeAnchor(anchorName);
a.setAttribute("href", "#/organizations/" + ev.organizationId + "/groups?search=" + shortId);
return a.outerHTML;
}