From c217eea47864a804b292f8cdf2108d6e5245a284 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 2 Oct 2024 20:42:09 +0100 Subject: [PATCH] add alert custom fields. --- Common/Models/DatabaseModels/Alert.ts | 15 +- .../Models/DatabaseModels/AlertCustomField.ts | 340 ++++++++++++++++++ Common/Models/DatabaseModels/Incident.ts | 2 - Common/Models/DatabaseModels/Index.ts | 25 +- Common/Types/Permission.ts | 83 +++-- Common/Types/Telemetry/TelemetryQuery.ts | 6 +- 6 files changed, 405 insertions(+), 66 deletions(-) create mode 100644 Common/Models/DatabaseModels/AlertCustomField.ts diff --git a/Common/Models/DatabaseModels/Alert.ts b/Common/Models/DatabaseModels/Alert.ts index 6df5b4b913..8ecd0cc936 100644 --- a/Common/Models/DatabaseModels/Alert.ts +++ b/Common/Models/DatabaseModels/Alert.ts @@ -37,7 +37,6 @@ import { } from "typeorm"; import { TelemetryQuery } from "../../Types/Telemetry/TelemetryQuery"; - @EnableDocumentation() @AccessControlColumn("labels") @MultiTenentQueryAllowed(true) @@ -225,7 +224,6 @@ export default class Alert extends BaseModel { }) public description?: string = undefined; - @ColumnAccessControl({ create: [ Permission.ProjectOwner, @@ -336,9 +334,7 @@ export default class Alert extends BaseModel { }) public deletedByUserId?: ObjectID = undefined; - - // monitor this alert was created for. - + // monitor this alert was created for. @ColumnAccessControl({ create: [ @@ -603,8 +599,7 @@ export default class Alert extends BaseModel { type: TableColumnType.Entity, modelType: AlertState, title: "Monitor status when this alert was created", - description: - "Monitor status when this alert was created", + description: "Monitor status when this alert was created", }) @ManyToOne( () => { @@ -644,8 +639,7 @@ export default class Alert extends BaseModel { type: TableColumnType.ObjectID, required: false, title: "Monitor Status ID when this alert was created", - description: - "Monitor Status ID when this alert was created", + description: "Monitor Status ID when this alert was created", }) @Column({ type: ColumnType.ObjectID, @@ -898,8 +892,7 @@ export default class Alert extends BaseModel { required: false, type: TableColumnType.Markdown, title: "Remediation Notes", - description: - "Notes on how to remediate this alert. This is in markdown.", + description: "Notes on how to remediate this alert. This is in markdown.", }) @Column({ nullable: true, diff --git a/Common/Models/DatabaseModels/AlertCustomField.ts b/Common/Models/DatabaseModels/AlertCustomField.ts new file mode 100644 index 0000000000..6f9fe56741 --- /dev/null +++ b/Common/Models/DatabaseModels/AlertCustomField.ts @@ -0,0 +1,340 @@ +import Project from "./Project"; +import User from "./User"; +import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel"; +import Route from "../../Types/API/Route"; +import { PlanType } from "../../Types/Billing/SubscriptionPlan"; +import CustomFieldType from "../../Types/CustomField/CustomFieldType"; +import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl"; +import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl"; +import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl"; +import ColumnLength from "../../Types/Database/ColumnLength"; +import ColumnType from "../../Types/Database/ColumnType"; +import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint"; +import EnableDocumentation from "../../Types/Database/EnableDocumentation"; +import TableColumn from "../../Types/Database/TableColumn"; +import TableColumnType from "../../Types/Database/TableColumnType"; +import TableMetadata from "../../Types/Database/TableMetadata"; +import TenantColumn from "../../Types/Database/TenantColumn"; +import UniqueColumnBy from "../../Types/Database/UniqueColumnBy"; +import IconProp from "../../Types/Icon/IconProp"; +import ObjectID from "../../Types/ObjectID"; +import Permission from "../../Types/Permission"; +import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm"; + +@EnableDocumentation() +@TableBillingAccessControl({ + create: PlanType.Growth, + read: PlanType.Growth, + update: PlanType.Growth, + delete: PlanType.Growth, +}) +@TenantColumn("projectId") +@TableAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + delete: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.DeleteAlertCustomField, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditAlertCustomField, + ], +}) +@CrudApiEndpoint(new Route("/alert-custom-field")) +@TableMetadata({ + tableName: "AlertCustomField", + singularName: "Alert Custom Field", + pluralName: "Alert Custom Fields", + icon: IconProp.TableCells, + tableDescription: "Manage custom fields for your alert.", +}) +@Entity({ + name: "AlertCustomField", +}) +export default class AlertCustomField extends BaseModel { + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "projectId", + type: TableColumnType.Entity, + modelType: Project, + title: "Project", + description: "Relation to Project Resource in which this object belongs", + }) + @ManyToOne( + () => { + return Project; + }, + { + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "projectId" }) + public project?: Project = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [], + }) + @Index() + @TableColumn({ + type: TableColumnType.ObjectID, + required: true, + canReadOnRelationQuery: true, + title: "Project ID", + description: "ID of your OneUptime Project in which this object belongs", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: false, + transformer: ObjectID.getDatabaseTransformer(), + }) + public projectId?: ObjectID = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditAlertCustomField, + ], + }) + @TableColumn({ + required: true, + type: TableColumnType.ShortText, + canReadOnRelationQuery: true, + title: "Name", + description: "Any friendly name of this object", + }) + @Column({ + nullable: false, + type: ColumnType.ShortText, + length: ColumnLength.ShortText, + }) + @UniqueColumnBy("projectId") + public name?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.EditAlertCustomField, + ], + }) + @TableColumn({ + required: false, + type: TableColumnType.LongText, + title: "Description", + description: + "Friendly description of this custom field that will help you remember", + }) + @Column({ + nullable: true, + type: ColumnType.LongText, + length: ColumnLength.LongText, + }) + public description?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [], + }) + @TableColumn({ + required: false, + type: TableColumnType.CustomFieldType, + title: "Custom Field Type", + description: "Is this field Text, Number or Boolean?", + }) + @Column({ + nullable: true, + type: ColumnType.ShortText, + length: ColumnLength.ShortText, + }) + public type?: CustomFieldType = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "createdByUserId", + type: TableColumnType.Entity, + modelType: User, + title: "Created by User", + description: + "Relation to User who created this object (if this object was created by a User)", + }) + @ManyToOne( + () => { + return User; + }, + { + eager: false, + nullable: true, + onDelete: "SET NULL", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "createdByUserId" }) + public createdByUser?: User = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.CreateAlertCustomField, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Created by User ID", + description: + "User ID who created this object (if this object was created by a User)", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public createdByUserId?: ObjectID = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "deletedByUserId", + type: TableColumnType.Entity, + title: "Deleted by User", + description: + "Relation to User who deleted this object (if this object was deleted by a User)", + }) + @ManyToOne( + () => { + return User; + }, + { + cascade: false, + eager: false, + nullable: true, + onDelete: "SET NULL", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "deletedByUserId" }) + public deletedByUser?: User = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadAlertCustomField, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Deleted by User ID", + description: + "User ID who deleted this object (if this object was deleted by a User)", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public deletedByUserId?: ObjectID = undefined; +} diff --git a/Common/Models/DatabaseModels/Incident.ts b/Common/Models/DatabaseModels/Incident.ts index bdfd64f0a4..b49f5db110 100644 --- a/Common/Models/DatabaseModels/Incident.ts +++ b/Common/Models/DatabaseModels/Incident.ts @@ -38,8 +38,6 @@ import { } from "typeorm"; import { TelemetryQuery } from "../../Types/Telemetry/TelemetryQuery"; - - @EnableDocumentation() @AccessControlColumn("labels") @MultiTenentQueryAllowed(true) diff --git a/Common/Models/DatabaseModels/Index.ts b/Common/Models/DatabaseModels/Index.ts index 61cce3cb80..845d65a660 100644 --- a/Common/Models/DatabaseModels/Index.ts +++ b/Common/Models/DatabaseModels/Index.ts @@ -176,9 +176,19 @@ const AllModelTypes: Array<{ Incident, IncidentCustomField, IncidentStateTimeline, - MonitorStatusTimeline, - IncidentPublicNote, IncidentInternalNote, + IncidentPublicNote, + IncidentTemplate, + IncidentTemplateOwnerTeam, + IncidentTemplateOwnerUser, + IncidentOwnerTeam, + IncidentOwnerUser, + IncidentSeverity, + IncidentNoteTemplate, + + MonitorStatusTimeline, + + File, Domain, @@ -186,7 +196,7 @@ const AllModelTypes: Array<{ StatusPageDomain, StatusPageCustomField, StatusPageResource, - IncidentSeverity, + StatusPageAnnouncement, StatusPageSubscriber, StatusPageFooterLink, @@ -219,8 +229,7 @@ const AllModelTypes: Array<{ MonitorOwnerTeam, MonitorOwnerUser, - IncidentOwnerTeam, - IncidentOwnerUser, + ScheduledMaintenanceOwnerTeam, ScheduledMaintenanceOwnerUser, @@ -245,12 +254,6 @@ const AllModelTypes: Array<{ ShortLink, - IncidentTemplate, - IncidentTemplateOwnerTeam, - IncidentTemplateOwnerUser, - - IncidentNoteTemplate, - ScheduledMaintenanceTemplate, ScheduledMaintenanceTemplateOwnerTeam, ScheduledMaintenanceTemplateOwnerUser, diff --git a/Common/Types/Permission.ts b/Common/Types/Permission.ts index 56a89d277e..d966c49308 100644 --- a/Common/Types/Permission.ts +++ b/Common/Types/Permission.ts @@ -144,7 +144,6 @@ enum Permission { EditAlertOwnerTeam = "EditAlertOwnerTeam", ReadAlertOwnerTeam = "ReadAlertOwnerTeam", - CreateAlertOwnerUser = "CreateAlertOwnerUser", DeleteAlertOwnerUser = "DeleteAlertOwnerUser", EditAlertOwnerUser = "EditAlertOwnerUser", @@ -165,7 +164,6 @@ enum Permission { EditIncidentNoteTemplate = "EditIncidentNoteTemplate", ReadIncidentNoteTemplate = "ReadIncidentNoteTemplate", - CreateAlertNoteTemplate = "CreateAlertNoteTemplate", DeleteAlertNoteTemplate = "DeleteAlertNoteTemplate", EditAlertNoteTemplate = "EditAlertNoteTemplate", @@ -256,12 +254,16 @@ enum Permission { EditIncidentCustomField = "EditIncidentCustomField", ReadIncidentCustomField = "ReadIncidentCustomField", + CreateAlertCustomField = "CreateAlertCustomField", + DeleteAlertCustomField = "DeleteAlertCustomField", + EditAlertCustomField = "EditAlertCustomField", + ReadAlertCustomField = "ReadAlertCustomField", + CreateProjectIncident = "CreateProjectIncident", DeleteProjectIncident = "DeleteProjectIncident", EditProjectIncident = "EditProjectIncident", ReadProjectIncident = "ReadProjectIncident", - CreateAlert = "CreateAlert", DeleteAlert = "DeleteAlert", EditAlert = "EditAlert", @@ -394,7 +396,6 @@ enum Permission { ReadIncidentState = "ReadIncidentState", DeleteIncidentState = "DeleteIncidentState", - CreateAlertState = "CreateAlertState", EditAlertState = "EditAlertState", ReadAlertState = "ReadAlertState", @@ -436,7 +437,6 @@ enum Permission { DeleteIncidentInternalNote = "DeleteIncidentInternalNote", ReadIncidentInternalNote = "ReadIncidentInternalNote", - CreateAlertInternalNote = "CreateAlertInternalNote", EditAlertInternalNote = "EditAlertInternalNote", DeleteAlertInternalNote = "DeleteAlertInternalNote", @@ -529,7 +529,6 @@ enum Permission { DeleteIncidentSeverity = "DeleteIncidentSeverity", ReadIncidentSeverity = "ReadIncidentSeverity", - CreateAlertSeverity = "CreateAlertSeverity", EditAlertSeverity = "EditAlertSeverity", DeleteAlertSeverity = "DeleteAlertSeverity", @@ -922,8 +921,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - - { permission: Permission.CreateAlertState, title: "Create Alert State", @@ -934,24 +931,21 @@ export class PermissionHelper { { permission: Permission.DeleteAlertState, title: "Delete Alert State", - description: - "This permission can delete alert states of this project.", + description: "This permission can delete alert states of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, { permission: Permission.EditAlertState, title: "Edit Alert State", - description: - "This permission can edit alert states of this project.", + description: "This permission can edit alert states of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, { permission: Permission.ReadAlertState, title: "Read Alert State", - description: - "This permission can read alert states of this project.", + description: "This permission can read alert states of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, @@ -989,8 +983,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - - { permission: Permission.CreateAlertStateTimeline, title: "Create Alert State Timeline", @@ -1713,12 +1705,10 @@ export class PermissionHelper { isAccessControlPermission: false, }, - { permission: Permission.CreateAlertSeverity, title: "Create Alert Severity", - description: - "This permission can create Alert Severity this project.", + description: "This permission can create Alert Severity this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, @@ -1733,21 +1723,18 @@ export class PermissionHelper { { permission: Permission.EditAlertSeverity, title: "Edit Alert Severity", - description: - "This permission can edit Alert Severity of this project.", + description: "This permission can edit Alert Severity of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, { permission: Permission.ReadAlertSeverity, title: "Read Alert Severity", - description: - "This permission can read Alert Severity of this project.", + description: "This permission can read Alert Severity of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, - { permission: Permission.CreateProjectTeam, title: "Create Team", @@ -1854,8 +1841,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - - { permission: Permission.CreateAlertInternalNote, title: "Create Alert Internal Note", @@ -1889,8 +1874,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - - { permission: Permission.CreateIncidentPublicNote, title: "Create Incident Status Page Note", @@ -2512,6 +2495,39 @@ export class PermissionHelper { isAccessControlPermission: false, }, + { + permission: Permission.CreateAlertCustomField, + title: "Create Alert Custom Field", + description: + "This permission can create Alert Custom Field this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.DeleteAlertCustomField, + title: "Delete Alert Custom Field", + description: + "This permission can delete Alert Custom Field of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.EditAlertCustomField, + title: "Edit Alert Custom Field", + description: + "This permission can edit Alert Custom Field of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.ReadAlertCustomField, + title: "Read Alert Custom Field", + description: + "This permission can read Alert Custom Field of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { permission: Permission.CreateStatusPageCustomField, title: "Create Status Page Custom Field", @@ -3206,7 +3222,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - { permission: Permission.CreateAlertOwnerTeam, title: "Create Alert Team Owner", @@ -3240,7 +3255,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - { permission: Permission.CreateIncidentNoteTemplate, title: "Create Incident Note Template", @@ -3274,8 +3288,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - - { permission: Permission.CreateAlertNoteTemplate, title: "Create Alert Note Template", @@ -3309,7 +3321,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - { permission: Permission.CreateScheduledMaintenanceNoteTemplate, title: "Create Scheduled Maintenance Note Template", @@ -3409,8 +3420,6 @@ export class PermissionHelper { isAccessControlPermission: false, }, - - { permission: Permission.CreateAlertOwnerUser, title: "Create Alert User Owner", @@ -3836,8 +3845,6 @@ export class PermissionHelper { isAccessControlPermission: true, }, - - { permission: Permission.CreateAlert, title: "Create Alert", @@ -3867,8 +3874,6 @@ export class PermissionHelper { isAccessControlPermission: true, }, - - { permission: Permission.CreateScheduledMaintenanceTemplate, title: "Create Scheduled Maintenance Template", diff --git a/Common/Types/Telemetry/TelemetryQuery.ts b/Common/Types/Telemetry/TelemetryQuery.ts index e9417504c6..0aa5b3c4dd 100644 --- a/Common/Types/Telemetry/TelemetryQuery.ts +++ b/Common/Types/Telemetry/TelemetryQuery.ts @@ -5,6 +5,6 @@ import Query from "../BaseDatabase/Query"; import TelemetryType from "./TelemetryType"; export interface TelemetryQuery { - telemetryType: TelemetryType; - telemetryQuery: Query | Query | Query; - } \ No newline at end of file + telemetryType: TelemetryType; + telemetryQuery: Query | Query | Query; +}