mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 21:33:27 +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:
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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$",
|
||||
|
||||
@@ -84,6 +84,15 @@
|
||||
<i class="bwi bwi-fw bwi-pencil" aria-hidden="true"></i>
|
||||
{{ "editMachineAccount" | i18n }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
*ngIf="viewEventsAllowed$ | async as allowed"
|
||||
(click)="openEventsDialog(serviceAccount)"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-billing" aria-hidden="true"></i>
|
||||
<span> {{ "viewEvents" | i18n }} </span>
|
||||
</button>
|
||||
<button type="button" bitMenuItem (click)="delete(serviceAccount)">
|
||||
<i class="bwi bwi-fw bwi-trash tw-text-danger" aria-hidden="true"></i>
|
||||
<span class="tw-text-danger">
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
// 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 { 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 {
|
||||
ServiceAccountSecretsDetailsView,
|
||||
@@ -17,7 +26,7 @@ import {
|
||||
templateUrl: "./service-accounts-list.component.html",
|
||||
standalone: false,
|
||||
})
|
||||
export class ServiceAccountsListComponent implements OnDestroy {
|
||||
export class ServiceAccountsListComponent implements OnDestroy, OnInit {
|
||||
protected dataSource = new TableDataSource<ServiceAccountSecretsDetailsView>();
|
||||
|
||||
@Input()
|
||||
@@ -43,18 +52,52 @@ export class ServiceAccountsListComponent implements OnDestroy {
|
||||
@Output() editServiceAccountEvent = new EventEmitter<string>();
|
||||
|
||||
private destroy$: Subject<void> = new Subject<void>();
|
||||
|
||||
protected viewEventsAllowed$: Observable<boolean>;
|
||||
protected isAdmin$: Observable<boolean>;
|
||||
selection = new SelectionModel<string>(true, []);
|
||||
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
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.onServiceAccountCheckedEvent.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();
|
||||
@@ -94,4 +137,13 @@ export class ServiceAccountsListComponent implements OnDestroy {
|
||||
});
|
||||
}
|
||||
}
|
||||
openEventsDialog = (serviceAccount: ServiceAccountView): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: serviceAccount.name,
|
||||
organizationId: serviceAccount.organizationId,
|
||||
entityId: serviceAccount.id,
|
||||
entity: "service-account",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// 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 { combineLatest, firstValueFrom, Observable, startWith, switchMap } from "rxjs";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { combineLatestWith, firstValueFrom, Observable, startWith, switchMap } from "rxjs";
|
||||
|
||||
import {
|
||||
getOrganizationById,
|
||||
@@ -10,7 +10,9 @@ 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 {
|
||||
ServiceAccountSecretsDetailsView,
|
||||
@@ -46,14 +48,16 @@ export class ServiceAccountsComponent implements OnInit {
|
||||
private serviceAccountService: ServiceAccountService,
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private toastService: ToastService,
|
||||
private router: Router,
|
||||
private i18nService: I18nService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.serviceAccounts$ = combineLatest([
|
||||
this.route.params,
|
||||
this.serviceAccountService.serviceAccount$.pipe(startWith(null)),
|
||||
]).pipe(
|
||||
switchMap(async ([params]) => {
|
||||
this.serviceAccounts$ = this.serviceAccountService.serviceAccount$.pipe(
|
||||
startWith(null),
|
||||
combineLatestWith(this.route.params),
|
||||
switchMap(async ([_, params]) => {
|
||||
this.organizationId = params.organizationId;
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.organizationEnabled = (
|
||||
@@ -64,11 +68,74 @@ export class ServiceAccountsComponent implements OnInit {
|
||||
)
|
||||
)?.enabled;
|
||||
|
||||
return await this.getServiceAccounts();
|
||||
const serviceAccounts = await this.getServiceAccounts();
|
||||
|
||||
const viewEvents = this.route.snapshot.queryParams.viewEvents;
|
||||
if (viewEvents) {
|
||||
const targetAccount = serviceAccounts.find((sa) => sa.id === viewEvents);
|
||||
|
||||
const userIsAdmin = (
|
||||
await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(params.organizationId)),
|
||||
)
|
||||
)?.isAdmin;
|
||||
|
||||
if (!targetAccount) {
|
||||
if (userIsAdmin) {
|
||||
this.openEventsDialogByEntityId(
|
||||
this.i18nService.t("nameUnavailableServiceAccountDeleted", viewEvents),
|
||||
viewEvents,
|
||||
);
|
||||
} else {
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("unknownServiceAccount"),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.openEventsDialog(targetAccount);
|
||||
}
|
||||
|
||||
await this.router.navigate([], {
|
||||
queryParams: { search: this.search },
|
||||
});
|
||||
}
|
||||
|
||||
return serviceAccounts;
|
||||
}),
|
||||
);
|
||||
|
||||
if (this.route.snapshot.queryParams.search) {
|
||||
this.search = this.route.snapshot.queryParams.search;
|
||||
}
|
||||
}
|
||||
|
||||
openEventsDialogByEntityId = (
|
||||
serviceAccountName: string,
|
||||
serviceAccountId: string,
|
||||
): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: serviceAccountName,
|
||||
organizationId: this.organizationId,
|
||||
entityId: serviceAccountId,
|
||||
entity: "service-account",
|
||||
},
|
||||
});
|
||||
|
||||
openEventsDialog = (serviceAccount: ServiceAccountView): DialogRef<void> =>
|
||||
openEntityEventsDialog(this.dialogService, {
|
||||
data: {
|
||||
name: serviceAccount.name,
|
||||
organizationId: this.organizationId,
|
||||
entityId: serviceAccount.id,
|
||||
entity: "service-account",
|
||||
},
|
||||
});
|
||||
|
||||
openNewServiceAccountDialog() {
|
||||
this.dialogService.open<unknown, ServiceAccountOperation>(ServiceAccountDialogComponent, {
|
||||
data: {
|
||||
|
||||
@@ -461,6 +461,13 @@ export abstract class ApiService {
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>>;
|
||||
abstract getEventsServiceAccount(
|
||||
orgId: string,
|
||||
id: string,
|
||||
start: string,
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>>;
|
||||
abstract getEventsProject(
|
||||
orgId: string,
|
||||
id: string,
|
||||
|
||||
@@ -108,4 +108,11 @@ export enum EventType {
|
||||
Project_Created = 2201,
|
||||
Project_Edited = 2202,
|
||||
Project_Deleted = 2203,
|
||||
|
||||
ServiceAccount_UserAdded = 2300,
|
||||
ServiceAccount_UserRemoved = 2301,
|
||||
ServiceAccount_GroupAdded = 2302,
|
||||
ServiceAccount_GroupRemoved = 2303,
|
||||
ServiceAccount_Created = 2304,
|
||||
ServiceAccount_Deleted = 2305,
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ export class EventResponse extends BaseResponse {
|
||||
secretId: string;
|
||||
projectId: string;
|
||||
serviceAccountId: string;
|
||||
grantedServiceAccountId: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
@@ -48,5 +49,6 @@ export class EventResponse extends BaseResponse {
|
||||
this.secretId = this.getResponseProperty("SecretId");
|
||||
this.projectId = this.getResponseProperty("ProjectId");
|
||||
this.serviceAccountId = this.getResponseProperty("ServiceAccountId");
|
||||
this.grantedServiceAccountId = this.getResponseProperty("GrantedServiceAccountId");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1272,6 +1272,28 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
return new ListResponse(r, EventResponse);
|
||||
}
|
||||
|
||||
async getEventsServiceAccount(
|
||||
orgId: string,
|
||||
id: string,
|
||||
start: string,
|
||||
end: string,
|
||||
token: string,
|
||||
): Promise<ListResponse<EventResponse>> {
|
||||
const r = await this.send(
|
||||
"GET",
|
||||
this.addEventParameters(
|
||||
"/organization/" + orgId + "/service-account/" + id + "/events",
|
||||
start,
|
||||
end,
|
||||
token,
|
||||
),
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
return new ListResponse(r, EventResponse);
|
||||
}
|
||||
|
||||
async getEventsProject(
|
||||
orgId: string,
|
||||
id: string,
|
||||
|
||||
Reference in New Issue
Block a user