mirror of
https://github.com/bitwarden/browser
synced 2026-02-08 12:40:26 +00:00
Merge branch 'main' into feature/passkey-provider
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,21 +467,60 @@ export class EventService {
|
||||
break;
|
||||
// Secrets Manager
|
||||
case EventType.Secret_Retrieved:
|
||||
msg = this.i18nService.t("accessedSecretWithId", this.formatSecretId(ev));
|
||||
msg = this.i18nService.t("accessedSecretWithId", this.formatSecretId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t("accessedSecretWithId", this.getShortId(ev.secretId));
|
||||
break;
|
||||
case EventType.Secret_Created:
|
||||
msg = this.i18nService.t("createdSecretWithId", this.formatSecretId(ev));
|
||||
msg = this.i18nService.t("createdSecretWithId", this.formatSecretId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t("createdSecretWithId", this.getShortId(ev.secretId));
|
||||
break;
|
||||
case EventType.Secret_Deleted:
|
||||
msg = this.i18nService.t("deletedSecretWithId", this.formatSecretId(ev));
|
||||
msg = this.i18nService.t("deletedSecretWithId", this.formatSecretId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t("deletedSecretWithId", this.getShortId(ev.secretId));
|
||||
break;
|
||||
case EventType.Secret_Permanently_Deleted:
|
||||
msg = this.i18nService.t(
|
||||
"permanentlyDeletedSecretWithId",
|
||||
this.formatSecretId(ev, options),
|
||||
);
|
||||
humanReadableMsg = this.i18nService.t(
|
||||
"permanentlyDeletedSecretWithId",
|
||||
this.getShortId(ev.secretId),
|
||||
);
|
||||
break;
|
||||
case EventType.Secret_Restored:
|
||||
msg = this.i18nService.t("restoredSecretWithId", this.formatSecretId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t("restoredSecretWithId", this.getShortId(ev.secretId));
|
||||
break;
|
||||
case EventType.Secret_Edited:
|
||||
msg = this.i18nService.t("editedSecretWithId", this.formatSecretId(ev));
|
||||
msg = this.i18nService.t("editedSecretWithId", this.formatSecretId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t("editedSecretWithId", this.getShortId(ev.secretId));
|
||||
break;
|
||||
case EventType.Project_Retrieved:
|
||||
msg = this.i18nService.t("accessedProjectWithId", this.formatProjectId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t(
|
||||
"accessedProjectWithId",
|
||||
this.getShortId(ev.projectId),
|
||||
);
|
||||
break;
|
||||
case EventType.Project_Created:
|
||||
msg = this.i18nService.t("createdProjectWithId", this.formatProjectId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t(
|
||||
"createdProjectWithId",
|
||||
this.getShortId(ev.projectId),
|
||||
);
|
||||
break;
|
||||
case EventType.Project_Deleted:
|
||||
msg = this.i18nService.t("deletedProjectWithId", this.formatProjectId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t(
|
||||
"deletedProjectWithId",
|
||||
this.getShortId(ev.projectId),
|
||||
);
|
||||
break;
|
||||
case EventType.Project_Edited:
|
||||
msg = this.i18nService.t("editedProjectWithId", this.formatProjectId(ev, options));
|
||||
humanReadableMsg = this.i18nService.t("editedProjectWithId", this.getShortId(ev.projectId));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -637,10 +676,41 @@ export class EventService {
|
||||
return a.outerHTML;
|
||||
}
|
||||
|
||||
formatSecretId(ev: EventResponse): string {
|
||||
formatSecretId(ev: EventResponse, options: EventOptions): string {
|
||||
const shortId = this.getShortId(ev.secretId);
|
||||
if (options.disableLink) {
|
||||
return shortId;
|
||||
}
|
||||
const a = this.makeAnchor(shortId);
|
||||
a.setAttribute("href", "#/sm/" + ev.organizationId + "/secrets?search=" + shortId);
|
||||
a.setAttribute(
|
||||
"href",
|
||||
"#/sm/" +
|
||||
ev.organizationId +
|
||||
"/secrets?search=" +
|
||||
shortId +
|
||||
"&viewEvents=" +
|
||||
ev.secretId +
|
||||
"&type=all",
|
||||
);
|
||||
return a.outerHTML;
|
||||
}
|
||||
|
||||
formatProjectId(ev: EventResponse, options: EventOptions): string {
|
||||
const shortId = this.getShortId(ev.projectId);
|
||||
if (options.disableLink) {
|
||||
return shortId;
|
||||
}
|
||||
const a = this.makeAnchor(shortId);
|
||||
a.setAttribute(
|
||||
"href",
|
||||
"#/sm/" +
|
||||
ev.organizationId +
|
||||
"/projects?search=" +
|
||||
shortId +
|
||||
"&viewEvents=" +
|
||||
ev.projectId +
|
||||
"&type=all",
|
||||
);
|
||||
return a.outerHTML;
|
||||
}
|
||||
|
||||
@@ -684,4 +754,5 @@ export class EventInfo {
|
||||
|
||||
export class EventOptions {
|
||||
cipherInfo = true;
|
||||
disableLink = false;
|
||||
}
|
||||
|
||||
@@ -7039,6 +7039,12 @@
|
||||
"unknownCipher": {
|
||||
"message": "Unknown item, you may need to request permission to access this item."
|
||||
},
|
||||
"unknownSecret": {
|
||||
"message": "Unknown secret, you may need to request permission to access this secret."
|
||||
},
|
||||
"unknownProject": {
|
||||
"message": "Unknown project, you may need to request permission to access this project."
|
||||
},
|
||||
"cannotSponsorSelf": {
|
||||
"message": "You cannot redeem for the active account. Enter a different email."
|
||||
},
|
||||
@@ -8361,6 +8367,24 @@
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"permanentlyDeletedSecretWithId": {
|
||||
"message": "Permanently deleted a secret with identifier: $SECRET_ID$",
|
||||
"placeholders": {
|
||||
"secret_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"restoredSecretWithId": {
|
||||
"message": "Restored a secret with identifier: $SECRET_ID$",
|
||||
"placeholders": {
|
||||
"secret_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdSecretWithId": {
|
||||
"message": "Created a new secret with identifier: $SECRET_ID$",
|
||||
@@ -8371,6 +8395,60 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"accessedProjectWithId": {
|
||||
"message": "Accessed a project with Id: $PROJECT_ID$.",
|
||||
"placeholders": {
|
||||
"project_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nameUnavailableProjectDeleted": {
|
||||
"message": "Deleted project Id: $PROJECT_ID$",
|
||||
"placeholders": {
|
||||
"project_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nameUnavailableSecretDeleted": {
|
||||
"message": "Deleted secret Id: $SECRET_ID$",
|
||||
"placeholders": {
|
||||
"secret_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"editedProjectWithId": {
|
||||
"message": "Edited a project with identifier: $PROJECT_ID$",
|
||||
"placeholders": {
|
||||
"project_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deletedProjectWithId": {
|
||||
"message": "Deleted a project with identifier: $PROJECT_ID$",
|
||||
"placeholders": {
|
||||
"project_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdProjectWithId": {
|
||||
"message": "Created a new project with identifier: $PROJECT_ID$",
|
||||
"placeholders": {
|
||||
"project_id": {
|
||||
"content": "$1",
|
||||
"example": "4d34e8a8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sdk": {
|
||||
"message": "SDK",
|
||||
"description": "Software Development Kit"
|
||||
@@ -10755,6 +10833,9 @@
|
||||
"upgradeEventLogMessage":{
|
||||
"message" : "These events are examples only and do not reflect real events within your Bitwarden organization."
|
||||
},
|
||||
"viewEvents":{
|
||||
"message" : "View Events"
|
||||
},
|
||||
"cannotCreateCollection": {
|
||||
"message": "Free organizations may have up to 2 collections. Upgrade to a paid plan to add more collections."
|
||||
},
|
||||
|
||||
@@ -5,7 +5,9 @@ import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
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 { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -41,6 +43,8 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
|
||||
private userNamePipe: UserNamePipe,
|
||||
fileDownloadService: FileDownloadService,
|
||||
toastService: ToastService,
|
||||
accountService: AccountService,
|
||||
organizationService: OrganizationService,
|
||||
) {
|
||||
super(
|
||||
eventService,
|
||||
@@ -50,6 +54,9 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
|
||||
logService,
|
||||
fileDownloadService,
|
||||
toastService,
|
||||
route,
|
||||
accountService,
|
||||
organizationService,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,6 +76,7 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
|
||||
}
|
||||
|
||||
async load() {
|
||||
this.initBase();
|
||||
const response = await this.apiService.getProviderUsers(this.providerId);
|
||||
response.data.forEach((u) => {
|
||||
const name = this.userNamePipe.transform(u);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import {
|
||||
combineLatest,
|
||||
firstValueFrom,
|
||||
@@ -17,9 +17,12 @@ import {
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { DialogRef, DialogService, ToastService } from "@bitwarden/components";
|
||||
import { openEntityEventsDialog } from "@bitwarden/web-vault/app/admin-console/organizations/manage/entity-events.component";
|
||||
|
||||
import { ProjectListView } from "../../models/view/project-list.view";
|
||||
import { ProjectView } from "../../models/view/project.view";
|
||||
import {
|
||||
BulkConfirmationDetails,
|
||||
BulkConfirmationDialogComponent,
|
||||
@@ -55,6 +58,9 @@ export class ProjectsComponent implements OnInit {
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private toastService: ToastService,
|
||||
private i18nService: I18nService,
|
||||
private router: Router,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -73,9 +79,53 @@ export class ProjectsComponent implements OnInit {
|
||||
)
|
||||
)?.enabled;
|
||||
|
||||
return await this.getProjects();
|
||||
const projects = await this.getProjects();
|
||||
const viewEvents = this.route.snapshot.queryParams.viewEvents;
|
||||
|
||||
if (viewEvents) {
|
||||
const targetProject = projects.find((project) => project.id === viewEvents);
|
||||
|
||||
const userIsAdmin = (
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
)
|
||||
)?.isAdmin;
|
||||
|
||||
// They would fall into here if they don't have access to a project, or if it has been permanently deleted.
|
||||
if (!targetProject) {
|
||||
//If they are an admin it was permanently deleted and we can show the events with project name redacted
|
||||
if (userIsAdmin) {
|
||||
this.openEventsDialogFromEntityId(
|
||||
this.i18nService.t("nameUnavailableProjectDeleted", viewEvents),
|
||||
params.organizationId,
|
||||
viewEvents,
|
||||
);
|
||||
} else {
|
||||
//They aren't an admin so we don't know if they have access to it, lets show the unknown cipher toast.
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("unknownProject"),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.openEventsDialog(targetProject);
|
||||
}
|
||||
|
||||
await this.router.navigate([], {
|
||||
queryParams: { search: this.search },
|
||||
});
|
||||
}
|
||||
|
||||
return projects;
|
||||
}),
|
||||
);
|
||||
|
||||
if (this.route.snapshot.queryParams.search) {
|
||||
this.search = this.route.snapshot.queryParams.search;
|
||||
}
|
||||
}
|
||||
|
||||
private async getProjects(): Promise<ProjectListView[]> {
|
||||
@@ -103,6 +153,30 @@ export class ProjectsComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
openEventsDialog = (project: ProjectView): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: project.name,
|
||||
organizationId: project.organizationId,
|
||||
entityId: project.id,
|
||||
entity: "project",
|
||||
},
|
||||
});
|
||||
|
||||
openEventsDialogFromEntityId = (
|
||||
headerName: string,
|
||||
organizationId: string,
|
||||
entityId: string,
|
||||
): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: headerName,
|
||||
organizationId: organizationId,
|
||||
entityId: entityId,
|
||||
entity: "project",
|
||||
},
|
||||
});
|
||||
|
||||
async openDeleteProjectDialog(projects: ProjectListView[]) {
|
||||
let projectsToDelete = projects;
|
||||
const readOnlyProjects = projects.filter((project) => project.write == false);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { combineLatestWith, firstValueFrom, Observable, startWith, switchMap } from "rxjs";
|
||||
|
||||
import {
|
||||
@@ -13,7 +13,8 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
import { DialogRef, DialogService, ToastService } from "@bitwarden/components";
|
||||
import { openEntityEventsDialog } from "@bitwarden/web-vault/app/admin-console/organizations/manage/entity-events.component";
|
||||
|
||||
import { SecretListView } from "../models/view/secret-list.view";
|
||||
import { SecretsListComponent } from "../shared/secrets-list.component";
|
||||
@@ -54,6 +55,8 @@ export class SecretsComponent implements OnInit {
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private logService: LogService,
|
||||
private toastService: ToastService,
|
||||
private router: Router,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -71,7 +74,53 @@ export class SecretsComponent implements OnInit {
|
||||
)
|
||||
)?.enabled;
|
||||
|
||||
return await this.getSecrets();
|
||||
const secrets = await this.getSecrets();
|
||||
const viewEvents = this.route.snapshot.queryParams.viewEvents;
|
||||
|
||||
if (viewEvents) {
|
||||
let targetSecret = secrets.find((secret) => secret.id === viewEvents);
|
||||
|
||||
const userIsAdmin = (
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
)
|
||||
)?.isAdmin;
|
||||
|
||||
// Secret might be deleted, make sure they are an admin before checking the trashed secrets
|
||||
if (!targetSecret && userIsAdmin) {
|
||||
targetSecret = (await this.secretService.getTrashedSecrets(this.organizationId)).find(
|
||||
(e) => e.id == viewEvents,
|
||||
);
|
||||
}
|
||||
|
||||
// They would fall into here if they don't have access to a secret, or if it has been permanently deleted.
|
||||
if (!targetSecret) {
|
||||
//If they are an admin it was permanently deleted and we can show the events even though we don't have the secret name
|
||||
if (userIsAdmin) {
|
||||
this.openEventsDialogByEntityId(
|
||||
this.i18nService.t("nameUnavailableSecretDeleted", viewEvents),
|
||||
viewEvents,
|
||||
);
|
||||
} else {
|
||||
//They aren't an admin so we don't know if they have access to it, lets show the unknown secret toast.
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("unknownSecret"),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.openEventsDialog(targetSecret);
|
||||
}
|
||||
|
||||
await this.router.navigate([], {
|
||||
queryParams: { search: this.search },
|
||||
});
|
||||
}
|
||||
|
||||
return secrets;
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -80,6 +129,26 @@ export class SecretsComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
openEventsDialogByEntityId = (secretName: string, secretId: string): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: secretName,
|
||||
organizationId: this.organizationId,
|
||||
entityId: secretId,
|
||||
entity: "secret",
|
||||
},
|
||||
});
|
||||
|
||||
openEventsDialog = (secret: SecretListView): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: secret.name,
|
||||
organizationId: this.organizationId,
|
||||
entityId: secret.id,
|
||||
entity: "secret",
|
||||
},
|
||||
});
|
||||
|
||||
private async getSecrets(): Promise<SecretListView[]> {
|
||||
return await this.secretService.getSecrets(this.organizationId);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import { takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
@@ -25,7 +27,6 @@ export class ServiceAccountEventsComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
exportFileName = "machine-account-events";
|
||||
private destroy$ = new Subject<void>();
|
||||
private serviceAccountId: string;
|
||||
|
||||
constructor(
|
||||
@@ -38,6 +39,8 @@ export class ServiceAccountEventsComponent
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService,
|
||||
toastService: ToastService,
|
||||
protected organizationService: OrganizationService,
|
||||
protected accountService: AccountService,
|
||||
) {
|
||||
super(
|
||||
eventService,
|
||||
@@ -47,10 +50,14 @@ export class ServiceAccountEventsComponent
|
||||
logService,
|
||||
fileDownloadService,
|
||||
toastService,
|
||||
route,
|
||||
accountService,
|
||||
organizationService,
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.initBase();
|
||||
// eslint-disable-next-line rxjs/no-async-subscribe
|
||||
this.route.params.pipe(takeUntil(this.destroy$)).subscribe(async (params) => {
|
||||
this.serviceAccountId = params.serviceAccountId;
|
||||
@@ -78,9 +85,4 @@ export class ServiceAccountEventsComponent
|
||||
email: "",
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { Component, EventEmitter, Input, OnDestroy, Output } from "@angular/core
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { TableDataSource, ToastService } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
@@ -49,7 +48,6 @@ export class ServiceAccountsListComponent implements OnDestroy {
|
||||
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.selection.changed
|
||||
|
||||
@@ -114,6 +114,15 @@
|
||||
<i class="bwi bwi-fw bwi-trash tw-text-danger" aria-hidden="true"></i>
|
||||
<span class="tw-text-danger">{{ "deleteProject" | i18n }}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
*ngIf="viewEventsAllowed$ | async as allowed"
|
||||
(click)="openEventsDialog(project)"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-billing" aria-hidden="true"></i>
|
||||
<span> {{ "viewEvents" | i18n }} </span>
|
||||
</button>
|
||||
</bit-menu>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { SelectionModel } from "@angular/cdk/collections";
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { map } from "rxjs";
|
||||
import { Component, EventEmitter, Input, Output, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { catchError, concatMap, map, Observable, of, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { TableDataSource, ToastService } from "@bitwarden/components";
|
||||
import { DialogRef, DialogService, TableDataSource, ToastService } from "@bitwarden/components";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
import { openEntityEventsDialog } from "@bitwarden/web-vault/app/admin-console/organizations/manage/entity-events.component";
|
||||
|
||||
import { ProjectListView } from "../models/view/project-list.view";
|
||||
import { ProjectView } from "../models/view/project.view";
|
||||
|
||||
@Component({
|
||||
selector: "sm-projects-list",
|
||||
templateUrl: "./projects-list.component.html",
|
||||
standalone: false,
|
||||
})
|
||||
export class ProjectsListComponent {
|
||||
export class ProjectsListComponent implements OnInit {
|
||||
@Input()
|
||||
get projects(): ProjectListView[] {
|
||||
return this._projects;
|
||||
@@ -26,6 +36,9 @@ export class ProjectsListComponent {
|
||||
this.dataSource.data = projects;
|
||||
}
|
||||
private _projects: ProjectListView[];
|
||||
protected viewEventsAllowed$: Observable<boolean>;
|
||||
protected isAdmin$: Observable<boolean>;
|
||||
private destroy$: Subject<void> = new Subject<void>();
|
||||
|
||||
@Input() showMenus?: boolean = true;
|
||||
|
||||
@@ -50,8 +63,41 @@ export class ProjectsListComponent {
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private toastService: ToastService,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private accountService: AccountService,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.viewEventsAllowed$ = this.activatedRoute.params.pipe(
|
||||
concatMap((params) =>
|
||||
getUserId(this.accountService.activeAccount$).pipe(
|
||||
switchMap((userId) =>
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
),
|
||||
),
|
||||
),
|
||||
map((org) => org.canAccessEventLogs),
|
||||
catchError((error: unknown) => {
|
||||
if (typeof error === "string") {
|
||||
this.toastService.showToast({
|
||||
message: error,
|
||||
variant: "error",
|
||||
title: "",
|
||||
});
|
||||
} else {
|
||||
this.logService.error(error);
|
||||
}
|
||||
return of(false);
|
||||
}),
|
||||
takeUntil(this.destroy$),
|
||||
);
|
||||
}
|
||||
|
||||
isAllSelected() {
|
||||
if (this.selection.selected?.length > 0) {
|
||||
const numSelected = this.selection.selected.length;
|
||||
@@ -87,6 +133,16 @@ export class ProjectsListComponent {
|
||||
}
|
||||
}
|
||||
|
||||
openEventsDialog = (project: ProjectView): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: project.name,
|
||||
organizationId: project.organizationId,
|
||||
entityId: project.id,
|
||||
entity: "project",
|
||||
},
|
||||
});
|
||||
|
||||
private selectedHasWriteAccess() {
|
||||
const selectedProjects = this.projects.filter((project) =>
|
||||
this.selection.isSelected(project.id),
|
||||
|
||||
@@ -148,6 +148,15 @@
|
||||
<i class="bwi bwi-fw bwi-refresh" aria-hidden="true"></i>
|
||||
{{ "restoreSecret" | i18n }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
*ngIf="viewEventsAllowed$ | async as allowed"
|
||||
(click)="openEventsDialog(secret)"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-billing" aria-hidden="true"></i>
|
||||
<span> {{ "viewEvents" | i18n }} </span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { SelectionModel } from "@angular/cdk/collections";
|
||||
import { Component, EventEmitter, Input, OnDestroy, Output } from "@angular/core";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import { Component, EventEmitter, Input, OnDestroy, Output, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { catchError, concatMap, map, Observable, of, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import {
|
||||
getOrganizationById,
|
||||
OrganizationService,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
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 { TableDataSource, ToastService } from "@bitwarden/components";
|
||||
import { DialogRef, DialogService, TableDataSource, ToastService } from "@bitwarden/components";
|
||||
import { openEntityEventsDialog } from "@bitwarden/web-vault/app/admin-console/organizations/manage/entity-events.component";
|
||||
|
||||
import { SecretListView } from "../models/view/secret-list.view";
|
||||
import { SecretView } from "../models/view/secret.view";
|
||||
import { SecretService } from "../secrets/secret.service";
|
||||
|
||||
@Component({
|
||||
@@ -17,7 +26,7 @@ import { SecretService } from "../secrets/secret.service";
|
||||
templateUrl: "./secrets-list.component.html",
|
||||
standalone: false,
|
||||
})
|
||||
export class SecretsListComponent implements OnDestroy {
|
||||
export class SecretsListComponent implements OnDestroy, OnInit {
|
||||
protected dataSource = new TableDataSource<SecretListView>();
|
||||
|
||||
@Input()
|
||||
@@ -52,17 +61,51 @@ export class SecretsListComponent implements OnDestroy {
|
||||
private destroy$: Subject<void> = new Subject<void>();
|
||||
|
||||
selection = new SelectionModel<string>(true, []);
|
||||
protected viewEventsAllowed$: Observable<boolean>;
|
||||
protected isAdmin$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private toastService: ToastService,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private accountService: AccountService,
|
||||
private logService: LogService,
|
||||
) {
|
||||
this.selection.changed
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((_) => this.onSecretCheckedEvent.emit(this.selection.selected));
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.viewEventsAllowed$ = this.activatedRoute.params.pipe(
|
||||
concatMap((params) =>
|
||||
getUserId(this.accountService.activeAccount$).pipe(
|
||||
switchMap((userId) =>
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
),
|
||||
),
|
||||
),
|
||||
map((org) => org.canAccessEventLogs),
|
||||
catchError((error: unknown) => {
|
||||
if (typeof error === "string") {
|
||||
this.toastService.showToast({
|
||||
message: error,
|
||||
variant: "error",
|
||||
title: "",
|
||||
});
|
||||
} else {
|
||||
this.logService.error(error);
|
||||
}
|
||||
return of(false);
|
||||
}),
|
||||
takeUntil(this.destroy$),
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
@@ -76,6 +119,15 @@ export class SecretsListComponent implements OnDestroy {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
openEventsDialog = (secret: SecretView): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: secret.name,
|
||||
organizationId: secret.organizationId,
|
||||
entityId: secret.id,
|
||||
entity: "secret",
|
||||
},
|
||||
});
|
||||
|
||||
toggleAll() {
|
||||
if (this.isAllSelected()) {
|
||||
|
||||
@@ -388,19 +388,23 @@ export abstract class ApiService {
|
||||
id: string,
|
||||
request: ProviderUserAcceptRequest,
|
||||
): Promise<any>;
|
||||
|
||||
abstract postProviderUserConfirm(
|
||||
providerId: string,
|
||||
id: string,
|
||||
request: ProviderUserConfirmRequest,
|
||||
): Promise<any>;
|
||||
|
||||
abstract postProviderUsersPublicKey(
|
||||
providerId: string,
|
||||
request: ProviderUserBulkRequest,
|
||||
): Promise<ListResponse<ProviderUserBulkPublicKeyResponse>>;
|
||||
|
||||
abstract postProviderUserBulkConfirm(
|
||||
providerId: string,
|
||||
request: ProviderUserBulkConfirmRequest,
|
||||
): Promise<ListResponse<ProviderUserBulkResponse>>;
|
||||
|
||||
abstract putProviderUser(
|
||||
providerId: string,
|
||||
id: string,
|
||||
@@ -435,6 +439,21 @@ export abstract class ApiService {
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>>;
|
||||
|
||||
abstract getEventsSecret(
|
||||
orgId: string,
|
||||
id: string,
|
||||
start: string,
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>>;
|
||||
abstract getEventsProject(
|
||||
orgId: string,
|
||||
id: string,
|
||||
start: string,
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>>;
|
||||
abstract getEventsOrganization(
|
||||
id: string,
|
||||
start: string,
|
||||
|
||||
@@ -93,4 +93,11 @@ export enum EventType {
|
||||
Secret_Created = 2101,
|
||||
Secret_Edited = 2102,
|
||||
Secret_Deleted = 2103,
|
||||
Secret_Permanently_Deleted = 2104,
|
||||
Secret_Restored = 2105,
|
||||
|
||||
Project_Retrieved = 2200,
|
||||
Project_Created = 2201,
|
||||
Project_Edited = 2202,
|
||||
Project_Deleted = 2203,
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ export class EventResponse extends BaseResponse {
|
||||
systemUser: EventSystemUser;
|
||||
domainName: string;
|
||||
secretId: string;
|
||||
projectId: string;
|
||||
serviceAccountId: string;
|
||||
|
||||
constructor(response: any) {
|
||||
@@ -45,6 +46,7 @@ export class EventResponse extends BaseResponse {
|
||||
this.systemUser = this.getResponseProperty("SystemUser");
|
||||
this.domainName = this.getResponseProperty("DomainName");
|
||||
this.secretId = this.getResponseProperty("SecretId");
|
||||
this.projectId = this.getResponseProperty("ProjectId");
|
||||
this.serviceAccountId = this.getResponseProperty("ServiceAccountId");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,6 +1267,50 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
return new ListResponse(r, EventResponse);
|
||||
}
|
||||
|
||||
async getEventsSecret(
|
||||
orgId: string,
|
||||
id: string,
|
||||
start: string,
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>> {
|
||||
const r = await this.send(
|
||||
"GET",
|
||||
this.addEventParameters(
|
||||
"/organization/" + orgId + "/secrets/" + id + "/events",
|
||||
start,
|
||||
end,
|
||||
token,
|
||||
),
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
return new ListResponse(r, EventResponse);
|
||||
}
|
||||
|
||||
async getEventsProject(
|
||||
orgId: string,
|
||||
id: string,
|
||||
start: string,
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>> {
|
||||
const r = await this.send(
|
||||
"GET",
|
||||
this.addEventParameters(
|
||||
"/organization/" + orgId + "/projects/" + id + "/events",
|
||||
start,
|
||||
end,
|
||||
token,
|
||||
),
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
return new ListResponse(r, EventResponse);
|
||||
}
|
||||
|
||||
async getEventsOrganization(
|
||||
id: string,
|
||||
start: string,
|
||||
|
||||
Reference in New Issue
Block a user