@oneuptime/common 7.0.4358 → 7.0.4372
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/ExceptionInstance.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +2 -2
- package/Models/DatabaseModels/Probe.ts +7 -1
- package/Models/DatabaseModels/ServiceCatalog.ts +2 -2
- package/Models/DatabaseModels/ServiceCopilotCodeRepository.ts +2 -2
- package/Server/Utils/OpenAPI.ts +564 -2
- package/Utils/Schema/AnalyticsModelSchema.ts +764 -0
- package/Utils/Schema/BaseSchema.ts +450 -0
- package/Utils/Schema/ModelSchema.ts +176 -407
- package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +2 -2
- package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Probe.js +7 -1
- package/build/dist/Models/DatabaseModels/Probe.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceCatalog.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceCatalog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceCopilotCodeRepository.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceCopilotCodeRepository.js.map +1 -1
- package/build/dist/Server/Utils/OpenAPI.js +445 -2
- package/build/dist/Server/Utils/OpenAPI.js.map +1 -1
- package/build/dist/Utils/Schema/AnalyticsModelSchema.js +636 -0
- package/build/dist/Utils/Schema/AnalyticsModelSchema.js.map +1 -0
- package/build/dist/Utils/Schema/BaseSchema.js +295 -0
- package/build/dist/Utils/Schema/BaseSchema.js.map +1 -0
- package/build/dist/Utils/Schema/ModelSchema.js +155 -337
- package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,42 +6,22 @@ import {
|
|
|
6
6
|
} from "../../Types/Database/TableColumn";
|
|
7
7
|
import Dictionary from "../../Types/Dictionary";
|
|
8
8
|
import DatabaseBaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
9
|
-
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
10
9
|
import logger from "../../Server/Utils/Logger";
|
|
11
10
|
import Color from "../../Types/Color";
|
|
12
11
|
import { z as ZodTypes } from "zod";
|
|
13
12
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
14
13
|
import Permission, { PermissionHelper } from "../../Types/Permission";
|
|
15
14
|
import { ColumnAccessControl } from "../../Types/BaseDatabase/AccessControl";
|
|
15
|
+
import { BaseSchema, SchemaExample, ShapeRecord } from "./BaseSchema";
|
|
16
16
|
|
|
17
17
|
export type ModelSchemaType = ZodSchema;
|
|
18
18
|
|
|
19
|
-
// Type for schema examples
|
|
20
|
-
type SchemaExample = Record<string, unknown>;
|
|
21
|
-
|
|
22
|
-
// Type for operator examples in OpenAPI format
|
|
23
|
-
type OperatorExample = {
|
|
24
|
-
properties: Record<
|
|
25
|
-
string,
|
|
26
|
-
{
|
|
27
|
-
type: string;
|
|
28
|
-
enum?: string[];
|
|
29
|
-
items?: { type: string };
|
|
30
|
-
}
|
|
31
|
-
>;
|
|
32
|
-
required: string[];
|
|
33
|
-
example: Record<string, unknown>;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Type for shape objects using Zod's type inference
|
|
37
|
-
type ShapeRecord = Record<string, ZodTypes.ZodTypeAny>;
|
|
38
|
-
|
|
39
19
|
// Type for schema method functions
|
|
40
20
|
type SchemaMethodFunction = (data: {
|
|
41
21
|
modelType: new () => DatabaseBaseModel;
|
|
42
22
|
}) => ModelSchemaType;
|
|
43
23
|
|
|
44
|
-
export class ModelSchema {
|
|
24
|
+
export class ModelSchema extends BaseSchema {
|
|
45
25
|
/**
|
|
46
26
|
* Format permissions array into a human-readable string for OpenAPI documentation
|
|
47
27
|
*/
|
|
@@ -49,7 +29,7 @@ export class ModelSchema {
|
|
|
49
29
|
permissions: Array<Permission> | undefined,
|
|
50
30
|
): string {
|
|
51
31
|
if (!permissions || permissions.length === 0) {
|
|
52
|
-
return "No
|
|
32
|
+
return "No access - you don't have permission for this operation";
|
|
53
33
|
}
|
|
54
34
|
|
|
55
35
|
return PermissionHelper.getPermissionTitles(permissions).join(", ");
|
|
@@ -92,11 +72,29 @@ export class ModelSchema {
|
|
|
92
72
|
|
|
93
73
|
const shape: ShapeRecord = {};
|
|
94
74
|
|
|
75
|
+
// Get column access control for permission filtering
|
|
76
|
+
const columnAccessControl: Dictionary<ColumnAccessControl> =
|
|
77
|
+
model.getColumnAccessControlForAllColumns();
|
|
78
|
+
|
|
95
79
|
for (const key in columns) {
|
|
96
80
|
const column: TableColumnMetadata | undefined = columns[key];
|
|
97
81
|
if (!column) {
|
|
98
82
|
continue;
|
|
99
83
|
}
|
|
84
|
+
|
|
85
|
+
// Filter out columns with no permissions (root-only access)
|
|
86
|
+
const accessControl: ColumnAccessControl | undefined =
|
|
87
|
+
columnAccessControl[key];
|
|
88
|
+
if (accessControl) {
|
|
89
|
+
// Check if column has any permissions defined for read operation (general schema assumes read access)
|
|
90
|
+
const hasReadPermissions: boolean =
|
|
91
|
+
accessControl.read && accessControl.read.length > 0;
|
|
92
|
+
|
|
93
|
+
// If no read permissions are defined, exclude the column from general schema
|
|
94
|
+
if (!hasReadPermissions) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
100
98
|
let zodType: ZodTypes.ZodTypeAny;
|
|
101
99
|
|
|
102
100
|
if (column.type === TableColumnType.ObjectID) {
|
|
@@ -380,72 +378,36 @@ export class ModelSchema {
|
|
|
380
378
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
381
379
|
const model: DatabaseBaseModel = new modelType();
|
|
382
380
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
(operatorType
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
} else if (operatorSchemas.length > 1) {
|
|
413
|
-
columnSchema = z
|
|
414
|
-
.union(
|
|
415
|
-
operatorSchemas as [
|
|
416
|
-
ZodTypes.ZodTypeAny,
|
|
417
|
-
ZodTypes.ZodTypeAny,
|
|
418
|
-
...ZodTypes.ZodTypeAny[],
|
|
419
|
-
],
|
|
420
|
-
)
|
|
421
|
-
.optional();
|
|
422
|
-
} else {
|
|
423
|
-
// Fallback for empty operators array
|
|
424
|
-
columnSchema = z.any().optional();
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Add OpenAPI documentation for query operators
|
|
428
|
-
const operatorExamples: Array<OperatorExample> =
|
|
429
|
-
this.getQueryOperatorExamples(column.type, validOperators);
|
|
430
|
-
columnSchema = columnSchema.openapi({
|
|
431
|
-
type: "object",
|
|
432
|
-
description: `Query operators for ${key} field of type ${column.type}. Supported operators: ${validOperators.join(", ")}`,
|
|
433
|
-
example:
|
|
434
|
-
operatorExamples.length > 0 && operatorExamples[0]
|
|
435
|
-
? operatorExamples[0].example
|
|
436
|
-
: {},
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
shape[key] = columnSchema;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
const schema: ModelSchemaType = z.object(shape).openapi({
|
|
443
|
-
type: "object",
|
|
444
|
-
description: `Query schema for ${model.tableName || "model"} model. Each field can use various operators based on its data type.`,
|
|
445
|
-
example: this.getQuerySchemaExample(modelType),
|
|
381
|
+
return this.generateQuerySchema({
|
|
382
|
+
model,
|
|
383
|
+
tableName: model.tableName || "model",
|
|
384
|
+
getColumns: (model: DatabaseBaseModel) => {
|
|
385
|
+
const columns: Dictionary<TableColumnMetadata> = getTableColumns(model);
|
|
386
|
+
return Object.keys(columns)
|
|
387
|
+
.map((key: string) => {
|
|
388
|
+
const column: TableColumnMetadata | undefined = columns[key];
|
|
389
|
+
return column ? { key, type: column.type } : null;
|
|
390
|
+
})
|
|
391
|
+
.filter((col: { key: string; type: any } | null) => {
|
|
392
|
+
return col !== null;
|
|
393
|
+
}) as Array<{ key: string; type: any }>;
|
|
394
|
+
},
|
|
395
|
+
getValidOperatorsForColumnType: (columnType: TableColumnType) => {
|
|
396
|
+
return this.getValidOperatorsForColumnType(columnType);
|
|
397
|
+
},
|
|
398
|
+
getOperatorSchema: (
|
|
399
|
+
operatorType: string,
|
|
400
|
+
columnType: TableColumnType,
|
|
401
|
+
) => {
|
|
402
|
+
return this.getOperatorSchema(operatorType, columnType);
|
|
403
|
+
},
|
|
404
|
+
getQuerySchemaExample: () => {
|
|
405
|
+
return this.getQuerySchemaExample(modelType);
|
|
406
|
+
},
|
|
407
|
+
getExampleValueForColumn: (columnType: TableColumnType) => {
|
|
408
|
+
return this.getExampleValueForColumn(columnType);
|
|
409
|
+
},
|
|
446
410
|
});
|
|
447
|
-
|
|
448
|
-
return schema;
|
|
449
411
|
}
|
|
450
412
|
|
|
451
413
|
private static getValidOperatorsForColumnType(
|
|
@@ -658,40 +620,23 @@ export class ModelSchema {
|
|
|
658
620
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
659
621
|
const model: DatabaseBaseModel = new modelType();
|
|
660
622
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
shape[key] = z
|
|
680
|
-
.enum([SortOrder.Ascending, SortOrder.Descending])
|
|
681
|
-
.optional()
|
|
682
|
-
.openapi({
|
|
683
|
-
type: "string",
|
|
684
|
-
enum: [SortOrder.Ascending, SortOrder.Descending],
|
|
685
|
-
description: `Sort order for ${key} field`,
|
|
686
|
-
example: SortOrder.Ascending,
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
return z.object(shape).openapi({
|
|
691
|
-
type: "object",
|
|
692
|
-
description: `Sort schema for ${model.tableName || "model"} model. Only sortable fields are included.`,
|
|
693
|
-
example: this.getSortSchemaExample(),
|
|
694
|
-
additionalProperties: false,
|
|
623
|
+
return this.generateSortSchema({
|
|
624
|
+
model,
|
|
625
|
+
tableName: model.tableName || "model",
|
|
626
|
+
getSortableTypes: () => {
|
|
627
|
+
return this.getSortableTypes();
|
|
628
|
+
},
|
|
629
|
+
getColumnsForSorting: (model: DatabaseBaseModel) => {
|
|
630
|
+
const columns: Dictionary<TableColumnMetadata> = getTableColumns(model);
|
|
631
|
+
return Object.keys(columns)
|
|
632
|
+
.map((key: string) => {
|
|
633
|
+
const column: TableColumnMetadata | undefined = columns[key];
|
|
634
|
+
return column ? { key, type: column.type } : null;
|
|
635
|
+
})
|
|
636
|
+
.filter((col: { key: string; type: any } | null) => {
|
|
637
|
+
return col !== null;
|
|
638
|
+
}) as Array<{ key: string; type: any }>;
|
|
639
|
+
},
|
|
695
640
|
});
|
|
696
641
|
}
|
|
697
642
|
|
|
@@ -702,50 +647,40 @@ export class ModelSchema {
|
|
|
702
647
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
703
648
|
const model: DatabaseBaseModel = new modelType();
|
|
704
649
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
description: `Select ${key} field in the response`,
|
|
740
|
-
example: true,
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
return z.object(shape).openapi({
|
|
745
|
-
type: "object",
|
|
746
|
-
description: `Select schema for ${model.tableName || "model"} model. Set fields to true to include them in the response.`,
|
|
747
|
-
example: this.getSelectSchemaExample(modelType),
|
|
748
|
-
additionalProperties: false,
|
|
650
|
+
return this.generateSelectSchema({
|
|
651
|
+
model,
|
|
652
|
+
tableName: model.tableName || "model",
|
|
653
|
+
getColumns: (model: DatabaseBaseModel) => {
|
|
654
|
+
const columns: Dictionary<TableColumnMetadata> = getTableColumns(model);
|
|
655
|
+
return Object.keys(columns)
|
|
656
|
+
.map((key: string) => {
|
|
657
|
+
const column: TableColumnMetadata | undefined = columns[key];
|
|
658
|
+
return column ? { key, type: column.type } : null;
|
|
659
|
+
})
|
|
660
|
+
.filter((col: { key: string; type: any } | null) => {
|
|
661
|
+
return col !== null;
|
|
662
|
+
}) as Array<{ key: string; type?: any }>;
|
|
663
|
+
},
|
|
664
|
+
getSelectSchemaExample: () => {
|
|
665
|
+
return this.getSelectSchemaExample(modelType);
|
|
666
|
+
},
|
|
667
|
+
allowNested: !data.isNested,
|
|
668
|
+
getNestedSchema: (key: string, model: DatabaseBaseModel) => {
|
|
669
|
+
const columns: Dictionary<TableColumnMetadata> = getTableColumns(model);
|
|
670
|
+
const column: TableColumnMetadata | undefined = columns[key];
|
|
671
|
+
if (
|
|
672
|
+
column &&
|
|
673
|
+
column.modelType &&
|
|
674
|
+
(column.type === TableColumnType.EntityArray ||
|
|
675
|
+
column.type === TableColumnType.Entity)
|
|
676
|
+
) {
|
|
677
|
+
return this.getSelectModelSchema({
|
|
678
|
+
modelType: column.modelType as new () => DatabaseBaseModel,
|
|
679
|
+
isNested: true,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
return null;
|
|
683
|
+
},
|
|
749
684
|
});
|
|
750
685
|
}
|
|
751
686
|
|
|
@@ -755,244 +690,44 @@ export class ModelSchema {
|
|
|
755
690
|
const modelType: new () => DatabaseBaseModel = data.modelType;
|
|
756
691
|
const model: DatabaseBaseModel = new modelType();
|
|
757
692
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
.
|
|
792
|
-
|
|
793
|
-
.openapi({
|
|
794
|
-
type: "boolean",
|
|
795
|
-
description: `Group by ${key} field. Only one field can be selected for grouping.`,
|
|
796
|
-
example: true,
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
return z.object(shape).openapi({
|
|
801
|
-
type: "object",
|
|
802
|
-
description: `Group by schema for ${model.tableName || "model"} model. Only one field can be set to true for grouping.`,
|
|
803
|
-
example: this.getGroupBySchemaExample(modelType),
|
|
804
|
-
additionalProperties: false,
|
|
693
|
+
return this.generateGroupBySchema({
|
|
694
|
+
model,
|
|
695
|
+
tableName: model.tableName || "model",
|
|
696
|
+
getColumns: (model: DatabaseBaseModel) => {
|
|
697
|
+
const columns: Dictionary<TableColumnMetadata> = getTableColumns(model);
|
|
698
|
+
return Object.keys(columns)
|
|
699
|
+
.map((key: string) => {
|
|
700
|
+
const column: TableColumnMetadata | undefined = columns[key];
|
|
701
|
+
return column ? { key, type: column.type } : null;
|
|
702
|
+
})
|
|
703
|
+
.filter((col: { key: string; type: any } | null) => {
|
|
704
|
+
return col !== null;
|
|
705
|
+
}) as Array<{ key: string; type: any }>;
|
|
706
|
+
},
|
|
707
|
+
getGroupableTypes: () => {
|
|
708
|
+
return [
|
|
709
|
+
TableColumnType.ShortText,
|
|
710
|
+
TableColumnType.LongText,
|
|
711
|
+
TableColumnType.Name,
|
|
712
|
+
TableColumnType.Email,
|
|
713
|
+
TableColumnType.Slug,
|
|
714
|
+
TableColumnType.ObjectID,
|
|
715
|
+
TableColumnType.Boolean,
|
|
716
|
+
TableColumnType.Date,
|
|
717
|
+
TableColumnType.Number,
|
|
718
|
+
TableColumnType.PositiveNumber,
|
|
719
|
+
TableColumnType.SmallNumber,
|
|
720
|
+
TableColumnType.SmallPositiveNumber,
|
|
721
|
+
TableColumnType.BigNumber,
|
|
722
|
+
TableColumnType.BigPositiveNumber,
|
|
723
|
+
];
|
|
724
|
+
},
|
|
725
|
+
getGroupBySchemaExample: () => {
|
|
726
|
+
return this.getGroupBySchemaExample(modelType);
|
|
727
|
+
},
|
|
805
728
|
});
|
|
806
729
|
}
|
|
807
730
|
|
|
808
|
-
private static getQueryOperatorExamples(
|
|
809
|
-
columnType: TableColumnType,
|
|
810
|
-
validOperators: Array<string>,
|
|
811
|
-
): Array<OperatorExample> {
|
|
812
|
-
const examples: Array<OperatorExample> = [];
|
|
813
|
-
|
|
814
|
-
for (const operator of validOperators) {
|
|
815
|
-
switch (operator) {
|
|
816
|
-
case "EqualTo":
|
|
817
|
-
examples.push({
|
|
818
|
-
properties: {
|
|
819
|
-
_type: { type: "string", enum: ["EqualTo"] },
|
|
820
|
-
value: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
821
|
-
},
|
|
822
|
-
required: ["_type", "value"],
|
|
823
|
-
example: {
|
|
824
|
-
_type: "EqualTo",
|
|
825
|
-
value: this.getExampleValueForColumn(columnType),
|
|
826
|
-
},
|
|
827
|
-
});
|
|
828
|
-
break;
|
|
829
|
-
case "NotEqual":
|
|
830
|
-
examples.push({
|
|
831
|
-
properties: {
|
|
832
|
-
_type: { type: "string", enum: ["NotEqual"] },
|
|
833
|
-
value: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
834
|
-
},
|
|
835
|
-
required: ["_type", "value"],
|
|
836
|
-
example: {
|
|
837
|
-
_type: "NotEqual",
|
|
838
|
-
value: this.getExampleValueForColumn(columnType),
|
|
839
|
-
},
|
|
840
|
-
});
|
|
841
|
-
break;
|
|
842
|
-
case "Search":
|
|
843
|
-
examples.push({
|
|
844
|
-
properties: {
|
|
845
|
-
_type: { type: "string", enum: ["Search"] },
|
|
846
|
-
value: { type: "string" },
|
|
847
|
-
},
|
|
848
|
-
required: ["_type", "value"],
|
|
849
|
-
example: { _type: "Search", value: "search term" },
|
|
850
|
-
});
|
|
851
|
-
break;
|
|
852
|
-
case "GreaterThan":
|
|
853
|
-
examples.push({
|
|
854
|
-
properties: {
|
|
855
|
-
_type: { type: "string", enum: ["GreaterThan"] },
|
|
856
|
-
value: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
857
|
-
},
|
|
858
|
-
required: ["_type", "value"],
|
|
859
|
-
example: {
|
|
860
|
-
_type: "GreaterThan",
|
|
861
|
-
value: this.getExampleValueForColumn(columnType),
|
|
862
|
-
},
|
|
863
|
-
});
|
|
864
|
-
break;
|
|
865
|
-
case "LessThan":
|
|
866
|
-
examples.push({
|
|
867
|
-
properties: {
|
|
868
|
-
_type: { type: "string", enum: ["LessThan"] },
|
|
869
|
-
value: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
870
|
-
},
|
|
871
|
-
required: ["_type", "value"],
|
|
872
|
-
example: {
|
|
873
|
-
_type: "LessThan",
|
|
874
|
-
value: this.getExampleValueForColumn(columnType),
|
|
875
|
-
},
|
|
876
|
-
});
|
|
877
|
-
break;
|
|
878
|
-
case "GreaterThanOrEqual":
|
|
879
|
-
examples.push({
|
|
880
|
-
properties: {
|
|
881
|
-
_type: { type: "string", enum: ["GreaterThanOrEqual"] },
|
|
882
|
-
value: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
883
|
-
},
|
|
884
|
-
required: ["_type", "value"],
|
|
885
|
-
example: {
|
|
886
|
-
_type: "GreaterThanOrEqual",
|
|
887
|
-
value: this.getExampleValueForColumn(columnType),
|
|
888
|
-
},
|
|
889
|
-
});
|
|
890
|
-
break;
|
|
891
|
-
case "LessThanOrEqual":
|
|
892
|
-
examples.push({
|
|
893
|
-
properties: {
|
|
894
|
-
_type: { type: "string", enum: ["LessThanOrEqual"] },
|
|
895
|
-
value: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
896
|
-
},
|
|
897
|
-
required: ["_type", "value"],
|
|
898
|
-
example: {
|
|
899
|
-
_type: "LessThanOrEqual",
|
|
900
|
-
value: this.getExampleValueForColumn(columnType),
|
|
901
|
-
},
|
|
902
|
-
});
|
|
903
|
-
break;
|
|
904
|
-
case "EqualToOrNull":
|
|
905
|
-
examples.push({
|
|
906
|
-
properties: {
|
|
907
|
-
_type: { type: "string", enum: ["EqualToOrNull"] },
|
|
908
|
-
value: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
909
|
-
},
|
|
910
|
-
required: ["_type", "value"],
|
|
911
|
-
example: {
|
|
912
|
-
_type: "EqualToOrNull",
|
|
913
|
-
value: this.getExampleValueForColumn(columnType),
|
|
914
|
-
},
|
|
915
|
-
});
|
|
916
|
-
break;
|
|
917
|
-
case "InBetween":
|
|
918
|
-
examples.push({
|
|
919
|
-
properties: {
|
|
920
|
-
_type: { type: "string", enum: ["InBetween"] },
|
|
921
|
-
startValue: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
922
|
-
endValue: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
923
|
-
},
|
|
924
|
-
required: ["_type", "startValue", "endValue"],
|
|
925
|
-
example: {
|
|
926
|
-
_type: "InBetween",
|
|
927
|
-
startValue: this.getExampleValueForColumn(columnType),
|
|
928
|
-
endValue: this.getExampleValueForColumn(columnType, true),
|
|
929
|
-
},
|
|
930
|
-
});
|
|
931
|
-
break;
|
|
932
|
-
case "IsNull":
|
|
933
|
-
examples.push({
|
|
934
|
-
properties: {
|
|
935
|
-
_type: { type: "string", enum: ["IsNull"] },
|
|
936
|
-
},
|
|
937
|
-
required: ["_type"],
|
|
938
|
-
example: { _type: "IsNull" },
|
|
939
|
-
});
|
|
940
|
-
break;
|
|
941
|
-
case "NotNull":
|
|
942
|
-
examples.push({
|
|
943
|
-
properties: {
|
|
944
|
-
_type: { type: "string", enum: ["NotNull"] },
|
|
945
|
-
},
|
|
946
|
-
required: ["_type"],
|
|
947
|
-
example: { _type: "NotNull" },
|
|
948
|
-
});
|
|
949
|
-
break;
|
|
950
|
-
case "Includes":
|
|
951
|
-
examples.push({
|
|
952
|
-
properties: {
|
|
953
|
-
_type: { type: "string", enum: ["Includes"] },
|
|
954
|
-
value: {
|
|
955
|
-
type: "array",
|
|
956
|
-
items: { type: this.getOpenAPITypeForColumn(columnType) },
|
|
957
|
-
},
|
|
958
|
-
},
|
|
959
|
-
required: ["_type", "value"],
|
|
960
|
-
example: {
|
|
961
|
-
_type: "Includes",
|
|
962
|
-
value: [
|
|
963
|
-
this.getExampleValueForColumn(columnType),
|
|
964
|
-
this.getExampleValueForColumn(columnType, true),
|
|
965
|
-
],
|
|
966
|
-
},
|
|
967
|
-
});
|
|
968
|
-
break;
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
return examples;
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
private static getOpenAPITypeForColumn(columnType: TableColumnType): string {
|
|
976
|
-
switch (columnType) {
|
|
977
|
-
case TableColumnType.Number:
|
|
978
|
-
case TableColumnType.PositiveNumber:
|
|
979
|
-
case TableColumnType.SmallNumber:
|
|
980
|
-
case TableColumnType.SmallPositiveNumber:
|
|
981
|
-
case TableColumnType.BigNumber:
|
|
982
|
-
case TableColumnType.BigPositiveNumber:
|
|
983
|
-
return "number";
|
|
984
|
-
case TableColumnType.Boolean:
|
|
985
|
-
return "boolean";
|
|
986
|
-
case TableColumnType.Date:
|
|
987
|
-
return "string";
|
|
988
|
-
case TableColumnType.JSON:
|
|
989
|
-
case TableColumnType.Array:
|
|
990
|
-
return "object";
|
|
991
|
-
default:
|
|
992
|
-
return "string";
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
|
|
996
731
|
private static getExampleValueForColumn(
|
|
997
732
|
columnType: TableColumnType,
|
|
998
733
|
isSecondValue: boolean = false,
|
|
@@ -1124,12 +859,6 @@ export class ModelSchema {
|
|
|
1124
859
|
return example;
|
|
1125
860
|
}
|
|
1126
861
|
|
|
1127
|
-
private static getSortSchemaExample(): SchemaExample {
|
|
1128
|
-
return {
|
|
1129
|
-
createdAt: "Descending",
|
|
1130
|
-
};
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
862
|
private static getSelectSchemaExample(
|
|
1134
863
|
modelType: new () => DatabaseBaseModel,
|
|
1135
864
|
): SchemaExample {
|
|
@@ -1257,6 +986,10 @@ export class ModelSchema {
|
|
|
1257
986
|
const columns: Dictionary<TableColumnMetadata> = getTableColumns(model);
|
|
1258
987
|
const shape: ShapeRecord = {};
|
|
1259
988
|
|
|
989
|
+
// Get column access control for permission filtering
|
|
990
|
+
const columnAccessControl: Dictionary<ColumnAccessControl> =
|
|
991
|
+
model.getColumnAccessControlForAllColumns();
|
|
992
|
+
|
|
1260
993
|
for (const key in columns) {
|
|
1261
994
|
const column: TableColumnMetadata | undefined = columns[key];
|
|
1262
995
|
if (!column) {
|
|
@@ -1273,6 +1006,42 @@ export class ModelSchema {
|
|
|
1273
1006
|
continue;
|
|
1274
1007
|
}
|
|
1275
1008
|
|
|
1009
|
+
// Filter out columns with no permissions (root-only access)
|
|
1010
|
+
const accessControl: ColumnAccessControl | undefined =
|
|
1011
|
+
columnAccessControl[key];
|
|
1012
|
+
if (accessControl) {
|
|
1013
|
+
let hasPermissions: boolean = false;
|
|
1014
|
+
|
|
1015
|
+
// Check if column has any permissions defined for the current operation
|
|
1016
|
+
if (
|
|
1017
|
+
data.schemaType === "create" &&
|
|
1018
|
+
accessControl.create &&
|
|
1019
|
+
accessControl.create.length > 0
|
|
1020
|
+
) {
|
|
1021
|
+
hasPermissions = true;
|
|
1022
|
+
} else if (
|
|
1023
|
+
data.schemaType === "read" &&
|
|
1024
|
+
accessControl.read &&
|
|
1025
|
+
accessControl.read.length > 0
|
|
1026
|
+
) {
|
|
1027
|
+
hasPermissions = true;
|
|
1028
|
+
} else if (
|
|
1029
|
+
data.schemaType === "update" &&
|
|
1030
|
+
accessControl.update &&
|
|
1031
|
+
accessControl.update.length > 0
|
|
1032
|
+
) {
|
|
1033
|
+
hasPermissions = true;
|
|
1034
|
+
} else if (data.schemaType === "delete") {
|
|
1035
|
+
// For delete operations, we don't filter by column permissions
|
|
1036
|
+
hasPermissions = true;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// If no permissions are defined for this operation, exclude the column
|
|
1040
|
+
if (!hasPermissions) {
|
|
1041
|
+
continue;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1276
1045
|
let zodType: ZodTypes.ZodTypeAny = this.getZodTypeForColumn(
|
|
1277
1046
|
column,
|
|
1278
1047
|
key,
|
|
@@ -9,8 +9,8 @@ export default class ExceptionInstance extends AnalyticsBaseModel {
|
|
|
9
9
|
super({
|
|
10
10
|
tableName: "ExceptionItem",
|
|
11
11
|
tableEngine: AnalyticsTableEngine.MergeTree,
|
|
12
|
-
singularName: "Exception",
|
|
13
|
-
pluralName: "
|
|
12
|
+
singularName: "Exception Instance",
|
|
13
|
+
pluralName: "Exception Instances",
|
|
14
14
|
enableRealtimeEventsOn: {
|
|
15
15
|
create: true,
|
|
16
16
|
},
|