mirror of
https://github.com/bitwarden/browser
synced 2026-01-04 01:23:57 +00:00
[SM-1274] Add Project Events to the Log List in Admin Console (#15442)
* 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 * Bug fix, make sure event logs related to service accounts are still links that take you to the object * removing unused import
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Directive } from "@angular/core";
|
||||
import { Directive, OnDestroy } from "@angular/core";
|
||||
import { FormControl, FormGroup } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatest, filter, map, Observable, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { EventView } from "@bitwarden/common/models/view/event.view";
|
||||
@@ -12,16 +17,17 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { EventService } from "../../core";
|
||||
import { EventOptions, EventService } from "../../core";
|
||||
import { EventExportService } from "../../tools/event-export";
|
||||
|
||||
@Directive()
|
||||
export abstract class BaseEventsComponent {
|
||||
export abstract class BaseEventsComponent implements OnDestroy {
|
||||
loading = true;
|
||||
loaded = false;
|
||||
events: EventView[];
|
||||
dirtyDates = true;
|
||||
continuationToken: string;
|
||||
canUseSM = false;
|
||||
|
||||
abstract readonly exportFileName: string;
|
||||
|
||||
@@ -30,6 +36,15 @@ export abstract class BaseEventsComponent {
|
||||
end: new FormControl(null),
|
||||
});
|
||||
|
||||
protected canUseSM$: Observable<boolean>;
|
||||
protected activeOrganization$: Observable<Organization | undefined>;
|
||||
protected organizations$: Observable<Organization[]>;
|
||||
private destroySubject$ = new Subject<void>();
|
||||
|
||||
protected get destroy$(): Observable<void> {
|
||||
return this.destroySubject$.asObservable();
|
||||
}
|
||||
|
||||
constructor(
|
||||
protected eventService: EventService,
|
||||
protected i18nService: I18nService,
|
||||
@@ -38,12 +53,39 @@ export abstract class BaseEventsComponent {
|
||||
protected logService: LogService,
|
||||
protected fileDownloadService: FileDownloadService,
|
||||
private toastService: ToastService,
|
||||
protected activeRoute: ActivatedRoute,
|
||||
protected accountService: AccountService,
|
||||
protected organizationService: OrganizationService,
|
||||
) {
|
||||
const defaultDates = this.eventService.getDefaultDateFilters();
|
||||
this.start = defaultDates[0];
|
||||
this.end = defaultDates[1];
|
||||
}
|
||||
|
||||
protected initBase(): void {
|
||||
this.organizations$ = this.accountService.activeAccount$.pipe(
|
||||
filter((account): account is Account => !!account?.id),
|
||||
switchMap((account) => this.organizationService.organizations$(account.id)),
|
||||
);
|
||||
|
||||
this.activeOrganization$ = combineLatest([this.activeRoute.paramMap, this.organizations$]).pipe(
|
||||
map(([params, orgs]) => orgs.find((org) => org.id === params.get("organizationId"))),
|
||||
);
|
||||
|
||||
this.canUseSM$ = this.activeOrganization$.pipe(
|
||||
map((org) => org?.canAccessSecretsManager ?? false),
|
||||
);
|
||||
|
||||
this.canUseSM$.pipe(takeUntil(this.destroy$)).subscribe((value) => {
|
||||
this.canUseSM = value;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroySubject$.next();
|
||||
this.destroySubject$.complete();
|
||||
}
|
||||
|
||||
get start(): string {
|
||||
return this.eventsForm.value.start;
|
||||
}
|
||||
@@ -139,7 +181,10 @@ export abstract class BaseEventsComponent {
|
||||
const events = await Promise.all(
|
||||
response.data.map(async (r) => {
|
||||
const userId = r.actingUserId == null ? r.userId : r.actingUserId;
|
||||
const eventInfo = await this.eventService.getEventInfo(r);
|
||||
const options = new EventOptions();
|
||||
options.disableLink = !this.canUseSM;
|
||||
|
||||
const eventInfo = await this.eventService.getEventInfo(r, options);
|
||||
const user = this.getUserName(r, userId);
|
||||
const userName = user != null ? user.name : this.i18nService.t("unknown");
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import { firstValueFrom, switchMap } from "rxjs";
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { EventView } from "@bitwarden/common/models/view/event.view";
|
||||
@@ -26,7 +28,7 @@ import { EventService } from "../../../core";
|
||||
import { SharedModule } from "../../../shared";
|
||||
|
||||
export interface EntityEventsDialogParams {
|
||||
entity: "user" | "cipher";
|
||||
entity: "user" | "cipher" | "secret" | "project";
|
||||
entityId: string;
|
||||
|
||||
organizationId?: string;
|
||||
@@ -72,6 +74,8 @@ export class EntityEventsComponent implements OnInit, OnDestroy {
|
||||
private toastService: ToastService,
|
||||
private router: Router,
|
||||
private activeRoute: ActivatedRoute,
|
||||
private accountService: AccountService,
|
||||
protected organizationService: OrganizationService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -162,6 +166,22 @@ export class EntityEventsComponent implements OnInit, OnDestroy {
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken,
|
||||
);
|
||||
} else if (this.params.entity === "secret") {
|
||||
response = await this.apiService.getEventsSecret(
|
||||
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,
|
||||
this.params.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken,
|
||||
);
|
||||
} else {
|
||||
response = await this.apiService.getEventsCipher(
|
||||
this.params.entityId,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { concatMap, firstValueFrom, lastValueFrom, Subject, takeUntil } from "rxjs";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { concatMap, firstValueFrom, lastValueFrom, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
@@ -60,8 +60,6 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
placeholderEvents = placeholderEvents as EventView[];
|
||||
|
||||
private orgUsersUserIdMap = new Map<string, any>();
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
readonly ProductTierType = ProductTierType;
|
||||
|
||||
protected isBreadcrumbEventLogsEnabled$ = this.configService.getFeatureFlag$(
|
||||
@@ -75,18 +73,18 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
i18nService: I18nService,
|
||||
exportService: EventExportService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
private router: Router,
|
||||
logService: LogService,
|
||||
private userNamePipe: UserNamePipe,
|
||||
private organizationService: OrganizationService,
|
||||
protected organizationService: OrganizationService,
|
||||
private organizationUserApiService: OrganizationUserApiService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private providerService: ProviderService,
|
||||
fileDownloadService: FileDownloadService,
|
||||
toastService: ToastService,
|
||||
private accountService: AccountService,
|
||||
protected accountService: AccountService,
|
||||
private dialogService: DialogService,
|
||||
private configService: ConfigService,
|
||||
protected activeRoute: ActivatedRoute,
|
||||
) {
|
||||
super(
|
||||
eventService,
|
||||
@@ -96,10 +94,15 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
logService,
|
||||
fileDownloadService,
|
||||
toastService,
|
||||
activeRoute,
|
||||
accountService,
|
||||
organizationService,
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.initBase();
|
||||
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.route.params
|
||||
.pipe(
|
||||
@@ -233,9 +236,4 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
}
|
||||
await this.load();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user