-
-
-
- {{ "loading" | i18n }}
-
-
-
+
+
+
+
diff --git a/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts b/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts
index d6ecb8ca94..e27efc43db 100644
--- a/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts
+++ b/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts
@@ -1,78 +1,114 @@
-import { Component, Input, OnInit } from "@angular/core";
+import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog";
+import { Component, Inject, OnInit } from "@angular/core";
+import { FormBuilder } from "@angular/forms";
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
+import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.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";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
+import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
+import { TableDataSource } from "@bitwarden/components";
import { EventService } from "../../../core";
+import { SharedModule } from "../../../shared";
+
+export interface EntityEventsDialogParams {
+ entity: "user" | "cipher";
+ entityId: string;
+
+ organizationId?: string;
+ providerId?: string;
+ showUser?: boolean;
+ name?: string;
+}
@Component({
- selector: "app-entity-events",
+ imports: [SharedModule],
templateUrl: "entity-events.component.html",
+ standalone: true,
})
export class EntityEventsComponent implements OnInit {
- @Input() name: string;
- @Input() entity: "user" | "cipher";
- @Input() entityId: string;
- @Input() organizationId: string;
- @Input() providerId: string;
- @Input() showUser = false;
-
loading = true;
- loaded = false;
- events: any[];
- start: string;
- end: string;
continuationToken: string;
- refreshPromise: Promise
;
- morePromise: Promise;
+ protected dataSource = new TableDataSource();
+ protected filterFormGroup = this.formBuilder.group({
+ start: [""],
+ end: [""],
+ });
private orgUsersUserIdMap = new Map();
private orgUsersIdMap = new Map();
+ get name() {
+ return this.params.name;
+ }
+
+ get showUser() {
+ return this.params.showUser ?? false;
+ }
+
constructor(
+ @Inject(DIALOG_DATA) private params: EntityEventsDialogParams,
private apiService: ApiService,
private i18nService: I18nService,
private eventService: EventService,
private platformUtilsService: PlatformUtilsService,
private userNamePipe: UserNamePipe,
private logService: LogService,
- private organizationUserService: OrganizationUserService
+ private organizationUserService: OrganizationUserService,
+ private formBuilder: FormBuilder,
+ private validationService: ValidationService
) {}
async ngOnInit() {
const defaultDates = this.eventService.getDefaultDateFilters();
- this.start = defaultDates[0];
- this.end = defaultDates[1];
+ this.filterFormGroup.setValue({
+ start: defaultDates[0],
+ end: defaultDates[1],
+ });
await this.load();
}
async load() {
- if (this.showUser) {
- const response = await this.organizationUserService.getAllUsers(this.organizationId);
- response.data.forEach((u) => {
- const name = this.userNamePipe.transform(u);
- this.orgUsersIdMap.set(u.id, { name: name, email: u.email });
- this.orgUsersUserIdMap.set(u.userId, { name: name, email: u.email });
- });
+ try {
+ if (this.showUser) {
+ const response = await this.organizationUserService.getAllUsers(this.params.organizationId);
+ response.data.forEach((u) => {
+ const name = this.userNamePipe.transform(u);
+ this.orgUsersIdMap.set(u.id, { name: name, email: u.email });
+ this.orgUsersUserIdMap.set(u.userId, { name: name, email: u.email });
+ });
+ }
+ await this.loadEvents(true);
+ } catch (e) {
+ this.logService.error(e);
+ this.validationService.showError(e);
}
- await this.loadEvents(true);
- this.loaded = true;
+
+ this.loading = false;
}
- async loadEvents(clearExisting: boolean) {
- if (this.refreshPromise != null || this.morePromise != null) {
- return;
- }
+ loadMoreEvents = async () => {
+ await this.loadEvents(false);
+ };
+ refreshEvents = async () => {
+ await this.loadEvents(true);
+ };
+
+ private async loadEvents(clearExisting: boolean) {
let dates: string[] = null;
try {
- dates = this.eventService.formatDateFilters(this.start, this.end);
+ dates = this.eventService.formatDateFilters(
+ this.filterFormGroup.value.start,
+ this.filterFormGroup.value.end
+ );
} catch (e) {
this.platformUtilsService.showToast(
"error",
@@ -82,46 +118,34 @@ export class EntityEventsComponent implements OnInit {
return;
}
- this.loading = true;
let response: ListResponse;
- try {
- let promise: Promise;
- if (this.entity === "user" && this.providerId) {
- promise = this.apiService.getEventsProviderUser(
- this.providerId,
- this.entityId,
- dates[0],
- dates[1],
- clearExisting ? null : this.continuationToken
- );
- } else if (this.entity === "user") {
- promise = this.apiService.getEventsOrganizationUser(
- this.organizationId,
- this.entityId,
- dates[0],
- dates[1],
- clearExisting ? null : this.continuationToken
- );
- } else {
- promise = this.apiService.getEventsCipher(
- this.entityId,
- dates[0],
- dates[1],
- clearExisting ? null : this.continuationToken
- );
- }
- if (clearExisting) {
- this.refreshPromise = promise;
- } else {
- this.morePromise = promise;
- }
- response = await promise;
- } catch (e) {
- this.logService.error(e);
+ if (this.params.entity === "user" && this.params.providerId) {
+ response = await this.apiService.getEventsProviderUser(
+ this.params.providerId,
+ this.params.entityId,
+ dates[0],
+ dates[1],
+ clearExisting ? null : this.continuationToken
+ );
+ } else if (this.params.entity === "user") {
+ response = await this.apiService.getEventsOrganizationUser(
+ this.params.organizationId,
+ this.params.entityId,
+ dates[0],
+ dates[1],
+ clearExisting ? null : this.continuationToken
+ );
+ } else {
+ response = await this.apiService.getEventsCipher(
+ this.params.entityId,
+ dates[0],
+ dates[1],
+ clearExisting ? null : this.continuationToken
+ );
}
this.continuationToken = response.continuationToken;
- const events = await Promise.all(
+ const events: EventView[] = await Promise.all(
response.data.map(async (r) => {
const userId = r.actingUserId == null ? r.userId : r.actingUserId;
const eventInfo = await this.eventService.getEventInfo(r);
@@ -129,8 +153,10 @@ export class EntityEventsComponent implements OnInit {
this.showUser && userId != null && this.orgUsersUserIdMap.has(userId)
? this.orgUsersUserIdMap.get(userId)
: null;
- return {
+
+ return new EventView({
message: eventInfo.message,
+ humanReadableMessage: eventInfo.humanReadableMessage,
appIcon: eventInfo.appIcon,
appName: eventInfo.appName,
userId: userId,
@@ -139,18 +165,29 @@ export class EntityEventsComponent implements OnInit {
date: r.date,
ip: r.ipAddress,
type: r.type,
- };
+ installationId: r.installationId,
+ systemUser: r.systemUser,
+ serviceAccountId: r.serviceAccountId,
+ });
})
);
- if (!clearExisting && this.events != null && this.events.length > 0) {
- this.events = this.events.concat(events);
+ if (!clearExisting && this.dataSource.data != null && this.dataSource.data.length > 0) {
+ this.dataSource.data = this.dataSource.data.concat(events);
} else {
- this.events = events;
+ this.dataSource.data = events;
}
-
- this.loading = false;
- this.morePromise = null;
- this.refreshPromise = null;
}
}
+
+/**
+ * Strongly typed helper to open a EntityEventsComponent as a dialog
+ * @param dialogService Instance of the dialog service that will be used to open the dialog
+ * @param config Configuration for the dialog
+ */
+export const openEntityEventsDialog = (
+ dialogService: DialogServiceAbstraction,
+ config: DialogConfig
+) => {
+ return dialogService.open(EntityEventsComponent, config);
+};
diff --git a/apps/web/src/app/admin-console/organizations/members/people.component.html b/apps/web/src/app/admin-console/organizations/members/people.component.html
index 8154340bb8..c93380b466 100644
--- a/apps/web/src/app/admin-console/organizations/members/people.component.html
+++ b/apps/web/src/app/admin-console/organizations/members/people.component.html
@@ -317,7 +317,6 @@
-
diff --git a/apps/web/src/app/admin-console/organizations/members/people.component.ts b/apps/web/src/app/admin-console/organizations/members/people.component.ts
index e86b5a27ec..64b7f2c20c 100644
--- a/apps/web/src/app/admin-console/organizations/members/people.component.ts
+++ b/apps/web/src/app/admin-console/organizations/members/people.component.ts
@@ -16,10 +16,10 @@ import {
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
import {
- SimpleDialogType,
DialogServiceAbstraction,
SimpleDialogCloseType,
SimpleDialogOptions,
+ SimpleDialogType,
} from "@bitwarden/angular/services/dialog";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
@@ -55,7 +55,7 @@ import { CollectionData } from "@bitwarden/common/vault/models/data/collection.d
import { Collection } from "@bitwarden/common/vault/models/domain/collection";
import { CollectionDetailsResponse } from "@bitwarden/common/vault/models/response/collection.response";
-import { EntityEventsComponent } from "../../../admin-console/organizations/manage/entity-events.component";
+import { openEntityEventsDialog } from "../../../admin-console/organizations/manage/entity-events.component";
import { BasePeopleComponent } from "../../../common/base.people.component";
import { GroupService } from "../core";
import { OrganizationUserView } from "../core/views/organization-user.view";
@@ -81,8 +81,6 @@ export class PeopleComponent
{
@ViewChild("groupsTemplate", { read: ViewContainerRef, static: true })
groupsModalRef: ViewContainerRef;
- @ViewChild("eventsTemplate", { read: ViewContainerRef, static: true })
- eventsModalRef: ViewContainerRef;
@ViewChild("confirmTemplate", { read: ViewContainerRef, static: true })
confirmModalRef: ViewContainerRef;
@ViewChild("resetPasswordTemplate", { read: ViewContainerRef, static: true })
@@ -513,12 +511,14 @@ export class PeopleComponent
}
async events(user: OrganizationUserView) {
- await this.modalService.openViewRef(EntityEventsComponent, this.eventsModalRef, (comp) => {
- comp.name = this.userNamePipe.transform(user);
- comp.organizationId = this.organization.id;
- comp.entityId = user.id;
- comp.showUser = false;
- comp.entity = "user";
+ await openEntityEventsDialog(this.dialogService, {
+ data: {
+ name: this.userNamePipe.transform(user),
+ organizationId: this.organization.id,
+ entityId: user.id,
+ showUser: false,
+ entity: "user",
+ },
});
}
diff --git a/apps/web/src/app/shared/loose-components.module.ts b/apps/web/src/app/shared/loose-components.module.ts
index c9f115a273..db6a427138 100644
--- a/apps/web/src/app/shared/loose-components.module.ts
+++ b/apps/web/src/app/shared/loose-components.module.ts
@@ -3,7 +3,6 @@ import { NgModule } from "@angular/core";
import { OrganizationSwitcherComponent } from "../admin-console/components/organization-switcher.component";
import { OrganizationCreateModule } from "../admin-console/organizations/create/organization-create.module";
import { OrganizationLayoutComponent } from "../admin-console/organizations/layouts/organization-layout.component";
-import { EntityEventsComponent as OrgEntityEventsComponent } from "../admin-console/organizations/manage/entity-events.component";
import { EventsComponent as OrgEventsComponent } from "../admin-console/organizations/manage/events.component";
import { UserConfirmComponent as OrgUserConfirmComponent } from "../admin-console/organizations/manage/user-confirm.component";
import { AcceptFamilySponsorshipComponent } from "../admin-console/organizations/sponsorships/accept-family-sponsorship.component";
@@ -166,7 +165,6 @@ import { SharedModule } from "./shared.module";
OrganizationPlansComponent,
OrgAttachmentsComponent,
OrgCollectionsComponent,
- OrgEntityEventsComponent,
OrgEventsComponent,
OrgExposedPasswordsReportComponent,
OrgInactiveTwoFactorReportComponent,
@@ -271,7 +269,6 @@ import { SharedModule } from "./shared.module";
OrganizationPlansComponent,
OrgAttachmentsComponent,
OrgCollectionsComponent,
- OrgEntityEventsComponent,
OrgEventsComponent,
OrgExposedPasswordsReportComponent,
OrgInactiveTwoFactorReportComponent,
diff --git a/apps/web/src/app/vault/org-vault/vault.component.html b/apps/web/src/app/vault/org-vault/vault.component.html
index d3109774c2..c586a94f7a 100644
--- a/apps/web/src/app/vault/org-vault/vault.component.html
+++ b/apps/web/src/app/vault/org-vault/vault.component.html
@@ -96,5 +96,4 @@
-
diff --git a/apps/web/src/app/vault/org-vault/vault.component.ts b/apps/web/src/app/vault/org-vault/vault.component.ts
index 8048ade1c7..7b6b926e49 100644
--- a/apps/web/src/app/vault/org-vault/vault.component.ts
+++ b/apps/web/src/app/vault/org-vault/vault.component.ts
@@ -56,7 +56,7 @@ import { CollectionView } from "@bitwarden/common/vault/models/view/collection.v
import { Icons } from "@bitwarden/components";
import { GroupService, GroupView } from "../../admin-console/organizations/core";
-import { EntityEventsComponent } from "../../admin-console/organizations/manage/entity-events.component";
+import { openEntityEventsDialog } from "../../admin-console/organizations/manage/entity-events.component";
import { VaultFilterService } from "../../vault/individual-vault/vault-filter/services/abstractions/vault-filter.service";
import { VaultFilter } from "../../vault/individual-vault/vault-filter/shared/models/vault-filter.model";
import {
@@ -109,8 +109,6 @@ export class VaultComponent implements OnInit, OnDestroy {
cipherAddEditModalRef: ViewContainerRef;
@ViewChild("collectionsModal", { read: ViewContainerRef, static: true })
collectionsModalRef: ViewContainerRef;
- @ViewChild("eventsTemplate", { read: ViewContainerRef, static: true })
- eventsModalRef: ViewContainerRef;
trashCleanupWarning: string = null;
activeFilter: VaultFilter = new VaultFilter();
@@ -885,12 +883,14 @@ export class VaultComponent implements OnInit, OnDestroy {
}
async viewEvents(cipher: CipherView) {
- await this.modalService.openViewRef(EntityEventsComponent, this.eventsModalRef, (comp) => {
- comp.name = cipher.name;
- comp.organizationId = this.organization.id;
- comp.entityId = cipher.id;
- comp.showUser = true;
- comp.entity = "cipher";
+ await openEntityEventsDialog(this.dialogService, {
+ data: {
+ name: cipher.name,
+ organizationId: this.organization.id,
+ entityId: cipher.id,
+ showUser: true,
+ entity: "cipher",
+ },
});
}
diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.html b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.html
index 00bf5eda26..152253fe4d 100644
--- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.html
+++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.html
@@ -209,7 +209,6 @@
-
diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts
index 7c787951d4..304ab346f3 100644
--- a/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts
+++ b/bitwarden_license/bit-web/src/app/admin-console/providers/manage/people.component.ts
@@ -21,7 +21,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
-import { EntityEventsComponent } from "@bitwarden/web-vault/app/admin-console/organizations/manage/entity-events.component";
+import { openEntityEventsDialog } from "@bitwarden/web-vault/app/admin-console/organizations/manage/entity-events.component";
import { BulkStatusComponent } from "@bitwarden/web-vault/app/admin-console/organizations/members/components/bulk/bulk-status.component";
import { BasePeopleComponent } from "@bitwarden/web-vault/app/common/base.people.component";
@@ -41,8 +41,6 @@ export class PeopleComponent
@ViewChild("addEdit", { read: ViewContainerRef, static: true }) addEditModalRef: ViewContainerRef;
@ViewChild("groupsTemplate", { read: ViewContainerRef, static: true })
groupsModalRef: ViewContainerRef;
- @ViewChild("eventsTemplate", { read: ViewContainerRef, static: true })
- eventsModalRef: ViewContainerRef;
@ViewChild("bulkStatusTemplate", { read: ViewContainerRef, static: true })
bulkStatusModalRef: ViewContainerRef;
@ViewChild("bulkConfirmTemplate", { read: ViewContainerRef, static: true })
@@ -167,12 +165,14 @@ export class PeopleComponent
}
async events(user: ProviderUserUserDetailsResponse) {
- await this.modalService.openViewRef(EntityEventsComponent, this.eventsModalRef, (comp) => {
- comp.name = this.userNamePipe.transform(user);
- comp.providerId = this.providerId;
- comp.entityId = user.id;
- comp.showUser = false;
- comp.entity = "user";
+ await openEntityEventsDialog(this.dialogService, {
+ data: {
+ name: this.userNamePipe.transform(user),
+ providerId: this.providerId,
+ entityId: user.id,
+ showUser: false,
+ entity: "user",
+ },
});
}