@rebasepro/cms 0.17.3 → 0.18.1
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/README.md +4 -0
- package/dist/{CollectionEditorDialog-B-akreOU.js → CollectionEditorDialog-BeX4b92r.js} +13 -7
- package/dist/{CollectionEditorDialog-B-akreOU.js.map → CollectionEditorDialog-BeX4b92r.js.map} +1 -1
- package/dist/{PropertyEditView-CiY84wkR.js → PropertyEditView-C7thfj4L.js} +3 -3
- package/dist/{PropertyEditView-CiY84wkR.js.map → PropertyEditView-C7thfj4L.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-DkAWda4N.js → RouterCollectionsStudioView-BtjzvB6E.js} +4 -4
- package/dist/{RouterCollectionsStudioView-DkAWda4N.js.map → RouterCollectionsStudioView-BtjzvB6E.js.map} +1 -1
- package/dist/{SchemaChangeDialog-DceT8QFX.js → SchemaChangeDialog-CkqK6KOC.js} +4 -2
- package/dist/{SchemaChangeDialog-DceT8QFX.js.map → SchemaChangeDialog-CkqK6KOC.js.map} +1 -1
- package/dist/collection_editor/api/generateCollectionApi.d.ts +1 -2
- package/dist/collection_editor_ui.d.ts +2 -0
- package/dist/collection_editor_ui.js +6 -5
- package/dist/collection_editor_ui.js.map +1 -1
- package/dist/components/DeleteEntityDialog.d.ts +2 -3
- package/dist/components/RebaseLayout.d.ts +11 -4
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/editor/sanitize-html.d.ts +15 -0
- package/dist/editor.js +195 -10
- package/dist/editor.js.map +1 -1
- package/dist/{export-Ben8E355.js → export--arni_VY.js} +2 -2
- package/dist/{export-Ben8E355.js.map → export--arni_VY.js.map} +1 -1
- package/dist/form/components/LabelWithIcon.d.ts +10 -0
- package/dist/{history-DIEVd26f.js → history-C2TpoQwi.js} +2 -2
- package/dist/{history-DIEVd26f.js.map → history-C2TpoQwi.js.map} +1 -1
- package/dist/hooks/navigation/useBuildNavigationStateController.d.ts +1 -1
- package/dist/hooks/navigation/useResolvedViews.d.ts +1 -1
- package/dist/hooks/navigation/useTopLevelNavigation.d.ts +1 -1
- package/dist/{import-D25x7ko-.js → import-DTkXNoBg.js} +2 -2
- package/dist/{import-D25x7ko-.js.map → import-DTkXNoBg.js.map} +1 -1
- package/dist/index.js +78 -33
- package/dist/index.js.map +1 -1
- package/dist/util/propertyConfigMapper.d.ts +1 -1
- package/dist/util-CfLFggP7.js +57 -0
- package/dist/util-CfLFggP7.js.map +1 -0
- package/dist/{util-DVqnqlLn.js → util-DE1WQW6h.js} +134 -112
- package/dist/util-DE1WQW6h.js.map +1 -0
- package/package.json +42 -34
- package/dist/util-DVqnqlLn.js.map +0 -1
- package/src/collection_editor/CollectionEditorDialogsContext.tsx +0 -25
- package/src/collection_editor/ConfigControllerProvider.tsx +0 -395
- package/src/collection_editor/_cms_internals.ts +0 -41
- package/src/collection_editor/api/generateCollectionApi.ts +0 -126
- package/src/collection_editor/api/index.ts +0 -1
- package/src/collection_editor/extensibility_types.ts +0 -168
- package/src/collection_editor/index.ts +0 -108
- package/src/collection_editor/liveSchemaClient.ts +0 -285
- package/src/collection_editor/relation_kinds.ts +0 -44
- package/src/collection_editor/serializable_types.ts +0 -535
- package/src/collection_editor/serializable_utils.ts +0 -729
- package/src/collection_editor/types/collection_editor_controller.tsx +0 -62
- package/src/collection_editor/types/collection_inference.ts +0 -18
- package/src/collection_editor/types/config_controller.tsx +0 -121
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +0 -199
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +0 -51
- package/src/collection_editor/ui/EditorCollectionAction.tsx +0 -54
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +0 -90
- package/src/collection_editor/ui/EditorEntityAction.tsx +0 -50
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +0 -114
- package/src/collection_editor/ui/KanbanSetupAction.tsx +0 -43
- package/src/collection_editor/ui/MissingReferenceWidget.tsx +0 -35
- package/src/collection_editor/ui/NewCollectionButton.tsx +0 -27
- package/src/collection_editor/ui/NewCollectionCard.tsx +0 -48
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +0 -49
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +0 -260
- package/src/collection_editor/ui/collection_editor/AIModifiedPathsContext.tsx +0 -90
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +0 -388
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +0 -1098
- package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +0 -301
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +0 -172
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +0 -620
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +0 -530
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +0 -462
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +0 -104
- package/src/collection_editor/ui/collection_editor/CollectionYupValidation.tsx +0 -9
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +0 -199
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +0 -315
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +0 -164
- package/src/collection_editor/ui/collection_editor/EntityActionsSelectDialog.tsx +0 -40
- package/src/collection_editor/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +0 -373
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +0 -288
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +0 -141
- package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +0 -194
- package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +0 -53
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +0 -980
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +0 -164
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +0 -364
- package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +0 -44
- package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +0 -41
- package/src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx +0 -470
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +0 -256
- package/src/collection_editor/ui/collection_editor/SwitchControl.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +0 -68
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +0 -67
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.tsx +0 -296
- package/src/collection_editor/ui/collection_editor/import/clean_import_data.ts +0 -57
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +0 -147
- package/src/collection_editor/ui/collection_editor/properties/BooleanPropertyField.tsx +0 -41
- package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +0 -113
- package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +0 -250
- package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +0 -126
- package/src/collection_editor/ui/collection_editor/properties/KeyValuePropertyField.tsx +0 -20
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +0 -153
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +0 -217
- package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +0 -117
- package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +0 -129
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +0 -335
- package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -107
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +0 -403
- package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +0 -148
- package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +0 -91
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +0 -34
- package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +0 -49
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +0 -925
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +0 -28
- package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +0 -626
- package/src/collection_editor/ui/collection_editor/properties/conditions/index.ts +0 -6
- package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +0 -93
- package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +0 -52
- package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +0 -63
- package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +0 -114
- package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +0 -154
- package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +0 -28
- package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +0 -112
- package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +0 -183
- package/src/collection_editor/ui/collection_editor/templates/products_template.ts +0 -88
- package/src/collection_editor/ui/collection_editor/templates/users_template.ts +0 -42
- package/src/collection_editor/ui/collection_editor/util.ts +0 -28
- package/src/collection_editor/ui/collection_editor/utils/strings.ts +0 -1
- package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +0 -276
- package/src/collection_editor/useCollectionEditorController.tsx +0 -9
- package/src/collection_editor/useCollectionsConfigController.tsx +0 -9
- package/src/collection_editor/useJsonCollectionsConfigController.tsx +0 -297
- package/src/collection_editor/useLiveSchemaEditing.tsx +0 -315
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -341
- package/src/collection_editor/useSafeSnackbarController.ts +0 -9
- package/src/collection_editor/validateCollectionJson.ts +0 -440
- package/src/collection_editor_ui.ts +0 -21
- package/src/components/AdditionalFieldValue.tsx +0 -68
- package/src/components/AdminModeSyncer.tsx +0 -56
- package/src/components/ArrayContainer.tsx +0 -542
- package/src/components/ClearFilterSortButton.tsx +0 -56
- package/src/components/CollectionEditorDialogs.tsx +0 -69
- package/src/components/CollectionPanel.tsx +0 -179
- package/src/components/CollectionTableBinding/CollectionRowActions.tsx +0 -244
- package/src/components/CollectionTableBinding/CollectionTableBinding.tsx +0 -394
- package/src/components/CollectionTableBinding/CollectionTableBindingProps.tsx +0 -172
- package/src/components/CollectionTableBinding/PropertyTableCell.tsx +0 -350
- package/src/components/CollectionTableBinding/column_utils.tsx +0 -155
- package/src/components/CollectionTableBinding/fields/TableMultipleRelationField.tsx +0 -131
- package/src/components/CollectionTableBinding/fields/TableReferenceField.tsx +0 -193
- package/src/components/CollectionTableBinding/fields/TableRelationField.tsx +0 -192
- package/src/components/CollectionTableBinding/fields/TableRelationSelectorField.tsx +0 -42
- package/src/components/CollectionTableBinding/fields/TableStorageUpload.tsx +0 -324
- package/src/components/CollectionTableBinding/fields/VirtualTableSelect.tsx +0 -132
- package/src/components/CollectionTableBinding/fields/VirtualTableUserSelect.tsx +0 -41
- package/src/components/CollectionTableBinding/index.tsx +0 -14
- package/src/components/CollectionTableBinding/internal/CollectionTableToolbar.tsx +0 -96
- package/src/components/CollectionTableBinding/internal/EntityTableCell.tsx +0 -309
- package/src/components/CollectionTableBinding/internal/EntityTableCellActions.tsx +0 -80
- package/src/components/CollectionTableBinding/internal/common.tsx +0 -74
- package/src/components/CollectionTableBinding/internal/popup_field/PopupFormField.tsx +0 -422
- package/src/components/CollectionTableBinding/internal/popup_field/useDraggable.tsx +0 -99
- package/src/components/CollectionTableBinding/internal/popup_field/useWindowSize.tsx +0 -22
- package/src/components/CollectionTableBinding/table_bindings.tsx +0 -350
- package/src/components/CollectionViewBinding/BoardCardBinding.tsx +0 -263
- package/src/components/CollectionViewBinding/CollectionBoardViewBinding.tsx +0 -662
- package/src/components/CollectionViewBinding/CollectionCardViewBinding.tsx +0 -159
- package/src/components/CollectionViewBinding/CollectionListViewBinding.tsx +0 -1430
- package/src/components/CollectionViewBinding/CollectionViewActions.tsx +0 -227
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +0 -1603
- package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +0 -240
- package/src/components/CollectionViewBinding/EntityCardBinding.tsx +0 -239
- package/src/components/CollectionViewBinding/FilterPresetsButton.tsx +0 -298
- package/src/components/CollectionViewBinding/FiltersDialog.tsx +0 -218
- package/src/components/CollectionViewBinding/SearchExplanation.tsx +0 -106
- package/src/components/CollectionViewBinding/SearchHighlight.tsx +0 -311
- package/src/components/CollectionViewBinding/SlotValue.tsx +0 -156
- package/src/components/CollectionViewBinding/SortButton.tsx +0 -354
- package/src/components/CollectionViewBinding/SplitListCloseButton.tsx +0 -49
- package/src/components/CollectionViewBinding/SplitListShowButton.tsx +0 -28
- package/src/components/CollectionViewBinding/SplitListView.tsx +0 -488
- package/src/components/CollectionViewBinding/SplitViewContext.tsx +0 -34
- package/src/components/CollectionViewBinding/ViewModeToggle.tsx +0 -250
- package/src/components/CollectionViewBinding/hooks/useCollectionInlineEditor.ts +0 -81
- package/src/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.ts +0 -181
- package/src/components/CollectionViewBinding/useBoardDataController.tsx +0 -802
- package/src/components/CollectionViewBinding/usePreviewSlots.ts +0 -703
- package/src/components/CollectionViewBinding/useSelectionController.tsx +0 -40
- package/src/components/CollectionViewBinding/utils.ts +0 -22
- package/src/components/DefaultAppBar.tsx +0 -264
- package/src/components/DefaultDrawer.tsx +0 -593
- package/src/components/DeleteEntityDialog.tsx +0 -205
- package/src/components/DetailViewBinding.tsx +0 -731
- package/src/components/DrawerNavigationGroup.tsx +0 -141
- package/src/components/DrawerNavigationItem.tsx +0 -115
- package/src/components/EditFormActions.tsx +0 -303
- package/src/components/EditViewBinding.tsx +0 -1069
- package/src/components/EntityDisplayHeader.tsx +0 -170
- package/src/components/EntityIdentityBar.tsx +0 -428
- package/src/components/EntityInspector.tsx +0 -156
- package/src/components/EntityPreviewBinding.tsx +0 -432
- package/src/components/EntityPreviewNesting.tsx +0 -50
- package/src/components/EntityViewBinding.tsx +0 -374
- package/src/components/FieldCaption.tsx +0 -14
- package/src/components/HomePage/ContentHomePage.tsx +0 -586
- package/src/components/HomePage/FavouritesView.tsx +0 -60
- package/src/components/HomePage/HomePageDnD.tsx +0 -704
- package/src/components/HomePage/NavigationCard.tsx +0 -81
- package/src/components/HomePage/NavigationCardBinding.tsx +0 -107
- package/src/components/HomePage/NavigationGroup.tsx +0 -156
- package/src/components/HomePage/RenameGroupDialog.tsx +0 -123
- package/src/components/HomePage/SmallNavigationCard.tsx +0 -41
- package/src/components/HomePage/index.tsx +0 -5
- package/src/components/InlineEntityPreview.tsx +0 -149
- package/src/components/JsonPreviewBinding.tsx +0 -66
- package/src/components/PropertyCollectionView.tsx +0 -336
- package/src/components/PropertyConfigBadge.tsx +0 -28
- package/src/components/PropertyIdCopyTooltip.tsx +0 -47
- package/src/components/RebaseAuthGate.tsx +0 -44
- package/src/components/RebaseCMS.tsx +0 -30
- package/src/components/RebaseLayout.tsx +0 -80
- package/src/components/RebaseNavigation.tsx +0 -369
- package/src/components/RebaseRouteDefs.tsx +0 -127
- package/src/components/RebaseShell.tsx +0 -83
- package/src/components/ReferenceTable/SelectionTableBinding.tsx +0 -389
- package/src/components/ReferenceWidget.tsx +0 -156
- package/src/components/RelationSelector.tsx +0 -926
- package/src/components/SearchIconsView.tsx +0 -78
- package/src/components/SelectableTable/SelectableTable.tsx +0 -309
- package/src/components/SelectableTable/SelectableTableContext.tsx +0 -7
- package/src/components/SelectableTable/SelectionStore.ts +0 -43
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +0 -59
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +0 -146
- package/src/components/SelectableTable/filters/FilterFieldBinding.tsx +0 -190
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +0 -250
- package/src/components/SelectableTable/filters/RelationFilterField.tsx +0 -238
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +0 -282
- package/src/components/SelectableTable/filters/null_filter.ts +0 -63
- package/src/components/SideDialogs.tsx +0 -238
- package/src/components/SidePanelBinding.tsx +0 -361
- package/src/components/SidePanelProvider.tsx +0 -80
- package/src/components/UserSelector.tsx +0 -513
- package/src/components/admin/CreationResultDialog.tsx +0 -138
- package/src/components/admin/index.ts +0 -1
- package/src/components/app/AppBar.tsx +0 -17
- package/src/components/app/Drawer.tsx +0 -38
- package/src/components/app/Scaffold.tsx +0 -366
- package/src/components/app/index.ts +0 -4
- package/src/components/app/useApp.tsx +0 -36
- package/src/components/common/default_entity_actions.tsx +0 -440
- package/src/components/common/index.ts +0 -1
- package/src/components/field_configs.tsx +0 -506
- package/src/components/history/EntityHistoryEntry.tsx +0 -203
- package/src/components/history/EntityHistoryView.tsx +0 -206
- package/src/components/history/LastEditedByFormAction.tsx +0 -24
- package/src/components/history/LastEditedByIndicator.tsx +0 -95
- package/src/components/history/UserChip.tsx +0 -15
- package/src/components/history/index.tsx +0 -5
- package/src/components/index.ts +0 -63
- package/src/contexts/BreacrumbsContext.tsx +0 -45
- package/src/contexts/SideDialogsControllerContext.tsx +0 -5
- package/src/contexts/SidePanelControllerContext.tsx +0 -5
- package/src/data_export/export/BasicExportAction.tsx +0 -142
- package/src/data_export/export/ExportCollectionAction.tsx +0 -321
- package/src/data_export/export/export.ts +0 -295
- package/src/data_export/export/fetch_export_data.ts +0 -90
- package/src/data_export/export/index.ts +0 -4
- package/src/data_export/index.ts +0 -1
- package/src/data_import/components/DataNewPropertiesMapping.tsx +0 -261
- package/src/data_import/components/ImportFileUpload.tsx +0 -42
- package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +0 -58
- package/src/data_import/components/ImportSaveInProgress.tsx +0 -121
- package/src/data_import/components/index.ts +0 -4
- package/src/data_import/hooks/index.ts +0 -1
- package/src/data_import/hooks/useImportConfig.tsx +0 -34
- package/src/data_import/import/ImportCollectionAction.tsx +0 -461
- package/src/data_import/import/index.ts +0 -1
- package/src/data_import/index.ts +0 -5
- package/src/data_import/types/column_mapping.ts +0 -32
- package/src/data_import/types/index.ts +0 -1
- package/src/data_import/utils/csv.ts +0 -153
- package/src/data_import/utils/data.ts +0 -181
- package/src/data_import/utils/file_headers.ts +0 -14
- package/src/data_import/utils/file_to_json.ts +0 -149
- package/src/data_import/utils/get_import_inference_type.ts +0 -33
- package/src/data_import/utils/get_properties_mapping.ts +0 -67
- package/src/data_import/utils/index.ts +0 -5
- package/src/data_import/utils/save_entities.ts +0 -138
- package/src/data_import/utils/transforms.ts +0 -70
- package/src/editor/components/SlashCommandMenu.tsx +0 -532
- package/src/editor/components/editor-bubble-item.tsx +0 -32
- package/src/editor/components/editor-bubble.tsx +0 -143
- package/src/editor/components/image-bubble.tsx +0 -183
- package/src/editor/components/index.ts +0 -14
- package/src/editor/components/table-bubble.tsx +0 -233
- package/src/editor/editor.tsx +0 -529
- package/src/editor/extensions/HighlightDecorationExtension.ts +0 -115
- package/src/editor/extensions/Image.ts +0 -159
- package/src/editor/extensions/TextLoadingDecorationExtension.tsx +0 -107
- package/src/editor/extensions/clipboard.ts +0 -72
- package/src/editor/extensions/custom-keymap.ts +0 -25
- package/src/editor/extensions/drag-and-drop.tsx +0 -508
- package/src/editor/hooks/useProseMirror.ts +0 -126
- package/src/editor/hooks/useProseMirrorContext.ts +0 -15
- package/src/editor/index.ts +0 -2
- package/src/editor/markdown-it-plugins.d.ts +0 -24
- package/src/editor/markdown.ts +0 -204
- package/src/editor/nodeViews/ImageComponent.tsx +0 -20
- package/src/editor/nodeViews/ReactNodeView.tsx +0 -89
- package/src/editor/nodeViews/TaskItemComponent.tsx +0 -30
- package/src/editor/nodeViews/index.ts +0 -35
- package/src/editor/plugins/index.ts +0 -58
- package/src/editor/plugins/inputrules.ts +0 -82
- package/src/editor/plugins/placeholderPlugin.ts +0 -55
- package/src/editor/plugins/slashCommandPlugin.ts +0 -65
- package/src/editor/schema.ts +0 -339
- package/src/editor/selectors/ai-selector.tsx +0 -110
- package/src/editor/selectors/color-selector.tsx +0 -199
- package/src/editor/selectors/link-selector.tsx +0 -122
- package/src/editor/selectors/node-selector.tsx +0 -159
- package/src/editor/selectors/text-buttons.tsx +0 -79
- package/src/editor/types.ts +0 -6
- package/src/editor/useProseMirror.ts +0 -125
- package/src/editor/utils/prosemirror-utils.ts +0 -113
- package/src/editor/utils/remove_classes.ts +0 -18
- package/src/editor/utils/useDebouncedCallback.ts +0 -25
- package/src/form/EntityForm.tsx +0 -761
- package/src/form/EntityFormActions.tsx +0 -160
- package/src/form/EntityFormBinding.tsx +0 -342
- package/src/form/PropertyFieldBinding.tsx +0 -348
- package/src/form/components/ErrorFocus.tsx +0 -44
- package/src/form/components/FieldBlock.tsx +0 -189
- package/src/form/components/FieldHelperText.tsx +0 -84
- package/src/form/components/FormRail.tsx +0 -153
- package/src/form/components/FormSections.tsx +0 -145
- package/src/form/components/LabelWithIcon.tsx +0 -43
- package/src/form/components/LabelWithIconAndTooltip.tsx +0 -28
- package/src/form/components/LocalChangesMenu.tsx +0 -147
- package/src/form/components/StorageItemPreview.tsx +0 -81
- package/src/form/components/StorageUploadProgress.tsx +0 -118
- package/src/form/components/index.tsx +0 -6
- package/src/form/components/useRailVisible.tsx +0 -47
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +0 -109
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -172
- package/src/form/field_bindings/BinaryFieldBinding.tsx +0 -177
- package/src/form/field_bindings/BlockFieldBinding.tsx +0 -282
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +0 -78
- package/src/form/field_bindings/GeopointFieldBinding.tsx +0 -200
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -574
- package/src/form/field_bindings/MapFieldBinding.tsx +0 -120
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +0 -259
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +0 -130
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +0 -168
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -94
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +0 -146
- package/src/form/field_bindings/RelationFieldBinding.tsx +0 -202
- package/src/form/field_bindings/RepeatFieldBinding.tsx +0 -143
- package/src/form/field_bindings/SelectFieldBinding.tsx +0 -111
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +0 -521
- package/src/form/field_bindings/SwitchFieldBinding.tsx +0 -70
- package/src/form/field_bindings/TextFieldBinding.tsx +0 -189
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +0 -71
- package/src/form/field_bindings/VectorFieldBinding.tsx +0 -209
- package/src/form/form_utils.ts +0 -243
- package/src/form/index.tsx +0 -36
- package/src/form/useClearRestoreValue.tsx +0 -36
- package/src/form/useUndoableDiscard.ts +0 -39
- package/src/form/validation.ts +0 -583
- package/src/hooks/index.ts +0 -16
- package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +0 -22
- package/src/hooks/navigation/contexts/NavigationStateContext.tsx +0 -16
- package/src/hooks/navigation/contexts/UrlContext.tsx +0 -24
- package/src/hooks/navigation/contexts/index.ts +0 -14
- package/src/hooks/navigation/useAsyncResolver.ts +0 -100
- package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +0 -218
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +0 -134
- package/src/hooks/navigation/useBuildUrlController.tsx +0 -66
- package/src/hooks/navigation/useNavigationResolution.ts +0 -271
- package/src/hooks/navigation/useResolvedCollections.ts +0 -102
- package/src/hooks/navigation/useResolvedViews.tsx +0 -139
- package/src/hooks/navigation/useTopLevelNavigation.ts +0 -273
- package/src/hooks/navigation/utils.ts +0 -200
- package/src/hooks/useAdminContext.tsx +0 -83
- package/src/hooks/useBreadcrumbsController.tsx +0 -17
- package/src/hooks/useBuildSideDialogsController.tsx +0 -145
- package/src/hooks/useBuildSidePanel.tsx +0 -315
- package/src/hooks/useChildViewSource.ts +0 -46
- package/src/hooks/useEntityDisplay.tsx +0 -262
- package/src/hooks/useEntityDisplayTitle.tsx +0 -49
- package/src/hooks/useHistory.ts +0 -178
- package/src/hooks/useRecordActions.tsx +0 -69
- package/src/hooks/useResolvedNavigationFrom.tsx +0 -167
- package/src/hooks/useResolvedUsers.ts +0 -148
- package/src/hooks/useSelectionDialog.tsx +0 -58
- package/src/hooks/useSideDialogsController.tsx +0 -25
- package/src/hooks/useSidePanel.tsx +0 -13
- package/src/index.ts +0 -124
- package/src/preview/PropertyPreview.tsx +0 -331
- package/src/preview/compact_text.ts +0 -68
- package/src/preview/components/ArrayEnumPreview.tsx +0 -39
- package/src/preview/components/BooleanPreview.tsx +0 -28
- package/src/preview/components/DatePreview.tsx +0 -106
- package/src/preview/components/EmptyValue.tsx +0 -10
- package/src/preview/components/EnumValuesChip.tsx +0 -39
- package/src/preview/components/ImagePreview.tsx +0 -144
- package/src/preview/components/InlineEntityListPreview.tsx +0 -42
- package/src/preview/components/ReferencePreview.tsx +0 -235
- package/src/preview/components/RelationPreview.tsx +0 -271
- package/src/preview/components/StorageThumbnail.tsx +0 -147
- package/src/preview/components/UrlComponentPreview.tsx +0 -116
- package/src/preview/components/UserPreview.tsx +0 -30
- package/src/preview/components/date_fns_locales.ts +0 -125
- package/src/preview/index.ts +0 -26
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -73
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -67
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +0 -77
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -49
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -70
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -79
- package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +0 -35
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -79
- package/src/preview/property_previews/MapPropertyPreview.tsx +0 -198
- package/src/preview/property_previews/NumberPropertyPreview.tsx +0 -39
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +0 -276
- package/src/preview/property_previews/StringPropertyPreview.tsx +0 -70
- package/src/preview/util.ts +0 -39
- package/src/routes/CustomViewRoute.tsx +0 -33
- package/src/routes/RebaseRoute.tsx +0 -467
- package/src/routes/index.ts +0 -2
- package/src/types/components/EntityFormActionsProps.tsx +0 -20
- package/src/types/components/EntityFormProps.tsx +0 -119
- package/src/types/components/PropertyPreviewProps.tsx +0 -85
- package/src/types/components/formex.tsx +0 -2
- package/src/types/components/index.ts +0 -3
- package/src/types/fields.tsx +0 -340
- package/src/types/index.ts +0 -4
- package/src/util/dataControllerAdapter.ts +0 -88
- package/src/util/entity_actions.ts +0 -28
- package/src/util/index.ts +0 -5
- package/src/util/navigation_utils.ts +0 -89
- package/src/util/number_format.ts +0 -46
- package/src/util/previews.ts +0 -131
- package/src/util/propertyConfigMapper.ts +0 -134
- package/src/util/property_utils.tsx +0 -236
- package/src/util/resolutions.ts +0 -96
- package/src/util/view_constants.ts +0 -33
- package/src/util/view_mode.ts +0 -176
|
@@ -1,530 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { getPolicyNamesForRule, getPolicyNamesForRules } from "@rebasepro/utils";
|
|
3
|
-
import { getGeneratedPolicyNames } from "@rebasepro/common";
|
|
4
|
-
import React, { useState, useEffect, useMemo } from "react";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Validates and double-quotes a SQL identifier to prevent injection.
|
|
8
|
-
* Only allows safe Postgres identifiers (letters, digits, underscores).
|
|
9
|
-
* Throws if the identifier contains unsafe characters.
|
|
10
|
-
*/
|
|
11
|
-
function sanitizeSqlIdentifier(name: string): string {
|
|
12
|
-
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
13
|
-
throw new Error(`Invalid SQL identifier: "${name}". Only letters, digits, and underscores are allowed.`);
|
|
14
|
-
}
|
|
15
|
-
return `"${name}"`;
|
|
16
|
-
}
|
|
17
|
-
import {
|
|
18
|
-
Button,
|
|
19
|
-
Chip,
|
|
20
|
-
CircularProgress,
|
|
21
|
-
cls,
|
|
22
|
-
Container,
|
|
23
|
-
defaultBorderMixin,
|
|
24
|
-
Dialog,
|
|
25
|
-
DialogActions,
|
|
26
|
-
DialogContent,
|
|
27
|
-
DialogTitle,
|
|
28
|
-
IconButton,
|
|
29
|
-
iconSize,
|
|
30
|
-
KeyIcon,
|
|
31
|
-
MultiSelect,
|
|
32
|
-
MultiSelectItem,
|
|
33
|
-
Paper,
|
|
34
|
-
Select,
|
|
35
|
-
SelectItem,
|
|
36
|
-
TextField,
|
|
37
|
-
Tooltip,
|
|
38
|
-
Trash2Icon,
|
|
39
|
-
Typography
|
|
40
|
-
} from "@rebasepro/ui";
|
|
41
|
-
import { useFormex } from "@rebasepro/forms";
|
|
42
|
-
import { useCollectionsConfigController } from "../../useCollectionsConfigController";
|
|
43
|
-
import { useRebaseContext, useTranslation } from "@rebasepro/app";
|
|
44
|
-
import type { AdminCollection } from "@rebasepro/cms-types";
|
|
45
|
-
import { RLS_ROLES_SQL, RLS_UID_SQL, type PostgresPolicy, type SecurityOperation, type SecurityRule } from "@rebasepro/types";
|
|
46
|
-
|
|
47
|
-
export type { PostgresPolicy } from "@rebasepro/types";
|
|
48
|
-
|
|
49
|
-
type CollectionWithSecurity = AdminCollection & {
|
|
50
|
-
securityRules?: SecurityRule[];
|
|
51
|
-
id?: string;
|
|
52
|
-
table?: string;
|
|
53
|
-
alias?: string;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* `pg_policies` reports the operation and the permissive flag in upper case;
|
|
58
|
-
* `SecurityRule` names them in lower case. These two used to be `.toLowerCase()`
|
|
59
|
-
* assigned straight into a `SecurityRule`, which typechecks only against a
|
|
60
|
-
* `string` field — and this file declared its own local `SecurityRule` with
|
|
61
|
-
* `operation?: string`, so it did. Against the real type it does not: an
|
|
62
|
-
* unrecognised `cmd` would have been written into the collection as a policy
|
|
63
|
-
* operation that compiles to nothing.
|
|
64
|
-
*/
|
|
65
|
-
function toSecurityOperation(cmd: PostgresPolicy["cmd"] | undefined): SecurityOperation | undefined {
|
|
66
|
-
switch (cmd) {
|
|
67
|
-
case "SELECT": return "select";
|
|
68
|
-
case "INSERT": return "insert";
|
|
69
|
-
case "UPDATE": return "update";
|
|
70
|
-
case "DELETE": return "delete";
|
|
71
|
-
case "ALL": return "all";
|
|
72
|
-
default: return undefined;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function toSecurityMode(permissive: PostgresPolicy["permissive"] | undefined): SecurityRule["mode"] {
|
|
77
|
-
// Absent stays absent. `permissive` is the default, so writing it out
|
|
78
|
-
// changes nothing semantically — but this value is serialized into the
|
|
79
|
-
// user's collection file, and defaulting here would grow a `mode:
|
|
80
|
-
// "permissive"` on every rule the editor touches. The `.toLowerCase()`
|
|
81
|
-
// this replaced returned `undefined` for an absent value; that part was
|
|
82
|
-
// right, and only the widened type was wrong.
|
|
83
|
-
if (!permissive) return undefined;
|
|
84
|
-
return permissive === "RESTRICTIVE" ? "restrictive" : "permissive";
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Build a {@link SecurityRule} from a `pg_policies` row.
|
|
89
|
-
*
|
|
90
|
-
* `SecurityRule` is a discriminated union and this is the part the local shadow
|
|
91
|
-
* type flattened away: a raw-SQL rule *requires* `using`, so a policy with only
|
|
92
|
-
* a `WITH CHECK` clause — every INSERT-only policy — is not one. It is a
|
|
93
|
-
* roles-only rule carrying the check. Assembling the object field-by-field
|
|
94
|
-
* against `operation?: string` accepted all of these and told the compiler
|
|
95
|
-
* nothing.
|
|
96
|
-
*/
|
|
97
|
-
function toSecurityRule(policy: Partial<PostgresPolicy>): SecurityRule {
|
|
98
|
-
const base = {
|
|
99
|
-
name: policy.policyname ?? "",
|
|
100
|
-
operation: toSecurityOperation(policy.cmd),
|
|
101
|
-
mode: toSecurityMode(policy.permissive),
|
|
102
|
-
roles: policy.roles ? [...policy.roles] : undefined
|
|
103
|
-
};
|
|
104
|
-
if (policy.qual) {
|
|
105
|
-
return {
|
|
106
|
-
...base,
|
|
107
|
-
using: policy.qual,
|
|
108
|
-
withCheck: policy.with_check || undefined
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
return base;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function CollectionRLSTab() {
|
|
115
|
-
const { values, setFieldValue } = useFormex<CollectionWithSecurity>();
|
|
116
|
-
const [editingPolicy, setEditingPolicy] = useState<PostgresPolicy | "new" | null>(null);
|
|
117
|
-
|
|
118
|
-
// Every other tab in this dialog disables its inputs when the backend will
|
|
119
|
-
// not accept an edit — the general and display forms behind a `fieldset
|
|
120
|
-
// disabled`, the properties editor per control. This one did not, so a
|
|
121
|
-
// read-only panel still invited you to write a policy, delete one, and
|
|
122
|
-
// reorder the lot, and only said no at the submit button on the way out.
|
|
123
|
-
const { readOnly, readOnlyReason } = useCollectionsConfigController();
|
|
124
|
-
const readOnlyTitle = readOnlyReason || "This backend does not accept collection edits.";
|
|
125
|
-
|
|
126
|
-
const rules: SecurityRule[] = values.securityRules || [];
|
|
127
|
-
|
|
128
|
-
const { databaseAdmin } = useRebaseContext();
|
|
129
|
-
const [dbPolicies, setDbPolicies] = useState<PostgresPolicy[]>([]);
|
|
130
|
-
const [isLoadingDb, setIsLoadingDb] = useState(false);
|
|
131
|
-
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
const fetchLivePolicies = async () => {
|
|
134
|
-
const tableName = values.id || values.table || values.alias;
|
|
135
|
-
if (!tableName || !databaseAdmin?.executeSql) return;
|
|
136
|
-
|
|
137
|
-
setIsLoadingDb(true);
|
|
138
|
-
try {
|
|
139
|
-
const safeTableName = sanitizeSqlIdentifier(tableName);
|
|
140
|
-
// safeTableName is validated to be [a-zA-Z_][a-zA-Z0-9_]* — safe for string literal
|
|
141
|
-
const quotedName = safeTableName.slice(1, -1); // strip double quotes to get raw name
|
|
142
|
-
const sql = `
|
|
143
|
-
SELECT policyname, permissive, roles, cmd, qual, with_check
|
|
144
|
-
FROM pg_policies
|
|
145
|
-
WHERE tablename = '${quotedName}' AND schemaname NOT IN ('information_schema', 'pg_catalog');
|
|
146
|
-
`;
|
|
147
|
-
const result = await databaseAdmin.executeSql(sql);
|
|
148
|
-
const extractRows = (res: unknown): Record<string, unknown>[] => {
|
|
149
|
-
if (res && typeof res === "object" && "rows" in res && Array.isArray((res as { rows: Record<string, unknown>[] }).rows)) {
|
|
150
|
-
return (res as { rows: Record<string, unknown>[] }).rows;
|
|
151
|
-
}
|
|
152
|
-
if (Array.isArray(res)) return res as Record<string, unknown>[];
|
|
153
|
-
return [];
|
|
154
|
-
};
|
|
155
|
-
const pRows = extractRows(result);
|
|
156
|
-
const policies: PostgresPolicy[] = pRows.map((p: Record<string, unknown>) => {
|
|
157
|
-
let parsedRoles: string[] = [];
|
|
158
|
-
const r = p.roles || p.ROLES;
|
|
159
|
-
if (Array.isArray(r)) {
|
|
160
|
-
parsedRoles = r as string[];
|
|
161
|
-
} else if (typeof r === "string") {
|
|
162
|
-
parsedRoles = r.replace(/^{|}$/g, "").split(",").map((s: string) => s.trim());
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
policyname: (p.policyname || p.POLICYNAME || "") as string,
|
|
166
|
-
tablename: tableName,
|
|
167
|
-
permissive: (p.permissive || p.PERMISSIVE || "PERMISSIVE") as "PERMISSIVE" | "RESTRICTIVE",
|
|
168
|
-
roles: parsedRoles,
|
|
169
|
-
cmd: (p.cmd || p.CMD || "ALL") as "SELECT" | "INSERT" | "UPDATE" | "DELETE" | "ALL",
|
|
170
|
-
qual: (p.qual || p.QUAL || null) as string | null,
|
|
171
|
-
with_check: (p.with_check || p.WITH_CHECK || null) as string | null
|
|
172
|
-
};
|
|
173
|
-
});
|
|
174
|
-
setDbPolicies(policies);
|
|
175
|
-
} catch (e) {
|
|
176
|
-
console.error("Failed to fetch DB policies", e);
|
|
177
|
-
} finally {
|
|
178
|
-
setIsLoadingDb(false);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
fetchLivePolicies();
|
|
182
|
-
}, [databaseAdmin, values.id, values.table, values.alias]);
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Application roles available to `SecurityRule.roles`.
|
|
186
|
-
*
|
|
187
|
-
* Deliberately NOT `fetchAvailableRoles` — that returns native pg_roles
|
|
188
|
-
* (postgres, rebase_user, …), which can never satisfy an application-role
|
|
189
|
-
* condition.
|
|
190
|
-
*/
|
|
191
|
-
const [availableRoles, setAvailableRoles] = useState<string[]>([]);
|
|
192
|
-
const [rolesUnavailable, setRolesUnavailable] = useState(false);
|
|
193
|
-
|
|
194
|
-
useEffect(() => {
|
|
195
|
-
let mounted = true;
|
|
196
|
-
const fetchRoles = async () => {
|
|
197
|
-
if (!databaseAdmin?.fetchApplicationRoles) {
|
|
198
|
-
// Older backend, or a driver with no application-role concept.
|
|
199
|
-
if (mounted) setRolesUnavailable(true);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
try {
|
|
203
|
-
const fetched = await databaseAdmin.fetchApplicationRoles();
|
|
204
|
-
if (mounted) {
|
|
205
|
-
setAvailableRoles(fetched);
|
|
206
|
-
setRolesUnavailable(false);
|
|
207
|
-
}
|
|
208
|
-
} catch (e) {
|
|
209
|
-
console.error("Failed to fetch application roles", e);
|
|
210
|
-
if (mounted) setRolesUnavailable(true);
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
fetchRoles();
|
|
214
|
-
return () => {
|
|
215
|
-
mounted = false;
|
|
216
|
-
};
|
|
217
|
-
}, [databaseAdmin]);
|
|
218
|
-
|
|
219
|
-
const tableName = values.id || values.table || values.alias;
|
|
220
|
-
|
|
221
|
-
// Every policy name `rebase db push` would write for this collection — see
|
|
222
|
-
// `getGeneratedPolicyNames`. This used to be derived here by hand, and the
|
|
223
|
-
// Studio's RLS editor derived a different subset of it by hand, which is
|
|
224
|
-
// exactly how the two came to disagree about which policies were drift.
|
|
225
|
-
const generatedPolicyNames = useMemo(() => {
|
|
226
|
-
if (!tableName) return new Set<string>();
|
|
227
|
-
return getGeneratedPolicyNames(values as AdminCollection);
|
|
228
|
-
}, [tableName, values]);
|
|
229
|
-
|
|
230
|
-
const unmappedPolicies = dbPolicies.filter(dp => !generatedPolicyNames.has(dp.policyname));
|
|
231
|
-
|
|
232
|
-
const handleSave = async (newPolicy: Partial<PostgresPolicy>) => {
|
|
233
|
-
const rule: SecurityRule = toSecurityRule(newPolicy);
|
|
234
|
-
|
|
235
|
-
let newRules;
|
|
236
|
-
if (editingPolicy === "new") {
|
|
237
|
-
newRules = [...rules, rule];
|
|
238
|
-
} else {
|
|
239
|
-
newRules = rules.map((r: SecurityRule) => r.name === (editingPolicy as PostgresPolicy).policyname ? rule : r);
|
|
240
|
-
}
|
|
241
|
-
setFieldValue("securityRules", newRules);
|
|
242
|
-
setEditingPolicy(null);
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
return (
|
|
246
|
-
<div className={"overflow-auto my-auto"}>
|
|
247
|
-
<Container maxWidth={"4xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
|
|
248
|
-
<div className="w-full flex flex-col">
|
|
249
|
-
<div className="flex items-center justify-between mb-8">
|
|
250
|
-
<Typography variant="h5">Row Level Security</Typography>
|
|
251
|
-
<Tooltip title={readOnly ? readOnlyTitle : undefined}>
|
|
252
|
-
<div>
|
|
253
|
-
<Button variant="filled" color="neutral" disabled={readOnly} onClick={() => setEditingPolicy("new")}>
|
|
254
|
-
CREATE POLICY
|
|
255
|
-
</Button>
|
|
256
|
-
</div>
|
|
257
|
-
</Tooltip>
|
|
258
|
-
</div>
|
|
259
|
-
|
|
260
|
-
{rules.length === 0 ? (
|
|
261
|
-
<div className="flex-grow flex items-center justify-center text-text-disabled py-12">
|
|
262
|
-
<Typography variant="body2">No RLS policies defined for this collection.</Typography>
|
|
263
|
-
</div>
|
|
264
|
-
) : (
|
|
265
|
-
<div className="flex flex-col gap-3">
|
|
266
|
-
{rules.map((rule: SecurityRule) => (
|
|
267
|
-
<Paper key={rule.name}
|
|
268
|
-
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-white dark:bg-surface-800 shadow-sm"}>
|
|
269
|
-
<div className="flex flex-col gap-1.5 min-w-0">
|
|
270
|
-
<div className="flex items-center gap-2">
|
|
271
|
-
<KeyIcon size={iconSize.smallest} className="text-text-disabled dark:text-text-disabled-dark shrink-0"/>
|
|
272
|
-
<Typography variant="subtitle2" className="truncate">
|
|
273
|
-
{/* Unnamed rules are still named in Postgres — show what they compile to
|
|
274
|
-
rather than an empty heading. */}
|
|
275
|
-
{rule.name || (tableName
|
|
276
|
-
? getPolicyNamesForRule(rule, tableName).join(", ")
|
|
277
|
-
: "Unnamed policy")}
|
|
278
|
-
</Typography>
|
|
279
|
-
</div>
|
|
280
|
-
<div className="flex gap-2 text-xs pl-6 overflow-x-auto hide-scrollbar">
|
|
281
|
-
<Chip size="small" className="bg-surface-100 dark:bg-surface-900 text-text-secondary border-none">Action: {rule.operation || "ALL"}</Chip>
|
|
282
|
-
<Chip size="small" className="bg-surface-100 dark:bg-surface-900 text-text-secondary border-none">Roles: {Array.isArray(rule.roles) ? rule.roles.join(", ") : rule.roles}</Chip>
|
|
283
|
-
</div>
|
|
284
|
-
</div>
|
|
285
|
-
<div className="flex items-center gap-1 sm:gap-2 shrink-0">
|
|
286
|
-
<Button size="small" variant="text" disabled={readOnly} onClick={() => setEditingPolicy({
|
|
287
|
-
policyname: rule.name ?? "",
|
|
288
|
-
tablename: values.id || values.table || values.alias || "your_table",
|
|
289
|
-
permissive: (rule.mode || "permissive").toUpperCase() as PostgresPolicy["permissive"],
|
|
290
|
-
cmd: (rule.operation || "ALL").toUpperCase() as PostgresPolicy["cmd"],
|
|
291
|
-
roles: [...(rule.roles ?? [])],
|
|
292
|
-
qual: rule.using || null,
|
|
293
|
-
with_check: rule.withCheck || null
|
|
294
|
-
})}>
|
|
295
|
-
EDIT
|
|
296
|
-
</Button>
|
|
297
|
-
<IconButton size="small" disabled={readOnly} onClick={() => {
|
|
298
|
-
setFieldValue("securityRules", rules.filter((r: SecurityRule) => r.name !== rule.name));
|
|
299
|
-
}}>
|
|
300
|
-
<Trash2Icon size={iconSize.smallest} className="text-text-secondary dark:text-text-secondary-dark hover:text-red-500 dark:hover:text-red-500 transition-colors"/>
|
|
301
|
-
</IconButton>
|
|
302
|
-
</div>
|
|
303
|
-
</Paper>
|
|
304
|
-
))}
|
|
305
|
-
</div>
|
|
306
|
-
)}
|
|
307
|
-
|
|
308
|
-
{isLoadingDb && unmappedPolicies.length === 0 && (
|
|
309
|
-
<div className="flex justify-center mt-8">
|
|
310
|
-
<CircularProgress size="small"/>
|
|
311
|
-
</div>
|
|
312
|
-
)}
|
|
313
|
-
|
|
314
|
-
{!isLoadingDb && unmappedPolicies.length > 0 && (
|
|
315
|
-
<div className="mt-12 flex flex-col gap-4">
|
|
316
|
-
<Typography variant="h6" className="text-text-secondary">Unmapped Database Policies</Typography>
|
|
317
|
-
<Typography variant="body2" className="text-text-secondary opacity-80 -mt-2">
|
|
318
|
-
These policies exist in your Postgres database but are not mapped to this collection's codebase configuration.
|
|
319
|
-
</Typography>
|
|
320
|
-
<div className="flex flex-col gap-3">
|
|
321
|
-
{unmappedPolicies.map(dp => (
|
|
322
|
-
<Paper key={dp.policyname}
|
|
323
|
-
className={"p-4 border border-orange-200 dark:border-orange-900/50 bg-orange-50/50 dark:bg-orange-900/10 rounded-lg flex flex-col sm:flex-row sm:items-center justify-between gap-4 transition-colors"}>
|
|
324
|
-
<div className="flex flex-col gap-1.5 min-w-0">
|
|
325
|
-
<div className="flex items-center gap-2">
|
|
326
|
-
<KeyIcon size={iconSize.smallest} className="text-orange-500 shrink-0"/>
|
|
327
|
-
<Typography variant="subtitle2" className="truncate">{dp.policyname}</Typography>
|
|
328
|
-
<Tooltip title="This policy is live in the database but missing from your codebase schema.">
|
|
329
|
-
<div className="px-1.5 py-0.5 rounded text-[10px] uppercase bg-orange-500/10 text-orange-600 border border-orange-500/20 shrink-0">
|
|
330
|
-
DB Only
|
|
331
|
-
</div>
|
|
332
|
-
</Tooltip>
|
|
333
|
-
</div>
|
|
334
|
-
<div className="flex gap-2 text-xs pl-6 overflow-x-auto hide-scrollbar">
|
|
335
|
-
<Chip size="small" className="bg-white dark:bg-surface-900 text-text-secondary border-none">Action: {dp.cmd || "ALL"}</Chip>
|
|
336
|
-
<Chip size="small" className="bg-white dark:bg-surface-900 text-text-secondary border-none">Roles: {Array.isArray(dp.roles) ? dp.roles.join(", ") : dp.roles}</Chip>
|
|
337
|
-
</div>
|
|
338
|
-
</div>
|
|
339
|
-
<div className="flex items-center gap-1 sm:gap-2 shrink-0">
|
|
340
|
-
{/* "Import to codebase" is the one action here that
|
|
341
|
-
names its destination, and it is the one the
|
|
342
|
-
backend refuses when it has no codebase to write. */}
|
|
343
|
-
<Tooltip title={readOnly ? readOnlyTitle : undefined}>
|
|
344
|
-
<div>
|
|
345
|
-
<Button size="small" variant="outlined" color="primary" disabled={readOnly} onClick={() => {
|
|
346
|
-
const rule: SecurityRule = toSecurityRule(dp);
|
|
347
|
-
setFieldValue("securityRules", [...rules, rule]);
|
|
348
|
-
}}>
|
|
349
|
-
Import to codebase
|
|
350
|
-
</Button>
|
|
351
|
-
</div>
|
|
352
|
-
</Tooltip>
|
|
353
|
-
</div>
|
|
354
|
-
</Paper>
|
|
355
|
-
))}
|
|
356
|
-
</div>
|
|
357
|
-
</div>
|
|
358
|
-
)}
|
|
359
|
-
</div>
|
|
360
|
-
<Dialog open={!!editingPolicy} onOpenChange={(open) => !open && setEditingPolicy(null)} maxWidth="4xl">
|
|
361
|
-
{editingPolicy && (
|
|
362
|
-
<InlinePolicyEditor
|
|
363
|
-
policy={editingPolicy === "new" ? undefined : editingPolicy}
|
|
364
|
-
table={values.id || values.table || values.alias || "your_table"}
|
|
365
|
-
availableRoles={availableRoles}
|
|
366
|
-
rolesUnavailable={rolesUnavailable}
|
|
367
|
-
onSave={handleSave}
|
|
368
|
-
onCancel={() => setEditingPolicy(null)}
|
|
369
|
-
/>
|
|
370
|
-
)}
|
|
371
|
-
</Dialog>
|
|
372
|
-
</Container>
|
|
373
|
-
</div>
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// ─── Inline Policy Editor (no Monaco dependency) ────────────────────
|
|
378
|
-
|
|
379
|
-
type PolicyCommand = "ALL" | "SELECT" | "INSERT" | "UPDATE" | "DELETE";
|
|
380
|
-
const COMMAND_OPTIONS: PolicyCommand[] = ["ALL", "SELECT", "INSERT", "UPDATE", "DELETE"];
|
|
381
|
-
|
|
382
|
-
function InlinePolicyEditor({
|
|
383
|
-
policy,
|
|
384
|
-
table,
|
|
385
|
-
availableRoles,
|
|
386
|
-
rolesUnavailable,
|
|
387
|
-
onSave,
|
|
388
|
-
onCancel
|
|
389
|
-
}: {
|
|
390
|
-
policy?: PostgresPolicy;
|
|
391
|
-
table: string;
|
|
392
|
-
availableRoles: string[];
|
|
393
|
-
rolesUnavailable: boolean;
|
|
394
|
-
onSave: (policyData: Partial<PostgresPolicy>) => void;
|
|
395
|
-
onCancel: () => void;
|
|
396
|
-
}) {
|
|
397
|
-
const { t } = useTranslation();
|
|
398
|
-
const [name, setName] = useState(policy?.policyname || "");
|
|
399
|
-
const [behavior, setBehavior] = useState<"PERMISSIVE" | "RESTRICTIVE">(policy?.permissive || "PERMISSIVE");
|
|
400
|
-
const [command, setCommand] = useState<PolicyCommand>((policy?.cmd as PolicyCommand) || "ALL");
|
|
401
|
-
// No roles means "not restricted by role". Seeding a value here would
|
|
402
|
-
// silently narrow every new policy to it.
|
|
403
|
-
const [roles, setRoles] = useState<string[]>(
|
|
404
|
-
policy?.roles ? (Array.isArray(policy.roles) ? policy.roles : [policy.roles]) : []
|
|
405
|
-
);
|
|
406
|
-
const [customRole, setCustomRole] = useState("");
|
|
407
|
-
const [usingExpr, setUsingExpr] = useState(policy?.qual || "");
|
|
408
|
-
const [checkExpr, setCheckExpr] = useState(policy?.with_check || "");
|
|
409
|
-
|
|
410
|
-
const showCheck = command === "ALL" || command === "INSERT" || command === "UPDATE";
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Roles offered in the dropdown: those in use in the project, plus any the
|
|
414
|
-
* rule already carries. The union matters — application roles are derived
|
|
415
|
-
* from what users hold, so a role that is referenced here but assigned to
|
|
416
|
-
* nobody would otherwise vanish from its own policy on the next save.
|
|
417
|
-
*/
|
|
418
|
-
const roleOptions = useMemo(
|
|
419
|
-
() => Array.from(new Set([...availableRoles, ...roles])).sort(),
|
|
420
|
-
[availableRoles, roles]
|
|
421
|
-
);
|
|
422
|
-
|
|
423
|
-
const addCustomRole = () => {
|
|
424
|
-
const trimmed = customRole.trim();
|
|
425
|
-
if (!trimmed || roles.includes(trimmed)) {
|
|
426
|
-
setCustomRole("");
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
setRoles([...roles, trimmed]);
|
|
430
|
-
setCustomRole("");
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
return (
|
|
434
|
-
<>
|
|
435
|
-
<DialogTitle variant="h6">
|
|
436
|
-
{policy ? "Edit Policy" : "Create Policy"}
|
|
437
|
-
<div className="text-sm font-normal text-text-secondary dark:text-text-secondary-dark tracking-wide mt-1">
|
|
438
|
-
Define RLS rules for <span className="font-mono text-primary bg-primary-bg dark:bg-primary-bg-dark px-1 py-0.5 rounded">public.{table}</span>
|
|
439
|
-
</div>
|
|
440
|
-
</DialogTitle>
|
|
441
|
-
<DialogContent className="p-4 md:p-6 border-t dark:border-surface-700 bg-surface-50 dark:bg-surface-800" includeMargin={false}>
|
|
442
|
-
<Paper className={cls("p-4 md:p-6 flex flex-col gap-6 bg-white dark:bg-surface-800 border-none sm:border-solid rounded-none sm:rounded-xl", defaultBorderMixin)}>
|
|
443
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
444
|
-
<div className="flex flex-col gap-1.5">
|
|
445
|
-
<Typography variant="caption" className="uppercase tracking-wider text-text-secondary">{t("studio_policy_name")}</Typography>
|
|
446
|
-
<TextField aria-label={t("studio_policy_name")} value={name} onChange={(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => setName(e.target.value)} placeholder="e.g. allow_read_all"/>
|
|
447
|
-
</div>
|
|
448
|
-
<div className="flex flex-col gap-1.5">
|
|
449
|
-
<Typography variant="caption" className="uppercase tracking-wider text-text-secondary">Behavior</Typography>
|
|
450
|
-
<Select value={behavior} onValueChange={(val: string) => setBehavior(val as "PERMISSIVE" | "RESTRICTIVE")} position="item-aligned">
|
|
451
|
-
<SelectItem value="PERMISSIVE">Permissive</SelectItem>
|
|
452
|
-
<SelectItem value="RESTRICTIVE">Restrictive</SelectItem>
|
|
453
|
-
</Select>
|
|
454
|
-
</div>
|
|
455
|
-
</div>
|
|
456
|
-
<div className="flex flex-col gap-1.5">
|
|
457
|
-
<Typography variant="caption" className="uppercase tracking-wider text-text-secondary">Command</Typography>
|
|
458
|
-
<div className="flex flex-wrap gap-1.5">
|
|
459
|
-
{COMMAND_OPTIONS.map(cmd => (
|
|
460
|
-
<Button key={cmd} size="small" variant={command === cmd ? "filled" : "text"} color="neutral" onClick={() => setCommand(cmd)}>
|
|
461
|
-
{cmd}
|
|
462
|
-
</Button>
|
|
463
|
-
))}
|
|
464
|
-
</div>
|
|
465
|
-
</div>
|
|
466
|
-
<div className="flex flex-col gap-1.5">
|
|
467
|
-
<Typography variant="caption" className="uppercase tracking-wider text-text-secondary">Application Roles</Typography>
|
|
468
|
-
<Typography variant="caption" className="text-text-secondary opacity-80 -mt-1">
|
|
469
|
-
Roles held by users of this project, matched via <span className="font-mono">{RLS_ROLES_SQL}</span>.
|
|
470
|
-
These are not PostgreSQL roles — leave empty to apply the policy to everyone.
|
|
471
|
-
</Typography>
|
|
472
|
-
{roleOptions.length > 0 && (
|
|
473
|
-
<MultiSelect size="small" value={roles} onValueChange={setRoles} placeholder="Select roles">
|
|
474
|
-
{roleOptions.map(r => <MultiSelectItem key={r} value={r}>{r}</MultiSelectItem>)}
|
|
475
|
-
</MultiSelect>
|
|
476
|
-
)}
|
|
477
|
-
{rolesUnavailable && roleOptions.length === 0 && (
|
|
478
|
-
<Typography variant="caption" className="text-text-secondary opacity-80">
|
|
479
|
-
Could not load the project's roles — enter them manually below.
|
|
480
|
-
</Typography>
|
|
481
|
-
)}
|
|
482
|
-
{!rolesUnavailable && roleOptions.length === 0 && (
|
|
483
|
-
<Typography variant="caption" className="text-text-secondary opacity-80">
|
|
484
|
-
No roles are assigned to any user yet — enter one manually below.
|
|
485
|
-
</Typography>
|
|
486
|
-
)}
|
|
487
|
-
<div className="flex gap-2 items-center">
|
|
488
|
-
<TextField size="small" aria-label="Add a custom role" value={customRole}
|
|
489
|
-
onChange={(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => setCustomRole(e.target.value)}
|
|
490
|
-
onKeyDown={(e: React.KeyboardEvent) => {
|
|
491
|
-
if (e.key === "Enter") {
|
|
492
|
-
e.preventDefault();
|
|
493
|
-
addCustomRole();
|
|
494
|
-
}
|
|
495
|
-
}}
|
|
496
|
-
placeholder="Add a role not listed, e.g. editor"/>
|
|
497
|
-
<Button size="small" variant="outlined" color="neutral"
|
|
498
|
-
disabled={!customRole.trim()} onClick={addCustomRole}>
|
|
499
|
-
Add
|
|
500
|
-
</Button>
|
|
501
|
-
</div>
|
|
502
|
-
</div>
|
|
503
|
-
{command !== "INSERT" && (
|
|
504
|
-
<div className="flex flex-col gap-1.5">
|
|
505
|
-
<Typography variant="caption" className="uppercase tracking-wider text-text-secondary">{t("studio_policy_using_expr")}</Typography>
|
|
506
|
-
<TextField aria-label={t("studio_policy_using_expr")} value={usingExpr} onChange={(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => setUsingExpr(e.target.value)} placeholder={`e.g. ${RLS_UID_SQL} = uid`}/>
|
|
507
|
-
</div>
|
|
508
|
-
)}
|
|
509
|
-
{showCheck && (
|
|
510
|
-
<div className="flex flex-col gap-1.5">
|
|
511
|
-
<Typography variant="caption" className="uppercase tracking-wider text-text-secondary">{t("studio_policy_check_expr")}</Typography>
|
|
512
|
-
<TextField aria-label={t("studio_policy_check_expr")} value={checkExpr} onChange={(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => setCheckExpr(e.target.value)} placeholder={`e.g. ${RLS_UID_SQL} = uid`}/>
|
|
513
|
-
</div>
|
|
514
|
-
)}
|
|
515
|
-
</Paper>
|
|
516
|
-
</DialogContent>
|
|
517
|
-
<DialogActions>
|
|
518
|
-
<Button size="small" variant="text" color="neutral" onClick={onCancel}>Cancel</Button>
|
|
519
|
-
<Button size="small" variant="filled" color="primary" disabled={!name}
|
|
520
|
-
onClick={() => onSave({ policyname: name,
|
|
521
|
-
permissive: behavior,
|
|
522
|
-
cmd: command,
|
|
523
|
-
roles,
|
|
524
|
-
qual: usingExpr,
|
|
525
|
-
with_check: showCheck ? checkExpr : null })}
|
|
526
|
-
>Save</Button>
|
|
527
|
-
</DialogActions>
|
|
528
|
-
</>
|
|
529
|
-
);
|
|
530
|
-
}
|