diff --git a/Common/Types/AnalyticsDatabase/TableColumn.ts b/Common/Types/AnalyticsDatabase/TableColumn.ts index 9bf30bd073..7c7e81369f 100644 --- a/Common/Types/AnalyticsDatabase/TableColumn.ts +++ b/Common/Types/AnalyticsDatabase/TableColumn.ts @@ -1,9 +1,11 @@ import { ColumnAccessControl } from '../BaseDatabase/AccessControl'; import ColumnBillingAccessControl from '../BaseDatabase/ColumnBillingAccessControl'; import TableColumnType from '../BaseDatabase/TableColumnType'; +import { JSONValue } from '../JSON'; export default class AnalyticsTableColumn { private _key: string = 'id'; + public get key(): string { return this._key; } @@ -65,13 +67,21 @@ export default class AnalyticsTableColumn { this._forceGetDefaultValueOnCreate = v; } - private _isDefaultValueColumn: boolean = false; + + private _defaultValue : JSONValue | undefined; + public get defaultValue() : JSONValue { + return this._defaultValue; + } + public set defaultValue(v : JSONValue) { + this._defaultValue = v; + } + + + public get isDefaultValueColumn(): boolean { - return this._isDefaultValueColumn; - } - public set isDefaultValueColumn(v: boolean) { - this._isDefaultValueColumn = v; + return Boolean(this.defaultValue !== undefined); } + private _billingAccessControl?: ColumnBillingAccessControl | undefined; public get billingAccessControl(): ColumnBillingAccessControl | undefined { @@ -102,9 +112,9 @@ export default class AnalyticsTableColumn { title: string; description: string; required: boolean; + defaultValue?: JSONValue | undefined; type: TableColumnType; billingAccessControl?: ColumnBillingAccessControl | undefined; - isDefaultValueColumn?: boolean | undefined; isTenantId?: boolean | undefined; accessControl?: ColumnAccessControl | undefined; allowAccessIfSubscriptionIsUnpaid?: boolean | undefined; @@ -120,7 +130,7 @@ export default class AnalyticsTableColumn { this.type = data.type; this.isTenantId = data.isTenantId || false; this.forceGetDefaultValueOnCreate = data.forceGetDefaultValueOnCreate; - this.isDefaultValueColumn = data.isDefaultValueColumn || false; + this.defaultValue = data.defaultValue; this.billingAccessControl = data.billingAccessControl; this.allowAccessIfSubscriptionIsUnpaid = data.allowAccessIfSubscriptionIsUnpaid || false; diff --git a/Common/Types/Database/SortOrder.ts b/Common/Types/BaseDatabase/SortOrder.ts similarity index 100% rename from Common/Types/Database/SortOrder.ts rename to Common/Types/BaseDatabase/SortOrder.ts diff --git a/CommonServer/API/StatusPageAPI.ts b/CommonServer/API/StatusPageAPI.ts index cecc1bd503..55e1de5c9e 100644 --- a/CommonServer/API/StatusPageAPI.ts +++ b/CommonServer/API/StatusPageAPI.ts @@ -30,7 +30,7 @@ import MonitorStatusService from '../Services/MonitorStatusService'; import OneUptimeDate from 'Common/Types/Date'; import MonitorStatusTimelineService from '../Services/MonitorStatusTimelineService'; import QueryHelper from '../Types/Database/QueryHelper'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import IncidentService from '../Services/IncidentService'; import IncidentPublicNote from 'Model/Models/IncidentPublicNote'; import IncidentPublicNoteService from '../Services/IncidentPublicNoteService'; diff --git a/CommonServer/Services/AnalyticsDatabaseService.ts b/CommonServer/Services/AnalyticsDatabaseService.ts index c022a717f9..6092ffb658 100644 --- a/CommonServer/Services/AnalyticsDatabaseService.ts +++ b/CommonServer/Services/AnalyticsDatabaseService.ts @@ -12,6 +12,9 @@ import CreateBy from '../Types/AnalyticsDatabase/CreateBy'; import { DatabaseTriggerType, OnCreate, + OnDelete, + OnFind, + OnUpdate, } from '../Types/AnalyticsDatabase/Hooks'; import Typeof from 'Common/Types/Typeof'; import ModelPermission from '../Types/AnalyticsDatabase/ModelPermission'; @@ -25,6 +28,10 @@ import Route from 'Common/Types/API/Route'; import { WorkflowRoute } from 'Common/ServiceRoute'; import Text from 'Common/Types/Text'; import ClusterKeyAuthorization from '../Middleware/ClusterKeyAuthorization'; +import DeleteBy from '../Types/AnalyticsDatabase/DeleteBy'; +import UpdateBy from '../Types/AnalyticsDatabase/UpdateBy'; +import FindBy from '../Types/AnalyticsDatabase/FindBy'; +import PositiveNumber from 'Common/Types/PositiveNumber'; export default class AnalyticsDatabaseService< TBaseModel extends AnalyticsBaseModel @@ -48,6 +55,118 @@ export default class AnalyticsDatabaseService< } } + + public async findBy( + findBy: FindBy + ): Promise> { + return await this._findBy(findBy); + } + + private async _findBy( + findBy: FindBy, + withDeleted?: boolean | undefined + ): Promise> { + try { + let automaticallyAddedCreatedAtInSelect: boolean = false; + + if (!findBy.sort || Object.keys(findBy.sort).length === 0) { + findBy.sort = { + createdAt: SortOrder.Descending, + }; + + if (!findBy.select) { + findBy.select = {} as any; + } + + if (!(findBy.select as any)['createdAt']) { + (findBy.select as any)['createdAt'] = true; + automaticallyAddedCreatedAtInSelect = true; + } + } + + const onFind: OnFind = findBy.props.ignoreHooks + ? { findBy, carryForward: [] } + : await this.onBeforeFind(findBy); + const onBeforeFind: FindBy = { ...onFind.findBy }; + const carryForward: any = onFind.carryForward; + + if ( + !onBeforeFind.select || + Object.keys(onBeforeFind.select).length === 0 + ) { + onBeforeFind.select = {} as any; + } + + if (!(onBeforeFind.select as any)['_id']) { + (onBeforeFind.select as any)['_id'] = true; + } + + const result: { + query: Query; + select: Select | null; + relationSelect: RelationSelect | null; + } = await ModelPermission.checkReadPermission( + this.modelType, + onBeforeFind.query, + onBeforeFind.select || null, + onBeforeFind.props + ); + + onBeforeFind.query = result.query; + onBeforeFind.select = result.select || undefined; + + if (!(onBeforeFind.skip instanceof PositiveNumber)) { + onBeforeFind.skip = new PositiveNumber(onBeforeFind.skip); + } + + if (!(onBeforeFind.limit instanceof PositiveNumber)) { + onBeforeFind.limit = new PositiveNumber(onBeforeFind.limit); + } + + const items: Array = await this.getRepository().find({ + skip: onBeforeFind.skip.toNumber(), + take: onBeforeFind.limit.toNumber(), + where: onBeforeFind.query as any, + order: onBeforeFind.sort as any, + relations: result.relationSelect as any, + select: onBeforeFind.select as any, + withDeleted: withDeleted || false, + }); + + let decryptedItems: Array = []; + + for (const item of items) { + decryptedItems.push(this.decrypt(item)); + } + + decryptedItems = this.sanitizeFindByItems( + decryptedItems, + onBeforeFind + ); + + for (const item of decryptedItems) { + if (automaticallyAddedCreatedAtInSelect) { + delete (item as any).createdAt; + } + } + + if (!findBy.props.ignoreHooks) { + decryptedItems = await ( + await this.onFindSuccess( + { findBy, carryForward }, + decryptedItems + ) + ).carryForward; + } + + return decryptedItems; + } catch (error) { + await this.onFindError(error as Exception); + throw this.getException(error as Exception); + } + } + + public toTableCreateStatement(): string { if (!this.database) { this.useDefaultDatabase(); @@ -75,6 +194,28 @@ export default class AnalyticsDatabaseService< return statement; } + + protected async onBeforeDelete( + deleteBy: DeleteBy + ): Promise> { + // A place holder method used for overriding. + return Promise.resolve({ deleteBy, carryForward: null }); + } + + protected async onBeforeUpdate( + updateBy: UpdateBy + ): Promise> { + // A place holder method used for overriding. + return Promise.resolve({ updateBy, carryForward: null }); + } + + protected async onBeforeFind( + findBy: FindBy + ): Promise> { + // A place holder method used for overriding. + return Promise.resolve({ findBy, carryForward: null }); + } + public toCreateStatement(data: { item: TBaseModel }): string { if (!data.item) { throw new BadDataException('Item cannot be null'); @@ -137,6 +278,57 @@ export default class AnalyticsDatabaseService< }); } + protected async onUpdateSuccess( + onUpdate: OnUpdate, + _updatedItemIds: Array + ): Promise> { + // A place holder method used for overriding. + return Promise.resolve(onUpdate); + } + + protected async onUpdateError(error: Exception): Promise { + // A place holder method used for overriding. + return Promise.resolve(error); + } + + protected async onDeleteSuccess( + onDelete: OnDelete, + _itemIdsBeforeDelete: Array + ): Promise> { + // A place holder method used for overriding. + return Promise.resolve(onDelete); + } + + protected async onDeleteError(error: Exception): Promise { + // A place holder method used for overriding. + return Promise.resolve(error); + } + + protected async onFindSuccess( + onFind: OnFind, + items: Array + ): Promise> { + // A place holder method used for overriding. + return Promise.resolve({ ...onFind, carryForward: items }); + } + + protected async onFindError(error: Exception): Promise { + // A place holder method used for overriding. + return Promise.resolve(error); + } + + protected async onCountSuccess( + count: PositiveNumber + ): Promise { + // A place holder method used for overriding. + return Promise.resolve(count); + } + + protected async onCountError(error: Exception): Promise { + // A place holder method used for overriding. + return Promise.resolve(error); + } + protected async onCreateSuccess( _onCreate: OnCreate, createdItem: TBaseModel diff --git a/CommonServer/Services/DatabaseService.ts b/CommonServer/Services/DatabaseService.ts index 62bfeb6590..841e275b28 100644 --- a/CommonServer/Services/DatabaseService.ts +++ b/CommonServer/Services/DatabaseService.ts @@ -22,7 +22,7 @@ import PostgresDatabase, { } from '../Infrastructure/PostgresDatabase'; import { DataSource, Repository, SelectQueryBuilder } from 'typeorm'; import ObjectID from 'Common/Types/ObjectID'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import { EncryptionSecret, WorkflowHostname } from '../EnvironmentConfig'; import { WorkflowRoute } from 'Common/ServiceRoute'; import HashedString from 'Common/Types/HashedString'; diff --git a/CommonServer/Services/IncidentService.ts b/CommonServer/Services/IncidentService.ts index 8b289c1edf..53465a5fcb 100644 --- a/CommonServer/Services/IncidentService.ts +++ b/CommonServer/Services/IncidentService.ts @@ -25,7 +25,7 @@ import UserService from './UserService'; import { JSONObject } from 'Common/Types/JSON'; import OnCallDutyPolicyService from './OnCallDutyPolicyService'; import UserNotificationEventType from 'Common/Types/UserNotification/UserNotificationEventType'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import DatabaseConfig from '../DatabaseConfig'; import MonitorStatus from 'Model/Models/MonitorStatus'; import MonitorStatusService from './MonitorStatusService'; diff --git a/CommonServer/Services/IncidentSeverityService.ts b/CommonServer/Services/IncidentSeverityService.ts index 729148e435..5fe3cbbdad 100644 --- a/CommonServer/Services/IncidentSeverityService.ts +++ b/CommonServer/Services/IncidentSeverityService.ts @@ -7,7 +7,7 @@ import LIMIT_MAX from 'Common/Types/Database/LimitMax'; import ObjectID from 'Common/Types/ObjectID'; import BadDataException from 'Common/Types/Exception/BadDataException'; import QueryHelper from '../Types/Database/QueryHelper'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import UpdateBy from '../Types/Database/UpdateBy'; import DeleteBy from '../Types/Database/DeleteBy'; diff --git a/CommonServer/Services/IncidentStateService.ts b/CommonServer/Services/IncidentStateService.ts index 9339da925b..aa644065c0 100644 --- a/CommonServer/Services/IncidentStateService.ts +++ b/CommonServer/Services/IncidentStateService.ts @@ -7,7 +7,7 @@ import LIMIT_MAX from 'Common/Types/Database/LimitMax'; import ObjectID from 'Common/Types/ObjectID'; import BadDataException from 'Common/Types/Exception/BadDataException'; import QueryHelper from '../Types/Database/QueryHelper'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import UpdateBy from '../Types/Database/UpdateBy'; import DeleteBy from '../Types/Database/DeleteBy'; diff --git a/CommonServer/Services/IncidentStateTimelineService.ts b/CommonServer/Services/IncidentStateTimelineService.ts index 65d366741d..a347c88b9f 100644 --- a/CommonServer/Services/IncidentStateTimelineService.ts +++ b/CommonServer/Services/IncidentStateTimelineService.ts @@ -8,7 +8,7 @@ import IncidentService from './IncidentService'; import DeleteBy from '../Types/Database/DeleteBy'; import ObjectID from 'Common/Types/ObjectID'; import PositiveNumber from 'Common/Types/PositiveNumber'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import IncidentState from 'Model/Models/IncidentState'; import IncidentStateService from './IncidentStateService'; import MonitorStatusTimeline from 'Model/Models/MonitorStatusTimeline'; diff --git a/CommonServer/Services/LogService.ts b/CommonServer/Services/LogService.ts index e1741c0fd5..28bd25515b 100644 --- a/CommonServer/Services/LogService.ts +++ b/CommonServer/Services/LogService.ts @@ -2,9 +2,9 @@ import Log from 'Model/AnalyticsModels/Log'; import AnalyticsDatabaseService from './AnalyticsDatabaseService'; import ClickhouseDatabase from '../Infrastructure/ClickhouseDatabase'; -export class Service extends AnalyticsDatabaseService { +export class LogService extends AnalyticsDatabaseService { public constructor(clickhouseDatabase?: ClickhouseDatabase | undefined) { super({ modelType: Log, database: clickhouseDatabase }); } } -export default new Service(); +export default new LogService(); diff --git a/CommonServer/Services/MonitorService.ts b/CommonServer/Services/MonitorService.ts index db1ec4a114..2810d374e0 100644 --- a/CommonServer/Services/MonitorService.ts +++ b/CommonServer/Services/MonitorService.ts @@ -27,7 +27,7 @@ import TeamMemberService from './TeamMemberService'; import User from 'Model/Models/User'; import URL from 'Common/Types/API/URL'; import { JSONObject } from 'Common/Types/JSON'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import DatabaseConfig from '../DatabaseConfig'; export class Service extends DatabaseService { diff --git a/CommonServer/Services/MonitorStatusService.ts b/CommonServer/Services/MonitorStatusService.ts index 58851daaff..1cb14d0447 100644 --- a/CommonServer/Services/MonitorStatusService.ts +++ b/CommonServer/Services/MonitorStatusService.ts @@ -9,7 +9,7 @@ import ObjectID from 'Common/Types/ObjectID'; import UpdateBy from '../Types/Database/UpdateBy'; import QueryHelper from '../Types/Database/QueryHelper'; import LIMIT_MAX from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; export class Service extends DatabaseService { public constructor(postgresDatabase?: PostgresDatabase) { diff --git a/CommonServer/Services/MonitorStatusTimelineService.ts b/CommonServer/Services/MonitorStatusTimelineService.ts index 72aa5acf10..54396bf5c2 100644 --- a/CommonServer/Services/MonitorStatusTimelineService.ts +++ b/CommonServer/Services/MonitorStatusTimelineService.ts @@ -7,7 +7,7 @@ import BadDataException from 'Common/Types/Exception/BadDataException'; import DeleteBy from '../Types/Database/DeleteBy'; import MonitorStatusTimeline from 'Model/Models/MonitorStatusTimeline'; import ObjectID from 'Common/Types/ObjectID'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import PositiveNumber from 'Common/Types/PositiveNumber'; import CreateBy from '../Types/Database/CreateBy'; import UserService from './UserService'; diff --git a/CommonServer/Services/OnCallDutyPolicyEscalationRuleService.ts b/CommonServer/Services/OnCallDutyPolicyEscalationRuleService.ts index 23a896e8ef..be9056841c 100644 --- a/CommonServer/Services/OnCallDutyPolicyEscalationRuleService.ts +++ b/CommonServer/Services/OnCallDutyPolicyEscalationRuleService.ts @@ -8,7 +8,7 @@ import QueryHelper from '../Types/Database/QueryHelper'; import DeleteBy from '../Types/Database/DeleteBy'; import ObjectID from 'Common/Types/ObjectID'; import LIMIT_MAX, { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import UpdateBy from '../Types/Database/UpdateBy'; import Query from '../Types/Database/Query'; import PositiveNumber from 'Common/Types/PositiveNumber'; diff --git a/CommonServer/Services/ScheduledMaintenanceService.ts b/CommonServer/Services/ScheduledMaintenanceService.ts index b647947a3d..c0146e7f50 100644 --- a/CommonServer/Services/ScheduledMaintenanceService.ts +++ b/CommonServer/Services/ScheduledMaintenanceService.ts @@ -21,7 +21,7 @@ import ScheduledMaintenanceOwnerTeam from 'Model/Models/ScheduledMaintenanceOwne import TeamMemberService from './TeamMemberService'; import User from 'Model/Models/User'; import URL from 'Common/Types/API/URL'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import DatabaseConfig from '../DatabaseConfig'; export class Service extends DatabaseService { diff --git a/CommonServer/Services/ScheduledMaintenanceStateService.ts b/CommonServer/Services/ScheduledMaintenanceStateService.ts index dc6d6d8394..ec1e0d5c70 100644 --- a/CommonServer/Services/ScheduledMaintenanceStateService.ts +++ b/CommonServer/Services/ScheduledMaintenanceStateService.ts @@ -7,7 +7,7 @@ import LIMIT_MAX from 'Common/Types/Database/LimitMax'; import ObjectID from 'Common/Types/ObjectID'; import BadDataException from 'Common/Types/Exception/BadDataException'; import QueryHelper from '../Types/Database/QueryHelper'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import UpdateBy from '../Types/Database/UpdateBy'; import DeleteBy from '../Types/Database/DeleteBy'; diff --git a/CommonServer/Services/ScheduledMaintenanceStateTimelineService.ts b/CommonServer/Services/ScheduledMaintenanceStateTimelineService.ts index 6dd3d122bb..a19ac726aa 100644 --- a/CommonServer/Services/ScheduledMaintenanceStateTimelineService.ts +++ b/CommonServer/Services/ScheduledMaintenanceStateTimelineService.ts @@ -8,7 +8,7 @@ import ScheduledMaintenanceService from './ScheduledMaintenanceService'; import DeleteBy from '../Types/Database/DeleteBy'; import ObjectID from 'Common/Types/ObjectID'; import PositiveNumber from 'Common/Types/PositiveNumber'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import ScheduledMaintenanceState from 'Model/Models/ScheduledMaintenanceState'; import ScheduledMaintenanceStateService from './ScheduledMaintenanceStateService'; import ScheduledMaintenance from 'Model/Models/ScheduledMaintenance'; diff --git a/CommonServer/Services/StatusPageFooterLinkService.ts b/CommonServer/Services/StatusPageFooterLinkService.ts index d1653dc7b4..ac2ecde313 100644 --- a/CommonServer/Services/StatusPageFooterLinkService.ts +++ b/CommonServer/Services/StatusPageFooterLinkService.ts @@ -11,7 +11,7 @@ import DeleteBy from '../Types/Database/DeleteBy'; import ObjectID from 'Common/Types/ObjectID'; import UpdateBy from '../Types/Database/UpdateBy'; import LIMIT_MAX from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; export class Service extends DatabaseService { public constructor(postgresDatabase?: PostgresDatabase) { diff --git a/CommonServer/Services/StatusPageGroupService.ts b/CommonServer/Services/StatusPageGroupService.ts index bf27e8a742..b8c6003f37 100644 --- a/CommonServer/Services/StatusPageGroupService.ts +++ b/CommonServer/Services/StatusPageGroupService.ts @@ -9,7 +9,7 @@ import ObjectID from 'Common/Types/ObjectID'; import UpdateBy from '../Types/Database/UpdateBy'; import QueryHelper from '../Types/Database/QueryHelper'; import LIMIT_MAX from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import PositiveNumber from 'Common/Types/PositiveNumber'; export class Service extends DatabaseService { diff --git a/CommonServer/Services/StatusPageHeaderLinkService.ts b/CommonServer/Services/StatusPageHeaderLinkService.ts index 452cb9ee74..2b122d988c 100644 --- a/CommonServer/Services/StatusPageHeaderLinkService.ts +++ b/CommonServer/Services/StatusPageHeaderLinkService.ts @@ -11,7 +11,7 @@ import DeleteBy from '../Types/Database/DeleteBy'; import ObjectID from 'Common/Types/ObjectID'; import UpdateBy from '../Types/Database/UpdateBy'; import LIMIT_MAX from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; export class Service extends DatabaseService { public constructor(postgresDatabase?: PostgresDatabase) { diff --git a/CommonServer/Services/StatusPageResourceService.ts b/CommonServer/Services/StatusPageResourceService.ts index b0d0b1620c..ebefe4769d 100644 --- a/CommonServer/Services/StatusPageResourceService.ts +++ b/CommonServer/Services/StatusPageResourceService.ts @@ -8,7 +8,7 @@ import QueryHelper from '../Types/Database/QueryHelper'; import DeleteBy from '../Types/Database/DeleteBy'; import ObjectID from 'Common/Types/ObjectID'; import LIMIT_MAX from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import UpdateBy from '../Types/Database/UpdateBy'; import Query from '../Types/Database/Query'; import PositiveNumber from 'Common/Types/PositiveNumber'; diff --git a/CommonServer/Types/AnalyticsDatabase/FindOneBy.ts b/CommonServer/Types/AnalyticsDatabase/FindOneBy.ts new file mode 100644 index 0000000000..78715de004 --- /dev/null +++ b/CommonServer/Types/AnalyticsDatabase/FindOneBy.ts @@ -0,0 +1,12 @@ +import Query from './Query'; +import Select from './Select'; +import Sort from './Sort'; +import BaseModel from 'Common/AnalyticsModels/BaseModel'; +import DatabaseCommonInteractionProps from 'Common/Types/BaseDatabase/DatabaseCommonInteractionProps'; + +export default interface FindOneBy { + query: Query; + select?: Select | undefined; + sort?: Sort | undefined; + props: DatabaseCommonInteractionProps; +} diff --git a/CommonServer/Types/AnalyticsDatabase/Query.ts b/CommonServer/Types/AnalyticsDatabase/Query.ts index 93bed851a5..83a8a33b50 100644 --- a/CommonServer/Types/AnalyticsDatabase/Query.ts +++ b/CommonServer/Types/AnalyticsDatabase/Query.ts @@ -3,10 +3,6 @@ import { JSONObject, JSONValue } from 'Common/Types/JSON'; export type QueryPropertyOptions = JSONValue | JSONObject; -/** - * Select find options. - */ - export declare type QueryOptions = { [P in keyof Entity]?: QueryPropertyOptions; }; diff --git a/CommonServer/Types/AnalyticsDatabase/Sort.ts b/CommonServer/Types/AnalyticsDatabase/Sort.ts new file mode 100644 index 0000000000..6e113917ad --- /dev/null +++ b/CommonServer/Types/AnalyticsDatabase/Sort.ts @@ -0,0 +1,12 @@ +import BaseModel from 'Common/AnalyticsModels/BaseModel'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; +/** + * Order by find options. + */ +export declare type FindOrder = { + [P in keyof Entity]?: SortOrder; +}; + +type Sort = FindOrder; + +export default Sort; diff --git a/CommonServer/Types/Database/Sort.ts b/CommonServer/Types/Database/Sort.ts index 1d4855b96e..bcb97aa773 100644 --- a/CommonServer/Types/Database/Sort.ts +++ b/CommonServer/Types/Database/Sort.ts @@ -1,7 +1,7 @@ import BaseModel from 'Common/Models/BaseModel'; import DatabaseProperty from 'Common/Types/Database/DatabaseProperty'; import { FindOptionsOrderProperty, FindOptionsOrderValue } from 'typeorm'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; export declare type FindOrderProperty = Property extends DatabaseProperty diff --git a/CommonServer/Utils/Probe/ProbeMonitorResponse.ts b/CommonServer/Utils/Probe/ProbeMonitorResponse.ts index 5f0466b9b4..fcdf1675b1 100644 --- a/CommonServer/Utils/Probe/ProbeMonitorResponse.ts +++ b/CommonServer/Utils/Probe/ProbeMonitorResponse.ts @@ -30,7 +30,7 @@ import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax'; import Dictionary from 'Common/Types/Dictionary'; import IncidentSeverity from 'Model/Models/IncidentSeverity'; import IncidentSeverityService from '../../Services/IncidentSeverityService'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import OnCallDutyPolicy from 'Model/Models/OnCallDutyPolicy'; import IncomingMonitorRequest from 'Common/Types/Monitor/IncomingMonitor/IncomingMonitorRequest'; import MonitorType from 'Common/Types/Monitor/MonitorType'; diff --git a/CommonUI/src/Components/ModelTable/ModelTable.tsx b/CommonUI/src/Components/ModelTable/ModelTable.tsx index fc731408a0..92548481a5 100644 --- a/CommonUI/src/Components/ModelTable/ModelTable.tsx +++ b/CommonUI/src/Components/ModelTable/ModelTable.tsx @@ -19,7 +19,7 @@ import ModelFormModal from '../ModelFormModal/ModelFormModal'; import IconProp from 'Common/Types/Icon/IconProp'; import { FormType, ModelField } from '../Forms/ModelForm'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import FieldType from '../Types/FieldType'; import Dictionary from 'Common/Types/Dictionary'; import ActionButtonSchema from '../ActionButton/ActionButtonSchema'; diff --git a/CommonUI/src/Components/Table/Table.tsx b/CommonUI/src/Components/Table/Table.tsx index 7c49e3652e..4b7de4add4 100644 --- a/CommonUI/src/Components/Table/Table.tsx +++ b/CommonUI/src/Components/Table/Table.tsx @@ -4,7 +4,7 @@ import TableBody from './TableBody'; import TableHeader from './TableHeader'; import Columns from './Types/Columns'; import Pagination from '../Pagination/Pagination'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import ActionButtonSchema from '../ActionButton/ActionButtonSchema'; import ErrorMessage from '../ErrorMessage/ErrorMessage'; import ComponentLoader from '../ComponentLoader/ComponentLoader'; diff --git a/CommonUI/src/Components/Table/TableHeader.tsx b/CommonUI/src/Components/Table/TableHeader.tsx index 26b5d536f9..72d71f19c6 100644 --- a/CommonUI/src/Components/Table/TableHeader.tsx +++ b/CommonUI/src/Components/Table/TableHeader.tsx @@ -3,7 +3,7 @@ import Column from './Types/Column'; import Columns from './Types/Columns'; import Icon, { ThickProp } from '../Icon/Icon'; import IconProp from 'Common/Types/Icon/IconProp'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import FieldType from '../Types/FieldType'; export interface ComponentProps { diff --git a/CommonUI/src/Utils/ModelAPI/Sort.ts b/CommonUI/src/Utils/ModelAPI/Sort.ts index d0b7679b0f..6d7fb6d409 100644 --- a/CommonUI/src/Utils/ModelAPI/Sort.ts +++ b/CommonUI/src/Utils/ModelAPI/Sort.ts @@ -1,5 +1,5 @@ import BaseModel from 'Common/Models/BaseModel'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import { JSONObject } from 'Common/Types/JSON'; type Sort = { diff --git a/Dashboard/src/Components/Form/Monitor/MonitorSteps.tsx b/Dashboard/src/Components/Form/Monitor/MonitorSteps.tsx index 95d1559dd6..4f1be2d97f 100644 --- a/Dashboard/src/Components/Form/Monitor/MonitorSteps.tsx +++ b/Dashboard/src/Components/Form/Monitor/MonitorSteps.tsx @@ -17,7 +17,7 @@ import IncidentSeverity from 'Model/Models/IncidentSeverity'; import HorizontalRule from 'CommonUI/src/Components/HorizontalRule/HorizontalRule'; import FieldLabelElement from 'CommonUI/src/Components/Forms/Fields/FieldLabel'; import ObjectID from 'Common/Types/ObjectID'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import OnCallDutyPolicy from 'Model/Models/OnCallDutyPolicy'; import useAsyncEffect from 'use-async-effect'; diff --git a/Dashboard/src/Pages/Monitor/View/Index.tsx b/Dashboard/src/Pages/Monitor/View/Index.tsx index b34a09b3be..0351943216 100644 --- a/Dashboard/src/Pages/Monitor/View/Index.tsx +++ b/Dashboard/src/Pages/Monitor/View/Index.tsx @@ -23,7 +23,7 @@ import OneUptimeDate from 'Common/Types/Date'; import useAsyncEffect from 'use-async-effect'; import InBetween from 'Common/Types/Database/InBetween'; import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import ModelAPI, { ListResult } from 'CommonUI/src/Utils/ModelAPI/ModelAPI'; import MonitorStatusTimeline from 'Model/Models/MonitorStatusTimeline'; import JSONFunctions from 'Common/Types/JSONFunctions'; diff --git a/Dashboard/src/Pages/OnCallDuty/OnCallDutyPolicy/Escalation.tsx b/Dashboard/src/Pages/OnCallDuty/OnCallDutyPolicy/Escalation.tsx index 0c6078a5ed..8e87d1c71a 100644 --- a/Dashboard/src/Pages/OnCallDuty/OnCallDutyPolicy/Escalation.tsx +++ b/Dashboard/src/Pages/OnCallDuty/OnCallDutyPolicy/Escalation.tsx @@ -19,7 +19,7 @@ import FieldType from 'CommonUI/src/Components/Types/FieldType'; import Team from 'Model/Models/Team'; import ProjectUser from '../../../Utils/ProjectUser'; import CardModelDetail from 'CommonUI/src/Components/ModelDetail/CardModelDetail'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import { JSONObject } from 'Common/Types/JSON'; import TeamView from '../../../Components/OnCallPolicy/EscalationRule/TeamView'; import UserView from '../../../Components/OnCallPolicy/EscalationRule/UserView'; diff --git a/Dashboard/src/Pages/Settings/IncidentSeverity.tsx b/Dashboard/src/Pages/Settings/IncidentSeverity.tsx index 848c9a17ea..838b2dd7e4 100644 --- a/Dashboard/src/Pages/Settings/IncidentSeverity.tsx +++ b/Dashboard/src/Pages/Settings/IncidentSeverity.tsx @@ -14,7 +14,7 @@ import FieldType from 'CommonUI/src/Components/Types/FieldType'; import { JSONObject } from 'Common/Types/JSON'; import Pill from 'CommonUI/src/Components/Pill/Pill'; import Color from 'Common/Types/Color'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import Navigation from 'CommonUI/src/Utils/Navigation'; const IncidentSeverityPage: FunctionComponent = ( _props: PageComponentProps diff --git a/Dashboard/src/Pages/Settings/IncidentState.tsx b/Dashboard/src/Pages/Settings/IncidentState.tsx index dad346b812..8df3ae5086 100644 --- a/Dashboard/src/Pages/Settings/IncidentState.tsx +++ b/Dashboard/src/Pages/Settings/IncidentState.tsx @@ -14,7 +14,7 @@ import FieldType from 'CommonUI/src/Components/Types/FieldType'; import { JSONObject } from 'Common/Types/JSON'; import Pill from 'CommonUI/src/Components/Pill/Pill'; import Color from 'Common/Types/Color'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import BadDataException from 'Common/Types/Exception/BadDataException'; import Navigation from 'CommonUI/src/Utils/Navigation'; const IncidentsPage: FunctionComponent = ( diff --git a/Dashboard/src/Pages/Settings/MonitorStatus.tsx b/Dashboard/src/Pages/Settings/MonitorStatus.tsx index 3288f16e8f..85cc414e4c 100644 --- a/Dashboard/src/Pages/Settings/MonitorStatus.tsx +++ b/Dashboard/src/Pages/Settings/MonitorStatus.tsx @@ -15,7 +15,7 @@ import { JSONObject } from 'Common/Types/JSON'; import StatusBubble from 'CommonUI/src/Components/StatusBubble/StatusBubble'; import Color from 'Common/Types/Color'; import BadDataException from 'Common/Types/Exception/BadDataException'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import DashboardNavigation from '../../Utils/Navigation'; import Navigation from 'CommonUI/src/Utils/Navigation'; import ObjectID from 'Common/Types/ObjectID'; diff --git a/Dashboard/src/Pages/Settings/ScheduledMaintenanceState.tsx b/Dashboard/src/Pages/Settings/ScheduledMaintenanceState.tsx index e6579dcbaa..5db5105510 100644 --- a/Dashboard/src/Pages/Settings/ScheduledMaintenanceState.tsx +++ b/Dashboard/src/Pages/Settings/ScheduledMaintenanceState.tsx @@ -14,7 +14,7 @@ import FieldType from 'CommonUI/src/Components/Types/FieldType'; import { JSONObject } from 'Common/Types/JSON'; import Pill from 'CommonUI/src/Components/Pill/Pill'; import Color from 'Common/Types/Color'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import BadDataException from 'Common/Types/Exception/BadDataException'; import Navigation from 'CommonUI/src/Utils/Navigation'; const ScheduledMaintenancesPage: FunctionComponent = ( diff --git a/Dashboard/src/Pages/StatusPages/View/FooterStyle.tsx b/Dashboard/src/Pages/StatusPages/View/FooterStyle.tsx index e48950f08d..ac96f45852 100644 --- a/Dashboard/src/Pages/StatusPages/View/FooterStyle.tsx +++ b/Dashboard/src/Pages/StatusPages/View/FooterStyle.tsx @@ -13,7 +13,7 @@ import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSc import FieldType from 'CommonUI/src/Components/Types/FieldType'; import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable'; import StatusPageFooterLink from 'Model/Models/StatusPageFooterLink'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import BadDataException from 'Common/Types/Exception/BadDataException'; import Navigation from 'CommonUI/src/Utils/Navigation'; diff --git a/Dashboard/src/Pages/StatusPages/View/Groups.tsx b/Dashboard/src/Pages/StatusPages/View/Groups.tsx index 07e52cad9d..1219c5b4a2 100644 --- a/Dashboard/src/Pages/StatusPages/View/Groups.tsx +++ b/Dashboard/src/Pages/StatusPages/View/Groups.tsx @@ -12,7 +12,7 @@ import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable'; import BadDataException from 'Common/Types/Exception/BadDataException'; import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType'; import FieldType from 'CommonUI/src/Components/Types/FieldType'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import Navigation from 'CommonUI/src/Utils/Navigation'; import StatusPage from 'Model/Models/StatusPage'; diff --git a/Dashboard/src/Pages/StatusPages/View/HeaderStyle.tsx b/Dashboard/src/Pages/StatusPages/View/HeaderStyle.tsx index f6b45326e5..7780094b6c 100644 --- a/Dashboard/src/Pages/StatusPages/View/HeaderStyle.tsx +++ b/Dashboard/src/Pages/StatusPages/View/HeaderStyle.tsx @@ -13,7 +13,7 @@ import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSc import FieldType from 'CommonUI/src/Components/Types/FieldType'; import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable'; import StatusPageHeaderLink from 'Model/Models/StatusPageHeaderLink'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import BadDataException from 'Common/Types/Exception/BadDataException'; import Navigation from 'CommonUI/src/Utils/Navigation'; diff --git a/Dashboard/src/Pages/StatusPages/View/Resources.tsx b/Dashboard/src/Pages/StatusPages/View/Resources.tsx index cad5a1efb8..1ece8250eb 100644 --- a/Dashboard/src/Pages/StatusPages/View/Resources.tsx +++ b/Dashboard/src/Pages/StatusPages/View/Resources.tsx @@ -16,7 +16,7 @@ import StatusPageResource from 'Model/Models/StatusPageResource'; import FieldType from 'CommonUI/src/Components/Types/FieldType'; import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType'; import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import BadDataException from 'Common/Types/Exception/BadDataException'; import Monitor from 'Model/Models/Monitor'; import { JSONObject } from 'Common/Types/JSON'; diff --git a/Dashboard/src/Pages/UserSettings/OnCallRules.tsx b/Dashboard/src/Pages/UserSettings/OnCallRules.tsx index d840b57494..552cb1f075 100644 --- a/Dashboard/src/Pages/UserSettings/OnCallRules.tsx +++ b/Dashboard/src/Pages/UserSettings/OnCallRules.tsx @@ -30,7 +30,7 @@ import NotifyAfterDropdownOptions from '../../Components/NotificationRule/Notify import FieldType from 'CommonUI/src/Components/Types/FieldType'; import { JSONObject } from 'Common/Types/JSON'; import NotificationRuleType from 'Common/Types/NotificationRule/NotificationRuleType'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import NotificationMethodView from '../../Components/NotificationMethods/NotificationMethod'; const Settings: FunctionComponent = ( diff --git a/DashboardAPI/Index.ts b/DashboardAPI/Index.ts index 175ccd5baf..9a734a5a01 100755 --- a/DashboardAPI/Index.ts +++ b/DashboardAPI/Index.ts @@ -379,6 +379,9 @@ import UserNotificationSettingService, { Service as UserNotificationSettingServiceType, } from 'CommonServer/Services/UserNotificationSettingService'; +import Log from 'Model/AnalyticsModels/Log'; +import LogService from 'CommonServer/Services/LogService'; + const app: ExpressApplication = Express.getExpressApp(); const APP_NAME: string = 'api'; @@ -1016,6 +1019,18 @@ const init: () => Promise = async (): Promise => { await ClickhouseAppInstance.connect( ClickhouseAppInstance.getDatasourceOptions() ); + + // add a log statement + const log: Log = new Log(); + log.severity = 'info'; + log.message = 'App Initialized'; + log.timestamp = new Date(); + LogService.create({ + data: log, + props: { + isRoot: true + } + }); } catch (err) { logger.error('App Init Failed:'); logger.error(err); diff --git a/Model/AnalyticsModels/Log.ts b/Model/AnalyticsModels/Log.ts index 683a48f818..bff0afbfaa 100644 --- a/Model/AnalyticsModels/Log.ts +++ b/Model/AnalyticsModels/Log.ts @@ -11,6 +11,7 @@ export default class Log extends AnalyticsBaseModel { singularName: 'Log', pluralName: 'Logs', tableColumns: [ + new AnalyticsTableColumn({ key: 'projectId', title: 'Project ID', @@ -18,22 +19,86 @@ export default class Log extends AnalyticsBaseModel { required: true, type: TableColumnType.ObjectID, }), + new AnalyticsTableColumn({ - key: 'logContainerId', - title: 'Log Container ID', - description: 'ID of the log container', + key: 'sourceId', + title: 'Source ID', + description: 'ID of the Log Source', required: true, type: TableColumnType.ObjectID, }), + new AnalyticsTableColumn({ - key: 'logData', - title: 'Log Data', - description: 'Data of the log container', + key: 'message', + title: 'Log Message', + description: 'Log message', required: true, type: TableColumnType.VeryLongText, }), + + new AnalyticsTableColumn({ + key: 'timestamp', + title: 'Timestamp', + description: 'When was the log created?', + required: true, + type: TableColumnType.Date, + }), + + new AnalyticsTableColumn({ + key: 'severity', + title: 'Severity', + description: 'Log Severity', + required: true, + type: TableColumnType.ShortText, + }), + ], - primaryKeys: ['projectId', 'logContainerId', 'createdAt'], + primaryKeys: ['projectId', 'sourceId', 'timestamp'], }); } + + public get severity() : string | undefined { + return this.getColumnValue('severity') as string | undefined; + } + public set severity(v : string | undefined) { + this.setColumnValue('severity', v); + } + + public get timestamp() : Date | undefined { + return this.getColumnValue('timestamp') as Date | undefined; + } + public set timestamp(v : Date | undefined) { + this.setColumnValue('timestamp', v); + } + + public get log() : string | undefined { + return this.getColumnValue('log') as string | undefined; + } + public set log(v : string | undefined) { + this.setColumnValue('log', v); + } + + public get sourceId() : string | undefined { + return this.getColumnValue('sourceId') as string | undefined; + } + + public set sourceId(v : string | undefined) { + this.setColumnValue('sourceId', v); + } + + public get projectId() : string | undefined { + return this.getColumnValue('projectId') as string | undefined; + } + + public set projectId(v : string | undefined) { + this.setColumnValue('projectId', v); + } + + public get message() : string | undefined { + return this.getColumnValue('message') as string | undefined; + } + + public set message(v : string | undefined) { + this.setColumnValue('message', v); + } } diff --git a/ProbeAPI/API/Monitor.ts b/ProbeAPI/API/Monitor.ts index 199112ba5d..1871b869a6 100644 --- a/ProbeAPI/API/Monitor.ts +++ b/ProbeAPI/API/Monitor.ts @@ -21,7 +21,7 @@ import SubscriptionStatus from 'Common/Types/Billing/SubscriptionStatus'; import ObjectID from 'Common/Types/ObjectID'; import ClusterKeyAuthorization from 'CommonServer/Middleware/ClusterKeyAuthorization'; import LIMIT_MAX from 'Common/Types/Database/LimitMax'; -import SortOrder from 'Common/Types/Database/SortOrder'; +import SortOrder from 'Common/Types/BaseDatabase/SortOrder'; import Query from 'CommonServer/Types/Database/Query'; import JSONFunctions from 'Common/Types/JSONFunctions'; import logger from 'CommonServer/Utils/Logger'; diff --git a/package.json b/package.json index 2787766229..afa8c214e0 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "save-logs": "export $(grep -v '^#' config.env | xargs) && docker compose logs --tail=100000 $npm_config_services > logs.txt", "logs": "export $(grep -v '^#' config.env | xargs) && docker compose logs --tail=100 -f $npm_config_services", "write-logs": "export $(grep -v '^#' config.env | xargs) && docker compose logs -f $npm_config_services > logs.txt", - "build": "docker compose build -f docker-compose.dev.yml $npm_config_services", + "build": "export $(grep -v '^#' config.env | xargs) && docker compose -f docker-compose.dev.yml build $npm_config_services", "force-build": "export $(grep -v '^#' config.env | xargs) && npm run prerun && docker compose -f docker-compose.dev.yml build --no-cache $npm_config_services", "force-build-dev": "npm run config-to-dev && npm run force-build", "kill": "npm run stop",