import Incident from "./Incident"; import Project from "./Project"; import User from "./User"; import File from "./File"; import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel"; import Route from "../../Types/API/Route"; import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl"; import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl"; import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn"; import ColumnType from "../../Types/Database/ColumnType"; import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint"; import EnableDocumentation from "../../Types/Database/EnableDocumentation"; import EnableWorkflow from "../../Types/Database/EnableWorkflow"; 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 IconProp from "../../Types/Icon/IconProp"; import ObjectID from "../../Types/ObjectID"; import Permission from "../../Types/Permission"; import { Column, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, } from "typeorm"; @EnableDocumentation() @CanAccessIfCanReadOn("incident") @TenantColumn("projectId") @TableAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], delete: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.DeleteIncidentInternalNote, ], update: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.EditIncidentInternalNote, ], }) @EnableWorkflow({ create: true, delete: true, update: true, read: true, }) @CrudApiEndpoint(new Route("/incident-internal-note")) @Entity({ name: "IncidentInternalNote", }) @TableMetadata({ tableName: "IncidentInternalNote", singularName: "Incident Internal Note", pluralName: "Incident Internal Notes", icon: IconProp.Lock, tableDescription: "Manage internal notes for your incident", }) export default class IncidentInternalNote extends BaseModel { @ColumnAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], 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.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], update: [], }) @Index() @TableColumn({ type: TableColumnType.ObjectID, required: true, canReadOnRelationQuery: true, title: "Project ID", description: "ID of your OneUptime Project in which this object belongs", example: "5f8b9c0d-e1a2-4b3c-8d5e-6f7a8b9c0d1e", }) @Column({ type: ColumnType.ObjectID, nullable: false, transformer: ObjectID.getDatabaseTransformer(), }) public projectId?: ObjectID = undefined; @ColumnAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], update: [], }) @TableColumn({ manyToOneRelationColumn: "incidentId", type: TableColumnType.Entity, modelType: Incident, title: "Incident", description: "Relation to Incident in which this resource belongs", }) @ManyToOne( () => { return Incident; }, { eager: false, nullable: true, onDelete: "CASCADE", orphanedRowAction: "nullify", }, ) @JoinColumn({ name: "incidentId" }) public incident?: Incident = undefined; @ColumnAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], update: [], }) @Index() @TableColumn({ type: TableColumnType.ObjectID, required: true, title: "Incident ID", description: "Relation to Incident ID in which this resource belongs", example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", }) @Column({ type: ColumnType.ObjectID, nullable: false, transformer: ObjectID.getDatabaseTransformer(), }) public incidentId?: ObjectID = undefined; @ColumnAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], 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.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], 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)", example: "7c8d9e0f-a1b2-3c4d-9e5f-8a9b0c1d2e3f", }) @Column({ type: ColumnType.ObjectID, nullable: true, transformer: ObjectID.getDatabaseTransformer(), }) public createdByUserId?: ObjectID = undefined; @ColumnAccessControl({ create: [], read: [], update: [], }) @TableColumn({ manyToOneRelationColumn: "deletedByUserId", type: TableColumnType.Entity, title: "Deleted by User", modelType: 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: [], 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)", example: "9d0e1f2a-b3c4-5d6e-af7b-8c9d0e1f2a3b", }) @Column({ type: ColumnType.ObjectID, nullable: true, transformer: ObjectID.getDatabaseTransformer(), }) public deletedByUserId?: ObjectID = undefined; @ColumnAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], update: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.EditIncidentInternalNote, ], }) @TableColumn({ type: TableColumnType.Markdown, title: "Note", description: "Notes in markdown", example: "## Root Cause Analysis\n\nInvestigated the database connection timeout. Found that the connection pool was exhausted due to a memory leak in the authentication service.\n\n**Action Items:**\n- Applied hotfix to authentication service\n- Increased connection pool size from 10 to 20\n- Added monitoring alerts for connection pool usage", }) @Column({ type: ColumnType.Markdown, nullable: false, unique: false, }) public note?: string = undefined; @ColumnAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], update: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.EditIncidentInternalNote, ], }) @TableColumn({ type: TableColumnType.EntityArray, modelType: File, title: "Attachments", description: "Files attached to this note", required: false, }) @ManyToMany( () => { return File; }, { eager: false, }, ) @JoinTable({ name: "IncidentInternalNoteFile", joinColumn: { name: "incidentInternalNoteId", referencedColumnName: "_id", }, inverseJoinColumn: { name: "fileId", referencedColumnName: "_id", }, }) public attachments?: Array = undefined; @ColumnAccessControl({ create: [], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], update: [], }) @Index() @TableColumn({ type: TableColumnType.Boolean, computed: true, hideColumnInDocumentation: true, required: true, isDefaultValueColumn: true, title: "Are Owners Notified", description: "Are owners notified of this resource ownership?", defaultValue: false, }) @Column({ type: ColumnType.Boolean, nullable: false, default: false, }) public isOwnerNotified?: boolean = undefined; @ColumnAccessControl({ create: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.CreateIncidentInternalNote, ], read: [ Permission.ProjectOwner, Permission.ProjectAdmin, Permission.ProjectMember, Permission.ReadIncidentInternalNote, Permission.ReadAllProjectResources, ], update: [], }) @Index() @TableColumn({ type: TableColumnType.LongText, title: "Posted from Slack Message ID", description: "Unique identifier for the Slack message this note was created from (channel_id:message_ts). Used to prevent duplicate notes when multiple users react to the same message.", required: false, example: "C1234567890:1234567890.123456", }) @Column({ type: ColumnType.LongText, nullable: true, }) public postedFromSlackMessageId?: string = undefined; }