@supabase/pg-delta 1.0.0-alpha.22 → 1.0.0-alpha.24
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/dist/core/post-diff-normalization.d.ts +7 -0
- package/dist/core/post-diff-normalization.js +33 -4
- package/dist/core/sort/cycle-breakers.js +139 -17
- 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
- package/src/core/post-diff-normalization.test.ts +123 -0
- package/src/core/post-diff-normalization.ts +40 -4
- package/src/core/sort/cycle-breakers.test.ts +236 -2
- package/src/core/sort/cycle-breakers.ts +184 -24
- package/src/core/sort/sort-changes.test.ts +317 -0
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
type PrivilegeProps,
|
|
7
7
|
privilegePropsSchema,
|
|
8
8
|
} from "../../base.privilege-diff.ts";
|
|
9
|
+
import {
|
|
10
|
+
type SecurityLabelProps,
|
|
11
|
+
securityLabelPropsSchema,
|
|
12
|
+
} from "../../security-label.types.ts";
|
|
9
13
|
|
|
10
14
|
const enumLabelSchema = z.object({
|
|
11
15
|
sort_order: z.number(),
|
|
@@ -33,6 +37,7 @@ const enumPropsSchema = z.object({
|
|
|
33
37
|
labels: z.array(enumLabelSchema),
|
|
34
38
|
comment: z.string().nullable(),
|
|
35
39
|
privileges: z.array(privilegePropsSchema),
|
|
40
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
36
41
|
});
|
|
37
42
|
|
|
38
43
|
type EnumPrivilegeProps = PrivilegeProps;
|
|
@@ -45,6 +50,7 @@ export class Enum extends BasePgModel {
|
|
|
45
50
|
public readonly labels: EnumProps["labels"];
|
|
46
51
|
public readonly comment: EnumProps["comment"];
|
|
47
52
|
public readonly privileges: EnumPrivilegeProps[];
|
|
53
|
+
public readonly security_labels: SecurityLabelProps[];
|
|
48
54
|
|
|
49
55
|
constructor(props: EnumProps) {
|
|
50
56
|
super();
|
|
@@ -58,6 +64,7 @@ export class Enum extends BasePgModel {
|
|
|
58
64
|
this.labels = props.labels;
|
|
59
65
|
this.comment = props.comment;
|
|
60
66
|
this.privileges = props.privileges;
|
|
67
|
+
this.security_labels = props.security_labels ?? [];
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
get stableId(): `type:${string}` {
|
|
@@ -105,6 +112,7 @@ export class Enum extends BasePgModel {
|
|
|
105
112
|
labels,
|
|
106
113
|
comment: this.comment,
|
|
107
114
|
privileges,
|
|
115
|
+
security_labels: this.security_labels,
|
|
108
116
|
};
|
|
109
117
|
}
|
|
110
118
|
}
|
|
@@ -118,6 +126,7 @@ export async function extractEnums(pool: Pool): Promise<Enum[]> {
|
|
|
118
126
|
owner: string;
|
|
119
127
|
comment: string | null;
|
|
120
128
|
privileges: { grantee: string; privilege: string; grantable: boolean }[];
|
|
129
|
+
security_labels: { provider: string; label: string }[];
|
|
121
130
|
}>(sql`
|
|
122
131
|
with extension_oids as (
|
|
123
132
|
select
|
|
@@ -147,7 +156,20 @@ select
|
|
|
147
156
|
)
|
|
148
157
|
from lateral aclexplode(COALESCE(t.typacl, acldefault('T', t.typowner))) as x(grantor, grantee, privilege_type, is_grantable)
|
|
149
158
|
), '[]'
|
|
150
|
-
) as privileges
|
|
159
|
+
) as privileges,
|
|
160
|
+
coalesce(
|
|
161
|
+
(
|
|
162
|
+
select json_agg(
|
|
163
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
164
|
+
order by sl.provider
|
|
165
|
+
)
|
|
166
|
+
from pg_catalog.pg_seclabel sl
|
|
167
|
+
where sl.objoid = t.oid
|
|
168
|
+
and sl.classoid = 'pg_type'::regclass
|
|
169
|
+
and sl.objsubid = 0
|
|
170
|
+
),
|
|
171
|
+
'[]'::json
|
|
172
|
+
) as security_labels
|
|
151
173
|
from
|
|
152
174
|
pg_catalog.pg_enum e
|
|
153
175
|
inner join pg_catalog.pg_type t on t.oid = e.enumtypid
|
|
@@ -170,6 +192,7 @@ order by
|
|
|
170
192
|
privilege: string;
|
|
171
193
|
grantable: boolean;
|
|
172
194
|
}[];
|
|
195
|
+
security_labels: { provider: string; label: string }[];
|
|
173
196
|
}
|
|
174
197
|
> = {};
|
|
175
198
|
for (const e of enumRows) {
|
|
@@ -182,6 +205,7 @@ order by
|
|
|
182
205
|
labels: [],
|
|
183
206
|
comment: e.comment,
|
|
184
207
|
privileges: e.privileges,
|
|
208
|
+
security_labels: e.security_labels,
|
|
185
209
|
};
|
|
186
210
|
}
|
|
187
211
|
grouped[key].labels.push({ sort_order: e.sort_order, label: e.label });
|
|
@@ -3,7 +3,11 @@ import type { Range } from "../range.model.ts";
|
|
|
3
3
|
|
|
4
4
|
abstract class BaseRangeChange extends BaseChange {
|
|
5
5
|
abstract readonly range: Range;
|
|
6
|
-
abstract readonly scope:
|
|
6
|
+
abstract readonly scope:
|
|
7
|
+
| "object"
|
|
8
|
+
| "comment"
|
|
9
|
+
| "privilege"
|
|
10
|
+
| "security_label";
|
|
7
11
|
readonly objectType: "range" = "range";
|
|
8
12
|
}
|
|
9
13
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../../base.change.ts";
|
|
2
|
+
import type { SecurityLabelProps } from "../../../security-label.types.ts";
|
|
3
|
+
import { stableId } from "../../../utils.ts";
|
|
4
|
+
import type { Range } from "../range.model.ts";
|
|
5
|
+
import { CreateRangeChange, DropRangeChange } from "./range.base.ts";
|
|
6
|
+
|
|
7
|
+
export type SecurityLabelRange =
|
|
8
|
+
| CreateSecurityLabelOnRange
|
|
9
|
+
| DropSecurityLabelOnRange;
|
|
10
|
+
|
|
11
|
+
export class CreateSecurityLabelOnRange extends CreateRangeChange {
|
|
12
|
+
public readonly range: Range;
|
|
13
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
14
|
+
public readonly scope = "security_label" as const;
|
|
15
|
+
|
|
16
|
+
constructor(props: { range: Range; securityLabel: SecurityLabelProps }) {
|
|
17
|
+
super();
|
|
18
|
+
this.range = props.range;
|
|
19
|
+
this.securityLabel = props.securityLabel;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get creates() {
|
|
23
|
+
return [
|
|
24
|
+
stableId.securityLabel(this.range.stableId, this.securityLabel.provider),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get requires() {
|
|
29
|
+
return [this.range.stableId];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
serialize(): string {
|
|
33
|
+
return [
|
|
34
|
+
"SECURITY LABEL FOR",
|
|
35
|
+
this.securityLabel.provider,
|
|
36
|
+
"ON TYPE",
|
|
37
|
+
`${this.range.schema}.${this.range.name}`,
|
|
38
|
+
"IS",
|
|
39
|
+
quoteLiteral(this.securityLabel.label),
|
|
40
|
+
].join(" ");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class DropSecurityLabelOnRange extends DropRangeChange {
|
|
45
|
+
public readonly range: Range;
|
|
46
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
47
|
+
public readonly scope = "security_label" as const;
|
|
48
|
+
|
|
49
|
+
constructor(props: { range: Range; securityLabel: SecurityLabelProps }) {
|
|
50
|
+
super();
|
|
51
|
+
this.range = props.range;
|
|
52
|
+
this.securityLabel = props.securityLabel;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get drops() {
|
|
56
|
+
return [
|
|
57
|
+
stableId.securityLabel(this.range.stableId, this.securityLabel.provider),
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get requires() {
|
|
62
|
+
return [
|
|
63
|
+
stableId.securityLabel(this.range.stableId, this.securityLabel.provider),
|
|
64
|
+
this.range.stableId,
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
serialize(): string {
|
|
69
|
+
return [
|
|
70
|
+
"SECURITY LABEL FOR",
|
|
71
|
+
this.securityLabel.provider,
|
|
72
|
+
"ON TYPE",
|
|
73
|
+
`${this.range.schema}.${this.range.name}`,
|
|
74
|
+
"IS NULL",
|
|
75
|
+
].join(" ");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { CommentRange } from "./range.comment.ts";
|
|
|
3
3
|
import type { CreateRange } from "./range.create.ts";
|
|
4
4
|
import type { DropRange } from "./range.drop.ts";
|
|
5
5
|
import type { RangePrivilege } from "./range.privilege.ts";
|
|
6
|
+
import type { SecurityLabelRange } from "./range.security-label.ts";
|
|
6
7
|
|
|
7
8
|
/** Union of all range-related change variants (`objectType: "range"`). @category Change Types */
|
|
8
9
|
export type RangeChange =
|
|
@@ -10,4 +11,5 @@ export type RangeChange =
|
|
|
10
11
|
| CommentRange
|
|
11
12
|
| CreateRange
|
|
12
13
|
| DropRange
|
|
13
|
-
| RangePrivilege
|
|
14
|
+
| RangePrivilege
|
|
15
|
+
| SecurityLabelRange;
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
filterPublicBuiltInDefaults,
|
|
6
6
|
} from "../../base.privilege-diff.ts";
|
|
7
7
|
import type { ObjectDiffContext } from "../../diff-context.ts";
|
|
8
|
+
import { diffSecurityLabels } from "../../security-label.types.ts";
|
|
8
9
|
import { hasNonAlterableChanges } from "../../utils.ts";
|
|
9
10
|
import { AlterRangeChangeOwner } from "./changes/range.alter.ts";
|
|
10
11
|
import {
|
|
@@ -18,6 +19,10 @@ import {
|
|
|
18
19
|
RevokeGrantOptionRangePrivileges,
|
|
19
20
|
RevokeRangePrivileges,
|
|
20
21
|
} from "./changes/range.privilege.ts";
|
|
22
|
+
import {
|
|
23
|
+
CreateSecurityLabelOnRange,
|
|
24
|
+
DropSecurityLabelOnRange,
|
|
25
|
+
} from "./changes/range.security-label.ts";
|
|
21
26
|
import type { RangeChange } from "./changes/range.types.ts";
|
|
22
27
|
import type { Range } from "./range.model.ts";
|
|
23
28
|
|
|
@@ -59,6 +64,14 @@ export function diffRanges(
|
|
|
59
64
|
if (createdRange.comment !== null) {
|
|
60
65
|
changes.push(new CreateCommentOnRange({ range: createdRange }));
|
|
61
66
|
}
|
|
67
|
+
for (const label of createdRange.security_labels) {
|
|
68
|
+
changes.push(
|
|
69
|
+
new CreateSecurityLabelOnRange({
|
|
70
|
+
range: createdRange,
|
|
71
|
+
securityLabel: label,
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
}
|
|
62
75
|
|
|
63
76
|
// PRIVILEGES: For created objects, compare against default privileges state
|
|
64
77
|
// The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
|
|
@@ -156,6 +169,26 @@ export function diffRanges(
|
|
|
156
169
|
}
|
|
157
170
|
}
|
|
158
171
|
|
|
172
|
+
// SECURITY LABELS
|
|
173
|
+
changes.push(
|
|
174
|
+
...diffSecurityLabels<
|
|
175
|
+
CreateSecurityLabelOnRange | DropSecurityLabelOnRange
|
|
176
|
+
>(
|
|
177
|
+
mainRange.security_labels,
|
|
178
|
+
branchRange.security_labels,
|
|
179
|
+
(securityLabel) =>
|
|
180
|
+
new CreateSecurityLabelOnRange({
|
|
181
|
+
range: branchRange,
|
|
182
|
+
securityLabel,
|
|
183
|
+
}),
|
|
184
|
+
(securityLabel) =>
|
|
185
|
+
new DropSecurityLabelOnRange({
|
|
186
|
+
range: mainRange,
|
|
187
|
+
securityLabel,
|
|
188
|
+
}),
|
|
189
|
+
),
|
|
190
|
+
);
|
|
191
|
+
|
|
159
192
|
// PRIVILEGES
|
|
160
193
|
// Filter out PUBLIC's built-in default USAGE privilege from main catalog
|
|
161
194
|
// (PostgreSQL grants it automatically, so we shouldn't compare it)
|
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
type PrivilegeProps,
|
|
7
7
|
privilegePropsSchema,
|
|
8
8
|
} from "../../base.privilege-diff.ts";
|
|
9
|
+
import {
|
|
10
|
+
type SecurityLabelProps,
|
|
11
|
+
securityLabelPropsSchema,
|
|
12
|
+
} from "../../security-label.types.ts";
|
|
9
13
|
|
|
10
14
|
const rangePropsSchema = z.object({
|
|
11
15
|
schema: z.string(),
|
|
@@ -30,6 +34,7 @@ const rangePropsSchema = z.object({
|
|
|
30
34
|
subtype_opclass_schema: z.string().nullable(),
|
|
31
35
|
subtype_opclass_name: z.string().nullable(),
|
|
32
36
|
privileges: z.array(privilegePropsSchema),
|
|
37
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
33
38
|
});
|
|
34
39
|
|
|
35
40
|
type RangePrivilegeProps = PrivilegeProps;
|
|
@@ -54,6 +59,7 @@ export class Range extends BasePgModel {
|
|
|
54
59
|
public readonly subtype_opclass_schema: RangeProps["subtype_opclass_schema"];
|
|
55
60
|
public readonly subtype_opclass_name: RangeProps["subtype_opclass_name"];
|
|
56
61
|
public readonly privileges: RangePrivilegeProps[];
|
|
62
|
+
public readonly security_labels: SecurityLabelProps[];
|
|
57
63
|
|
|
58
64
|
constructor(props: RangeProps) {
|
|
59
65
|
super();
|
|
@@ -75,6 +81,7 @@ export class Range extends BasePgModel {
|
|
|
75
81
|
this.subtype_opclass_schema = props.subtype_opclass_schema;
|
|
76
82
|
this.subtype_opclass_name = props.subtype_opclass_name;
|
|
77
83
|
this.privileges = props.privileges;
|
|
84
|
+
this.security_labels = props.security_labels ?? [];
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
get stableId(): `type:${string}` {
|
|
@@ -102,6 +109,7 @@ export class Range extends BasePgModel {
|
|
|
102
109
|
subtype_opclass_name: this.subtype_opclass_name,
|
|
103
110
|
comment: this.comment,
|
|
104
111
|
privileges: this.privileges,
|
|
112
|
+
security_labels: this.security_labels,
|
|
105
113
|
};
|
|
106
114
|
}
|
|
107
115
|
}
|
|
@@ -166,7 +174,20 @@ select
|
|
|
166
174
|
)
|
|
167
175
|
from lateral aclexplode(COALESCE(t.typacl, acldefault('T', t.typowner))) as x(grantor, grantee, privilege_type, is_grantable)
|
|
168
176
|
), '[]'
|
|
169
|
-
) as privileges
|
|
177
|
+
) as privileges,
|
|
178
|
+
coalesce(
|
|
179
|
+
(
|
|
180
|
+
select json_agg(
|
|
181
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
182
|
+
order by sl.provider
|
|
183
|
+
)
|
|
184
|
+
from pg_catalog.pg_seclabel sl
|
|
185
|
+
where sl.objoid = t.oid
|
|
186
|
+
and sl.classoid = 'pg_type'::regclass
|
|
187
|
+
and sl.objsubid = 0
|
|
188
|
+
),
|
|
189
|
+
'[]'::json
|
|
190
|
+
) as security_labels
|
|
170
191
|
from pg_catalog.pg_range r
|
|
171
192
|
join pg_catalog.pg_type t on t.oid = r.rngtypid
|
|
172
193
|
join pg_catalog.pg_type subt on subt.oid = r.rngsubtype
|
|
@@ -77,6 +77,9 @@ export const stableId = {
|
|
|
77
77
|
comment(objectStableId: string) {
|
|
78
78
|
return `comment:${objectStableId}` as const;
|
|
79
79
|
},
|
|
80
|
+
securityLabel(objectStableId: string, provider: string) {
|
|
81
|
+
return `securityLabel:${objectStableId}::provider:${provider}` as const;
|
|
82
|
+
},
|
|
80
83
|
role(role: string) {
|
|
81
84
|
return `role:${role}` as const;
|
|
82
85
|
},
|
|
@@ -3,7 +3,11 @@ import type { View } from "../view.model.ts";
|
|
|
3
3
|
|
|
4
4
|
abstract class BaseViewChange extends BaseChange {
|
|
5
5
|
abstract readonly view: View;
|
|
6
|
-
abstract readonly scope:
|
|
6
|
+
abstract readonly scope:
|
|
7
|
+
| "object"
|
|
8
|
+
| "comment"
|
|
9
|
+
| "privilege"
|
|
10
|
+
| "security_label";
|
|
7
11
|
readonly objectType: "view" = "view";
|
|
8
12
|
}
|
|
9
13
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
|
|
3
|
+
import { stableId } from "../../utils.ts";
|
|
4
|
+
import { View, type ViewProps } from "../view.model.ts";
|
|
5
|
+
import {
|
|
6
|
+
CreateSecurityLabelOnView,
|
|
7
|
+
DropSecurityLabelOnView,
|
|
8
|
+
} from "./view.security-label.ts";
|
|
9
|
+
|
|
10
|
+
const makeView = (): View =>
|
|
11
|
+
new View({
|
|
12
|
+
schema: "public",
|
|
13
|
+
name: "v",
|
|
14
|
+
definition: "SELECT 1",
|
|
15
|
+
row_security: false,
|
|
16
|
+
force_row_security: false,
|
|
17
|
+
has_indexes: false,
|
|
18
|
+
has_rules: false,
|
|
19
|
+
has_triggers: false,
|
|
20
|
+
has_subclasses: false,
|
|
21
|
+
is_populated: true,
|
|
22
|
+
replica_identity: "d",
|
|
23
|
+
is_partition: false,
|
|
24
|
+
options: null,
|
|
25
|
+
partition_bound: null,
|
|
26
|
+
owner: "postgres",
|
|
27
|
+
comment: null,
|
|
28
|
+
columns: [],
|
|
29
|
+
privileges: [],
|
|
30
|
+
} as ViewProps);
|
|
31
|
+
|
|
32
|
+
describe("view.security-label", () => {
|
|
33
|
+
test("create serializes and tracks dependencies", async () => {
|
|
34
|
+
const view = makeView();
|
|
35
|
+
const change = new CreateSecurityLabelOnView({
|
|
36
|
+
view,
|
|
37
|
+
securityLabel: { provider: "dummy", label: "classified" },
|
|
38
|
+
});
|
|
39
|
+
expect(change.scope).toBe("security_label");
|
|
40
|
+
expect(change.creates).toEqual([
|
|
41
|
+
stableId.securityLabel(view.stableId, "dummy"),
|
|
42
|
+
]);
|
|
43
|
+
expect(change.requires).toEqual([view.stableId]);
|
|
44
|
+
await assertValidSql(change.serialize());
|
|
45
|
+
expect(change.serialize()).toBe(
|
|
46
|
+
"SECURITY LABEL FOR dummy ON VIEW public.v IS 'classified'",
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("drop serializes to IS NULL", async () => {
|
|
51
|
+
const view = makeView();
|
|
52
|
+
const change = new DropSecurityLabelOnView({
|
|
53
|
+
view,
|
|
54
|
+
securityLabel: { provider: "dummy", label: "classified" },
|
|
55
|
+
});
|
|
56
|
+
expect(change.drops).toEqual([
|
|
57
|
+
stableId.securityLabel(view.stableId, "dummy"),
|
|
58
|
+
]);
|
|
59
|
+
await assertValidSql(change.serialize());
|
|
60
|
+
expect(change.serialize()).toBe(
|
|
61
|
+
"SECURITY LABEL FOR dummy ON VIEW public.v IS NULL",
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.ts";
|
|
2
|
+
import type { SecurityLabelProps } from "../../security-label.types.ts";
|
|
3
|
+
import { stableId } from "../../utils.ts";
|
|
4
|
+
import type { View } from "../view.model.ts";
|
|
5
|
+
import { CreateViewChange, DropViewChange } from "./view.base.ts";
|
|
6
|
+
|
|
7
|
+
export type SecurityLabelView =
|
|
8
|
+
| CreateSecurityLabelOnView
|
|
9
|
+
| DropSecurityLabelOnView;
|
|
10
|
+
|
|
11
|
+
export class CreateSecurityLabelOnView extends CreateViewChange {
|
|
12
|
+
public readonly view: View;
|
|
13
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
14
|
+
public readonly scope = "security_label" as const;
|
|
15
|
+
|
|
16
|
+
constructor(props: { view: View; securityLabel: SecurityLabelProps }) {
|
|
17
|
+
super();
|
|
18
|
+
this.view = props.view;
|
|
19
|
+
this.securityLabel = props.securityLabel;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get creates() {
|
|
23
|
+
return [
|
|
24
|
+
stableId.securityLabel(this.view.stableId, this.securityLabel.provider),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get requires() {
|
|
29
|
+
return [this.view.stableId];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
serialize(): string {
|
|
33
|
+
return [
|
|
34
|
+
"SECURITY LABEL FOR",
|
|
35
|
+
this.securityLabel.provider,
|
|
36
|
+
"ON VIEW",
|
|
37
|
+
`${this.view.schema}.${this.view.name}`,
|
|
38
|
+
"IS",
|
|
39
|
+
quoteLiteral(this.securityLabel.label),
|
|
40
|
+
].join(" ");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class DropSecurityLabelOnView extends DropViewChange {
|
|
45
|
+
public readonly view: View;
|
|
46
|
+
public readonly securityLabel: SecurityLabelProps;
|
|
47
|
+
public readonly scope = "security_label" as const;
|
|
48
|
+
|
|
49
|
+
constructor(props: { view: View; securityLabel: SecurityLabelProps }) {
|
|
50
|
+
super();
|
|
51
|
+
this.view = props.view;
|
|
52
|
+
this.securityLabel = props.securityLabel;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get drops() {
|
|
56
|
+
return [
|
|
57
|
+
stableId.securityLabel(this.view.stableId, this.securityLabel.provider),
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get requires() {
|
|
62
|
+
return [
|
|
63
|
+
stableId.securityLabel(this.view.stableId, this.securityLabel.provider),
|
|
64
|
+
this.view.stableId,
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
serialize(): string {
|
|
69
|
+
return [
|
|
70
|
+
"SECURITY LABEL FOR",
|
|
71
|
+
this.securityLabel.provider,
|
|
72
|
+
"ON VIEW",
|
|
73
|
+
`${this.view.schema}.${this.view.name}`,
|
|
74
|
+
"IS NULL",
|
|
75
|
+
].join(" ");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { CommentView } from "./view.comment.ts";
|
|
|
3
3
|
import type { CreateView } from "./view.create.ts";
|
|
4
4
|
import type { DropView } from "./view.drop.ts";
|
|
5
5
|
import type { ViewPrivilege } from "./view.privilege.ts";
|
|
6
|
+
import type { SecurityLabelView } from "./view.security-label.ts";
|
|
6
7
|
|
|
7
8
|
/** Union of all view-related change variants (`objectType: "view"`). @category Change Types */
|
|
8
9
|
export type ViewChange =
|
|
@@ -10,4 +11,5 @@ export type ViewChange =
|
|
|
10
11
|
| CommentView
|
|
11
12
|
| CreateView
|
|
12
13
|
| DropView
|
|
13
|
-
| ViewPrivilege
|
|
14
|
+
| ViewPrivilege
|
|
15
|
+
| SecurityLabelView;
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
emitColumnPrivilegeChanges,
|
|
6
6
|
} from "../base.privilege-diff.ts";
|
|
7
7
|
import type { ObjectDiffContext } from "../diff-context.ts";
|
|
8
|
+
import { diffSecurityLabels } from "../security-label.types.ts";
|
|
8
9
|
import { deepEqual, hasNonAlterableChanges } from "../utils.ts";
|
|
9
10
|
import {
|
|
10
11
|
AlterViewChangeOwner,
|
|
@@ -22,6 +23,10 @@ import {
|
|
|
22
23
|
RevokeGrantOptionViewPrivileges,
|
|
23
24
|
RevokeViewPrivileges,
|
|
24
25
|
} from "./changes/view.privilege.ts";
|
|
26
|
+
import {
|
|
27
|
+
CreateSecurityLabelOnView,
|
|
28
|
+
DropSecurityLabelOnView,
|
|
29
|
+
} from "./changes/view.security-label.ts";
|
|
25
30
|
import type { ViewChange } from "./changes/view.types.ts";
|
|
26
31
|
import type { View } from "./view.model.ts";
|
|
27
32
|
|
|
@@ -57,6 +62,12 @@ export function diffViews(
|
|
|
57
62
|
changes.push(new CreateCommentOnView({ view }));
|
|
58
63
|
}
|
|
59
64
|
|
|
65
|
+
for (const label of view.security_labels) {
|
|
66
|
+
changes.push(
|
|
67
|
+
new CreateSecurityLabelOnView({ view, securityLabel: label }),
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
60
71
|
// PRIVILEGES: For created objects, compare against default privileges state
|
|
61
72
|
// The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
|
|
62
73
|
// so objects are created with the default privileges state in effect.
|
|
@@ -195,6 +206,26 @@ export function diffViews(
|
|
|
195
206
|
}
|
|
196
207
|
}
|
|
197
208
|
|
|
209
|
+
// SECURITY LABELS
|
|
210
|
+
changes.push(
|
|
211
|
+
...diffSecurityLabels<
|
|
212
|
+
CreateSecurityLabelOnView | DropSecurityLabelOnView
|
|
213
|
+
>(
|
|
214
|
+
mainView.security_labels,
|
|
215
|
+
branchView.security_labels,
|
|
216
|
+
(securityLabel) =>
|
|
217
|
+
new CreateSecurityLabelOnView({
|
|
218
|
+
view: branchView,
|
|
219
|
+
securityLabel,
|
|
220
|
+
}),
|
|
221
|
+
(securityLabel) =>
|
|
222
|
+
new DropSecurityLabelOnView({
|
|
223
|
+
view: mainView,
|
|
224
|
+
securityLabel,
|
|
225
|
+
}),
|
|
226
|
+
),
|
|
227
|
+
);
|
|
228
|
+
|
|
198
229
|
// Note: View renaming would also use ALTER VIEW ... RENAME TO ...
|
|
199
230
|
// But since our View model uses 'name' as the identity field,
|
|
200
231
|
// a name change would be handled as drop + create by diffObjects()
|
|
@@ -15,6 +15,11 @@ import {
|
|
|
15
15
|
type ExtractRetryOptions,
|
|
16
16
|
extractWithDefinitionRetry,
|
|
17
17
|
} from "../extract-with-retry.ts";
|
|
18
|
+
import {
|
|
19
|
+
normalizeSecurityLabels,
|
|
20
|
+
type SecurityLabelProps,
|
|
21
|
+
securityLabelPropsSchema,
|
|
22
|
+
} from "../security-label.types.ts";
|
|
18
23
|
import { ReplicaIdentitySchema } from "../table/table.model.ts";
|
|
19
24
|
|
|
20
25
|
const viewPropsSchema = z.object({
|
|
@@ -36,6 +41,7 @@ const viewPropsSchema = z.object({
|
|
|
36
41
|
comment: z.string().nullable(),
|
|
37
42
|
columns: z.array(columnPropsSchema),
|
|
38
43
|
privileges: z.array(privilegePropsSchema),
|
|
44
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
39
45
|
});
|
|
40
46
|
|
|
41
47
|
// pg_get_viewdef(oid) can return NULL when the underlying view (or its
|
|
@@ -69,6 +75,7 @@ export class View extends BasePgModel implements TableLikeObject {
|
|
|
69
75
|
public readonly comment: ViewProps["comment"];
|
|
70
76
|
public readonly columns: ViewProps["columns"];
|
|
71
77
|
public readonly privileges: ViewPrivilegeProps[];
|
|
78
|
+
public readonly security_labels: SecurityLabelProps[];
|
|
72
79
|
|
|
73
80
|
constructor(props: ViewProps) {
|
|
74
81
|
super();
|
|
@@ -94,6 +101,7 @@ export class View extends BasePgModel implements TableLikeObject {
|
|
|
94
101
|
this.comment = props.comment;
|
|
95
102
|
this.columns = props.columns;
|
|
96
103
|
this.privileges = props.privileges;
|
|
104
|
+
this.security_labels = props.security_labels ?? [];
|
|
97
105
|
}
|
|
98
106
|
|
|
99
107
|
get stableId(): `view:${string}` {
|
|
@@ -125,6 +133,7 @@ export class View extends BasePgModel implements TableLikeObject {
|
|
|
125
133
|
comment: this.comment,
|
|
126
134
|
columns: this.columns,
|
|
127
135
|
privileges: this.privileges,
|
|
136
|
+
security_labels: this.security_labels,
|
|
128
137
|
};
|
|
129
138
|
}
|
|
130
139
|
|
|
@@ -134,6 +143,7 @@ export class View extends BasePgModel implements TableLikeObject {
|
|
|
134
143
|
data: {
|
|
135
144
|
...this.dataFields,
|
|
136
145
|
columns: normalizeColumns(this.columns),
|
|
146
|
+
security_labels: normalizeSecurityLabels(this.security_labels),
|
|
137
147
|
},
|
|
138
148
|
};
|
|
139
149
|
}
|
|
@@ -264,7 +274,20 @@ select
|
|
|
264
274
|
join lateral aclexplode(src.acl) as x(grantor, grantee, privilege_type, is_grantable) on true
|
|
265
275
|
group by x.grantee, x.privilege_type
|
|
266
276
|
) as grp
|
|
267
|
-
), '[]') as privileges
|
|
277
|
+
), '[]') as privileges,
|
|
278
|
+
coalesce(
|
|
279
|
+
(
|
|
280
|
+
select json_agg(
|
|
281
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
282
|
+
order by sl.provider
|
|
283
|
+
)
|
|
284
|
+
from pg_catalog.pg_seclabel sl
|
|
285
|
+
where sl.objoid = v.oid
|
|
286
|
+
and sl.classoid = 'pg_class'::regclass
|
|
287
|
+
and sl.objsubid = 0
|
|
288
|
+
),
|
|
289
|
+
'[]'::json
|
|
290
|
+
) as security_labels
|
|
268
291
|
from
|
|
269
292
|
views v
|
|
270
293
|
left join pg_attribute a on a.attrelid = v.oid and a.attnum > 0 and not a.attisdropped
|
|
@@ -281,5 +304,5 @@ order by
|
|
|
281
304
|
const validatedRows = viewRows.filter(
|
|
282
305
|
(row): row is ViewProps => row.definition !== null,
|
|
283
306
|
);
|
|
284
|
-
return validatedRows.map((row
|
|
307
|
+
return validatedRows.map((row) => new View(row));
|
|
285
308
|
}
|