@supabase/pg-delta 1.0.0-alpha.22 → 1.0.0-alpha.23
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/dist/core/catalog.model.js +1 -0
- package/dist/core/integrations/filter/flatten.js +13 -0
- package/dist/core/objects/aggregate/aggregate.diff.js +16 -0
- package/dist/core/objects/aggregate/aggregate.model.d.ts +10 -0
- package/dist/core/objects/aggregate/aggregate.model.js +19 -1
- package/dist/core/objects/aggregate/changes/aggregate.base.d.ts +1 -1
- package/dist/core/objects/aggregate/changes/aggregate.security-label.d.ts +28 -0
- package/dist/core/objects/aggregate/changes/aggregate.security-label.js +64 -0
- package/dist/core/objects/aggregate/changes/aggregate.types.d.ts +2 -1
- package/dist/core/objects/base.model.d.ts +8 -0
- package/dist/core/objects/base.model.js +2 -0
- package/dist/core/objects/domain/changes/domain.base.d.ts +1 -1
- package/dist/core/objects/domain/changes/domain.security-label.d.ts +28 -0
- package/dist/core/objects/domain/changes/domain.security-label.js +61 -0
- package/dist/core/objects/domain/changes/domain.types.d.ts +2 -1
- package/dist/core/objects/domain/domain.diff.js +16 -0
- package/dist/core/objects/domain/domain.model.d.ts +10 -0
- package/dist/core/objects/domain/domain.model.js +19 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.base.d.ts +1 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.d.ts +28 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.js +61 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.types.d.ts +2 -1
- package/dist/core/objects/event-trigger/event-trigger.diff.js +16 -0
- package/dist/core/objects/event-trigger/event-trigger.model.d.ts +10 -0
- package/dist/core/objects/event-trigger/event-trigger.model.js +19 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.d.ts +1 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.d.ts +28 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.js +61 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.d.ts +2 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +22 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +20 -1
- package/dist/core/objects/materialized-view/changes/materialized-view.base.d.ts +1 -1
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.d.ts +28 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.js +61 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.types.d.ts +2 -1
- package/dist/core/objects/materialized-view/materialized-view.diff.js +18 -0
- package/dist/core/objects/materialized-view/materialized-view.model.d.ts +22 -0
- package/dist/core/objects/materialized-view/materialized-view.model.js +20 -1
- package/dist/core/objects/procedure/changes/procedure.base.d.ts +1 -1
- package/dist/core/objects/procedure/changes/procedure.security-label.d.ts +28 -0
- package/dist/core/objects/procedure/changes/procedure.security-label.js +69 -0
- package/dist/core/objects/procedure/changes/procedure.types.d.ts +2 -1
- package/dist/core/objects/procedure/procedure.diff.js +16 -0
- package/dist/core/objects/procedure/procedure.model.d.ts +10 -0
- package/dist/core/objects/procedure/procedure.model.js +19 -1
- package/dist/core/objects/publication/changes/publication.base.d.ts +1 -1
- package/dist/core/objects/publication/changes/publication.security-label.d.ts +28 -0
- package/dist/core/objects/publication/changes/publication.security-label.js +61 -0
- package/dist/core/objects/publication/changes/publication.types.d.ts +2 -1
- package/dist/core/objects/publication/publication.diff.js +16 -0
- package/dist/core/objects/publication/publication.model.d.ts +14 -0
- package/dist/core/objects/publication/publication.model.js +20 -1
- package/dist/core/objects/role/changes/role.base.d.ts +1 -1
- package/dist/core/objects/role/changes/role.security-label.d.ts +28 -0
- package/dist/core/objects/role/changes/role.security-label.js +61 -0
- package/dist/core/objects/role/changes/role.types.d.ts +2 -1
- package/dist/core/objects/role/role.diff.js +16 -0
- package/dist/core/objects/role/role.model.d.ts +10 -0
- package/dist/core/objects/role/role.model.js +29 -0
- package/dist/core/objects/schema/changes/schema.base.d.ts +1 -1
- package/dist/core/objects/schema/changes/schema.security-label.d.ts +28 -0
- package/dist/core/objects/schema/changes/schema.security-label.js +61 -0
- package/dist/core/objects/schema/changes/schema.types.d.ts +2 -1
- package/dist/core/objects/schema/schema.diff.js +24 -1
- package/dist/core/objects/schema/schema.model.d.ts +10 -0
- package/dist/core/objects/schema/schema.model.js +18 -1
- package/dist/core/objects/security-label.types.d.ts +20 -0
- package/dist/core/objects/security-label.types.js +46 -0
- package/dist/core/objects/sequence/changes/sequence.base.d.ts +1 -1
- package/dist/core/objects/sequence/changes/sequence.security-label.d.ts +28 -0
- package/dist/core/objects/sequence/changes/sequence.security-label.js +61 -0
- package/dist/core/objects/sequence/changes/sequence.types.d.ts +2 -1
- package/dist/core/objects/sequence/sequence.diff.js +16 -0
- package/dist/core/objects/sequence/sequence.model.d.ts +10 -0
- package/dist/core/objects/sequence/sequence.model.js +19 -1
- package/dist/core/objects/subscription/changes/subscription.base.d.ts +1 -1
- package/dist/core/objects/subscription/changes/subscription.security-label.d.ts +28 -0
- package/dist/core/objects/subscription/changes/subscription.security-label.js +61 -0
- package/dist/core/objects/subscription/changes/subscription.types.d.ts +2 -1
- package/dist/core/objects/subscription/subscription.diff.js +16 -0
- package/dist/core/objects/subscription/subscription.model.d.ts +10 -0
- package/dist/core/objects/subscription/subscription.model.js +19 -1
- package/dist/core/objects/table/changes/table.base.d.ts +1 -1
- package/dist/core/objects/table/changes/table.security-label.d.ts +63 -0
- package/dist/core/objects/table/changes/table.security-label.js +134 -0
- package/dist/core/objects/table/changes/table.types.d.ts +2 -1
- package/dist/core/objects/table/table.diff.js +49 -0
- package/dist/core/objects/table/table.model.d.ts +30 -0
- package/dist/core/objects/table/table.model.js +34 -2
- package/dist/core/objects/type/composite-type/changes/composite-type.base.d.ts +1 -1
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.d.ts +28 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.js +61 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.types.d.ts +2 -1
- package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -0
- package/dist/core/objects/type/composite-type/composite-type.model.d.ts +22 -0
- package/dist/core/objects/type/composite-type/composite-type.model.js +22 -2
- package/dist/core/objects/type/enum/changes/enum.base.d.ts +1 -1
- package/dist/core/objects/type/enum/changes/enum.security-label.d.ts +28 -0
- package/dist/core/objects/type/enum/changes/enum.security-label.js +61 -0
- package/dist/core/objects/type/enum/changes/enum.types.d.ts +2 -1
- package/dist/core/objects/type/enum/enum.diff.js +16 -0
- package/dist/core/objects/type/enum/enum.model.d.ts +10 -0
- package/dist/core/objects/type/enum/enum.model.js +20 -1
- package/dist/core/objects/type/range/changes/range.base.d.ts +1 -1
- package/dist/core/objects/type/range/changes/range.security-label.d.ts +28 -0
- package/dist/core/objects/type/range/changes/range.security-label.js +61 -0
- package/dist/core/objects/type/range/changes/range.types.d.ts +2 -1
- package/dist/core/objects/type/range/range.diff.js +16 -0
- package/dist/core/objects/type/range/range.model.d.ts +10 -0
- package/dist/core/objects/type/range/range.model.js +19 -1
- package/dist/core/objects/utils.d.ts +1 -0
- package/dist/core/objects/utils.js +3 -0
- package/dist/core/objects/view/changes/view.base.d.ts +1 -1
- package/dist/core/objects/view/changes/view.security-label.d.ts +28 -0
- package/dist/core/objects/view/changes/view.security-label.js +61 -0
- package/dist/core/objects/view/changes/view.types.d.ts +2 -1
- package/dist/core/objects/view/view.diff.js +13 -0
- package/dist/core/objects/view/view.model.d.ts +26 -0
- package/dist/core/objects/view/view.model.js +20 -1
- package/dist/core/plan/sql-format/fixtures.js +1 -0
- package/package.json +1 -1
- package/src/core/catalog.model.ts +1 -0
- package/src/core/integrations/filter/dsl.test.ts +27 -0
- package/src/core/integrations/filter/flatten.ts +16 -0
- package/src/core/objects/aggregate/aggregate.diff.ts +33 -0
- package/src/core/objects/aggregate/aggregate.model.ts +22 -1
- package/src/core/objects/aggregate/changes/aggregate.base.ts +5 -1
- package/src/core/objects/aggregate/changes/aggregate.security-label.ts +99 -0
- package/src/core/objects/aggregate/changes/aggregate.types.ts +3 -1
- package/src/core/objects/base.model.ts +2 -0
- package/src/core/objects/domain/changes/domain.base.ts +5 -1
- package/src/core/objects/domain/changes/domain.security-label.test.ts +56 -0
- package/src/core/objects/domain/changes/domain.security-label.ts +77 -0
- package/src/core/objects/domain/changes/domain.types.ts +3 -1
- package/src/core/objects/domain/domain.diff.ts +33 -0
- package/src/core/objects/domain/domain.model.ts +22 -1
- package/src/core/objects/event-trigger/changes/event-trigger.base.ts +1 -1
- package/src/core/objects/event-trigger/changes/event-trigger.security-label.ts +95 -0
- package/src/core/objects/event-trigger/changes/event-trigger.types.ts +3 -1
- package/src/core/objects/event-trigger/event-trigger.diff.ts +33 -0
- package/src/core/objects/event-trigger/event-trigger.model.ts +22 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.ts +95 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +3 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +33 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +24 -1
- package/src/core/objects/materialized-view/changes/materialized-view.base.ts +5 -1
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.test.ts +63 -0
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.ts +95 -0
- package/src/core/objects/materialized-view/changes/materialized-view.types.ts +3 -1
- package/src/core/objects/materialized-view/materialized-view.diff.ts +37 -0
- package/src/core/objects/materialized-view/materialized-view.model.ts +25 -4
- package/src/core/objects/procedure/changes/procedure.base.ts +5 -1
- package/src/core/objects/procedure/changes/procedure.security-label.ts +105 -0
- package/src/core/objects/procedure/changes/procedure.types.ts +3 -1
- package/src/core/objects/procedure/procedure.diff.ts +33 -0
- package/src/core/objects/procedure/procedure.model.ts +23 -2
- package/src/core/objects/publication/changes/publication.base.ts +1 -1
- package/src/core/objects/publication/changes/publication.security-label.ts +95 -0
- package/src/core/objects/publication/changes/publication.types.ts +3 -1
- package/src/core/objects/publication/publication.diff.ts +33 -0
- package/src/core/objects/publication/publication.model.ts +24 -1
- package/src/core/objects/role/changes/role.base.ts +2 -1
- package/src/core/objects/role/changes/role.security-label.ts +77 -0
- package/src/core/objects/role/changes/role.types.ts +3 -1
- package/src/core/objects/role/role.diff.ts +33 -0
- package/src/core/objects/role/role.model.ts +32 -0
- package/src/core/objects/schema/changes/schema.alter.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.base.ts +5 -1
- package/src/core/objects/schema/changes/schema.create.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.drop.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.security-label.test.ts +76 -0
- package/src/core/objects/schema/changes/schema.security-label.ts +77 -0
- package/src/core/objects/schema/changes/schema.types.ts +3 -1
- package/src/core/objects/schema/schema.diff.test.ts +1 -0
- package/src/core/objects/schema/schema.diff.ts +43 -1
- package/src/core/objects/schema/schema.model.ts +21 -1
- package/src/core/objects/security-label.types.test.ts +106 -0
- package/src/core/objects/security-label.types.ts +61 -0
- package/src/core/objects/sequence/changes/sequence.base.ts +5 -1
- package/src/core/objects/sequence/changes/sequence.security-label.test.ts +58 -0
- package/src/core/objects/sequence/changes/sequence.security-label.ts +92 -0
- package/src/core/objects/sequence/changes/sequence.types.ts +3 -1
- package/src/core/objects/sequence/sequence.diff.ts +33 -0
- package/src/core/objects/sequence/sequence.model.ts +22 -1
- package/src/core/objects/subscription/changes/subscription.base.ts +1 -1
- package/src/core/objects/subscription/changes/subscription.security-label.ts +95 -0
- package/src/core/objects/subscription/changes/subscription.types.ts +3 -1
- package/src/core/objects/subscription/subscription.diff.ts +33 -0
- package/src/core/objects/subscription/subscription.model.ts +22 -1
- package/src/core/objects/table/changes/table.base.ts +5 -1
- package/src/core/objects/table/changes/table.security-label.test.ts +140 -0
- package/src/core/objects/table/changes/table.security-label.ts +183 -0
- package/src/core/objects/table/changes/table.types.ts +3 -1
- package/src/core/objects/table/table.diff.ts +87 -0
- package/src/core/objects/table/table.model.ts +42 -2
- package/src/core/objects/type/composite-type/changes/composite-type.base.ts +5 -1
- package/src/core/objects/type/composite-type/changes/composite-type.security-label.ts +95 -0
- package/src/core/objects/type/composite-type/changes/composite-type.types.ts +3 -1
- package/src/core/objects/type/composite-type/composite-type.diff.ts +33 -0
- package/src/core/objects/type/composite-type/composite-type.model.ts +26 -2
- package/src/core/objects/type/enum/changes/enum.base.ts +5 -1
- package/src/core/objects/type/enum/changes/enum.security-label.ts +77 -0
- package/src/core/objects/type/enum/changes/enum.types.ts +3 -1
- package/src/core/objects/type/enum/enum.diff.ts +33 -0
- package/src/core/objects/type/enum/enum.model.ts +25 -1
- package/src/core/objects/type/range/changes/range.base.ts +5 -1
- package/src/core/objects/type/range/changes/range.security-label.ts +77 -0
- package/src/core/objects/type/range/changes/range.types.ts +3 -1
- package/src/core/objects/type/range/range.diff.ts +33 -0
- package/src/core/objects/type/range/range.model.ts +22 -1
- package/src/core/objects/utils.ts +3 -0
- package/src/core/objects/view/changes/view.base.ts +5 -1
- package/src/core/objects/view/changes/view.security-label.test.ts +64 -0
- package/src/core/objects/view/changes/view.security-label.ts +77 -0
- package/src/core/objects/view/changes/view.types.ts +3 -1
- package/src/core/objects/view/view.diff.ts +31 -0
- package/src/core/objects/view/view.model.ts +25 -2
- package/src/core/plan/sql-format/fixtures.ts +1 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.ts";
|
|
2
2
|
import type { ObjectDiffContext } from "../diff-context.ts";
|
|
3
|
+
import { diffSecurityLabels } from "../security-label.types.ts";
|
|
3
4
|
import { hasNonAlterableChanges } from "../utils.ts";
|
|
4
5
|
import {
|
|
5
6
|
AlterSubscriptionDisable,
|
|
@@ -15,6 +16,10 @@ import {
|
|
|
15
16
|
} from "./changes/subscription.comment.ts";
|
|
16
17
|
import { CreateSubscription } from "./changes/subscription.create.ts";
|
|
17
18
|
import { DropSubscription } from "./changes/subscription.drop.ts";
|
|
19
|
+
import {
|
|
20
|
+
CreateSecurityLabelOnSubscription,
|
|
21
|
+
DropSecurityLabelOnSubscription,
|
|
22
|
+
} from "./changes/subscription.security-label.ts";
|
|
18
23
|
import type { SubscriptionChange } from "./changes/subscription.types.ts";
|
|
19
24
|
import type { Subscription } from "./subscription.model.ts";
|
|
20
25
|
import type { SubscriptionSettableOption } from "./utils.ts";
|
|
@@ -61,6 +66,14 @@ export function diffSubscriptions(
|
|
|
61
66
|
if (subscription.comment !== null) {
|
|
62
67
|
changes.push(new CreateCommentOnSubscription({ subscription }));
|
|
63
68
|
}
|
|
69
|
+
for (const label of subscription.security_labels) {
|
|
70
|
+
changes.push(
|
|
71
|
+
new CreateSecurityLabelOnSubscription({
|
|
72
|
+
subscription,
|
|
73
|
+
securityLabel: label,
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
64
77
|
}
|
|
65
78
|
|
|
66
79
|
for (const id of dropped) {
|
|
@@ -236,6 +249,26 @@ export function diffSubscriptions(
|
|
|
236
249
|
);
|
|
237
250
|
}
|
|
238
251
|
}
|
|
252
|
+
|
|
253
|
+
// SECURITY LABELS
|
|
254
|
+
changes.push(
|
|
255
|
+
...diffSecurityLabels<
|
|
256
|
+
CreateSecurityLabelOnSubscription | DropSecurityLabelOnSubscription
|
|
257
|
+
>(
|
|
258
|
+
mainSubscription.security_labels,
|
|
259
|
+
branchSubscription.security_labels,
|
|
260
|
+
(securityLabel) =>
|
|
261
|
+
new CreateSecurityLabelOnSubscription({
|
|
262
|
+
subscription: branchSubscription,
|
|
263
|
+
securityLabel,
|
|
264
|
+
}),
|
|
265
|
+
(securityLabel) =>
|
|
266
|
+
new DropSecurityLabelOnSubscription({
|
|
267
|
+
subscription: mainSubscription,
|
|
268
|
+
securityLabel,
|
|
269
|
+
}),
|
|
270
|
+
),
|
|
271
|
+
);
|
|
239
272
|
}
|
|
240
273
|
|
|
241
274
|
return changes;
|
|
@@ -2,6 +2,10 @@ import type { Pool } from "pg";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { extractVersion } from "../../context.ts";
|
|
4
4
|
import { BasePgModel } from "../base.model.ts";
|
|
5
|
+
import {
|
|
6
|
+
type SecurityLabelProps,
|
|
7
|
+
securityLabelPropsSchema,
|
|
8
|
+
} from "../security-label.types.ts";
|
|
5
9
|
|
|
6
10
|
const subscriptionPropsSchema = z.object({
|
|
7
11
|
name: z.string(),
|
|
@@ -23,6 +27,7 @@ const subscriptionPropsSchema = z.object({
|
|
|
23
27
|
synchronous_commit: z.string(),
|
|
24
28
|
publications: z.array(z.string()),
|
|
25
29
|
origin: z.enum(["any", "none"]),
|
|
30
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
26
31
|
});
|
|
27
32
|
|
|
28
33
|
export type SubscriptionProps = z.infer<typeof subscriptionPropsSchema>;
|
|
@@ -47,6 +52,7 @@ export class Subscription extends BasePgModel {
|
|
|
47
52
|
public readonly synchronous_commit: SubscriptionProps["synchronous_commit"];
|
|
48
53
|
public readonly publications: SubscriptionProps["publications"];
|
|
49
54
|
public readonly origin: SubscriptionProps["origin"];
|
|
55
|
+
public readonly security_labels: SecurityLabelProps[];
|
|
50
56
|
|
|
51
57
|
constructor(props: SubscriptionProps) {
|
|
52
58
|
super();
|
|
@@ -72,6 +78,7 @@ export class Subscription extends BasePgModel {
|
|
|
72
78
|
a.localeCompare(b),
|
|
73
79
|
);
|
|
74
80
|
this.origin = props.origin;
|
|
81
|
+
this.security_labels = props.security_labels ?? [];
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
get stableId(): `subscription:${string}` {
|
|
@@ -104,6 +111,7 @@ export class Subscription extends BasePgModel {
|
|
|
104
111
|
synchronous_commit: this.synchronous_commit,
|
|
105
112
|
publications: this.publications,
|
|
106
113
|
origin: this.origin,
|
|
114
|
+
security_labels: this.security_labels,
|
|
107
115
|
};
|
|
108
116
|
}
|
|
109
117
|
}
|
|
@@ -173,7 +181,20 @@ export async function extractSubscriptions(
|
|
|
173
181
|
),
|
|
174
182
|
'[]'::json
|
|
175
183
|
) as publications,
|
|
176
|
-
${originExpr} as origin
|
|
184
|
+
${originExpr} as origin,
|
|
185
|
+
coalesce(
|
|
186
|
+
(
|
|
187
|
+
select json_agg(
|
|
188
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
189
|
+
order by sl.provider
|
|
190
|
+
)
|
|
191
|
+
from pg_catalog.pg_seclabel sl
|
|
192
|
+
where sl.objoid = s.oid
|
|
193
|
+
and sl.classoid = 'pg_subscription'::regclass
|
|
194
|
+
and sl.objsubid = 0
|
|
195
|
+
),
|
|
196
|
+
'[]'::json
|
|
197
|
+
) as security_labels
|
|
177
198
|
from scoped_subscriptions s
|
|
178
199
|
left join pg_replication_slots r
|
|
179
200
|
on r.slot_name = s.subslotname
|
|
@@ -3,7 +3,11 @@ import type { Table } from "../table.model.ts";
|
|
|
3
3
|
|
|
4
4
|
abstract class BaseTableChange extends BaseChange {
|
|
5
5
|
abstract readonly table: Table;
|
|
6
|
-
abstract readonly scope:
|
|
6
|
+
abstract readonly scope:
|
|
7
|
+
| "object"
|
|
8
|
+
| "comment"
|
|
9
|
+
| "privilege"
|
|
10
|
+
| "security_label";
|
|
7
11
|
readonly objectType: "table" = "table";
|
|
8
12
|
}
|
|
9
13
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
|
|
3
|
+
import type { ColumnProps } from "../../base.model.ts";
|
|
4
|
+
import { stableId } from "../../utils.ts";
|
|
5
|
+
import { Table, type TableProps } from "../table.model.ts";
|
|
6
|
+
import {
|
|
7
|
+
CreateSecurityLabelOnColumn,
|
|
8
|
+
CreateSecurityLabelOnTable,
|
|
9
|
+
DropSecurityLabelOnColumn,
|
|
10
|
+
DropSecurityLabelOnTable,
|
|
11
|
+
} from "./table.security-label.ts";
|
|
12
|
+
|
|
13
|
+
const makeColumn = (overrides: Partial<ColumnProps> = {}): ColumnProps => ({
|
|
14
|
+
name: "id",
|
|
15
|
+
position: 1,
|
|
16
|
+
data_type: "integer",
|
|
17
|
+
data_type_str: "integer",
|
|
18
|
+
is_custom_type: false,
|
|
19
|
+
custom_type_type: null,
|
|
20
|
+
custom_type_category: null,
|
|
21
|
+
custom_type_schema: null,
|
|
22
|
+
custom_type_name: null,
|
|
23
|
+
not_null: false,
|
|
24
|
+
is_identity: false,
|
|
25
|
+
is_identity_always: false,
|
|
26
|
+
is_generated: false,
|
|
27
|
+
collation: null,
|
|
28
|
+
default: null,
|
|
29
|
+
comment: null,
|
|
30
|
+
...overrides,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const makeTable = (): Table =>
|
|
34
|
+
new Table({
|
|
35
|
+
schema: "public",
|
|
36
|
+
name: "users",
|
|
37
|
+
persistence: "p",
|
|
38
|
+
row_security: false,
|
|
39
|
+
force_row_security: false,
|
|
40
|
+
has_indexes: false,
|
|
41
|
+
has_rules: false,
|
|
42
|
+
has_triggers: false,
|
|
43
|
+
has_subclasses: false,
|
|
44
|
+
is_populated: true,
|
|
45
|
+
replica_identity: "d",
|
|
46
|
+
is_partition: false,
|
|
47
|
+
options: null,
|
|
48
|
+
partition_bound: null,
|
|
49
|
+
partition_by: null,
|
|
50
|
+
owner: "postgres",
|
|
51
|
+
comment: null,
|
|
52
|
+
parent_schema: null,
|
|
53
|
+
parent_name: null,
|
|
54
|
+
columns: [makeColumn({ name: "email" })],
|
|
55
|
+
privileges: [],
|
|
56
|
+
security_labels: [],
|
|
57
|
+
} as TableProps);
|
|
58
|
+
|
|
59
|
+
describe("table.security-label", () => {
|
|
60
|
+
test("table create serializes and tracks dependencies", async () => {
|
|
61
|
+
const table = makeTable();
|
|
62
|
+
const change = new CreateSecurityLabelOnTable({
|
|
63
|
+
table,
|
|
64
|
+
securityLabel: { provider: "dummy", label: "classified" },
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(change.scope).toBe("security_label");
|
|
68
|
+
expect(change.objectType).toBe("table");
|
|
69
|
+
expect(change.operation).toBe("create");
|
|
70
|
+
expect(change.creates).toEqual([
|
|
71
|
+
stableId.securityLabel(table.stableId, "dummy"),
|
|
72
|
+
]);
|
|
73
|
+
expect(change.requires).toEqual([table.stableId]);
|
|
74
|
+
await assertValidSql(change.serialize());
|
|
75
|
+
expect(change.serialize()).toBe(
|
|
76
|
+
"SECURITY LABEL FOR dummy ON TABLE public.users IS 'classified'",
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("table drop serializes to IS NULL", async () => {
|
|
81
|
+
const table = makeTable();
|
|
82
|
+
const change = new DropSecurityLabelOnTable({
|
|
83
|
+
table,
|
|
84
|
+
securityLabel: { provider: "dummy", label: "classified" },
|
|
85
|
+
});
|
|
86
|
+
expect(change.drops).toEqual([
|
|
87
|
+
stableId.securityLabel(table.stableId, "dummy"),
|
|
88
|
+
]);
|
|
89
|
+
expect(change.requires).toEqual([
|
|
90
|
+
stableId.securityLabel(table.stableId, "dummy"),
|
|
91
|
+
table.stableId,
|
|
92
|
+
]);
|
|
93
|
+
await assertValidSql(change.serialize());
|
|
94
|
+
expect(change.serialize()).toBe(
|
|
95
|
+
"SECURITY LABEL FOR dummy ON TABLE public.users IS NULL",
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("column create serializes and tracks dependencies", async () => {
|
|
100
|
+
const table = makeTable();
|
|
101
|
+
const column = makeColumn({ name: "email" });
|
|
102
|
+
const change = new CreateSecurityLabelOnColumn({
|
|
103
|
+
table,
|
|
104
|
+
column,
|
|
105
|
+
securityLabel: { provider: "dummy", label: "classified" },
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const colStableId = stableId.column(table.schema, table.name, column.name);
|
|
109
|
+
expect(change.creates).toEqual([
|
|
110
|
+
stableId.securityLabel(colStableId, "dummy"),
|
|
111
|
+
]);
|
|
112
|
+
expect(change.requires).toEqual([colStableId]);
|
|
113
|
+
await assertValidSql(change.serialize());
|
|
114
|
+
expect(change.serialize()).toBe(
|
|
115
|
+
"SECURITY LABEL FOR dummy ON COLUMN public.users.email IS 'classified'",
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("column drop serializes to IS NULL", async () => {
|
|
120
|
+
const table = makeTable();
|
|
121
|
+
const column = makeColumn({ name: "email" });
|
|
122
|
+
const change = new DropSecurityLabelOnColumn({
|
|
123
|
+
table,
|
|
124
|
+
column,
|
|
125
|
+
securityLabel: { provider: "dummy", label: "x" },
|
|
126
|
+
});
|
|
127
|
+
const colStableId = stableId.column(table.schema, table.name, column.name);
|
|
128
|
+
expect(change.drops).toEqual([
|
|
129
|
+
stableId.securityLabel(colStableId, "dummy"),
|
|
130
|
+
]);
|
|
131
|
+
expect(change.requires).toEqual([
|
|
132
|
+
stableId.securityLabel(colStableId, "dummy"),
|
|
133
|
+
colStableId,
|
|
134
|
+
]);
|
|
135
|
+
await assertValidSql(change.serialize());
|
|
136
|
+
expect(change.serialize()).toBe(
|
|
137
|
+
"SECURITY LABEL FOR dummy ON COLUMN public.users.email IS NULL",
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.ts";
|
|
2
|
+
import type { ColumnProps } from "../../base.model.ts";
|
|
3
|
+
import type { SecurityLabelProps } from "../../security-label.types.ts";
|
|
4
|
+
import { stableId } from "../../utils.ts";
|
|
5
|
+
import type { Table } from "../table.model.ts";
|
|
6
|
+
import { CreateTableChange, DropTableChange } from "./table.base.ts";
|
|
7
|
+
|
|
8
|
+
export type SecurityLabelTable =
|
|
9
|
+
| CreateSecurityLabelOnTable
|
|
10
|
+
| DropSecurityLabelOnTable
|
|
11
|
+
| CreateSecurityLabelOnColumn
|
|
12
|
+
| DropSecurityLabelOnColumn;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* SECURITY LABEL FOR <provider> ON TABLE <schema>.<table> IS <literal>
|
|
16
|
+
*/
|
|
17
|
+
export class CreateSecurityLabelOnTable extends CreateTableChange {
|
|
18
|
+
public readonly table: Table;
|
|
19
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
20
|
+
public readonly scope = "security_label" as const;
|
|
21
|
+
|
|
22
|
+
constructor(props: { table: Table; securityLabel: SecurityLabelProps }) {
|
|
23
|
+
super();
|
|
24
|
+
this.table = props.table;
|
|
25
|
+
this.securityLabel = props.securityLabel;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get creates() {
|
|
29
|
+
return [
|
|
30
|
+
stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get requires() {
|
|
35
|
+
return [this.table.stableId];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
serialize(): string {
|
|
39
|
+
return [
|
|
40
|
+
"SECURITY LABEL FOR",
|
|
41
|
+
this.securityLabel.provider,
|
|
42
|
+
"ON TABLE",
|
|
43
|
+
`${this.table.schema}.${this.table.name}`,
|
|
44
|
+
"IS",
|
|
45
|
+
quoteLiteral(this.securityLabel.label),
|
|
46
|
+
].join(" ");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class DropSecurityLabelOnTable extends DropTableChange {
|
|
51
|
+
public readonly table: Table;
|
|
52
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
53
|
+
public readonly scope = "security_label" as const;
|
|
54
|
+
|
|
55
|
+
constructor(props: { table: Table; securityLabel: SecurityLabelProps }) {
|
|
56
|
+
super();
|
|
57
|
+
this.table = props.table;
|
|
58
|
+
this.securityLabel = props.securityLabel;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get drops() {
|
|
62
|
+
return [
|
|
63
|
+
stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get requires() {
|
|
68
|
+
return [
|
|
69
|
+
stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
|
|
70
|
+
this.table.stableId,
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
serialize(): string {
|
|
75
|
+
return [
|
|
76
|
+
"SECURITY LABEL FOR",
|
|
77
|
+
this.securityLabel.provider,
|
|
78
|
+
"ON TABLE",
|
|
79
|
+
`${this.table.schema}.${this.table.name}`,
|
|
80
|
+
"IS NULL",
|
|
81
|
+
].join(" ");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* SECURITY LABEL FOR <provider> ON COLUMN <schema>.<table>.<column> IS <literal>
|
|
87
|
+
*/
|
|
88
|
+
export class CreateSecurityLabelOnColumn extends CreateTableChange {
|
|
89
|
+
public readonly table: Table;
|
|
90
|
+
public readonly column: ColumnProps;
|
|
91
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
92
|
+
public readonly scope = "security_label" as const;
|
|
93
|
+
|
|
94
|
+
constructor(props: {
|
|
95
|
+
table: Table;
|
|
96
|
+
column: ColumnProps;
|
|
97
|
+
securityLabel: SecurityLabelProps;
|
|
98
|
+
}) {
|
|
99
|
+
super();
|
|
100
|
+
this.table = props.table;
|
|
101
|
+
this.column = props.column;
|
|
102
|
+
this.securityLabel = props.securityLabel;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
get creates() {
|
|
106
|
+
const columnStableId = stableId.column(
|
|
107
|
+
this.table.schema,
|
|
108
|
+
this.table.name,
|
|
109
|
+
this.column.name,
|
|
110
|
+
);
|
|
111
|
+
return [
|
|
112
|
+
stableId.securityLabel(columnStableId, this.securityLabel.provider),
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
get requires() {
|
|
117
|
+
return [
|
|
118
|
+
stableId.column(this.table.schema, this.table.name, this.column.name),
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
serialize(): string {
|
|
123
|
+
return [
|
|
124
|
+
"SECURITY LABEL FOR",
|
|
125
|
+
this.securityLabel.provider,
|
|
126
|
+
"ON COLUMN",
|
|
127
|
+
`${this.table.schema}.${this.table.name}.${this.column.name}`,
|
|
128
|
+
"IS",
|
|
129
|
+
quoteLiteral(this.securityLabel.label),
|
|
130
|
+
].join(" ");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export class DropSecurityLabelOnColumn extends DropTableChange {
|
|
135
|
+
public readonly table: Table;
|
|
136
|
+
public readonly column: ColumnProps;
|
|
137
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
138
|
+
public readonly scope = "security_label" as const;
|
|
139
|
+
|
|
140
|
+
constructor(props: {
|
|
141
|
+
table: Table;
|
|
142
|
+
column: ColumnProps;
|
|
143
|
+
securityLabel: SecurityLabelProps;
|
|
144
|
+
}) {
|
|
145
|
+
super();
|
|
146
|
+
this.table = props.table;
|
|
147
|
+
this.column = props.column;
|
|
148
|
+
this.securityLabel = props.securityLabel;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
get drops() {
|
|
152
|
+
const columnStableId = stableId.column(
|
|
153
|
+
this.table.schema,
|
|
154
|
+
this.table.name,
|
|
155
|
+
this.column.name,
|
|
156
|
+
);
|
|
157
|
+
return [
|
|
158
|
+
stableId.securityLabel(columnStableId, this.securityLabel.provider),
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
get requires() {
|
|
163
|
+
const columnStableId = stableId.column(
|
|
164
|
+
this.table.schema,
|
|
165
|
+
this.table.name,
|
|
166
|
+
this.column.name,
|
|
167
|
+
);
|
|
168
|
+
return [
|
|
169
|
+
stableId.securityLabel(columnStableId, this.securityLabel.provider),
|
|
170
|
+
columnStableId,
|
|
171
|
+
];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
serialize(): string {
|
|
175
|
+
return [
|
|
176
|
+
"SECURITY LABEL FOR",
|
|
177
|
+
this.securityLabel.provider,
|
|
178
|
+
"ON COLUMN",
|
|
179
|
+
`${this.table.schema}.${this.table.name}.${this.column.name}`,
|
|
180
|
+
"IS NULL",
|
|
181
|
+
].join(" ");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { CommentTable } from "./table.comment.ts";
|
|
|
3
3
|
import type { CreateTable } from "./table.create.ts";
|
|
4
4
|
import type { DropTable } from "./table.drop.ts";
|
|
5
5
|
import type { TablePrivilege } from "./table.privilege.ts";
|
|
6
|
+
import type { SecurityLabelTable } from "./table.security-label.ts";
|
|
6
7
|
|
|
7
8
|
/** Union of all table-related change variants (`objectType: "table"`). @category Change Types */
|
|
8
9
|
export type TableChange =
|
|
@@ -10,4 +11,5 @@ export type TableChange =
|
|
|
10
11
|
| CommentTable
|
|
11
12
|
| CreateTable
|
|
12
13
|
| DropTable
|
|
13
|
-
| TablePrivilege
|
|
14
|
+
| TablePrivilege
|
|
15
|
+
| SecurityLabelTable;
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
emitColumnPrivilegeChanges,
|
|
5
5
|
} from "../base.privilege-diff.ts";
|
|
6
6
|
import type { ObjectDiffContext } from "../diff-context.ts";
|
|
7
|
+
import { diffSecurityLabels } from "../security-label.types.ts";
|
|
7
8
|
import { deepEqual } from "../utils.ts";
|
|
8
9
|
import {
|
|
9
10
|
AlterTableAddColumn,
|
|
@@ -47,6 +48,12 @@ import {
|
|
|
47
48
|
RevokeGrantOptionTablePrivileges,
|
|
48
49
|
RevokeTablePrivileges,
|
|
49
50
|
} from "./changes/table.privilege.ts";
|
|
51
|
+
import {
|
|
52
|
+
CreateSecurityLabelOnColumn,
|
|
53
|
+
CreateSecurityLabelOnTable,
|
|
54
|
+
DropSecurityLabelOnColumn,
|
|
55
|
+
DropSecurityLabelOnTable,
|
|
56
|
+
} from "./changes/table.security-label.ts";
|
|
50
57
|
import type { TableChange } from "./changes/table.types.ts";
|
|
51
58
|
import { Table } from "./table.model.ts";
|
|
52
59
|
|
|
@@ -279,6 +286,29 @@ export function diffTables(
|
|
|
279
286
|
}
|
|
280
287
|
}
|
|
281
288
|
|
|
289
|
+
// Table security labels on creation
|
|
290
|
+
for (const label of branchTable.security_labels) {
|
|
291
|
+
changes.push(
|
|
292
|
+
new CreateSecurityLabelOnTable({
|
|
293
|
+
table: branchTable,
|
|
294
|
+
securityLabel: label,
|
|
295
|
+
}),
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Column security labels on creation
|
|
300
|
+
for (const col of branchTable.columns) {
|
|
301
|
+
for (const label of col.security_labels ?? []) {
|
|
302
|
+
changes.push(
|
|
303
|
+
new CreateSecurityLabelOnColumn({
|
|
304
|
+
table: branchTable,
|
|
305
|
+
column: col,
|
|
306
|
+
securityLabel: label,
|
|
307
|
+
}),
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
282
312
|
// PRIVILEGES: For created objects, compare against default privileges state
|
|
283
313
|
// The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
|
|
284
314
|
// so objects are created with the default privileges state in effect.
|
|
@@ -440,6 +470,26 @@ export function diffTables(
|
|
|
440
470
|
}
|
|
441
471
|
}
|
|
442
472
|
|
|
473
|
+
// TABLE SECURITY LABELS
|
|
474
|
+
changes.push(
|
|
475
|
+
...diffSecurityLabels<
|
|
476
|
+
CreateSecurityLabelOnTable | DropSecurityLabelOnTable
|
|
477
|
+
>(
|
|
478
|
+
mainTable.security_labels,
|
|
479
|
+
branchTable.security_labels,
|
|
480
|
+
(securityLabel) =>
|
|
481
|
+
new CreateSecurityLabelOnTable({
|
|
482
|
+
table: branchTable,
|
|
483
|
+
securityLabel,
|
|
484
|
+
}),
|
|
485
|
+
(securityLabel) =>
|
|
486
|
+
new DropSecurityLabelOnTable({
|
|
487
|
+
table: mainTable,
|
|
488
|
+
securityLabel,
|
|
489
|
+
}),
|
|
490
|
+
),
|
|
491
|
+
);
|
|
492
|
+
|
|
443
493
|
// PARTITION ATTACH/DETACH
|
|
444
494
|
const mainIsPartition = Boolean(
|
|
445
495
|
mainTable.parent_schema && mainTable.parent_name,
|
|
@@ -886,6 +936,43 @@ export function diffTables(
|
|
|
886
936
|
);
|
|
887
937
|
}
|
|
888
938
|
}
|
|
939
|
+
|
|
940
|
+
// SECURITY LABELS on column
|
|
941
|
+
changes.push(
|
|
942
|
+
...diffSecurityLabels<
|
|
943
|
+
CreateSecurityLabelOnColumn | DropSecurityLabelOnColumn
|
|
944
|
+
>(
|
|
945
|
+
mainCol.security_labels ?? [],
|
|
946
|
+
branchCol.security_labels ?? [],
|
|
947
|
+
(securityLabel) =>
|
|
948
|
+
new CreateSecurityLabelOnColumn({
|
|
949
|
+
table: branchTable,
|
|
950
|
+
column: branchCol,
|
|
951
|
+
securityLabel,
|
|
952
|
+
}),
|
|
953
|
+
(securityLabel) =>
|
|
954
|
+
new DropSecurityLabelOnColumn({
|
|
955
|
+
table: mainTable,
|
|
956
|
+
column: mainCol,
|
|
957
|
+
securityLabel,
|
|
958
|
+
}),
|
|
959
|
+
),
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// Added columns with security labels (for created columns on existing tables)
|
|
964
|
+
for (const [name, col] of branchCols) {
|
|
965
|
+
if (!mainCols.has(name)) {
|
|
966
|
+
for (const label of col.security_labels ?? []) {
|
|
967
|
+
changes.push(
|
|
968
|
+
new CreateSecurityLabelOnColumn({
|
|
969
|
+
table: branchTable,
|
|
970
|
+
column: col,
|
|
971
|
+
securityLabel: label,
|
|
972
|
+
}),
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
889
976
|
}
|
|
890
977
|
|
|
891
978
|
// PRIVILEGES (unified object and column privileges)
|
|
@@ -16,6 +16,11 @@ import {
|
|
|
16
16
|
type ExtractRetryOptions,
|
|
17
17
|
extractWithDefinitionRetry,
|
|
18
18
|
} from "../extract-with-retry.ts";
|
|
19
|
+
import {
|
|
20
|
+
normalizeSecurityLabels,
|
|
21
|
+
type SecurityLabelProps,
|
|
22
|
+
securityLabelPropsSchema,
|
|
23
|
+
} from "../security-label.types.ts";
|
|
19
24
|
|
|
20
25
|
const RelationPersistenceSchema = z.enum([
|
|
21
26
|
"p", // permanent
|
|
@@ -119,6 +124,7 @@ const tablePropsSchema = z.object({
|
|
|
119
124
|
columns: z.array(columnPropsSchema),
|
|
120
125
|
constraints: z.array(tableConstraintPropsSchema).optional(),
|
|
121
126
|
privileges: z.array(privilegePropsSchema),
|
|
127
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
122
128
|
});
|
|
123
129
|
|
|
124
130
|
const tableRowSchema = tablePropsSchema.extend({
|
|
@@ -126,6 +132,10 @@ const tableRowSchema = tablePropsSchema.extend({
|
|
|
126
132
|
});
|
|
127
133
|
|
|
128
134
|
type TablePrivilegeProps = PrivilegeProps;
|
|
135
|
+
/**
|
|
136
|
+
* Table input props. `security_labels` is optional on direct construction
|
|
137
|
+
* (defaults to `[]`); extraction always produces it via the Zod default.
|
|
138
|
+
*/
|
|
129
139
|
export type TableProps = z.infer<typeof tablePropsSchema>;
|
|
130
140
|
type TableRow = z.infer<typeof tableRowSchema>;
|
|
131
141
|
|
|
@@ -153,6 +163,7 @@ export class Table extends BasePgModel implements TableLikeObject {
|
|
|
153
163
|
public readonly columns: TableProps["columns"];
|
|
154
164
|
public readonly constraints: TableConstraintProps[];
|
|
155
165
|
public readonly privileges: TablePrivilegeProps[];
|
|
166
|
+
public readonly security_labels: SecurityLabelProps[];
|
|
156
167
|
|
|
157
168
|
constructor(props: TableProps) {
|
|
158
169
|
super();
|
|
@@ -183,6 +194,7 @@ export class Table extends BasePgModel implements TableLikeObject {
|
|
|
183
194
|
this.columns = props.columns;
|
|
184
195
|
this.constraints = props.constraints ?? [];
|
|
185
196
|
this.privileges = props.privileges;
|
|
197
|
+
this.security_labels = props.security_labels ?? [];
|
|
186
198
|
}
|
|
187
199
|
|
|
188
200
|
get stableId(): `table:${string}` {
|
|
@@ -214,6 +226,7 @@ export class Table extends BasePgModel implements TableLikeObject {
|
|
|
214
226
|
columns: this.columns,
|
|
215
227
|
constraints: this.constraints,
|
|
216
228
|
privileges: this.privileges,
|
|
229
|
+
security_labels: this.security_labels,
|
|
217
230
|
};
|
|
218
231
|
}
|
|
219
232
|
|
|
@@ -233,6 +246,7 @@ export class Table extends BasePgModel implements TableLikeObject {
|
|
|
233
246
|
options: this.options ? [...this.options].sort() : this.options,
|
|
234
247
|
constraints: normalizeConstraints(),
|
|
235
248
|
privileges: normalizePrivileges(this.privileges),
|
|
249
|
+
security_labels: normalizeSecurityLabels(this.security_labels),
|
|
236
250
|
},
|
|
237
251
|
};
|
|
238
252
|
}
|
|
@@ -446,7 +460,20 @@ select
|
|
|
446
460
|
and a.attcollation <> t2.typcollation
|
|
447
461
|
),
|
|
448
462
|
'default', pg_get_expr(ad.adbin, ad.adrelid),
|
|
449
|
-
'comment', col_description(a.attrelid, a.attnum)
|
|
463
|
+
'comment', col_description(a.attrelid, a.attnum),
|
|
464
|
+
'security_labels', coalesce(
|
|
465
|
+
(
|
|
466
|
+
select json_agg(
|
|
467
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
468
|
+
order by sl.provider
|
|
469
|
+
)
|
|
470
|
+
from pg_catalog.pg_seclabel sl
|
|
471
|
+
where sl.objoid = t.oid
|
|
472
|
+
and sl.classoid = 'pg_class'::regclass
|
|
473
|
+
and sl.objsubid = a.attnum
|
|
474
|
+
),
|
|
475
|
+
'[]'::json
|
|
476
|
+
)
|
|
450
477
|
)
|
|
451
478
|
end
|
|
452
479
|
order by a.attnum
|
|
@@ -486,7 +513,20 @@ select
|
|
|
486
513
|
join lateral aclexplode(src.acl) as x(grantor, grantee, privilege_type, is_grantable) on true
|
|
487
514
|
group by x.grantee, x.privilege_type
|
|
488
515
|
) as grp
|
|
489
|
-
), '[]') as privileges
|
|
516
|
+
), '[]') as privileges,
|
|
517
|
+
coalesce(
|
|
518
|
+
(
|
|
519
|
+
select json_agg(
|
|
520
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
521
|
+
order by sl.provider
|
|
522
|
+
)
|
|
523
|
+
from pg_catalog.pg_seclabel sl
|
|
524
|
+
where sl.objoid = t.oid
|
|
525
|
+
and sl.classoid = 'pg_class'::regclass
|
|
526
|
+
and sl.objsubid = 0
|
|
527
|
+
),
|
|
528
|
+
'[]'::json
|
|
529
|
+
) as security_labels
|
|
490
530
|
from
|
|
491
531
|
tables t
|
|
492
532
|
left join pg_attribute a on a.attrelid = t.oid and a.attnum > 0 and not a.attisdropped
|