1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 13:23:34 +00:00

[SM-1489] machine account event logs (#15997)

* Adding enums for additional event logs for secrets

* updating messages

* Updating messages to be consistent for logs

* Displaying project logs, and fixing search query param searching in projects list, having deleted log for secrets and projects not show as a link

* Viewing secret and project event logs in event modal, adding to the context menu for secrets and projects the ability to view the logs if user has permission. Restricting logs to SM projs and Secs if the logged in user has event log access but not SM access.

* lint

* Lint Fixes

* fix to messages file

* fixing lint

* Adding machine account event logs

* lint fix

* Update event.service.ts

* removing duplicate function issue from merge

* Update service-accounts-list.component.ts

* fixing message

* Fixes to QA bugs

* lint fix

* linter for messages is annoying

* lint
This commit is contained in:
cd-bitwarden
2025-10-03 03:52:00 -04:00
committed by GitHub
parent 2ddf1c34b2
commit cb20889a94
10 changed files with 375 additions and 19 deletions

View File

@@ -28,7 +28,7 @@ import { EventService } from "../../../core";
import { SharedModule } from "../../../shared";
export interface EntityEventsDialogParams {
entity: "user" | "cipher" | "secret" | "project";
entity: "user" | "cipher" | "secret" | "project" | "service-account";
entityId: string;
organizationId?: string;
@@ -174,6 +174,14 @@ export class EntityEventsComponent implements OnInit, OnDestroy {
dates[1],
clearExisting ? null : this.continuationToken,
);
} else if (this.params.entity === "service-account") {
response = await this.apiService.getEventsServiceAccount(
this.params.organizationId,
this.params.entityId,
dates[0],
dates[1],
clearExisting ? null : this.continuationToken,
);
} else if (this.params.entity === "project") {
response = await this.apiService.getEventsProject(
this.params.organizationId,

View File

@@ -559,9 +559,12 @@ export class EventService {
humanReadableMsg = this.i18nService.t("editedSecretWithId", this.getShortId(ev.secretId));
break;
case EventType.Project_Retrieved:
msg = this.i18nService.t("accessedProjectWithId", this.formatProjectId(ev, options));
msg = this.i18nService.t(
"accessedProjectWithIdentifier",
this.formatProjectId(ev, options),
);
humanReadableMsg = this.i18nService.t(
"accessedProjectWithId",
"accessedProjectWithIdentifier",
this.getShortId(ev.projectId),
);
break;
@@ -583,6 +586,74 @@ export class EventService {
msg = this.i18nService.t("editedProjectWithId", this.formatProjectId(ev, options));
humanReadableMsg = this.i18nService.t("editedProjectWithId", this.getShortId(ev.projectId));
break;
case EventType.ServiceAccount_UserAdded:
msg = this.i18nService.t(
"addedUserToServiceAccountWithId",
this.formatUserId(ev, options),
this.formatServiceAccountId(ev, options),
);
humanReadableMsg = this.i18nService.t(
"addedUserToServiceAccountWithId",
this.formatUserId(ev, options),
this.formatServiceAccountId(ev, options),
);
break;
case EventType.ServiceAccount_UserRemoved:
msg = this.i18nService.t(
"removedUserToServiceAccountWithId",
this.formatUserId(ev, options),
this.formatServiceAccountId(ev, options),
);
humanReadableMsg = this.i18nService.t(
"removedUserToServiceAccountWithId",
this.formatUserId(ev, options),
this.formatServiceAccountId(ev, options),
);
break;
case EventType.ServiceAccount_GroupRemoved:
msg = this.i18nService.t(
"removedGroupFromServiceAccountWithId",
this.formatGroupId(ev),
this.formatServiceAccountId(ev, options),
);
humanReadableMsg = this.i18nService.t(
"removedGroupFromServiceAccountWithId",
this.formatGroupId(ev),
this.formatServiceAccountId(ev, options),
);
break;
case EventType.ServiceAccount_GroupAdded:
msg = this.i18nService.t(
"addedGroupToServiceAccountId",
this.formatGroupId(ev),
this.formatServiceAccountId(ev, options),
);
humanReadableMsg = this.i18nService.t(
"addedGroupToServiceAccountId",
this.formatGroupId(ev),
this.formatServiceAccountId(ev, options),
);
break;
case EventType.ServiceAccount_Created:
msg = this.i18nService.t(
"serviceAccountCreatedWithId",
this.formatServiceAccountId(ev, options),
);
humanReadableMsg = this.i18nService.t(
"serviceAccountCreatedWithId",
this.formatServiceAccountId(ev, options),
);
break;
case EventType.ServiceAccount_Deleted:
msg = this.i18nService.t(
"serviceAccountDeletedWithId",
this.formatServiceAccountId(ev, options),
);
humanReadableMsg = this.i18nService.t(
"serviceAccountDeletedWithId",
this.formatServiceAccountId(ev, options),
);
break;
default:
break;
}
@@ -757,6 +828,35 @@ export class EventService {
return a.outerHTML;
}
formatServiceAccountId(ev: EventResponse, options: EventOptions): string {
const shortId = this.getShortId(ev.grantedServiceAccountId);
if (options.disableLink) {
return shortId;
}
const a = this.makeAnchor(shortId);
a.setAttribute(
"href",
"#/sm/" +
ev.organizationId +
"/machine-accounts?search=" +
shortId +
"&viewEvents=" +
ev.grantedServiceAccountId +
"&type=all",
);
return a.outerHTML;
}
formatUserId(ev: EventResponse, options: EventOptions): string {
const shortId = this.getShortId(ev.userId);
if (options.disableLink) {
return shortId;
}
const a = this.makeAnchor(shortId);
a.setAttribute("href", "#/organizations/" + ev.organizationId + "/members?search=" + shortId);
return a.outerHTML;
}
formatProjectId(ev: EventResponse, options: EventOptions): string {
const shortId = this.getShortId(ev.projectId);
if (options.disableLink) {

View File

@@ -7219,6 +7219,9 @@
"unknownSecret": {
"message": "Unknown secret, you may need to request permission to access this secret."
},
"unknownServiceAccount": {
"message": "Unknown machine account, you may need to request permission to access this machine account."
},
"unknownProject": {
"message": "Unknown project, you may need to request permission to access this project."
},
@@ -8569,8 +8572,8 @@
}
}
},
"accessedProjectWithId": {
"message": "Accessed a project with Id: $PROJECT_ID$.",
"accessedProjectWithIdentifier": {
"message": "Accessed a project with identifier: $PROJECT_ID$.",
"placeholders": {
"project_id": {
"content": "$1",
@@ -8595,6 +8598,15 @@
"example": "4d34e8a8"
}
}
},
"nameUnavailableServiceAccountDeleted": {
"message": "Deleted machine account Id: $SERVICE_ACCOUNT_ID$",
"placeholders": {
"service_account_id": {
"content": "$1",
"example": "4d34e8a8"
}
}
},
"editedProjectWithId": {
"message": "Edited a project with identifier: $PROJECT_ID$",
@@ -8604,6 +8616,76 @@
"example": "4d34e8a8"
}
}
},
"addedUserToServiceAccountWithId": {
"message": "Added user: $USER_ID$ to machine account with identifier: $SERVICE_ACCOUNT_ID$",
"placeholders": {
"user_id": {
"content": "$1",
"example": "4d34e8a8"
},
"service_account_id": {
"content": "$2",
"example": "4d34e8a8"
}
}
},
"removedUserToServiceAccountWithId": {
"message": "Removed user: $USER_ID$ from machine account with identifier: $SERVICE_ACCOUNT_ID$",
"placeholders": {
"user_id": {
"content": "$1",
"example": "4d34e8a8"
},
"service_account_id": {
"content": "$2",
"example": "4d34e8a8"
}
}
},
"removedGroupFromServiceAccountWithId": {
"message": "Removed group: $GROUP_ID$ from machine account with identifier: $SERVICE_ACCOUNT_ID$",
"placeholders": {
"group_id": {
"content": "$1",
"example": "4d34e8a8"
},
"service_account_id": {
"content": "$2",
"example": "4d34e8a8"
}
}
},
"serviceAccountCreatedWithId": {
"message": "Created machine account with identifier: $SERVICE_ACCOUNT_ID$",
"placeholders": {
"service_account_id": {
"content": "$1",
"example": "4d34e8a8"
}
}
},
"addedGroupToServiceAccountId": {
"message": "Added group: $GROUP_ID$ to machine account with identifier: $SERVICE_ACCOUNT_ID$",
"placeholders": {
"group_id": {
"content": "$1",
"example": "4d34e8a8"
},
"service_account_id": {
"content": "$2",
"example": "4d34e8a8"
}
}
},
"serviceAccountDeletedWithId": {
"message": "Deleted machine account with identifier: $SERVICE_ACCOUNT_ID$",
"placeholders": {
"service_account_id": {
"content": "$1",
"example": "4d34e8a8"
}
}
},
"deletedProjectWithId": {
"message": "Deleted a project with identifier: $PROJECT_ID$",