mirror of
https://github.com/bitwarden/browser
synced 2026-02-05 11:13:44 +00:00
PM-24655 Add delete option to integrations
This commit is contained in:
@@ -18,7 +18,7 @@ import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../../../../../shared/shared.module";
|
||||
import { openHecConnectDialog } from "../integration-dialog/index";
|
||||
import { HecConnectDialogResultStatus, openHecConnectDialog } from "../integration-dialog/index";
|
||||
import { HecConfiguration, HecConfigurationTemplate, Integration } from "../models";
|
||||
import { OrganizationIntegrationService } from "../services/organization-integration.service";
|
||||
|
||||
@@ -141,6 +141,19 @@ export class IntegrationCardComponent implements AfterViewInit, OnDestroy {
|
||||
const integration = new HecConfiguration(result.url, result.bearerToken, result.service);
|
||||
const configurationTemplate = new HecConfigurationTemplate(result.index, result.service);
|
||||
|
||||
if (result.success === HecConnectDialogResultStatus.Edited) {
|
||||
await this.saveIntegration(integration, configurationTemplate);
|
||||
}
|
||||
|
||||
if (result.success === HecConnectDialogResultStatus.Delete) {
|
||||
await this.deleteIntegration(integration, configurationTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
async saveIntegration(
|
||||
integration: HecConfiguration,
|
||||
configurationTemplate: HecConfigurationTemplate,
|
||||
) {
|
||||
// save the integration
|
||||
try {
|
||||
await this.organizationIntegrationService.saveHec(
|
||||
@@ -158,4 +171,25 @@ export class IntegrationCardComponent implements AfterViewInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteIntegration(
|
||||
integration: HecConfiguration,
|
||||
configurationTemplate: HecConfigurationTemplate,
|
||||
) {
|
||||
// delete the integration
|
||||
try {
|
||||
await this.organizationIntegrationService.deleteHec(
|
||||
this.organizationId,
|
||||
integration,
|
||||
configurationTemplate,
|
||||
);
|
||||
} catch {
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: "",
|
||||
message: this.i18nService.t("failedToDeleteIntegration"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,18 @@
|
||||
<button type="button" bitButton bitDialogClose buttonType="secondary" [disabled]="loading">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
|
||||
@if (canDelete()) {
|
||||
<div class="tw-ml-auto">
|
||||
<button
|
||||
bitIconButton="bwi-trash"
|
||||
type="button"
|
||||
buttonType="danger"
|
||||
[appA11yTitle]="'delete' | i18n"
|
||||
[bitAction]="delete"
|
||||
></button>
|
||||
</div>
|
||||
}
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
</form>
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
HecConnectDialogParams,
|
||||
HecConnectDialogResult,
|
||||
openHecConnectDialog,
|
||||
HecConnectDialogResultStatus,
|
||||
} from "./connect-dialog-hec.component";
|
||||
|
||||
beforeAll(() => {
|
||||
@@ -57,6 +58,7 @@ describe("ConnectDialogHecComponent", () => {
|
||||
let component: ConnectHecDialogComponent;
|
||||
let fixture: ComponentFixture<ConnectHecDialogComponent>;
|
||||
let dialogRefMock = mock<DialogRef<HecConnectDialogResult>>();
|
||||
const dialogService = mock<DialogService>();
|
||||
const mockI18nService = mock<I18nService>();
|
||||
|
||||
const integrationMock: Integration = {
|
||||
@@ -72,13 +74,6 @@ describe("ConnectDialogHecComponent", () => {
|
||||
} as Integration;
|
||||
const connectInfo: HecConnectDialogParams = {
|
||||
settings: integrationMock,
|
||||
configuration: {
|
||||
uri: "",
|
||||
scheme: "https",
|
||||
token: "",
|
||||
service: "mock-service",
|
||||
}, // Provide appropriate mock configuration if needed
|
||||
template: null, // Provide appropriate mock template if needed
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -92,8 +87,18 @@ describe("ConnectDialogHecComponent", () => {
|
||||
{ provide: DialogRef, useValue: dialogRefMock },
|
||||
{ provide: I18nPipe, useValue: mock<I18nPipe>() },
|
||||
{ provide: I18nService, useValue: mockI18nService },
|
||||
{ provide: DialogService, useValue: dialogService },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
TestBed.overrideComponent(ConnectHecDialogComponent, {
|
||||
add: {
|
||||
providers: [{ provide: DialogService, useValue: dialogService }],
|
||||
},
|
||||
remove: {
|
||||
providers: [DialogService],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -163,8 +168,48 @@ describe("ConnectDialogHecComponent", () => {
|
||||
bearerToken: "token",
|
||||
index: "1",
|
||||
service: "Test Service",
|
||||
success: true,
|
||||
error: null,
|
||||
success: HecConnectDialogResultStatus.Edited,
|
||||
});
|
||||
});
|
||||
|
||||
describe("ConnectHecDialogComponent.delete", () => {
|
||||
it("should call dialogService.openSimpleDialog and close dialog with delete result if confirmed", async () => {
|
||||
// Arrange
|
||||
const confirmed = true;
|
||||
dialogService.openSimpleDialog.mockResolvedValue(confirmed);
|
||||
component.formGroup.setValue({
|
||||
url: "https://test.com",
|
||||
bearerToken: "token",
|
||||
index: "1",
|
||||
service: "Test Service",
|
||||
});
|
||||
|
||||
// Act
|
||||
await component.delete();
|
||||
|
||||
// Assert
|
||||
expect(dialogService.openSimpleDialog).toHaveBeenCalledWith({
|
||||
title: { key: "deleteItem" },
|
||||
content: { key: "deleteItemConfirmation" },
|
||||
type: "warning",
|
||||
});
|
||||
expect(dialogRefMock.close).toHaveBeenCalledWith({
|
||||
integrationSettings: integrationMock,
|
||||
url: "https://test.com",
|
||||
bearerToken: "token",
|
||||
index: "1",
|
||||
service: "Test Service",
|
||||
success: HecConnectDialogResultStatus.Delete,
|
||||
});
|
||||
});
|
||||
|
||||
it("should not close dialog if not confirmed", async () => {
|
||||
dialogService.openSimpleDialog.mockResolvedValue(false);
|
||||
|
||||
await component.delete();
|
||||
|
||||
expect(dialogService.openSimpleDialog).toHaveBeenCalled();
|
||||
expect(dialogRefMock.close).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,10 +16,17 @@ export interface HecConnectDialogResult {
|
||||
bearerToken: string;
|
||||
index: string;
|
||||
service: string;
|
||||
success: boolean;
|
||||
error: string | null;
|
||||
success: HecConnectDialogResultStatusType | null;
|
||||
}
|
||||
|
||||
export const HecConnectDialogResultStatus = {
|
||||
Edited: "edit",
|
||||
Delete: "delete",
|
||||
} as const;
|
||||
|
||||
export type HecConnectDialogResultStatusType =
|
||||
(typeof HecConnectDialogResultStatus)[keyof typeof HecConnectDialogResultStatus];
|
||||
|
||||
@Component({
|
||||
templateUrl: "./connect-dialog-hec.component.html",
|
||||
imports: [SharedModule],
|
||||
@@ -37,6 +44,7 @@ export class ConnectHecDialogComponent implements OnInit {
|
||||
@Inject(DIALOG_DATA) protected connectInfo: HecConnectDialogParams,
|
||||
protected formBuilder: FormBuilder,
|
||||
private dialogRef: DialogRef<HecConnectDialogResult>,
|
||||
private dialogService: DialogService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -52,6 +60,10 @@ export class ConnectHecDialogComponent implements OnInit {
|
||||
return !!this.connectInfo.settings.HecConfiguration;
|
||||
}
|
||||
|
||||
canDelete(): boolean {
|
||||
return !!this.connectInfo.settings.HecConfiguration;
|
||||
}
|
||||
|
||||
getSettingsAsJson(configuration: string) {
|
||||
try {
|
||||
return JSON.parse(configuration);
|
||||
@@ -61,22 +73,43 @@ export class ConnectHecDialogComponent implements OnInit {
|
||||
}
|
||||
|
||||
submit = async (): Promise<void> => {
|
||||
const formJson = this.formGroup.getRawValue();
|
||||
|
||||
const result: HecConnectDialogResult = {
|
||||
integrationSettings: this.connectInfo.settings,
|
||||
url: formJson.url || "",
|
||||
bearerToken: formJson.bearerToken || "",
|
||||
index: formJson.index || "",
|
||||
service: formJson.service || "",
|
||||
success: true,
|
||||
error: null,
|
||||
};
|
||||
const result = this.getHecConnectDialogResult(HecConnectDialogResultStatus.Edited);
|
||||
|
||||
this.dialogRef.close(result);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
delete = async (): Promise<void> => {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "deleteItem" },
|
||||
content: {
|
||||
key: "deleteItemConfirmation",
|
||||
},
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
// Perform the deletion logic here
|
||||
const result = this.getHecConnectDialogResult(HecConnectDialogResultStatus.Delete);
|
||||
this.dialogRef.close(result);
|
||||
}
|
||||
};
|
||||
|
||||
private getHecConnectDialogResult(
|
||||
status: HecConnectDialogResultStatusType,
|
||||
): HecConnectDialogResult {
|
||||
const formJson = this.formGroup.getRawValue();
|
||||
|
||||
return {
|
||||
integrationSettings: this.connectInfo.settings,
|
||||
url: formJson.url || "",
|
||||
bearerToken: formJson.bearerToken || "",
|
||||
index: formJson.index || "",
|
||||
service: formJson.service || "",
|
||||
success: status,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function openHecConnectDialog(
|
||||
|
||||
@@ -5,7 +5,9 @@ import { mock } from "jest-mock-extended";
|
||||
import {
|
||||
OrganizationIntegrationApiService,
|
||||
OrganizationIntegrationConfigurationApiService,
|
||||
OrganizationIntegrationConfigurationResponse,
|
||||
} from "@bitwarden/bit-common/dirt/integrations";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
|
||||
import { OrganizationIntegrationService } from "./organization-integration.service";
|
||||
|
||||
@@ -139,4 +141,202 @@ describe("OrganizationIntegrationService", () => {
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("deleteHecIntegrationConfiguration", () => {
|
||||
const organizationId = "org-123" as any;
|
||||
const integrationId = "int-1" as any;
|
||||
const serviceName = "splunk";
|
||||
|
||||
let mockConfig: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockConfig = { id: "conf-1", template: '{"service":"splunk"}' };
|
||||
|
||||
jest.resetAllMocks();
|
||||
|
||||
// Set up integrationConfigurations$ with a matching config/template
|
||||
service["integrationConfigurations$"].next([
|
||||
{
|
||||
integrationId,
|
||||
configurationResponses: [mockConfig],
|
||||
},
|
||||
]);
|
||||
|
||||
jest.spyOn(service, "convertToJson").mockImplementation((json: string) => {
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should delete configuration when config and template exist", async () => {
|
||||
mockOrgIntegrationConfigurationApiService.deleteOrganizationIntegrationConfiguration.mockResolvedValue(
|
||||
undefined,
|
||||
);
|
||||
|
||||
await service.deleteHecIntegrationConfiguration(organizationId, integrationId, serviceName);
|
||||
|
||||
expect(
|
||||
mockOrgIntegrationConfigurationApiService.deleteOrganizationIntegrationConfiguration,
|
||||
).toHaveBeenCalledWith(organizationId, integrationId, mockConfig.id);
|
||||
|
||||
// The configurationResponses should be filtered (removed)
|
||||
const updatedConfigs = service["integrationConfigurations$"].value.find(
|
||||
(c) => c.integrationId === integrationId,
|
||||
);
|
||||
expect(updatedConfigs?.configurationResponses).toEqual([]);
|
||||
});
|
||||
|
||||
it("should do nothing if config or template is missing", async () => {
|
||||
// Set up with no matching config/template
|
||||
service["integrationConfigurations$"].next([
|
||||
{
|
||||
integrationId,
|
||||
configurationResponses: [
|
||||
{
|
||||
id: "conf-2",
|
||||
eventType: EventType.Cipher_AttachmentCreated,
|
||||
configuration: "",
|
||||
template: '{"service":"other"}',
|
||||
} as OrganizationIntegrationConfigurationResponse,
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
await service.deleteHecIntegrationConfiguration(organizationId, integrationId, serviceName);
|
||||
|
||||
expect(
|
||||
mockOrgIntegrationConfigurationApiService.deleteOrganizationIntegrationConfiguration,
|
||||
).not.toHaveBeenCalled();
|
||||
|
||||
// configurationResponses should remain unchanged
|
||||
const configs = service["integrationConfigurations$"].value.find(
|
||||
(c) => c.integrationId === integrationId,
|
||||
);
|
||||
expect(configs?.configurationResponses.length).toBe(1);
|
||||
});
|
||||
|
||||
it("should do nothing if integrationConfigurations is empty", async () => {
|
||||
service["integrationConfigurations$"].next([]);
|
||||
|
||||
await service.deleteHecIntegrationConfiguration(organizationId, integrationId, serviceName);
|
||||
|
||||
expect(
|
||||
mockOrgIntegrationConfigurationApiService.deleteOrganizationIntegrationConfiguration,
|
||||
).not.toHaveBeenCalled();
|
||||
expect(service["integrationConfigurations$"].value).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("deleteHecIntegration", () => {
|
||||
const organizationId = "org-123" as any;
|
||||
const integrationId = "int-1" as any;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
service["integrations$"].next([
|
||||
{ id: integrationId, type: "Hec", configuration: "{}", service: "splunk" } as any,
|
||||
{ id: "int-2", type: "Other", configuration: "{}" } as any,
|
||||
]);
|
||||
});
|
||||
|
||||
it("should call deleteOrganizationIntegration and remove integration from store", async () => {
|
||||
mockOrgIntegrationApiService.deleteOrganizationIntegration.mockResolvedValue(undefined);
|
||||
|
||||
await service.deleteHecIntegration(organizationId, integrationId);
|
||||
|
||||
expect(mockOrgIntegrationApiService.deleteOrganizationIntegration).toHaveBeenCalledWith(
|
||||
organizationId,
|
||||
integrationId,
|
||||
);
|
||||
const remainingIntegrations = service["integrations$"].value;
|
||||
expect(remainingIntegrations).toEqual([{ id: "int-2", type: "Other", configuration: "{}" }]);
|
||||
});
|
||||
|
||||
it("should not throw if integration does not exist", async () => {
|
||||
mockOrgIntegrationApiService.deleteOrganizationIntegration.mockResolvedValue(undefined);
|
||||
service["integrations$"].next([{ id: "int-2", type: "Other", configuration: "{}" } as any]);
|
||||
|
||||
await expect(
|
||||
service.deleteHecIntegration(organizationId, integrationId),
|
||||
).resolves.not.toThrow();
|
||||
expect(service["integrations$"].value).toEqual([
|
||||
{ id: "int-2", type: "Other", configuration: "{}" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should handle empty integrations list", async () => {
|
||||
mockOrgIntegrationApiService.deleteOrganizationIntegration.mockResolvedValue(undefined);
|
||||
service["integrations$"].next([]);
|
||||
|
||||
await expect(
|
||||
service.deleteHecIntegration(organizationId, integrationId),
|
||||
).resolves.not.toThrow();
|
||||
expect(service["integrations$"].value).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("deleteHec", () => {
|
||||
const organizationId = "org-123" as any;
|
||||
const hecConfiguration = { service: "splunk", toString: () => '{"service":"splunk"}' } as any;
|
||||
const hecConfigurationTemplate = {
|
||||
service: "splunk",
|
||||
toString: () => '{"service":"splunk"}',
|
||||
} as any;
|
||||
const integrationId = "int-1";
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
// Set up integrations$ with a matching Hec integration
|
||||
service["integrations$"].next([
|
||||
{ id: integrationId, type: "Hec", configuration: '{"service":"splunk"}' } as any,
|
||||
]);
|
||||
// Spy on getIntegration to return the expected integration
|
||||
jest.spyOn(service as any, "getIntegration").mockReturnValue({
|
||||
id: integrationId,
|
||||
type: "Hec",
|
||||
configuration: '{"service":"splunk"}',
|
||||
});
|
||||
});
|
||||
|
||||
it("should delete HEC integration configuration and then integration", async () => {
|
||||
const deleteConfigSpy = jest
|
||||
.spyOn(service, "deleteHecIntegrationConfiguration")
|
||||
.mockResolvedValue(undefined);
|
||||
const deleteIntegrationSpy = jest
|
||||
.spyOn(service, "deleteHecIntegration")
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
await service.deleteHec(organizationId, hecConfiguration, hecConfigurationTemplate);
|
||||
|
||||
expect(deleteConfigSpy).toHaveBeenCalledWith(
|
||||
organizationId,
|
||||
integrationId,
|
||||
hecConfigurationTemplate.service,
|
||||
);
|
||||
expect(deleteIntegrationSpy).toHaveBeenCalledWith(organizationId, integrationId);
|
||||
});
|
||||
|
||||
it("should handle errors thrown by deleteHecIntegrationConfiguration", async () => {
|
||||
jest
|
||||
.spyOn(service, "deleteHecIntegrationConfiguration")
|
||||
.mockRejectedValue(new Error("Config error"));
|
||||
jest.spyOn(service, "deleteHecIntegration").mockResolvedValue(undefined);
|
||||
|
||||
await expect(
|
||||
service.deleteHec(organizationId, hecConfiguration, hecConfigurationTemplate),
|
||||
).rejects.toThrow("Config error");
|
||||
});
|
||||
|
||||
it("should handle errors thrown by deleteHecIntegration", async () => {
|
||||
jest.spyOn(service, "deleteHecIntegrationConfiguration").mockResolvedValue(undefined);
|
||||
jest.spyOn(service, "deleteHecIntegration").mockRejectedValue(new Error("Integration error"));
|
||||
|
||||
await expect(
|
||||
service.deleteHec(organizationId, hecConfiguration, hecConfigurationTemplate),
|
||||
).rejects.toThrow("Integration error");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,6 +68,15 @@ export class OrganizationIntegrationService {
|
||||
.subscribe(([integrations, configurations]) => {
|
||||
const existingIntegrations = [...this.masterIntegrationList$.value];
|
||||
|
||||
// reset - to original values
|
||||
existingIntegrations.forEach((integration) => {
|
||||
integration.isConnected = false;
|
||||
integration.configuration = "";
|
||||
integration.template = "";
|
||||
integration.HecConfiguration = null;
|
||||
integration.HecConfigurationTemplate = null;
|
||||
});
|
||||
|
||||
// Update the integrations list with the fetched integrations
|
||||
if (integrations && integrations.length > 0) {
|
||||
integrations.forEach((integration) => {
|
||||
@@ -81,7 +90,7 @@ export class OrganizationIntegrationService {
|
||||
existingIntegration.configuration = integration.configuration || "";
|
||||
existingIntegration.HecConfiguration = hecConfigJson;
|
||||
|
||||
const template = this.getIntegrationConfiguration(
|
||||
const { template } = this.getIntegrationConfiguration(
|
||||
integration.id,
|
||||
serviceName,
|
||||
configurations,
|
||||
@@ -199,9 +208,7 @@ export class OrganizationIntegrationService {
|
||||
);
|
||||
|
||||
// find the existing integration
|
||||
const existingIntegration = this.integrations$.value.find(
|
||||
(i) => i.type === OrganizationIntegrationType.Hec,
|
||||
);
|
||||
const existingIntegration = this.getIntegration(OrganizationIntegrationType.Hec);
|
||||
|
||||
if (existingIntegration) {
|
||||
// existing integration record found, invoke update API endpoint
|
||||
@@ -261,20 +268,12 @@ export class OrganizationIntegrationService {
|
||||
// check if we have an existing configuration for this integration
|
||||
const integrationConfigurations = this.integrationConfigurations$.value;
|
||||
|
||||
// find the existing configuration by integrationId
|
||||
const existingConfigurations = integrationConfigurations
|
||||
.filter((config) => config.integrationId === integrationId)
|
||||
.flatMap((config) => config.configurationResponses || []);
|
||||
|
||||
// find the configuration by service
|
||||
const existingConfiguration =
|
||||
existingConfigurations.length > 0
|
||||
? existingConfigurations.find(
|
||||
(config) =>
|
||||
config.template &&
|
||||
this.convertToJson<HecConfigurationTemplate>(config.template)?.service === service,
|
||||
)
|
||||
: null;
|
||||
const { config } = this.getIntegrationConfiguration(
|
||||
integrationId,
|
||||
service,
|
||||
integrationConfigurations,
|
||||
);
|
||||
const existingConfiguration = config;
|
||||
|
||||
if (existingConfiguration) {
|
||||
// existing configuration found, invoke update API endpoint
|
||||
@@ -328,13 +327,95 @@ export class OrganizationIntegrationService {
|
||||
}
|
||||
}
|
||||
|
||||
async deleteHec(
|
||||
organizationId: OrganizationId,
|
||||
integration: HecConfiguration,
|
||||
template: HecConfigurationTemplate,
|
||||
) {
|
||||
// find the existing integration
|
||||
const existingIntegration = this.getIntegration(OrganizationIntegrationType.Hec);
|
||||
|
||||
if (existingIntegration === null) {
|
||||
// couldn't find existing integration for Hec and Service name
|
||||
return;
|
||||
}
|
||||
|
||||
// drop HEC Integration Configuration first
|
||||
await this.deleteHecIntegrationConfiguration(
|
||||
organizationId,
|
||||
existingIntegration.id,
|
||||
template.service,
|
||||
);
|
||||
|
||||
// drop HEC Integration
|
||||
await this.deleteHecIntegration(organizationId, existingIntegration.id);
|
||||
}
|
||||
|
||||
async deleteHecIntegration(
|
||||
organizationId: OrganizationId,
|
||||
integrationId: OrganizationIntegrationId,
|
||||
) {
|
||||
// drop HEC Integration
|
||||
await this.integrationApiService.deleteOrganizationIntegration(organizationId, integrationId);
|
||||
|
||||
const updatedIntegrations = this.integrations$.value.filter((i) => i.id !== integrationId);
|
||||
|
||||
this.integrations$.next(updatedIntegrations);
|
||||
}
|
||||
|
||||
async deleteHecIntegrationConfiguration(
|
||||
organizationId: OrganizationId,
|
||||
integrationId: OrganizationIntegrationId,
|
||||
service: string,
|
||||
) {
|
||||
const integrationConfigurations = this.integrationConfigurations$.value;
|
||||
|
||||
const { config, template } = this.getIntegrationConfiguration(
|
||||
integrationId,
|
||||
service,
|
||||
integrationConfigurations,
|
||||
);
|
||||
|
||||
if (!config || !template) {
|
||||
return;
|
||||
}
|
||||
|
||||
// drop HEC Integration Configuration first
|
||||
await this.integrationConfigurationApiService.deleteOrganizationIntegrationConfiguration(
|
||||
organizationId,
|
||||
integrationId,
|
||||
config.id,
|
||||
);
|
||||
|
||||
// remove the configuration from the local store
|
||||
integrationConfigurations.forEach((integrationConfig) => {
|
||||
if (integrationConfig.integrationId === integrationId) {
|
||||
integrationConfig.configurationResponses = integrationConfig.configurationResponses.filter(
|
||||
(config) => config.id !== config.id,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this.integrationConfigurations$.next(integrationConfigurations);
|
||||
}
|
||||
|
||||
private getIntegration(
|
||||
integrationType: OrganizationIntegrationType,
|
||||
): OrganizationIntegrationResponse | null {
|
||||
const integrations = this.integrations$.value;
|
||||
return integrations.find((i) => i.type === integrationType) ?? null;
|
||||
}
|
||||
|
||||
private getIntegrationConfiguration(
|
||||
integrationId: OrganizationIntegrationId,
|
||||
service: string,
|
||||
integrationConfigurations: OrganizationIntegrationConfigurationResponseWithIntegrationId[],
|
||||
): HecConfigurationTemplate | null {
|
||||
): {
|
||||
config: OrganizationIntegrationConfigurationResponse | null;
|
||||
template: HecConfigurationTemplate | null;
|
||||
} {
|
||||
if (integrationConfigurations.length === 0) {
|
||||
return null;
|
||||
return { config: null, template: null };
|
||||
}
|
||||
|
||||
const integrationConfigs = integrationConfigurations.find(
|
||||
@@ -342,17 +423,17 @@ export class OrganizationIntegrationService {
|
||||
);
|
||||
|
||||
if (!integrationConfigs) {
|
||||
return null;
|
||||
return { config: null, template: null };
|
||||
}
|
||||
|
||||
for (const config of integrationConfigs.configurationResponses) {
|
||||
const template = this.convertToJson<HecConfigurationTemplate>(config.template || "");
|
||||
if (template && template.service === service) {
|
||||
return template;
|
||||
return { config, template };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return { config: null, template: null };
|
||||
}
|
||||
|
||||
convertToJson<T>(jsonString?: string): T | null {
|
||||
|
||||
Reference in New Issue
Block a user