@rebasepro/cms 0.21.2-canary.g1ea48be → 0.23.0
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/{CollectionEditorDialog-B1mG1cfx.js → CollectionEditorDialog-DLHCka00.js} +103 -58
- package/dist/CollectionEditorDialog-DLHCka00.js.map +1 -0
- package/dist/{PropertyEditView-gKNUHxLY.js → PropertyEditView-_pu5hzZn.js} +53 -21
- package/dist/PropertyEditView-_pu5hzZn.js.map +1 -0
- package/dist/{RouterCollectionsStudioView-qgDWC6E2.js → RouterCollectionsStudioView-ChPNl_uU.js} +34 -10
- package/dist/RouterCollectionsStudioView-ChPNl_uU.js.map +1 -0
- package/dist/collection_editor/_cms_internals.d.ts +1 -0
- package/dist/collection_editor/relation_kinds.d.ts +11 -0
- package/dist/collection_editor/ui/collection_editor/CollectionStudioView.d.ts +8 -1
- package/dist/collection_editor_ui.js +4 -4
- package/dist/components/CollectionTableBinding/fields/CompactEntityCellField.d.ts +12 -13
- package/dist/components/CollectionTableBinding/fields/TableMultipleRelationField.d.ts +6 -3
- package/dist/components/CollectionTableBinding/fields/TableReferenceField.d.ts +8 -1
- package/dist/components/CollectionTableBinding/fields/TableRelationField.d.ts +8 -1
- package/dist/components/CollectionTableBinding/fields/TableRelationSelectorField.d.ts +13 -3
- package/dist/components/CollectionTableBinding/fields/VirtualTableSelect.d.ts +10 -0
- package/dist/components/CollectionTableBinding/fields/VirtualTableUserSelect.d.ts +10 -0
- package/dist/components/CollectionTableBinding/internal/EntityTableCell.d.ts +21 -0
- package/dist/components/CollectionTableBinding/internal/TableCellOpener.d.ts +45 -0
- package/dist/components/CollectionTableBinding/table_bindings.d.ts +24 -0
- package/dist/components/CollectionViewBinding/CollectionViewBinding.d.ts +7 -1
- package/dist/components/EntityPreviewBinding.d.ts +8 -1
- package/dist/components/EntityPreviewNesting.d.ts +15 -0
- package/dist/components/PickerTrigger.d.ts +17 -0
- package/dist/components/ReferenceTable/SelectionTableBinding.d.ts +12 -0
- package/dist/components/RelationSelector.d.ts +24 -7
- package/dist/components/UserSelector.d.ts +8 -1
- package/dist/data_export/export/additional_fields.d.ts +13 -0
- package/dist/data_export/export/export.d.ts +6 -0
- package/dist/data_import/utils/csv.d.ts +3 -2
- package/dist/data_import/utils/id_column.d.ts +16 -0
- package/dist/editor.js +1 -1
- package/dist/{export-DIyk1720.js → export-4bJWdlDK.js} +63 -209
- package/dist/export-4bJWdlDK.js.map +1 -0
- package/dist/form/form_utils.d.ts +13 -0
- package/dist/form/validation.d.ts +13 -0
- package/dist/{history-CrZEzQ5b.js → history-BElrZ5Rw.js} +2 -2
- package/dist/{history-CrZEzQ5b.js.map → history-BElrZ5Rw.js.map} +1 -1
- package/dist/hooks/useEntityDisplay.d.ts +4 -5
- package/dist/{import-ByaJMZuT.js → import-TCgkTVlS.js} +3 -4
- package/dist/import-TCgkTVlS.js.map +1 -0
- package/dist/index.js +16 -10
- package/dist/index.js.map +1 -1
- package/dist/preview/util.d.ts +25 -0
- package/dist/util/navigation_utils.d.ts +14 -2
- package/dist/util/view_mode.d.ts +12 -18
- package/dist/{util-DB31IoJE.js → util-CC0ozHoD.js} +35 -2
- package/dist/util-CC0ozHoD.js.map +1 -0
- package/dist/{util-qfCPxJzB.js → util-DybQBkug.js} +1482 -717
- package/dist/util-DybQBkug.js.map +1 -0
- package/package.json +9 -9
- package/dist/CollectionEditorDialog-B1mG1cfx.js.map +0 -1
- package/dist/PropertyEditView-gKNUHxLY.js.map +0 -1
- package/dist/RouterCollectionsStudioView-qgDWC6E2.js.map +0 -1
- package/dist/export-DIyk1720.js.map +0 -1
- package/dist/import-ByaJMZuT.js.map +0 -1
- package/dist/util-DB31IoJE.js.map +0 -1
- package/dist/util-qfCPxJzB.js.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { A as getFieldId, At as
|
|
3
|
-
import { a as updatePropertyFromWidget, c as useAIModifiedPaths, i as supportedFields, n as PropertyForm, o as PropertyTree, r as PropertyFormDialog, s as AIModifiedPathsProvider } from "./PropertyEditView-
|
|
2
|
+
import { $t as PropertyConfigBadge, A as getFieldId, At as guessIdColumn, Dn as CollectionTableBinding, Ft as useImportConfig, It as ImportSaveInProgress, Mn as useUrlController, Ot as ImportNewPropertyFieldPreview, Pn as useNavigationStateController, Pt as getInferenceType, S as isSchemaChangeCancelled, Tn as useSelectionController, Tt as useCollectionEditorController, _ as useCollectionsConfigController, ct as useSafeSnackbarController, en as SearchIconsView, i as namespaceToPropertiesOrderPath, jt as convertDataToEntity, k as getFieldConfig, kt as DataNewPropertiesMapping, l as validateCollectionJson, m as toSerializableCollectionConfig, n as getFullIdPath, o as CollectionGenerationApiError, r as idToPropertiesPath, t as getFullId, tn as FieldCaption, ur as useCollectionRegistryController, zt as ImportFileUpload } from "./util-DybQBkug.js";
|
|
3
|
+
import { a as updatePropertyFromWidget, c as useAIModifiedPaths, i as supportedFields, n as PropertyForm, o as PropertyTree, r as PropertyFormDialog, s as AIModifiedPathsProvider } from "./PropertyEditView-_pu5hzZn.js";
|
|
4
4
|
import * as React$1 from "react";
|
|
5
5
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { Alert, AppWindow, ArrowLeftIcon, BooleanSwitchWithLabel, Button, Card, CheckIcon, Chip, CircularProgress, CircularProgressCenter, CodeIcon, ColumnsIcon, Container, CopyIcon, DebouncedTextField, Dialog, DialogActions, DialogContent, DialogTitle, ErrorBoundary, FileIcon, FileSearchIcon, FileTextIcon, IconButton, KanbanIcon, KeyIcon, LayoutGridIcon, ListIcon, LoadingButton, Menu, MultiSelect, MultiSelectItem, PanelLeftIcon, Paper, PlusIcon, Select, SelectItem, ShoppingCartIcon, SquareIcon, Tab, TableIcon, Tabs, TextField, ToggleButtonGroup, Tooltip, Trash2Icon, Typography, UserIcon, XIcon, cls, coolIconKeys, defaultBorderMixin, iconSize } from "@rebasepro/ui";
|
|
7
|
-
import { buildCollectionFromTableMetadata, getGeneratedPolicyNames, getSubcollections, getTableName, isPropertyBuilder } from "@rebasepro/common";
|
|
7
|
+
import { buildCollectionFromTableMetadata, getGeneratedPolicyNames, getSubcollections, getTableName, isPropertyBuilder, policyToSecurityRule } from "@rebasepro/common";
|
|
8
8
|
import { AIIcon, ConfirmationDialog, ErrorView, IconForView, UnsavedChangesDialog, getIcon, removeInitialAndTrailingSlashes, useAuthController, useCustomizationController, useLargeLayout, useRebaseContext, useTranslation, useUnsavedChangesDialog } from "@rebasepro/app";
|
|
9
9
|
import { Field, Formex, clone, getIn, useCreateFormex, useFormex } from "@rebasepro/forms";
|
|
10
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
import { RLS_ROLES_SQL, RLS_UID_SQL, getDataSourceCapabilities } from "@rebasepro/types";
|
|
11
|
+
import { RLS_ROLES_SQL, RLS_UID_SQL, getDataSourceCapabilities, isPostgresCollectionConfig } from "@rebasepro/types";
|
|
12
12
|
import { camelCase, getPolicyNamesForRule, isEmptyObject, mergeDeep, prettifyIdentifier, randomString, removeUndefined, singular, slugify, toSnakeCase, unslugify } from "@rebasepro/utils";
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
import { buildEntityPropertiesFromData, buildPropertyFromData } from "@rebasepro/inference";
|
|
@@ -103,6 +103,7 @@ function GeneralSettingsForm({ isNewCollection, existingPaths, existingIds, pare
|
|
|
103
103
|
as: DebouncedTextField,
|
|
104
104
|
label: "Table name",
|
|
105
105
|
required: true,
|
|
106
|
+
disabled: !isNewCollection,
|
|
106
107
|
error: showErrors && Boolean(errors.table)
|
|
107
108
|
}), /* @__PURE__ */ jsx(FieldCaption, {
|
|
108
109
|
error: touched.table && Boolean(errors.table),
|
|
@@ -962,6 +963,8 @@ function CollectionPropertiesEditorForm({ showErrors, isNewCollection, propertyE
|
|
|
962
963
|
const initialErrors = selectedPropertyKey && propertyErrorsRef?.current?.properties ? propertyErrorsRef.current.properties[selectedPropertyKey] : void 0;
|
|
963
964
|
const emptyCollection = (values?.propertiesOrder === void 0 || values.propertiesOrder.length === 0) && (!values?.properties || Object.keys(values.properties).length === 0);
|
|
964
965
|
const usedPropertiesOrder = values.propertiesOrder ? values.propertiesOrder : Object.keys(values.properties);
|
|
966
|
+
const selectedNamespaceOrder = getCurrentPropertiesOrder(selectedPropertyNamespace);
|
|
967
|
+
const otherPropertyKeys = useMemo(() => (selectedNamespaceOrder ?? []).filter((key) => key !== selectedPropertyKey), [selectedNamespaceOrder, selectedPropertyKey]);
|
|
965
968
|
const owner = useMemo(() => values.ownerId && getUser ? getUser(values.ownerId) : null, [getUser, values.ownerId]);
|
|
966
969
|
const generationCounter = useAIModifiedPaths()?.generationCounter ?? 0;
|
|
967
970
|
const onPropertyClick = (propertyKey, namespace) => {
|
|
@@ -1071,6 +1074,7 @@ function CollectionPropertiesEditorForm({ showErrors, isNewCollection, propertyE
|
|
|
1071
1074
|
propertyKey: selectedPropertyKey,
|
|
1072
1075
|
propertyNamespace: selectedPropertyNamespace,
|
|
1073
1076
|
property: selectedProperty,
|
|
1077
|
+
existingPropertyKeys: otherPropertyKeys,
|
|
1074
1078
|
onPropertyChanged,
|
|
1075
1079
|
onDelete: deleteProperty,
|
|
1076
1080
|
onError: onPropertyErrorInternal,
|
|
@@ -2328,12 +2332,9 @@ function cleanPropertiesFromImport(properties, parentSlug = "") {
|
|
|
2328
2332
|
headersMapping: {},
|
|
2329
2333
|
properties: {}
|
|
2330
2334
|
});
|
|
2331
|
-
const firstKey = Object.keys(result.headersMapping)?.[0];
|
|
2332
|
-
let idColumn;
|
|
2333
|
-
if (firstKey?.includes("id") || firstKey?.includes("key")) idColumn = firstKey;
|
|
2334
2335
|
return {
|
|
2335
2336
|
...result,
|
|
2336
|
-
idColumn
|
|
2337
|
+
idColumn: guessIdColumn(Object.keys(result.headersMapping), result.headersMapping, result.properties)
|
|
2337
2338
|
};
|
|
2338
2339
|
}
|
|
2339
2340
|
//#endregion
|
|
@@ -2371,48 +2372,88 @@ function toSecurityMode(permissive) {
|
|
|
2371
2372
|
return permissive === "RESTRICTIVE" ? "restrictive" : "permissive";
|
|
2372
2373
|
}
|
|
2373
2374
|
/**
|
|
2374
|
-
* Build a
|
|
2375
|
+
* Build a rule from what the inline editor saved. Its `roles` are application
|
|
2376
|
+
* roles; a live policy's are its `TO` list, which `policyToSecurityRule` reads.
|
|
2375
2377
|
*
|
|
2376
|
-
*
|
|
2377
|
-
*
|
|
2378
|
-
*
|
|
2379
|
-
* roles-only rule carrying the check. Assembling the object field-by-field
|
|
2380
|
-
* against `operation?: string` accepted all of these and told the compiler
|
|
2381
|
-
* nothing.
|
|
2378
|
+
* The WITH CHECK is kept whether or not there is a USING: every INSERT-only
|
|
2379
|
+
* policy has only a check, and a roles-only rule with no roles compiles to
|
|
2380
|
+
* `WITH CHECK (false)`, which stops every insert.
|
|
2382
2381
|
*/
|
|
2383
2382
|
function toSecurityRule(policy) {
|
|
2384
|
-
|
|
2383
|
+
return {
|
|
2385
2384
|
name: policy.policyname ?? "",
|
|
2386
2385
|
operation: toSecurityOperation(policy.cmd),
|
|
2387
2386
|
mode: toSecurityMode(policy.permissive),
|
|
2388
|
-
roles: policy.roles ? [...policy.roles] : void 0
|
|
2387
|
+
roles: policy.roles ? [...policy.roles] : void 0,
|
|
2388
|
+
...policy.qual ? { using: policy.qual } : {},
|
|
2389
|
+
...policy.with_check ? { withCheck: policy.with_check } : {}
|
|
2389
2390
|
};
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2391
|
+
}
|
|
2392
|
+
/**
|
|
2393
|
+
* The rule with what the editor changed, and nothing else.
|
|
2394
|
+
*
|
|
2395
|
+
* The editor shows a rule as a policy — name, command, mode, application roles
|
|
2396
|
+
* and raw USING / WITH CHECK — and has no field for `ownerField`, `access`, a
|
|
2397
|
+
* structured `condition`, `operations` (it shows them as ALL) or `pgRoles`.
|
|
2398
|
+
* The rule used to be rebuilt from the form, which dropped all of them:
|
|
2399
|
+
* renaming an owner rule saved a roles-only rule with no roles, which compiles
|
|
2400
|
+
* to `USING (false)`. So a field is only written when it differs from what the
|
|
2401
|
+
* editor was opened with. A condition typed in replaces the rule's condition
|
|
2402
|
+
* whole — the forms are exclusive.
|
|
2403
|
+
*
|
|
2404
|
+
* Studio's RLS editor does the same in `policyRules.ts`; there the editor's
|
|
2405
|
+
* roles are the policy's `TO` list, `pgRoles`, and here they are `roles`.
|
|
2406
|
+
*/
|
|
2407
|
+
function editedRule(rule, original, edited) {
|
|
2408
|
+
const next = toSecurityRule(edited);
|
|
2409
|
+
const result = { ...rule };
|
|
2410
|
+
if ((edited.policyname ?? "") !== original.policyname) if (next.name) result.name = next.name;
|
|
2411
|
+
else delete result.name;
|
|
2412
|
+
if (edited.cmd !== original.cmd) {
|
|
2413
|
+
delete result.operations;
|
|
2414
|
+
result.operation = next.operation;
|
|
2415
|
+
}
|
|
2416
|
+
if (edited.permissive !== original.permissive) result.mode = next.mode;
|
|
2417
|
+
if (!sameRoles(edited.roles, original.roles)) if (next.roles && next.roles.length > 0) result.roles = next.roles;
|
|
2418
|
+
else delete result.roles;
|
|
2419
|
+
if ((edited.qual || null) !== (original.qual || null) || (edited.with_check || null) !== (original.with_check || null)) {
|
|
2420
|
+
delete result.ownerField;
|
|
2421
|
+
delete result.access;
|
|
2422
|
+
delete result.condition;
|
|
2423
|
+
delete result.check;
|
|
2424
|
+
delete result.using;
|
|
2425
|
+
delete result.withCheck;
|
|
2426
|
+
if (next.using) result.using = next.using;
|
|
2427
|
+
if (next.withCheck) result.withCheck = next.withCheck;
|
|
2428
|
+
}
|
|
2429
|
+
return result;
|
|
2430
|
+
}
|
|
2431
|
+
function sameRoles(a, b) {
|
|
2432
|
+
const left = [...a ?? []].sort();
|
|
2433
|
+
const right = [...b ?? []].sort();
|
|
2434
|
+
return left.length === right.length && left.every((role, i) => role === right[i]);
|
|
2396
2435
|
}
|
|
2397
2436
|
function CollectionRLSTab() {
|
|
2398
2437
|
const { values, setFieldValue } = useFormex();
|
|
2399
|
-
const [
|
|
2438
|
+
const [editing, setEditing] = useState(null);
|
|
2400
2439
|
const { readOnly, readOnlyReason } = useCollectionsConfigController();
|
|
2401
2440
|
const readOnlyTitle = readOnlyReason || "This backend does not accept collection edits.";
|
|
2402
2441
|
const rules = values.securityRules || [];
|
|
2403
2442
|
const { databaseAdmin } = useRebaseContext();
|
|
2404
2443
|
const [dbPolicies, setDbPolicies] = useState([]);
|
|
2405
2444
|
const [isLoadingDb, setIsLoadingDb] = useState(false);
|
|
2445
|
+
const tableName = getTableName(values);
|
|
2446
|
+
const schemaName = isPostgresCollectionConfig(values) && values.schema ? values.schema : "public";
|
|
2406
2447
|
useEffect(() => {
|
|
2407
2448
|
const fetchLivePolicies = async () => {
|
|
2408
|
-
const tableName = values.id || values.table || values.alias;
|
|
2409
2449
|
if (!tableName || !databaseAdmin?.executeSql) return;
|
|
2410
2450
|
setIsLoadingDb(true);
|
|
2411
2451
|
try {
|
|
2452
|
+
const rawTableName = sanitizeSqlIdentifier(tableName).slice(1, -1);
|
|
2412
2453
|
const sql = `
|
|
2413
2454
|
SELECT policyname, permissive, roles, cmd, qual, with_check
|
|
2414
2455
|
FROM pg_policies
|
|
2415
|
-
WHERE
|
|
2456
|
+
WHERE schemaname = '${sanitizeSqlIdentifier(schemaName).slice(1, -1)}' AND tablename = '${rawTableName}';
|
|
2416
2457
|
`;
|
|
2417
2458
|
const result = await databaseAdmin.executeSql(sql);
|
|
2418
2459
|
const extractRows = (res) => {
|
|
@@ -2445,9 +2486,8 @@ function CollectionRLSTab() {
|
|
|
2445
2486
|
fetchLivePolicies();
|
|
2446
2487
|
}, [
|
|
2447
2488
|
databaseAdmin,
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
values.alias
|
|
2489
|
+
tableName,
|
|
2490
|
+
schemaName
|
|
2451
2491
|
]);
|
|
2452
2492
|
/**
|
|
2453
2493
|
* Application roles available to `SecurityRule.roles`.
|
|
@@ -2481,19 +2521,16 @@ function CollectionRLSTab() {
|
|
|
2481
2521
|
mounted = false;
|
|
2482
2522
|
};
|
|
2483
2523
|
}, [databaseAdmin]);
|
|
2484
|
-
const tableName = values.id || values.table || values.alias;
|
|
2485
2524
|
const generatedPolicyNames = useMemo(() => {
|
|
2486
2525
|
if (!tableName) return /* @__PURE__ */ new Set();
|
|
2487
2526
|
return getGeneratedPolicyNames(values);
|
|
2488
2527
|
}, [tableName, values]);
|
|
2489
2528
|
const unmappedPolicies = dbPolicies.filter((dp) => !generatedPolicyNames.has(dp.policyname));
|
|
2490
|
-
const handleSave =
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
if (editingPolicy === "new") newRules = [...rules, rule];
|
|
2494
|
-
else newRules = rules.map((r) => r.name === editingPolicy.policyname ? rule : r);
|
|
2529
|
+
const handleSave = (newPolicy) => {
|
|
2530
|
+
if (!editing) return;
|
|
2531
|
+
const newRules = editing === "new" ? [...rules, toSecurityRule(newPolicy)] : rules.map((r, i) => i === editing.index ? editedRule(r, editing.policy, newPolicy) : r);
|
|
2495
2532
|
setFieldValue("securityRules", newRules);
|
|
2496
|
-
|
|
2533
|
+
setEditing(null);
|
|
2497
2534
|
};
|
|
2498
2535
|
return /* @__PURE__ */ jsx("div", {
|
|
2499
2536
|
className: "overflow-auto my-auto",
|
|
@@ -2514,7 +2551,7 @@ function CollectionRLSTab() {
|
|
|
2514
2551
|
variant: "filled",
|
|
2515
2552
|
color: "neutral",
|
|
2516
2553
|
disabled: readOnly,
|
|
2517
|
-
onClick: () =>
|
|
2554
|
+
onClick: () => setEditing("new"),
|
|
2518
2555
|
children: "CREATE POLICY"
|
|
2519
2556
|
}) })
|
|
2520
2557
|
})]
|
|
@@ -2527,7 +2564,7 @@ function CollectionRLSTab() {
|
|
|
2527
2564
|
})
|
|
2528
2565
|
}) : /* @__PURE__ */ jsx("div", {
|
|
2529
2566
|
className: "flex flex-col gap-3",
|
|
2530
|
-
children: rules.map((rule) => /* @__PURE__ */ jsxs(Paper, {
|
|
2567
|
+
children: rules.map((rule, index) => /* @__PURE__ */ jsxs(Paper, {
|
|
2531
2568
|
className: "p-4 border border-transparent hover:border-surface-200 dark:hover:border-surface-700 rounded-lg flex flex-col sm:flex-row sm:items-center justify-between gap-4 transition-colors bg-surface-card shadow-sm",
|
|
2532
2569
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
2533
2570
|
className: "flex flex-col gap-1.5 min-w-0",
|
|
@@ -2559,21 +2596,24 @@ function CollectionRLSTab() {
|
|
|
2559
2596
|
size: "small",
|
|
2560
2597
|
variant: "text",
|
|
2561
2598
|
disabled: readOnly,
|
|
2562
|
-
onClick: () =>
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2599
|
+
onClick: () => setEditing({
|
|
2600
|
+
index,
|
|
2601
|
+
policy: {
|
|
2602
|
+
policyname: rule.name ?? "",
|
|
2603
|
+
tablename: tableName || "your_table",
|
|
2604
|
+
permissive: (rule.mode || "permissive").toUpperCase(),
|
|
2605
|
+
cmd: (rule.operation || "ALL").toUpperCase(),
|
|
2606
|
+
roles: [...rule.roles ?? []],
|
|
2607
|
+
qual: rule.using || null,
|
|
2608
|
+
with_check: rule.withCheck || null
|
|
2609
|
+
}
|
|
2570
2610
|
}),
|
|
2571
2611
|
children: "EDIT"
|
|
2572
2612
|
}), /* @__PURE__ */ jsx(IconButton, {
|
|
2573
2613
|
size: "small",
|
|
2574
2614
|
disabled: readOnly,
|
|
2575
2615
|
onClick: () => {
|
|
2576
|
-
setFieldValue("securityRules", rules.filter((
|
|
2616
|
+
setFieldValue("securityRules", rules.filter((_r, i) => i !== index));
|
|
2577
2617
|
},
|
|
2578
2618
|
children: /* @__PURE__ */ jsx(Trash2Icon, {
|
|
2579
2619
|
size: iconSize.smallest,
|
|
@@ -2581,7 +2621,7 @@ function CollectionRLSTab() {
|
|
|
2581
2621
|
})
|
|
2582
2622
|
})]
|
|
2583
2623
|
})]
|
|
2584
|
-
}, rule.name))
|
|
2624
|
+
}, `${index}:${rule.name ?? ""}`))
|
|
2585
2625
|
}),
|
|
2586
2626
|
isLoadingDb && unmappedPolicies.length === 0 && /* @__PURE__ */ jsx("div", {
|
|
2587
2627
|
className: "flex justify-center mt-8",
|
|
@@ -2648,7 +2688,7 @@ function CollectionRLSTab() {
|
|
|
2648
2688
|
color: "primary",
|
|
2649
2689
|
disabled: readOnly,
|
|
2650
2690
|
onClick: () => {
|
|
2651
|
-
const rule =
|
|
2691
|
+
const rule = policyToSecurityRule(dp);
|
|
2652
2692
|
setFieldValue("securityRules", [...rules, rule]);
|
|
2653
2693
|
},
|
|
2654
2694
|
children: "Import to codebase"
|
|
@@ -2661,16 +2701,17 @@ function CollectionRLSTab() {
|
|
|
2661
2701
|
})
|
|
2662
2702
|
]
|
|
2663
2703
|
}), /* @__PURE__ */ jsx(Dialog, {
|
|
2664
|
-
open: !!
|
|
2665
|
-
onOpenChange: (open) => !open &&
|
|
2704
|
+
open: !!editing,
|
|
2705
|
+
onOpenChange: (open) => !open && setEditing(null),
|
|
2666
2706
|
maxWidth: "4xl",
|
|
2667
|
-
children:
|
|
2668
|
-
policy:
|
|
2669
|
-
table:
|
|
2707
|
+
children: editing && /* @__PURE__ */ jsx(InlinePolicyEditor, {
|
|
2708
|
+
policy: editing === "new" ? void 0 : editing.policy,
|
|
2709
|
+
table: tableName || "your_table",
|
|
2710
|
+
schema: schemaName,
|
|
2670
2711
|
availableRoles,
|
|
2671
2712
|
rolesUnavailable,
|
|
2672
2713
|
onSave: handleSave,
|
|
2673
|
-
onCancel: () =>
|
|
2714
|
+
onCancel: () => setEditing(null)
|
|
2674
2715
|
})
|
|
2675
2716
|
})]
|
|
2676
2717
|
})
|
|
@@ -2683,7 +2724,7 @@ var COMMAND_OPTIONS = [
|
|
|
2683
2724
|
"UPDATE",
|
|
2684
2725
|
"DELETE"
|
|
2685
2726
|
];
|
|
2686
|
-
function InlinePolicyEditor({ policy, table, availableRoles, rolesUnavailable, onSave, onCancel }) {
|
|
2727
|
+
function InlinePolicyEditor({ policy, table, schema, availableRoles, rolesUnavailable, onSave, onCancel }) {
|
|
2687
2728
|
const { t } = useTranslation();
|
|
2688
2729
|
const [name, setName] = useState(policy?.policyname || "");
|
|
2689
2730
|
const [behavior, setBehavior] = useState(policy?.permissive || "PERMISSIVE");
|
|
@@ -2716,7 +2757,11 @@ function InlinePolicyEditor({ policy, table, availableRoles, rolesUnavailable, o
|
|
|
2716
2757
|
className: "text-sm font-normal text-text-secondary dark:text-text-secondary-dark tracking-wide mt-1",
|
|
2717
2758
|
children: ["Define RLS rules for ", /* @__PURE__ */ jsxs("span", {
|
|
2718
2759
|
className: "font-mono text-primary bg-primary-bg px-1 py-0.5 rounded",
|
|
2719
|
-
children: [
|
|
2760
|
+
children: [
|
|
2761
|
+
schema,
|
|
2762
|
+
".",
|
|
2763
|
+
table
|
|
2764
|
+
]
|
|
2720
2765
|
})]
|
|
2721
2766
|
})]
|
|
2722
2767
|
}),
|
|
@@ -3582,4 +3627,4 @@ var validateId = (value, isNewCollection, existingPaths, existingIds) => {
|
|
|
3582
3627
|
//#endregion
|
|
3583
3628
|
export { CollectionEditorDialog as n, CollectionEditorDialog_exports as r, CollectionEditor as t };
|
|
3584
3629
|
|
|
3585
|
-
//# sourceMappingURL=CollectionEditorDialog-
|
|
3630
|
+
//# sourceMappingURL=CollectionEditorDialog-DLHCka00.js.map
|