mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
feat: Add monitorId to MonitorTest model and related migrations
This commit is contained in:
@@ -21,6 +21,7 @@ import Permission from "../../Types/Permission";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import { MonitorStepProbeResponse } from "./MonitorProbe";
|
||||
import Probe from "./Probe";
|
||||
import Monitor from "./Monitor";
|
||||
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
@@ -475,4 +476,70 @@ export default class MonitorTest extends BaseModel {
|
||||
default: true,
|
||||
})
|
||||
public isInQueue?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectMonitor,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectMonitor,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Monitor ID",
|
||||
description: "ID of the Monitor this test is related to.",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public monitorId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectMonitor,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectMonitor,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "monitorId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Monitor,
|
||||
title: "Monitor",
|
||||
description: "Relation to Monitor Resource in which this test belongs.",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Monitor;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "monitorId" })
|
||||
public monitor?: Monitor = undefined;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1747674762672 implements MigrationInterface {
|
||||
public name = "MigrationName1747674762672";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "MonitorTest" ADD "monitorId" uuid`);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_4650119024eca8c91608effb95" ON "MonitorTest" ("monitorId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "MonitorTest" ADD CONSTRAINT "FK_4650119024eca8c91608effb959" FOREIGN KEY ("monitorId") REFERENCES "Monitor"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "MonitorTest" DROP CONSTRAINT "FK_4650119024eca8c91608effb959"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_4650119024eca8c91608effb95"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "MonitorTest" DROP COLUMN "monitorId"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,7 @@ import { MigrationName1743714801105 } from "./1743714801105-MigrationName";
|
||||
import { MigrationName1744804990712 } from "./1744804990712-MigrationName";
|
||||
import { MigrationName1744809770336 } from "./1744809770336-MigrationName";
|
||||
import { MigrationName1747305098533 } from "./1747305098533-MigrationName";
|
||||
import { MigrationName1747674762672 } from "./1747674762672-MigrationName";
|
||||
|
||||
export default [
|
||||
InitialMigration,
|
||||
@@ -268,4 +269,5 @@ export default [
|
||||
MigrationName1744804990712,
|
||||
MigrationName1744809770336,
|
||||
MigrationName1747305098533,
|
||||
MigrationName1747674762672,
|
||||
];
|
||||
|
||||
@@ -26,6 +26,7 @@ import { MonitorStepProbeResponse } from "Common/Models/DatabaseModels/MonitorPr
|
||||
import SummaryInfo from "../../Monitor/SummaryView/SummaryInfo";
|
||||
|
||||
export interface ComponentProps {
|
||||
monitorId?: ObjectID | undefined;
|
||||
monitorSteps: MonitorSteps;
|
||||
monitorType: MonitorType;
|
||||
probes: Array<Probe>;
|
||||
@@ -70,6 +71,9 @@ const MonitorTestForm: FunctionComponent<ComponentProps> = (
|
||||
monitorTestObj.probeId = probeId;
|
||||
monitorTestObj.monitorType = props.monitorType;
|
||||
monitorTestObj.isInQueue = true;
|
||||
if (props.monitorId) {
|
||||
monitorTestObj.monitorId = props.monitorId;
|
||||
}
|
||||
|
||||
// save the monitor test to the database.
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ const MonitorCriteria: FunctionComponent<
|
||||
description: "Here is the criteria we use to monitor this resource.",
|
||||
rightElement: monitorSteps ? (
|
||||
<MonitorTestForm
|
||||
monitorId={modelId}
|
||||
buttonSize={ButtonSize.Normal}
|
||||
monitorSteps={monitorSteps}
|
||||
monitorType={monitorType}
|
||||
|
||||
@@ -526,6 +526,7 @@ router.post(
|
||||
monitorSteps: true,
|
||||
_id: true,
|
||||
projectId: true,
|
||||
monitorId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@@ -555,13 +556,38 @@ router.post(
|
||||
|
||||
await Promise.all(updatePromises);
|
||||
|
||||
logger.debug("Populating secrets");
|
||||
logger.debug(monitorTests);
|
||||
|
||||
// check if the monitor needs secrets to be filled.
|
||||
|
||||
let monitorTestsWithSecretPopulated: Array<MonitorTest> = [];
|
||||
const monitorTestsWithSecretsPopulatePromises: Array<
|
||||
Promise<MonitorTest>
|
||||
> = [];
|
||||
|
||||
for (const monitorTest of monitorTests) {
|
||||
monitorTestsWithSecretsPopulatePromises.push(
|
||||
MonitorUtil.populateSecretsOnMonitorTest(monitorTest),
|
||||
);
|
||||
}
|
||||
|
||||
monitorTestsWithSecretPopulated = await Promise.all(
|
||||
monitorTestsWithSecretsPopulatePromises,
|
||||
);
|
||||
|
||||
logger.debug("Populated secrets");
|
||||
logger.debug(monitorTestsWithSecretPopulated);
|
||||
|
||||
// return the list of monitors to be monitored
|
||||
|
||||
logger.debug("Sending response");
|
||||
|
||||
return Response.sendEntityArrayResponse(
|
||||
req,
|
||||
res,
|
||||
monitorTests,
|
||||
new PositiveNumber(monitorTests.length),
|
||||
monitorTestsWithSecretPopulated,
|
||||
new PositiveNumber(monitorTestsWithSecretPopulated.length),
|
||||
MonitorTest,
|
||||
);
|
||||
} catch (err) {
|
||||
|
||||
@@ -2,7 +2,6 @@ import Hostname from "Common/Types/API/Hostname";
|
||||
import URL from "Common/Types/API/URL";
|
||||
import { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
|
||||
import Dictionary from "Common/Types/Dictionary";
|
||||
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
|
||||
import IP from "Common/Types/IP/IP";
|
||||
import { JSONObject } from "Common/Types/JSON";
|
||||
import JSONFunctions from "Common/Types/JSONFunctions";
|
||||
@@ -11,53 +10,56 @@ import MonitorSecretService from "Common/Server/Services/MonitorSecretService";
|
||||
import VMUtil from "Common/Server/Utils/VM/VMAPI";
|
||||
import Monitor from "Common/Models/DatabaseModels/Monitor";
|
||||
import MonitorSecret from "Common/Models/DatabaseModels/MonitorSecret";
|
||||
import MonitorTest from "Common/Models/DatabaseModels/MonitorTest";
|
||||
import ObjectID from "Common/Types/ObjectID";
|
||||
import MonitorSteps from "Common/Types/Monitor/MonitorSteps";
|
||||
|
||||
export default class MonitorUtil {
|
||||
public static async populateSecrets(monitor: Monitor): Promise<Monitor> {
|
||||
public static async loadMonitorSecrets(
|
||||
monitorId: ObjectID,
|
||||
): Promise<MonitorSecret[]> {
|
||||
const secrets: Array<MonitorSecret> = await MonitorSecretService.findBy({
|
||||
query: {
|
||||
monitors: [monitorId] as any,
|
||||
},
|
||||
select: {
|
||||
secretValue: true,
|
||||
name: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
return secrets;
|
||||
}
|
||||
|
||||
public static async populateSecretsInMonitorSteps(data: {
|
||||
monitorSteps: MonitorSteps;
|
||||
monitorType: MonitorType;
|
||||
monitorId: ObjectID;
|
||||
}): Promise<MonitorSteps> {
|
||||
const isSecretsLoaded: boolean = false;
|
||||
let monitorSecrets: MonitorSecret[] = [];
|
||||
|
||||
const loadSecrets: PromiseVoidFunction = async (): Promise<void> => {
|
||||
if (isSecretsLoaded) {
|
||||
return;
|
||||
}
|
||||
const monitorSteps: MonitorSteps = data.monitorSteps;
|
||||
const monitorType: MonitorType = data.monitorType;
|
||||
const monitorId: ObjectID = data.monitorId;
|
||||
|
||||
if (!monitor.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const secrets: Array<MonitorSecret> = await MonitorSecretService.findBy({
|
||||
query: {
|
||||
monitors: [monitor.id] as any,
|
||||
},
|
||||
select: {
|
||||
secretValue: true,
|
||||
name: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
monitorSecrets = secrets;
|
||||
};
|
||||
|
||||
if (!monitor.monitorSteps) {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
if (monitor.monitorType === MonitorType.API) {
|
||||
for (const monitorStep of monitor.monitorSteps?.data
|
||||
?.monitorStepsInstanceArray || []) {
|
||||
if (monitorType === MonitorType.API) {
|
||||
for (const monitorStep of monitorSteps?.data?.monitorStepsInstanceArray ||
|
||||
[]) {
|
||||
if (
|
||||
monitorStep.data?.requestHeaders &&
|
||||
this.hasSecrets(
|
||||
JSONFunctions.toString(monitorStep.data.requestHeaders),
|
||||
)
|
||||
) {
|
||||
await loadSecrets();
|
||||
if (!isSecretsLoaded) {
|
||||
monitorSecrets = await MonitorUtil.loadMonitorSecrets(monitorId);
|
||||
}
|
||||
|
||||
monitorStep.data.requestHeaders =
|
||||
(await MonitorUtil.fillSecretsInStringOrJSON({
|
||||
@@ -68,7 +70,9 @@ export default class MonitorUtil {
|
||||
monitorStep.data?.requestBody &&
|
||||
this.hasSecrets(JSONFunctions.toString(monitorStep.data.requestBody))
|
||||
) {
|
||||
await loadSecrets();
|
||||
if (!isSecretsLoaded) {
|
||||
monitorSecrets = await MonitorUtil.loadMonitorSecrets(monitorId);
|
||||
}
|
||||
|
||||
monitorStep.data.requestBody =
|
||||
(await MonitorUtil.fillSecretsInStringOrJSON({
|
||||
@@ -80,15 +84,15 @@ export default class MonitorUtil {
|
||||
}
|
||||
|
||||
if (
|
||||
monitor.monitorType === MonitorType.API ||
|
||||
monitor.monitorType === MonitorType.IP ||
|
||||
monitor.monitorType === MonitorType.Ping ||
|
||||
monitor.monitorType === MonitorType.Port ||
|
||||
monitor.monitorType === MonitorType.Website ||
|
||||
monitor.monitorType === MonitorType.SSLCertificate
|
||||
monitorType === MonitorType.API ||
|
||||
monitorType === MonitorType.IP ||
|
||||
monitorType === MonitorType.Ping ||
|
||||
monitorType === MonitorType.Port ||
|
||||
monitorType === MonitorType.Website ||
|
||||
monitorType === MonitorType.SSLCertificate
|
||||
) {
|
||||
for (const monitorStep of monitor.monitorSteps?.data
|
||||
?.monitorStepsInstanceArray || []) {
|
||||
for (const monitorStep of monitorSteps?.data?.monitorStepsInstanceArray ||
|
||||
[]) {
|
||||
if (
|
||||
monitorStep.data?.monitorDestination &&
|
||||
this.hasSecrets(
|
||||
@@ -96,7 +100,9 @@ export default class MonitorUtil {
|
||||
)
|
||||
) {
|
||||
// replace secret in monitorDestination.
|
||||
await loadSecrets();
|
||||
if (!isSecretsLoaded) {
|
||||
monitorSecrets = await MonitorUtil.loadMonitorSecrets(monitorId);
|
||||
}
|
||||
|
||||
monitorStep.data.monitorDestination =
|
||||
(await MonitorUtil.fillSecretsInStringOrJSON({
|
||||
@@ -108,17 +114,19 @@ export default class MonitorUtil {
|
||||
}
|
||||
|
||||
if (
|
||||
monitor.monitorType === MonitorType.SyntheticMonitor ||
|
||||
monitor.monitorType === MonitorType.CustomJavaScriptCode
|
||||
monitorType === MonitorType.SyntheticMonitor ||
|
||||
monitorType === MonitorType.CustomJavaScriptCode
|
||||
) {
|
||||
for (const monitorStep of monitor.monitorSteps?.data
|
||||
?.monitorStepsInstanceArray || []) {
|
||||
for (const monitorStep of monitorSteps?.data?.monitorStepsInstanceArray ||
|
||||
[]) {
|
||||
if (
|
||||
monitorStep.data?.customCode &&
|
||||
this.hasSecrets(JSONFunctions.toString(monitorStep.data.customCode))
|
||||
) {
|
||||
// replace secret in script
|
||||
await loadSecrets();
|
||||
if (!isSecretsLoaded) {
|
||||
monitorSecrets = await MonitorUtil.loadMonitorSecrets(monitorId);
|
||||
}
|
||||
|
||||
monitorStep.data.customCode =
|
||||
(await MonitorUtil.fillSecretsInStringOrJSON({
|
||||
@@ -129,6 +137,62 @@ export default class MonitorUtil {
|
||||
}
|
||||
}
|
||||
|
||||
return monitorSteps;
|
||||
}
|
||||
|
||||
public static async populateSecretsOnMonitorTest(
|
||||
monitorTest: MonitorTest,
|
||||
): Promise<MonitorTest> {
|
||||
const monitorId: ObjectID | undefined = monitorTest.monitorId;
|
||||
|
||||
if (!monitorId) {
|
||||
return monitorTest;
|
||||
}
|
||||
|
||||
if (!monitorTest.monitorSteps) {
|
||||
return monitorTest;
|
||||
}
|
||||
|
||||
if (!monitorTest.monitorSteps.data) {
|
||||
return monitorTest;
|
||||
}
|
||||
|
||||
if (!monitorTest.monitorType) {
|
||||
return monitorTest;
|
||||
}
|
||||
|
||||
monitorTest.monitorSteps = await MonitorUtil.populateSecretsInMonitorSteps({
|
||||
monitorSteps: monitorTest.monitorSteps,
|
||||
monitorType: monitorTest.monitorType,
|
||||
monitorId: monitorId,
|
||||
});
|
||||
|
||||
return monitorTest;
|
||||
}
|
||||
|
||||
public static async populateSecrets(monitor: Monitor): Promise<Monitor> {
|
||||
if (!monitor.id) {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
if (!monitor.monitorSteps) {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
if (!monitor.monitorSteps.data) {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
if (!monitor.monitorType) {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
monitor.monitorSteps = await MonitorUtil.populateSecretsInMonitorSteps({
|
||||
monitorSteps: monitor.monitorSteps,
|
||||
monitorType: monitor.monitorType,
|
||||
monitorId: monitor.id,
|
||||
});
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user