@redocly/realm 0.136.0-next.1 → 0.136.0-next.11
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/CHANGELOG.md +208 -0
- package/dist/bin.js +1 -1
- package/dist/cli/build/analytics/collect-analytics.js +1 -1
- package/dist/cli/build/index.js +1 -1
- package/dist/cli/eject/ejectComponent.d.ts +1 -1
- package/dist/cli/eject/ejectTheme.d.ts +1 -1
- package/dist/cli/eject/resolveEjectParams.js +1 -1
- package/dist/cli/eject/themeOperations.d.ts +2 -2
- package/dist/cli/stats/collectors/openapi/index.js +1 -1
- package/dist/cli/stats/index.js +1 -1
- package/dist/client/App.js +1 -1
- package/dist/client/ErrorBoundary.js +1 -1
- package/dist/client/ScriptLoader.js +1 -1
- package/dist/client/TestProvider.d.ts +1 -1
- package/dist/client/TestProvider.js +1 -1
- package/dist/client/api-docs-builder-entry.d.ts +3 -0
- package/dist/client/api-docs-builder-entry.js +1 -0
- package/dist/client/app/ConditionalLink.d.ts +1 -1
- package/dist/client/app/Feedback/useSubmitFeedback.js +1 -1
- package/dist/client/app/Link.js +1 -1
- package/dist/client/app/Sidebar/Sidebar.js +3 -3
- package/dist/client/app/Sidebar/helpers/hide-empty-separators.d.ts +13 -0
- package/dist/client/app/Sidebar/helpers/hide-empty-separators.js +1 -0
- package/dist/client/app/Sidebar/useActions.js +1 -1
- package/dist/client/app/Sidebar/useBreadcrumbs.js +1 -1
- package/dist/client/app/Sidebar/useSidebarItems.js +1 -1
- package/dist/client/app/Sidebar/utils.d.ts +1 -1
- package/dist/client/app/Sidebar/utils.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogClassic.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogFilter.d.ts +1 -1
- package/dist/client/app/hooks/catalog/useCatalogFilter.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogSearch.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogSort.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalogViewMode.js +1 -1
- package/dist/client/app/hooks/catalog/useFetchCatalogEntities.d.ts +1 -1
- package/dist/client/app/hooks/catalog/useFetchCatalogEntities.js +1 -1
- package/dist/client/app/hooks/catalog/useFetchCatalogEntitiesRelations.d.ts +2 -2
- package/dist/client/app/hooks/catalog/useFetchCatalogEntitiesRelations.js +1 -1
- package/dist/client/app/hooks/catalog/useFetchCatalogEntityRevisions.d.ts +1 -1
- package/dist/client/app/hooks/catalog/useSearchTracker.d.ts +2 -5
- package/dist/client/app/hooks/catalog/useSearchTracker.js +1 -1
- package/dist/client/app/hooks/codeHighlight/useCodeHighlight.d.ts +1 -6
- package/dist/client/app/hooks/codeHighlight/useCodeHighlight.js +1 -1
- package/dist/client/app/hooks/index.d.ts +1 -0
- package/dist/client/app/hooks/index.js +1 -1
- package/dist/client/app/hooks/products/useCurrentProduct.js +1 -1
- package/dist/client/app/hooks/useAutoScroll.js +1 -1
- package/dist/client/app/hooks/useBanner.js +1 -1
- package/dist/client/app/hooks/useL10nConfig.js +1 -1
- package/dist/client/app/hooks/useLoginUrl.js +1 -1
- package/dist/client/app/hooks/usePageTimeTracker.js +1 -1
- package/dist/client/app/hooks/useRouteChangeTracker.js +1 -1
- package/dist/client/app/hooks/useUserClaims.js +1 -1
- package/dist/client/app/l10n/hooks/index.d.ts +1 -0
- package/dist/client/app/l10n/hooks/index.js +1 -1
- package/dist/client/app/l10n/hooks/useTranslate.js +1 -1
- package/dist/client/app/l10n/hooks/useTranslationKeys.d.ts +2 -0
- package/dist/client/app/l10n/hooks/useTranslationKeys.js +1 -0
- package/dist/client/app/l10n/initL10n.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/json-schema.d.ts +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/json-schema.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/openapi-code-sample.d.ts +1 -5
- package/dist/client/app/markdoc/custom-components/openapi/openapi-code-sample.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/openapi-example.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/openapi-response-sample.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.d.ts +8 -24
- package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -1
- package/dist/client/app/markdoc/hooks/use-store.d.ts +8 -6
- package/dist/client/app/markdoc/utils/build-replay-operation-source-map.d.ts +20 -0
- package/dist/client/app/markdoc/utils/build-replay-operation-source-map.js +1 -0
- package/dist/client/app/markdoc/utils/find-api-item.d.ts +15 -0
- package/dist/client/app/markdoc/utils/find-api-item.js +1 -0
- package/dist/client/app/markdoc/utils/find-code-sample-panel.d.ts +11 -0
- package/dist/client/app/markdoc/utils/find-code-sample-panel.js +1 -0
- package/dist/client/app/markdoc/utils/find-openapi-response-samples.d.ts +15 -0
- package/dist/client/app/markdoc/utils/find-openapi-response-samples.js +1 -0
- package/dist/client/app/markdoc/utils/openapi-panel-entry.d.ts +18 -0
- package/dist/client/app/markdoc/utils/openapi-panel-entry.js +1 -0
- package/dist/client/app/pages/DevLogin/DevLogin.js +1 -1
- package/dist/client/app/pages/DevLogin/DevLoginForm.d.ts +1 -1
- package/dist/client/app/seo/hooks/useHreflangLinks.js +1 -1
- package/dist/client/app/useGlobalData.d.ts +1 -1
- package/dist/client/app/useMobileMenu.js +1 -1
- package/dist/client/app/usePreloadHistory.d.ts +2 -2
- package/dist/client/app/usePreloadHistory.js +1 -1
- package/dist/client/app/utils/loadAndNavigate.d.ts +2 -2
- package/dist/client/app/utils/loadAndNavigate.js +1 -1
- package/dist/client/app/utils/resolveRouteBySlug.js +1 -1
- package/dist/client/app/utils/same-resolved-route.d.ts +5 -0
- package/dist/client/app/utils/same-resolved-route.js +1 -0
- package/dist/client/browser-entry.js +2 -2
- package/dist/client/providers/hooks.d.ts +1 -1
- package/dist/client/providers/hooks.js +1 -1
- package/dist/client/providers/page-data/hooks.d.ts +2 -2
- package/dist/client/providers/page-data/hooks.js +1 -1
- package/dist/client/providers/post-message/PostMessageProvider.js +1 -1
- package/dist/client/providers/post-message/use-post-message.d.ts +1 -1
- package/dist/client/providers/theme/ThemeDataProvider.js +1 -1
- package/dist/client/runtime/loader.js +1 -1
- package/dist/client/templates/api-docs/helpers.d.ts +10 -0
- package/dist/client/templates/api-docs/helpers.js +1 -0
- package/dist/client/templates/api-docs/template.d.ts +17 -0
- package/dist/client/templates/api-docs/template.js +14 -0
- package/dist/client/templates/openapi-docs/helpers.d.ts +1 -1
- package/dist/client/templates/openapi-docs/helpers.js +2 -2
- package/dist/client/types/sidebar.d.ts +0 -1
- package/dist/client/utils/utils.d.ts +0 -2
- package/dist/client/utils/utils.js +1 -1
- package/dist/constants/common.d.ts +14 -1
- package/dist/constants/common.js +1 -1
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/markdoc/tags/index.d.ts +48 -2
- package/dist/server/api-routes/helpers/enhance-context.js +1 -1
- package/dist/server/api-routes/helpers/read-stream-with-size-limit.d.ts +1 -1
- package/dist/server/api-routes/run-api-routes-worker.d.ts +1 -1
- package/dist/server/api-routes/run-api-routes-worker.js +1 -1
- package/dist/server/config/env-config.d.ts +2 -4
- package/dist/server/config/env-schema.d.ts +5 -10
- package/dist/server/config/env-schemas/feature-flags.d.ts +4 -8
- package/dist/server/config/env-schemas/feature-flags.js +1 -1
- package/dist/server/constants/common.d.ts +2 -0
- package/dist/server/constants/common.js +1 -1
- package/dist/server/constants/entitlements.js +1 -1
- package/dist/server/constants/plugins/api-docs.d.ts +3 -0
- package/dist/server/constants/plugins/api-docs.js +1 -0
- package/dist/server/esbuild/esbuild-logger.js +3 -3
- package/dist/server/esbuild/esbuild.js +3 -3
- package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.d.ts +9 -0
- package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.js +1 -0
- package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.d.ts +2 -0
- package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.js +1 -0
- package/dist/server/esbuild/plugins/api-docs-module-replacer/index.d.ts +6 -0
- package/dist/server/esbuild/plugins/api-docs-module-replacer/index.js +1 -0
- package/dist/server/esbuild/plugins/themes-resolver.js +4 -2
- package/dist/server/persistence/cache/mappers/create-cache-db-record.d.ts +1 -1
- package/dist/server/persistence/file-hashes/mappers/create-file-hash-db-record.d.ts +1 -1
- package/dist/server/persistence/kv/mappers/create-kv-db-record.d.ts +1 -1
- package/dist/server/plugins/api-docs/get-server-props.d.ts +4 -0
- package/dist/server/plugins/api-docs/get-server-props.js +1 -0
- package/dist/server/plugins/api-docs/get-template-path.d.ts +2 -0
- package/dist/server/plugins/api-docs/get-template-path.js +1 -0
- package/dist/server/plugins/api-docs/import-api-docs-builder.d.ts +8 -0
- package/dist/server/plugins/api-docs/import-api-docs-builder.js +1 -0
- package/dist/server/plugins/api-docs/index.d.ts +19 -0
- package/dist/server/plugins/api-docs/index.js +1 -0
- package/dist/server/plugins/api-docs/loader.d.ts +35 -0
- package/dist/server/plugins/api-docs/loader.js +3 -0
- package/dist/server/plugins/api-docs/options.d.ts +14 -0
- package/dist/server/plugins/api-docs/options.js +1 -0
- package/dist/server/plugins/api-docs/search/get-ai-search-documents.d.ts +20 -0
- package/dist/server/plugins/api-docs/search/get-ai-search-documents.js +105 -0
- package/dist/server/plugins/api-docs/search/search-facets.d.ts +10 -0
- package/dist/server/plugins/api-docs/search/search-facets.js +1 -0
- package/dist/server/plugins/api-docs/search/search-indexer.d.ts +9 -0
- package/dist/server/plugins/api-docs/search/search-indexer.js +1 -0
- package/dist/server/plugins/api-docs/search/search-resolver.d.ts +5 -0
- package/dist/server/plugins/api-docs/search/search-resolver.js +1 -0
- package/dist/server/plugins/api-docs/spec-download.api.d.ts +4 -0
- package/dist/server/plugins/api-docs/spec-download.api.js +1 -0
- package/dist/server/plugins/api-docs/store-definition-bundles.d.ts +3 -0
- package/dist/server/plugins/api-docs/store-definition-bundles.js +1 -0
- package/dist/server/plugins/api-docs/utils/build-item-positions.d.ts +17 -0
- package/dist/server/plugins/api-docs/utils/build-item-positions.js +1 -0
- package/dist/server/plugins/api-docs/utils/build-routes-mapping.d.ts +3 -0
- package/dist/server/plugins/api-docs/utils/build-routes-mapping.js +1 -0
- package/dist/server/plugins/api-docs/utils/collect-item-routes.d.ts +12 -0
- package/dist/server/plugins/api-docs/utils/collect-item-routes.js +1 -0
- package/dist/server/plugins/api-docs/utils/decorators.d.ts +26 -0
- package/dist/server/plugins/api-docs/utils/decorators.js +1 -0
- package/dist/server/plugins/api-docs/utils/format-bundle-error.d.ts +6 -0
- package/dist/server/plugins/api-docs/utils/format-bundle-error.js +5 -0
- package/dist/server/plugins/api-docs/utils/normalize-api-version.d.ts +2 -0
- package/dist/server/plugins/api-docs/utils/normalize-api-version.js +1 -0
- package/dist/server/plugins/api-docs/utils/normalize-feedback-options.d.ts +2 -0
- package/dist/server/plugins/api-docs/utils/normalize-feedback-options.js +1 -0
- package/dist/server/plugins/api-docs/utils/relative-path-to-base-slug.d.ts +20 -0
- package/dist/server/plugins/api-docs/utils/relative-path-to-base-slug.js +1 -0
- package/dist/server/plugins/api-docs/utils/replace-file-extension.d.ts +2 -0
- package/dist/server/plugins/api-docs/utils/replace-file-extension.js +1 -0
- package/dist/server/plugins/api-docs/utils/resolve-api-doc-title.d.ts +3 -0
- package/dist/server/plugins/api-docs/utils/resolve-api-doc-title.js +1 -0
- package/dist/server/plugins/api-docs/utils/resolve-config-rbac.d.ts +10 -0
- package/dist/server/plugins/api-docs/utils/resolve-config-rbac.js +1 -0
- package/dist/server/plugins/api-docs/utils/to-relative-slug.d.ts +2 -0
- package/dist/server/plugins/api-docs/utils/to-relative-slug.js +1 -0
- package/dist/server/plugins/api-functions/index.js +1 -1
- package/dist/server/plugins/arazzo-docs/index.js +1 -1
- package/dist/server/plugins/asyncapi-docs/index.js +1 -1
- package/dist/server/plugins/catalog-classic/index.js +1 -1
- package/dist/server/plugins/catalog-entities/database/catalog-entities-diff-publisher.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/catalog-entities-revisions-pruner.d.ts +4 -2
- package/dist/server/plugins/catalog-entities/database/catalog-entities-revisions-pruner.js +23 -3
- package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +5 -5
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-attributes-db-record.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-db-record.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-db-record-from-file-schema.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/remote-publish-lock-service.d.ts +3 -3
- package/dist/server/plugins/catalog-entities/database/repositories/bffEntities/bff-entities-read-repository.d.ts +2 -2
- package/dist/server/plugins/catalog-entities/database/repositories/catalog-entities-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/filters-repository.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-read-repository.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.d.ts +2 -2
- package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/entityAttributes/entity-attributes-write-repository.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/relations/relations-read-repository.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.d.ts +13 -5
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.d.ts +5 -2
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.d.ts +6 -5
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +2 -2
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.d.ts +12 -5
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/plugin.js +1 -1
- package/dist/server/plugins/catalog-entities/template/index.js +1 -1
- package/dist/server/plugins/catalog-entities/types/openapi.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/utils/get-not-accessible-catalog-resources.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/utils/openapi-component-content-extractor.d.ts +4 -4
- package/dist/server/plugins/catalog-entities/utils/openapi-component-content-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/utils/openapi-schema-resolver.d.ts +4 -3
- package/dist/server/plugins/catalog-entities/utils/openapi-schema-resolver.js +1 -1
- package/dist/server/plugins/config-parser/index.js +1 -1
- package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
- package/dist/server/plugins/create-slugify.d.ts +17 -0
- package/dist/server/plugins/create-slugify.js +1 -0
- package/dist/server/plugins/default-theme/index.js +1 -1
- package/dist/server/plugins/dev-onboarding/index.d.ts +1 -1
- package/dist/server/plugins/dev-onboarding/index.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/App.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/AppsList.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/ApiKeyItem.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/ApiLogDetails.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/ApiLogs.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/CreateApiKey.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/DeleteAppDialog.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/EditApis.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/EditAppDescriptionDialog.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/EditAppDialog.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/EditCallbackUrlDialog.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/RevokeAPIKey.d.ts +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/RevokeAPIKey.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/RollAPIKey.d.ts +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/RollAPIKey.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/UpdateApiKey.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/index.js +1 -1
- package/dist/server/plugins/entitlements/index.js +1 -1
- package/dist/server/plugins/graphql-docs/index.js +1 -1
- package/dist/server/plugins/graphql-docs/search/ai/utils.d.ts +1 -1
- package/dist/server/plugins/helpers/parse-partials.d.ts +3 -0
- package/dist/server/plugins/helpers/parse-partials.js +1 -0
- package/dist/server/plugins/l10n/index.js +1 -1
- package/dist/server/plugins/lifecycle.js +2 -2
- package/dist/server/plugins/markdown/attribute-resolvers/helpers/load-openapi-bundle.d.ts +5 -3
- package/dist/server/plugins/markdown/attribute-resolvers/helpers/load-openapi-bundle.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-json-example-ref.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-open-api-ref.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-openapi-code-samples.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-openapi-response-samples.js +1 -1
- package/dist/server/plugins/markdown/index.js +1 -1
- package/dist/server/plugins/markdown/markdoc/markdoc-options.d.ts +9 -9
- package/dist/server/plugins/markdown/markdoc/plugins/utils.d.ts +5 -0
- package/dist/server/plugins/markdown/markdoc/plugins/utils.js +1 -1
- package/dist/server/plugins/markdown/runtime-transform.js +1 -1
- package/dist/server/plugins/markdown/search/create-render-tag-fn.d.ts +2 -1
- package/dist/server/plugins/markdown/search/create-render-tag-fn.js +1 -1
- package/dist/server/plugins/markdown/search/get-ai-search-documents.js +9 -9
- package/dist/server/plugins/markdown/search/walk-sections.js +1 -1
- package/dist/server/plugins/markdown/utils/resolve-markdown-template.d.ts +1 -1
- package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +3 -0
- package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
- package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +1 -1
- package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +1 -1
- package/dist/server/plugins/mcp/codemode/code-audit.d.ts +12 -0
- package/dist/server/plugins/mcp/codemode/code-audit.js +1 -0
- package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +11 -0
- package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -0
- package/dist/server/plugins/mcp/codemode/constants.js +1 -1
- package/dist/server/plugins/mcp/codemode/prompts.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +2 -3
- package/dist/server/plugins/mcp/codemode/tools/execute-schema.d.ts +1 -1
- package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/execute.d.ts +1 -0
- package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/manage-credentials.d.ts +19 -0
- package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -0
- package/dist/server/plugins/mcp/constants.d.ts +3 -1
- package/dist/server/plugins/mcp/constants.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/core/create-anonymous-session.d.ts +11 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/core/create-anonymous-session.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/constants.d.ts +4 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/constants.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/get-graphql-type-list.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/get-graphql-type.js +7 -4
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/types.d.ts +7 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/types.js +0 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/utils.d.ts +5 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/utils.js +4 -2
- package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +4 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.d.ts +2 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoint-info.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoints.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-full-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-security-schemes.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.d.ts +6 -2
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/types.d.ts +2 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.d.ts +2 -2
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/utils.d.ts +3 -3
- package/dist/server/plugins/mcp/docs-mcp/utils.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +48 -0
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +3 -0
- package/dist/server/plugins/mcp/gateway-mcp/eligibility.d.ts +5 -17
- package/dist/server/plugins/mcp/gateway-mcp/eligibility.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.d.ts +9 -9
- package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.d.ts +17 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-errors.d.ts +11 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-errors.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.d.ts +14 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/normalize-path.d.ts +6 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/normalize-path.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/redact.d.ts +4 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/redact.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-blocklist.d.ts +22 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-blocklist.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.d.ts +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-safe-lookup.d.ts +13 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-safe-lookup.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.d.ts +8 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.d.ts +3 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/edge-limiter.d.ts +16 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/edge-limiter.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/ip-key.d.ts +2 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/ip-key.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/limits.d.ts +7 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/limits.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/rate-limit-telemetry.d.ts +8 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/rate-limit-telemetry.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/window-counter.d.ts +15 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/window-counter.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.d.ts +27 -0
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/subject.d.ts +20 -0
- package/dist/server/plugins/mcp/gateway-mcp/subject.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.d.ts +18 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +11 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.js +1 -0
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/errors.d.ts +3 -3
- package/dist/server/plugins/mcp/handlers/errors.js +1 -1
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.d.ts +5 -0
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +120 -0
- package/dist/server/plugins/mcp/index.d.ts +1 -0
- package/dist/server/plugins/mcp/index.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.d.ts +3 -1
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/servers/mcp-server.d.ts +15 -8
- package/dist/server/plugins/mcp/servers/mcp-server.js +3 -1
- package/dist/server/plugins/mcp/types.d.ts +16 -20
- package/dist/server/plugins/mcp/utils/json-schema-validator.d.ts +9 -0
- package/dist/server/plugins/mcp/utils/json-schema-validator.js +1 -0
- package/dist/server/plugins/mcp/utils/jwt.d.ts +0 -9
- package/dist/server/plugins/mcp/utils/jwt.js +1 -1
- package/dist/server/plugins/mcp/utils/mode.d.ts +12 -2
- package/dist/server/plugins/mcp/utils/mode.js +1 -1
- package/dist/server/plugins/mcp/utils/telemetry-attributes.d.ts +8 -0
- package/dist/server/plugins/mcp/utils/telemetry-attributes.js +1 -0
- package/dist/server/plugins/mcp/utils/xmcp-utils.d.ts +1 -1
- package/dist/server/plugins/mcp/utils.d.ts +17 -5
- package/dist/server/plugins/mcp/utils.js +1 -1
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
- package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +10 -2
- package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
- package/dist/server/plugins/openapi-docs/index.js +1 -1
- package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +16 -16
- package/dist/server/plugins/openapi-docs/utils.js +1 -1
- package/dist/server/plugins/pages/index.js +1 -1
- package/dist/server/plugins/scorecard-classic/compute-scorecard.d.ts +1 -1
- package/dist/server/plugins/scorecard-classic/compute-scorecard.js +4 -4
- package/dist/server/plugins/scorecard-classic/index.d.ts +1 -1
- package/dist/server/plugins/scorecard-classic/index.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/ApiDetailsPage.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/RuleDetailsPage.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/components.d.ts +1 -1
- package/dist/server/plugins/scorecard-classic/template/index.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/useData.d.ts +1 -1
- package/dist/server/plugins/scorecard-classic/template/utils.d.ts +1 -1
- package/dist/server/plugins/scorecard-classic/template/views.js +1 -1
- package/dist/server/plugins/scorecards/plugin.js +1 -1
- package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.d.ts +1 -1
- package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +2 -2
- package/dist/server/plugins/search/documents/search-documents.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
- package/dist/server/plugins/search/engines/search-engine.d.ts +1 -1
- package/dist/server/plugins/search/engines/typesense/index.js +1 -1
- package/dist/server/plugins/search/index.js +1 -1
- package/dist/server/plugins/search/llmstxt/index.d.ts +1 -1
- package/dist/server/plugins/search/llmstxt/index.js +4 -4
- package/dist/server/plugins/sidebars/index.d.ts +1 -1
- package/dist/server/plugins/sidebars/index.js +1 -1
- package/dist/server/plugins/sitemap/index.js +1 -1
- package/dist/server/plugins/sso/index.js +1 -1
- package/dist/server/providers/database/database-path-generator.d.ts +2 -2
- package/dist/server/providers/database/utils/storage-limit-validator.d.ts +1 -1
- package/dist/server/sandbox/sandbox.js +2 -2
- package/dist/server/sandbox/types.d.ts +3 -2
- package/dist/server/sandbox/utils/execution-budget.d.ts +4 -3
- package/dist/server/sandbox/utils/execution-budget.js +1 -1
- package/dist/server/ssr/render.js +1 -1
- package/dist/server/ssr/server-side-props/get-default-static-props.d.ts +1 -1
- package/dist/server/ssr/server-side-props/get-server-props-from-user-handler.d.ts +1 -1
- package/dist/server/ssr/template.d.ts +1 -1
- package/dist/server/ssr/utils.d.ts +1 -0
- package/dist/server/ssr/utils.js +5 -5
- package/dist/server/store.d.ts +2 -6
- package/dist/server/store.js +1 -1
- package/dist/server/tools/notifiers/logger.js +1 -1
- package/dist/server/tools/notifiers/reporter.js +6 -6
- package/dist/server/types/plugin-hooks.d.ts +1 -1
- package/dist/server/types/plugins/common.d.ts +4 -6
- package/dist/server/types/plugins/markdown.d.ts +1 -3
- package/dist/server/types/plugins/search.d.ts +1 -0
- package/dist/server/utils/catalog-classic/get-route-slug-to-catalog-slug-map.test.js +1 -1
- package/dist/server/utils/crypto/constants.d.ts +5 -0
- package/dist/server/utils/crypto/constants.js +1 -0
- package/dist/server/utils/crypto/decrypt-aes-gcm.d.ts +6 -0
- package/dist/server/utils/crypto/decrypt-aes-gcm.js +1 -0
- package/dist/server/utils/crypto/decrypt-claim-value.d.ts +6 -0
- package/dist/server/utils/crypto/decrypt-claim-value.js +1 -0
- package/dist/server/utils/crypto/derive-key.d.ts +5 -0
- package/dist/server/utils/crypto/derive-key.js +1 -0
- package/dist/server/utils/crypto/encrypt-aes-gcm.d.ts +6 -0
- package/dist/server/utils/crypto/encrypt-aes-gcm.js +1 -0
- package/dist/server/utils/crypto/encrypt-claim-value.d.ts +6 -0
- package/dist/server/utils/crypto/encrypt-claim-value.js +1 -0
- package/dist/server/utils/l10n/get-build-translate-context.d.ts +7 -0
- package/dist/server/utils/l10n/get-build-translate-context.js +1 -0
- package/dist/server/utils/llmstxt/agent-feedback-llms-footer.js +1 -1
- package/dist/server/utils/rbac.d.ts +4 -0
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/utils/report-all-errors.js +1 -1
- package/dist/server/utils/sandbox-context.d.ts +18 -0
- package/dist/server/utils/sandbox-context.js +1 -0
- package/dist/server/utils/shared-data.js +1 -1
- package/dist/server/web-server/auth.d.ts +34 -4
- package/dist/server/web-server/auth.js +3 -3
- package/dist/server/web-server/handle-api-route-request.js +1 -1
- package/dist/server/web-server/middleware/catalogAuthMiddleware.d.ts +1 -1
- package/dist/server/web-server/middleware/telemetry-middleware.js +1 -1
- package/dist/server/web-server/routes/api-routes/api-routes.js +1 -1
- package/dist/server/web-server/routes/auth.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog-revisions.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog.js +1 -1
- package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.d.ts +1 -1
- package/dist/server/web-server/routes/catalog/helpers/upsert-pages-stats.d.ts +1 -1
- package/dist/server/web-server/routes/dynamic-route.js +1 -1
- package/dist/server/web-server/routes/feedback.d.ts +1 -1
- package/dist/server/web-server/routes/helpers/process-redirects.d.ts +1 -1
- package/dist/server/web-server/routes/mcp-routes/a2a.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/agent-card.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.d.ts +10 -6
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-routes.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/utils/build-agent-card.d.ts +1 -1
- package/dist/server/web-server/routes/page-data.js +1 -1
- package/dist/server/web-server/routes/resolve-route.js +1 -1
- package/dist/server/web-server/routes/search.js +1 -1
- package/dist/server/web-server/routes/skills/skill-markdown.js +1 -1
- package/dist/server/web-server/routes/skills/skills-index.js +1 -1
- package/dist/server/web-server/utils/prepare-list-response.d.ts +1 -1
- package/dist/server/workers/api-routes-worker-pool.js +1 -1
- package/dist/server/workers/mcp-tool-worker-pool.js +1 -1
- package/dist/server/workers/worker-pool.d.ts +1 -0
- package/dist/server/workers/worker-pool.js +1 -1
- package/dist/types/entitlements.d.ts +6 -1
- package/dist/types/markdoc.d.ts +2 -1
- package/dist/utils/l10n/build-i18n-config.d.ts +24 -0
- package/dist/utils/l10n/build-i18n-config.js +1 -0
- package/dist/utils/l10n/create-translate.d.ts +19 -0
- package/dist/utils/l10n/create-translate.js +1 -0
- package/dist/utils/url/get-shared-data-fetch-url.d.ts +17 -0
- package/dist/utils/url/get-shared-data-fetch-url.js +1 -0
- package/dist/utils/url/parse-preview-url.d.ts +22 -0
- package/dist/utils/url/parse-preview-url.js +1 -0
- package/package.json +21 -20
- package/dist/markdoc/helpers/get-operation/get-operation-info-by-id.d.ts +0 -4
- package/dist/markdoc/helpers/get-operation/get-operation-info-by-id.js +0 -1
- package/dist/markdoc/helpers/get-operation/get-operation-info-by-pointer.d.ts +0 -4
- package/dist/markdoc/helpers/get-operation/get-operation-info-by-pointer.js +0 -1
- package/dist/markdoc/helpers/get-operation/get-operation.d.ts +0 -14
- package/dist/markdoc/helpers/get-operation/get-operation.js +0 -1
- package/dist/markdoc/helpers/get-operation/index.d.ts +0 -4
- package/dist/markdoc/helpers/get-operation/index.js +0 -1
- package/dist/markdoc/helpers/get-operation/types/index.d.ts +0 -4
- package/dist/markdoc/helpers/get-operation/types/index.js +0 -0
- package/dist/markdoc/helpers/get-operation/types/operation-identifier.d.ts +0 -5
- package/dist/markdoc/helpers/get-operation/types/operation-identifier.js +0 -0
- package/dist/markdoc/helpers/get-operation/types/operation-info.d.ts +0 -6
- package/dist/markdoc/helpers/get-operation/types/operation-info.js +0 -0
- package/dist/markdoc/helpers/get-operation/types/operation-parameters.d.ts +0 -3
- package/dist/markdoc/helpers/get-operation/types/operation-parameters.js +0 -0
- package/dist/server/plugins/markdown/attribute-resolvers/helpers/get-media-content-samples.d.ts +0 -4
- package/dist/server/plugins/markdown/attribute-resolvers/helpers/get-media-content-samples.js +0 -1
- package/dist/server/plugins/mcp/handlers/sse-keepalive.d.ts +0 -15
- package/dist/server/plugins/mcp/handlers/sse-keepalive.js +0 -3
|
@@ -11,6 +11,7 @@ export declare function getScopeItemsForResource(rbacConfig: RbacConfig | undefi
|
|
|
11
11
|
fsPath?: string;
|
|
12
12
|
slug?: string;
|
|
13
13
|
}): RbacScopeItems;
|
|
14
|
+
export declare function hasScopeAccess(scopeItems: RbacScopeItems, teams: string[], email?: string): boolean;
|
|
14
15
|
export declare function canAccessFeature(feature: RbacFeatures, auth: AuthDetails, rbacConfig?: RbacConfig, requiresLogin?: boolean): boolean;
|
|
15
16
|
export declare function isResourcePubliclyAccessible(resource: {
|
|
16
17
|
slug: string;
|
|
@@ -140,6 +141,9 @@ export declare const normalizeRbacConfig: (rbacConfig: RbacConfig) => {
|
|
|
140
141
|
aiSearch?: {
|
|
141
142
|
[x: string]: string;
|
|
142
143
|
} | undefined;
|
|
144
|
+
mcp?: {
|
|
145
|
+
[x: string]: string;
|
|
146
|
+
} | undefined;
|
|
143
147
|
} | undefined;
|
|
144
148
|
reunite?: {
|
|
145
149
|
[x: string]: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import y from"path";import
|
|
1
|
+
import y from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as _,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{ServerRoutes as k}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as x,PUBLIC_RBAC_SCOPE_ITEM as R,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_ASSETS_FOLDER as w}from"../constants/common.js";import{removeTrailingSlash as B}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as b}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as M}from"../../utils/path/parse-path-versions.js";import{reporter as U}from"../tools/notifiers/reporter.js";import{bold as W}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as $}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as v}from"../../utils/guards/is-truthy.js";import{canExpandConfig as Y,expandRbacConfig as z,getTeamFolderDefaults as K,parseTeamFoldersTemplate as H,parseTeamNameTemplate as G}from"./rbac-expand.js";import{getUserParamsFromCookies as V}from"../web-server/auth.js";import{getDeeperGlobPattern as J}from"./globs.js";import{EntitlementsProvider as Q}from"../entitlements/entitlements-provider.js";const C=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],X=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Pt(t,e){const r=C.indexOf(t.toUpperCase()),n=C.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return R;const r=t.content,{slug:n,fsPath:s}=e;if(!n&&!s)return R;const o=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const g=`fsPath:${a}`,S=E[g]??P(b(a));return E[g]=S,!!(n&&p(n))||!!(s&&S(s))};if(tt(n||s||"")&&Object.keys(r).filter(p=>o(p)).length===0)return r[L]||R;const f=Object.keys(r).filter(a=>o(a));if(f.length==0)return R;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=J(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,s=[];for(const o of n)t[o]?s.push(t[o]):t[l]&&o!==r&&s.push(t[l]);return s.some(o=>o.toLowerCase()!=="none")}function xt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const s=r.features?.[t];return s?F(s,e.teams):!0}function Dt(t,e){return O(t,{isAuthenticated:!1,teams:[x]},e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(k).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||t.slug==="/mcp"&&Q.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const s=z(r,e.teams||[]),o=t[_]||T(s,t[A]||{});return Object.keys(o||{}).length===0?!1:Object.keys(o).length===1&&o[l]&&o[l].toLowerCase()!=="none"?!0:F(o,e?.teams||[],e?.email)}function gt(t,e,r,n){if(!t.startsWith(I)&&!t.startsWith(j))return!0;const s=t.replace(new RegExp(`^${I}/`),"").replace(new RegExp(`^${j}/`),""),c=s==="."?"":s,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function St(t,e,r,n,s){if(!t.startsWith(w))return!0;const o=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!o)return!0;const c=n[o];if(!c)return!0;const{base:i,ext:f}=y.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:y.posix.join(d,`${u}.${h}`)},slug:t};return O(p,s,e,r)}async function _t(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:s,federatedIdToken:o,...c}=await V(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==x):f=[x],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const s=[];for(const o of t){const c=N(o,e,r,n);c!==void 0&&s.push(c)}return s}if(typeof t=="object"){if(!O(t,e,r,n))return;let s=!1;const o={};for(const c in t){if(c===_||c===A)continue;if(X.has(c)){o[c]=t[c];continue}const i=N(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){s=!0;continue}i!==void 0&&(o[c]=i),c==="paths"&&Z(i)&&q(i)}return s?void 0:o}return t}function Lt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function jt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([o,c])=>o===L?[[o,c]]:[[o,c],...t.localeFolders.map(i=>[o.startsWith("/")?`/${i.toLocaleLowerCase()}${o}`:y.posix.join(t.localizationFolder,i,o),c])]),s=Object.fromEntries(n);return{...e,content:s}}async function It(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:s})=>{const{versionFolderPath:o}=M(s)||{},c=y.dirname(s);return o?[o,c]:c}));for(const s of n)r[$(s)]=s;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function Z(t){return m(t)&&Object.keys(t).length>0}function q(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function tt(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const et=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ct=async t=>{if(t){if(Object.keys(t).length===0)return{};if(et(t))return rt(t);await U.panicOnContentError(`You are using an incorrect format of ${W("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},rt=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const s=B(n);r[s]=e.content[n]}e.content=r}return e};function Ft(t,e){const r=t.fsPath,n=t.slug,s=[];if(Y(e)&&(r||n)){const o=[r,n].filter(v),c=H(e,o);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];s.push(...i);const f=T({content:{...K(e),...e.content}},t);s.push(...D(f))}else{const i=T(e,t);s.push(...D(i))}}else{const o=T(e,t);s.push(...D(o))}return nt(e,s)}function D(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,s]of Object.entries({...r,...t}))s.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function nt(t,e){return e.map(n=>G(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{C as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,jt as applyL10nToRbacConfig,St as canAccessAsset,xt as canAccessFeature,O as canAccessResource,gt as canDownloadApiDefinition,nt as expandTeamsForRead,D as extractTeamsFromScopeItems,N as filterDataByAccessDeep,_t as getAuthDetailsFromCookies,Pt as getHigherRole,Ft as getRbacTeamsListForResource,T as getScopeItemsForResource,F as hasScopeAccess,et as isRbacConfigValid,Dt as isResourcePubliclyAccessible,rt as normalizeRbacConfig,Ct as parseRbacConfig,Lt as parseTeamClaimToArray,It as resolveDirectoryHashes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{envConfig as
|
|
1
|
+
import{envConfig as d}from"../config/env-config.js";import{reporter as r}from"../tools/notifiers/reporter.js";import{isMarkdocError as p}from"../plugins/markdown/errors.js";import{telemetryTraceStep as m}from"../../cli/telemetry/helpers/trace-step.js";async function y(i){await m("com.redocly.build.validationErrors",async n=>{let e=0;for(const[a,c]of i.cache.errors.entries()){const f=a.split(":")[1];for(const o of c)p(o)?(r.reportMarkdocProblem(o),o.type!=="BROKEN_LINK"&&e++):await r.panicOnBuild(o.message,f)}const s=await i.getConfig();if(!d.isBuildMode)return;const t=r.getPageRenderProblems().length;n?.setAttribute("markdocErrors",e.toString()),n?.setAttribute("pageRenderErrors",t.toString()),e>0&&!s?.reunite?.ignoreMarkdocErrors?(r.printErrors(),await r.panic(`Need to fix ${e} Markdoc issue(s) or set the \`ignoreMarkdocErrors\` option to \`true\` in the \`reunite\` section of your \`redocly.yaml\``)):t>0&&(r.printErrors(),await r.panic(`Need to fix ${t} runtime error(s) in React pages`))})}export{y as reportAllErrors};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class SandboxContext {
|
|
2
|
+
#private;
|
|
3
|
+
readonly serverOutDir: string;
|
|
4
|
+
static register({ serverOutDir, readRoots, }: {
|
|
5
|
+
serverOutDir: string;
|
|
6
|
+
readRoots?: string[];
|
|
7
|
+
}): void;
|
|
8
|
+
static resolve(fallbackServerOutDir: string): SandboxContext;
|
|
9
|
+
private constructor();
|
|
10
|
+
get tmpDir(): string;
|
|
11
|
+
get execArgv(): string[];
|
|
12
|
+
get env(): {
|
|
13
|
+
TMPDIR: string;
|
|
14
|
+
TMP: string;
|
|
15
|
+
TEMP: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=sandbox-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as a}from"node:fs";import{dirname as l,join as m}from"node:path";class s{serverOutDir;static#e;static register({serverOutDir:e,readRoots:t}){s.#e=new s(e,t)}static resolve(e){return s.#e??new s(e)}#t;constructor(e,t=[]){this.serverOutDir=e,this.#t=s.#n(e,t)}get tmpDir(){return`${this.serverOutDir}/.data/tmp`}get execArgv(){return["--permission",...this.#t.map(e=>`--allow-fs-read=${e}/*`),`--allow-fs-write=${this.serverOutDir}/.data/*`,"--allow-addons"]}get env(){return{TMPDIR:this.tmpDir,TMP:this.tmpDir,TEMP:this.tmpDir}}static#r(e){if(!e)return e;const r=e.indexOf("/node_modules/");return r!==-1?e.slice(0,r):s.#s(e)??s.#i(e)??e}static#s(e){let t=e;for(;;){if(a(m(t,"node_modules",".pnpm")))return t;const r=l(t);if(r===t)return;t=r}}static#i(e){let t=e;for(;;){if(a(m(t,"node_modules")))return t;const r=l(t);if(r===t)return;t=r}}static#n(e,t){const r=[s.#r(e),...t].filter(Boolean).map(i=>i.replace(/\/+$/,"")).filter(Boolean),n=[...new Set(r)];return n.filter(i=>!n.some(o=>o!==i&&i.startsWith(`${o}/`)))}}export{s as SandboxContext};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import s from"path";import{readFile as l,writeFileSync as p}from"fs";import{stat as u}from"fs/promises";import{LRUCache as w}from"lru-cache";import{getSharedDataUrl as z}from"../../utils/url/get-shared-data-url.js";import{logger as D}from"../tools/notifiers/logger.js";import{ensureDir as S}from"./fs.js";const o={},h=new w({max:64,maxSize:192*1024*1024,sizeCalculation:a=>Math.max(a.size,1)}),R=async(a,n,e)=>{const i=c(a,e);await o[i],h.delete(i),p(S(i),n,{encoding:"utf-8",flush:!0})},C=async(a,n)=>{try{const e=c(a,n),i=o[e];if(i)return i;const t=await u(e).catch(()=>{});if(t){const r=h.get(e);if(r&&r.mtimeMs===t.mtimeMs&&r.size===t.size)return r.data}const d=new Promise(r=>l(e,"utf-8",(m,f)=>{r(m?void 0:JSON.parse(f))}));return o[e]=d,d.finally(()=>{delete o[e]}).then(r=>(t&&r!==void 0&&h.set(e,{mtimeMs:t.mtimeMs,size:t.size,data:r},{size:Math.max(t.size,1)}),r))}catch(e){D.warnProd(`Failed to read shared data ${a} with error: ${e instanceof Error?e.message:"Unknown error"}`);return}},c=(a,n)=>{const e=s.join(n,z(a)),i=s.resolve(n,"page-data/shared"),t=s.resolve(n,e);if(s.relative(i,t).startsWith(".."))throw new Error(`Invalid shared data id: ${a}`);return t};export{C as readSharedData,R as writeSharedData};
|
|
@@ -35,13 +35,17 @@ export declare function isSaml2ProviderConfig(providerConfig: AuthProviderConfig
|
|
|
35
35
|
export declare function getAuthProviderLoginParams(idpId: string, providerConfig: AuthProviderConfig): Promise<AuthProviderLoginParams | undefined>;
|
|
36
36
|
export declare function getOidcLoginParams(idpId: string, providerConfig: OidcProviderConfig): Promise<OidcLoginParams>;
|
|
37
37
|
export declare function getSaml2LoginParams(idpId: string, providerConfig: Saml2ProviderConfig): Saml2LoginParams;
|
|
38
|
-
export
|
|
38
|
+
export type OidcTokenResponse = {
|
|
39
39
|
access_token?: string;
|
|
40
40
|
id_token?: string;
|
|
41
|
+
refresh_token?: string;
|
|
42
|
+
expires_in?: number;
|
|
41
43
|
error?: string;
|
|
42
44
|
error_description?: string;
|
|
43
|
-
}
|
|
44
|
-
export declare function
|
|
45
|
+
};
|
|
46
|
+
export declare function oidcExchangeCodeForToken(tokenUrl: string, code: string, redirectUri: string, idpConfig: OidcProviderConfig, extraParams?: Record<string, string>): Promise<OidcTokenResponse>;
|
|
47
|
+
export declare function oidcRefreshTokenGrant(tokenUrl: string, refreshToken: string, idpConfig: OidcProviderConfig): Promise<OidcTokenResponse>;
|
|
48
|
+
export declare function buildOidcLoginUrl(origin: string, { authorizationEndpoint, clientId, responseType, scope, extraParams, idpId, pkce, }: Partial<OidcLoginParams>, redirectTo: string | null, inviteCode?: string, options?: {
|
|
45
49
|
redirectUriOverride?: string;
|
|
46
50
|
sourceOverride?: 'portal' | 'mcp';
|
|
47
51
|
branchOverride?: string | undefined;
|
|
@@ -58,7 +62,10 @@ type McpAuthorizationCodePayload = {
|
|
|
58
62
|
client_id: string;
|
|
59
63
|
redirect_uri: string;
|
|
60
64
|
id_token: string;
|
|
65
|
+
idp_id?: string;
|
|
61
66
|
idp_access_token?: string;
|
|
67
|
+
idp_access_token_enc?: string;
|
|
68
|
+
idp_refresh_token_enc?: string;
|
|
62
69
|
code_challenge?: string;
|
|
63
70
|
code_challenge_method?: string;
|
|
64
71
|
iat: number;
|
|
@@ -66,7 +73,9 @@ type McpAuthorizationCodePayload = {
|
|
|
66
73
|
};
|
|
67
74
|
export declare function createMcpAuthorizationCode(params: {
|
|
68
75
|
idToken: string;
|
|
69
|
-
|
|
76
|
+
idpId?: string;
|
|
77
|
+
idpAccessTokenEnc?: string;
|
|
78
|
+
idpRefreshTokenEnc?: string;
|
|
70
79
|
clientId: string;
|
|
71
80
|
redirectUri: string;
|
|
72
81
|
codeChallenge?: string;
|
|
@@ -74,6 +83,26 @@ export declare function createMcpAuthorizationCode(params: {
|
|
|
74
83
|
ttlSec?: number;
|
|
75
84
|
}): Promise<string>;
|
|
76
85
|
export declare function verifyMcpAuthorizationCode(code: string): Promise<McpAuthorizationCodePayload>;
|
|
86
|
+
export type McpRefreshTokenPayload = {
|
|
87
|
+
type: 'mcp_refresh_token';
|
|
88
|
+
client_id: string;
|
|
89
|
+
idp_id?: string;
|
|
90
|
+
claims: Record<string, unknown>;
|
|
91
|
+
idp_access_token_enc?: string;
|
|
92
|
+
idp_refresh_token_enc?: string;
|
|
93
|
+
session_exp: number;
|
|
94
|
+
iat: number;
|
|
95
|
+
exp: number;
|
|
96
|
+
};
|
|
97
|
+
export declare function createMcpRefreshToken(params: {
|
|
98
|
+
clientId: string;
|
|
99
|
+
idpId?: string;
|
|
100
|
+
claims: Record<string, unknown>;
|
|
101
|
+
idpAccessTokenEnc?: string;
|
|
102
|
+
idpRefreshTokenEnc?: string;
|
|
103
|
+
sessionExp: number;
|
|
104
|
+
}): Promise<string>;
|
|
105
|
+
export declare function verifyMcpRefreshToken(token: string): Promise<McpRefreshTokenPayload>;
|
|
77
106
|
export declare function createMcpSessionResource(sessionId: string | null | undefined): {
|
|
78
107
|
id: string;
|
|
79
108
|
object: 'mcpSession';
|
|
@@ -114,6 +143,7 @@ export declare const oidcJwksCache: {
|
|
|
114
143
|
}) | null>;
|
|
115
144
|
};
|
|
116
145
|
export declare function getOidcMetadata(idpId: string, providerConfig: OidcProviderConfig): Promise<OidcIssuerMetadata>;
|
|
146
|
+
export declare function discoverJwks(ssoConfig: SsoConfig): Promise<void>;
|
|
117
147
|
export declare function getRedoclyTokenPayload(token: string): Promise<Record<string, unknown>>;
|
|
118
148
|
export declare function isRedoclySso(config: OidcProviderConfig): boolean;
|
|
119
149
|
export declare function verifySAMLResponse(responseXml: string, cert: string): Promise<boolean>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import"../node-crypto-polyfill.js";import{DOMParser as
|
|
1
|
+
import"../node-crypto-polyfill.js";import{DOMParser as M}from"@xmldom/xmldom";import{SignedXml as Y}from"xml-crypto";import G from"xpath";import{deflateSync as Q,inflateSync as X}from"fflate";import{createHash as Z}from"crypto";import{ulid as ee}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as P}from"@redocly/config";import{AUTH_URL as te,JWT_SECRET_KEY as y}from"../constants/common.js";import{envConfig as ne}from"../config/env-config.js";import{decryptClaimValue as re}from"../utils/crypto/decrypt-claim-value.js";import{getPathPrefix as oe,withPathPrefix as se}from"@redocly/theme/core/utils";import{ServerRoutes as b}from"../../constants/api.js";import{AuthCookieNames as A,DEFAULT_AUTHENTICATED_TEAM as ae,REQUIRED_OIDC_SCOPES as v}from"../../constants/common.js";import{appendQueryParams as ie}from"../../utils/url/append-query-params.js";import{parsePreviewUrl as N}from"../../utils/url/parse-preview-url.js";import{logger as ce}from"../tools/notifiers/logger.js";import{randomString as ue}from"../utils/crypto/random-string.js";import{randomUUID as U}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as h,JwtTokenExpired as de}from"./jwt/types.js";import*as d from"./jwt/jwt.js";import{parseTeamClaimToArray as le}from"../utils/index.js";import{arrayBufferToBase64 as me,decodeBase64 as j,encodeBase64URL as pe,urlSafeBase64 as V}from"./jwt/encode.js";import{formatSamlCertificate as fe}from"./utils/format-saml-certificate.js";function $(e){return e?.type===u.OIDC}function he(e){return e?.type===u.SAML2}async function rt(e,t){if($(t))return ye(e,t);if(he(t))return we(e,t)}async function ye(e,t){const n=await q(e,t),r=new Set((t.scopes||[]).concat(v)),o=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:n.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(r).join(" "),extraParams:o,pkce:t.pkce}}function we(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}function B(e){return Array.from(new Set((e.scopes||[]).concat(v))).join(" ")}async function H(e,t,n){return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:t.clientId,...t.clientSecret?{client_secret:t.clientSecret}:{},...n}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(r=>r.json())}async function ot(e,t,n,r,o={}){return await H(e,r,{scope:B(r),code:t,redirect_uri:F(n),grant_type:"authorization_code",...o})}async function st(e,t,n){return await H(e,n,{scope:B(n),grant_type:"refresh_token",refresh_token:t})}function Se(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:o,extraParams:s,idpId:a,pkce:l},p,x,f){if(!t||!n||!r||!o)return{loginUrl:void 0};const i=new URL(t),w=f?.redirectUriOverride??`${e}${se(b.OIDC_CALLBACK)}`,g={state:U(),idpId:a,redirectUri:w,redirectTo:p,branch:f?.branchOverride??_e(e),inviteCode:x,source:f?.sourceOverride??"portal",uiLocales:f?.uiLocales},S={};if(l){const m=V(ue(50)),k=V(Z("sha256").update(m).digest("base64")),I="S256";i.searchParams.append("code_challenge",k),i.searchParams.append("code_challenge_method",I),S.code_verifier={value:m,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:oe()||"/"}}}i.searchParams.append("client_id",n),i.searchParams.append("scope",o),i.searchParams.append("response_type",r),i.searchParams.append("redirect_uri",F(w)),i.searchParams.append("state",pe(JSON.stringify(g))),f?.uiLocales&&i.searchParams.append("ui_locales",f.uiLocales);for(const m in s)s[m]!==void 0&&i.searchParams.append(m,s[m]);return{loginUrl:i.toString(),cookies:S}}function at(e,t,n,r){const o=new URL(e);return o.searchParams.append("post_logout_redirect_uri",t),r&&o.searchParams.append("state",r),o.searchParams.append("id_token_hint",n),o.toString()}async function it(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return d.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpId?{idp_id:e.idpId}:{},...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},...e.codeChallenge?{code_challenge:e.codeChallenge}:{},...e.codeChallengeMethod?{code_challenge_method:e.codeChallengeMethod}:{},iat:t,exp:n},y,h.HS256)}async function ct(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_auth_code")throw new Error("Invalid authorization code type");if(!t.client_id||!t.redirect_uri)throw new Error("Authorization code missing required claims");if(typeof t.exp=="number"&&Date.now()>=t.exp*1e3)throw new Error("Authorization code expired");return t}async function ut(e){const t=Math.floor(Date.now()/1e3);return d.sign({type:"mcp_refresh_token",client_id:e.clientId,...e.idpId?{idp_id:e.idpId}:{},claims:e.claims,...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},session_exp:e.sessionExp,iat:t,exp:e.sessionExp},y,h.HS256)}async function dt(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_refresh_token")throw new Error("Invalid refresh token type");if(!t.client_id||typeof t.claims!="object"||t.claims===null)throw new Error("Refresh token missing required claims");if(typeof t.session_exp!="number")throw new Error("Refresh token missing session expiry");return t}function lt(e){const t=e||ee(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcpSession",uri:`urn:redocly:realm:mcp:session:${n}`}}function F(e){const t=N(e);if(!t)return e;const n=Ae(t.hostname);if(n)return t.hostname=`previewauth--${n.previewBranch}${n.after}`,z(e,t);const r=W(t.hostname);return r?(t.hostname=`${r.projectSlug}.previewauth.${r.after}`,z(e,t)):e}function _e(e){const t=N(e);if(t)return W(t.hostname)?.previewBranch}function z(e,t){return e.replace(/^https?:\/\/[^/?#]+/i,`${t.protocol}//${t.host}`)}function W(e){const t=e.split(".preview.",2);if(t.length<2)return null;const[n,r]=t,o=n.indexOf("--");if(o===-1)return null;const s=n.slice(0,o),a=n.slice(o+2);return!s||!a||a.includes(".")?null:{projectSlug:s,previewBranch:a,after:r}}function Ae(e){const t=e.indexOf("."),n=t===-1?e:e.slice(0,t);if(!n.startsWith("preview-"))return null;const r=n.indexOf("--");if(r===-1)return null;const o=n.slice(r+2);if(!o)return null;const s=t===-1?"":e.slice(t);return{previewBranch:o,after:s}}function xe(e){return e.type===u.OIDC}function ge(e){return e.type===u.SAML2}function mt(e,t,n,r,o){return xe(e)?Se(t,e,n,r,{uiLocales:o}):ge(e)?ke(t,e,n,r,o):{}}function ke(e,t,n,r,o){const a=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
|
2
2
|
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
|
3
3
|
Version="2.0"
|
|
4
4
|
ID="_${U()}"
|
|
5
5
|
IssueInstant="${new Date().toISOString()}"
|
|
6
|
-
AssertionConsumerServiceURL="${e}${
|
|
6
|
+
AssertionConsumerServiceURL="${e}${b.SAML_CALLBACK}"
|
|
7
7
|
AttributeConsumingServiceIndex="0">
|
|
8
8
|
<saml:Issuer>${t.entityId}</saml:Issuer>
|
|
9
9
|
<samlp:NameIDPolicy
|
|
10
10
|
AllowCreate="true"
|
|
11
11
|
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
|
|
12
|
-
</samlp:AuthnRequest>`,l=
|
|
12
|
+
</samlp:AuthnRequest>`,l=Ie(a);return{loginUrl:ie(t.ssoUrl,{SAMLRequest:l,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal",uiLocales:o})})}}function Ie(e){return me(Q(new TextEncoder().encode(e)).buffer)}function pt(e){const t=j(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=X(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function ft(e){try{return JSON.parse(j(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function ht(e){const t=new M().parseFromString(e,"application/xml"),r=c(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,s=c(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",a=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=a&&a.nodeValue||void 0,p=c(t,"//*[local-name(.)='Audience']/text()")[0],x=p&&p.nodeValue||void 0,i=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",w=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],g=w&&w.nodeValue||"",S=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],m=S&&S.nodeValue||"",k=c(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],I=Te(k),C={},R=c(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(R.length)for(const L of R){const O=c(L,"./@Name")[0];if(O.nodeValue){const D=c(L,"./*[local-name(.)='AttributeValue']/text()")[0];D?.nodeValue&&(C[O.nodeValue]=D.nodeValue)}}return{uid:g,success:r,expiresAt:I,issuerId:l,entityId:x,attrs:C,cert:i,nameFormat:m,destination:s}}function Te(e){const t=typeof e?.nodeValue=="string"&&T(Date.parse(e.nodeValue)),n=T(Date.now()),r=T(Date.now()+720*60*1e3);return t?t>n&&t<r?r:t:n}function T(e){return Math.floor(e/1e3)}const E={},_={jwks:{}};async function q(e,t){if(!E[e]){const n=t.configurationUrl?await J(t.configurationUrl):t.configuration;E[e]=Ee()?Re(n):n}return E[e]}function Ee(){const e=ne.REDOCLY_ENFORCE_RESIDENCY;return!!e&&e.includes("host.docker.internal")}const Ce=["authorization_endpoint","end_session_endpoint"];function Re(e){if(typeof e!="object"||e===null)return e;const t={...e};for(const n of Object.keys(t)){if(Ce.includes(String(n)))continue;const r=t[n];typeof r=="string"&&r.includes("://localhost")&&(t[n]=r.replace("://localhost","://host.docker.internal"))}return t}async function Le(e){for(const t of Object.keys(e)){const n=e[t];if(!$(n))continue;const r=await q(t,n);if(r.jwks_uri){const o=await J(r.jwks_uri);for(const s of o.keys)_.jwks[s.kid]={...s,idpId:t}}}}async function J(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function yt(e){return fetch(`${te}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function wt(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com","cba.au.redocly.com"].some(r=>Oe(t.hostname,r))}function Oe(e,t){return e===t||e.endsWith(`.${t}`)}async function St(e,t){const n=new M().parseFromString(e,"application/xml"),r=c(n,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!r)throw new Error("Cannot find Signature in the SAML response");const o=fe(t),s=new Y({publicCert:o});s.loadSignature(r);try{return s.checkSignature(e)}catch{return!1}}function _t(e,t,n,r){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=n["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const s=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],a=s?.match(/.+@.+/);return o=o||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(a?s:void 0),o=o?.toLowerCase(),{sub:e,given_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:n["http://schemas.microsoft.com/identity/claims/displayname"]||s,email:o,email_verified:!0,teams:r?le(n[r]):[]}}function K(e,t={}){return e.map(n=>t[n]||n)}async function At(e,t){if(!t)return{};const n=t[A.AUTHORIZATION];if(!n)return{};try{const r=d.decode(n);if(r.header.alg===h.RS256){_.jwks[r.header.kid]===void 0&&await Le(e);const p=_.jwks[r.header.kid];if(!p)return _.jwks[r.header.kid]=null,{};await d.verify(n,p,h.RS256)}else await d.verify(n,y,h.HS256);const o=r.payload.idpId||_.jwks[r.header.kid]?.idpId,s=e[o]||{},a=Pe(s),l=Me(s);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...K(r.payload.teams||[],l),..."defaultTeams"in s&&s.defaultTeams||[],...K("teamsClaimName"in s&&r.payload[a||""]||[],l),ae])),name:De(r.payload),isAuthenticated:!0,idpAccessToken:re(r.payload.idp_access_token,y)||t[A.IDP_ACCESS_TOKEN],federatedAccessToken:t[A.FEDERATED_ACCESS_TOKEN],federatedIdToken:t[A.FEDERATED_ID_TOKEN],authCookie:n}}catch(r){r instanceof de||ce.error("Malformed JWT token: %s",r.message)}return{}}function De(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function Me(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function Pe(e){switch(e.type){case u.SAML2:return e.teamsAttributeName??P;case u.OIDC:return e.teamsClaimName;default:return P}}function c(e,t){return G.select(t,e)||[]}export{mt as buildLoginUrl,Se as buildOidcLoginUrl,at as buildOidcLogoutUrl,ke as buildSAML2LoginUrl,it as createMcpAuthorizationCode,ut as createMcpRefreshToken,lt as createMcpSessionResource,pt as decodeSamlResponse,Le as discoverJwks,Ie as encodeSAML2,_t as extractUserClaims,rt as getAuthProviderLoginParams,ye as getOidcLoginParams,q as getOidcMetadata,yt as getRedoclyTokenPayload,we as getSaml2LoginParams,At as getUserParamsFromCookies,De as getUsernameFromPayload,$ as isOidcProviderConfig,wt as isRedoclySso,he as isSaml2ProviderConfig,ot as oidcExchangeCodeForToken,_ as oidcJwksCache,E as oidcMetadataCache,st as oidcRefreshTokenGrant,ft as parseOidcState,_e as parsePreviewBranch,ht as parseSamlResponse,F as rewritePreviewAuthRedirectUri,ct as verifyMcpAuthorizationCode,dt as verifyMcpRefreshToken,St as verifySAMLResponse};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as n}from"../tools/notifiers/logger.js";import{envConfig as o}from"../config/env-config.js";import{runApiRoutesWorker as m}from"../api-routes/run-api-routes-worker.js";import{MCP_DOCS_SERVER_HANDLER_ID as
|
|
1
|
+
import{logger as n}from"../tools/notifiers/logger.js";import{envConfig as o}from"../config/env-config.js";import{runApiRoutesWorker as m}from"../api-routes/run-api-routes-worker.js";import{MCP_CREDENTIALS_HANDLER_ID as i,MCP_DOCS_SERVER_HANDLER_ID as u}from"../plugins/mcp/index.js";import{handleMcpRequest as d}from"../plugins/mcp/handlers/handle-mcp-request.js";async function l(r,s,a){try{const e=n.startTiming(),t=r.requestHandlerId===u||r.requestHandlerId===i?await d(r,s,a):await m(r,s,a);return n.infoTime(e,`API request handled "${new URL(s.req.url).pathname}" with status "${t.status}" and content type "${t.headers?.get("content-type")}"`),t.headers.set("X-Source","REALM_API_FUNCTION"),t}catch(e){return n.error(`[${r.requestHandlerId}] ${e.stack}`),e.name==="RequestBodySizeLimitError"?s.json({message:e.message},{status:413}):e.name==="ResponseSizeLimitError"?s.json({message:e.message},{status:500}):e.name==="MemoryUsageLimitError"?s.json({message:e.message},{status:502}):e.name==="TimeoutExceededError"?s.json({message:e.message},{status:504}):o.isDevelopMode?s.json({message:e.message},{status:500}):s.json({message:"Internal server error"},{status:500})}}export{l as handleApiRouteRequest};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context, Next } from 'hono';
|
|
2
|
-
export declare function catalogAuthMiddleware({ serverOutDir, protectReadMethods }: {
|
|
2
|
+
export declare function catalogAuthMiddleware({ serverOutDir, protectReadMethods, }: {
|
|
3
3
|
serverOutDir: string;
|
|
4
4
|
protectReadMethods?: boolean;
|
|
5
5
|
}): (ctx: Context, next: Next) => Promise<Response | void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{withPathPrefix as u}from"@redocly/theme/core/utils";import{OTEL_EXCLUDED_ROUTES as o}from"../../constants/common.js";import{telemetryTraceStep as
|
|
1
|
+
import{withPathPrefix as u}from"@redocly/theme/core/utils";import{OTEL_EXCLUDED_ROUTES as o}from"../../constants/common.js";import{telemetryTraceStep as m}from"../../telemetry/helpers/trace-step.js";import{getClientIp as d}from"../utils/get-client-ip.js";function A(){return async(e,t)=>{if(o.some(r=>e.req.path===u(r)))return t();await m("com.redocly.request.performed",async r=>{r?.setAttribute("id",e.req.path||""),r?.setAttribute("object","request"),r?.setAttribute("uri",e.req.url||""),r?.setAttribute("method",e.req.method||""),r?.setAttribute("host",e.req.header("host")||""),r?.setAttribute("url",e.req.url||""),r?.setAttribute("path",e.req.path||""),r?.setAttribute("user_agent",e.req.header("user-agent")||"");const i=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,s=d(e.req.raw)||e.req.raw.context.remoteAddr?.ipAddress;r?.setAttribute("user_id",i),r?.setAttribute("user_ip",s),await t()})}}export{A as telemetryMiddleware};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TrieRouter as
|
|
1
|
+
import{TrieRouter as _}from"hono/router/trie-router";import{REDOCLY_ROUTE_RBAC as u}from"@redocly/config";import{withPathPrefix as L,withoutPathPrefix as O}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as w}from"../../../constants/common.js";import{canAccessResource as P}from"../../../utils/rbac.js";import{handleUnauthorizedApiRequest as U}from"../../utils.js";import{handleApiRouteRequest as q}from"../../handle-api-route-request.js";import{sortApiFunctionRoutes as T}from"../../utils/sort-api-function-routes.js";function h(t){return t.headers.set("Cache-Control",w),t}function F(t,o){t.all("*",async(e,m)=>{const{method:p,path:c}=e.req,R=o.getAllApiRoutes(),f=T(R),i=new _;for(const n of f){const C=n.httpMethod?.toUpperCase()||"ALL",E=L(n.slug);i.add(C,E,n)}const r=i.match(p.toUpperCase(),c);if(!r||r[0].length===0)return m();const l=r[0],[s]=l[0],{isAuthenticated:A,claims:{email:d},teams:g}=e.get("auth"),a=O(c);return P({...s,slug:a,[u]:{...s[u],slug:a}},{isAuthenticated:A,email:d,teams:g},o.config.access?.rbac,o.config.access?.requiresLogin)?h(await q(s,e,o)):h(U(e))})}export{F as installApiRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{setCookie as R,deleteCookie as Y}from"hono/cookie";import{AuthProviderType as Q,DEFAULT_TEAM_CLAIM_NAME as x}from"@redocly/config";import{withPathPrefix as _,getPathPrefix as y}from"@redocly/theme/core/utils";import{compareURIs as ee}from"../../../utils/url/compare-uris.js";import{ensureArray as q}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as F,JWT_SECRET_KEY as v,ORG_SLUG as re,ORG_ID as oe}from"../../constants/common.js";import{AUTH_SEGMENT as ne,ServerRoutes as P}from"../../../constants/api.js";import{AuthCookieNames as L,DEFAULT_COOKIE_EXPIRATION as H}from"../../../constants/common.js";import{sanitizeRedirectPathname as B}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as T}from"../../telemetry/index.js";import{envConfig as j}from"../../config/env-config.js";import{fetchWithClient as te}from"../../utils/fetch-with-client.js";import{clearAuthCookies as K,clearPostLogoutCookie as $,hasPostLogoutCookie as se,setPostLogoutCookie as z}from"../../utils/cookie.js";import{getAuthProviderLoginParams as ie,isOidcProviderConfig as E,isSaml2ProviderConfig as ae,oidcExchangeCodeForToken as de,buildLoginUrl as ce,decodeSamlResponse as le,extractUserClaims as ue,parseSamlResponse as pe,parseOidcState as ge,verifySAMLResponse as fe,getUsernameFromPayload as me,buildOidcLogoutUrl as he,getOidcMetadata as G,getRedoclyTokenPayload as Ce,isRedoclySso as Ae,rewritePreviewAuthRedirectUri as Ie,parsePreviewBranch as J,buildOidcLoginUrl as we,createMcpSessionResource as D}from"../auth.js";import*as k from"../jwt/jwt.js";import{AlgorithmTypes as U}from"../jwt/types.js";import{handleErrorPageRender as Le}from"../utils.js";import{encodeBase64URL as Re}from"../jwt/encode.js";import{resolveUiLocalesForIdpLogin as _e}from"./helpers/resolve-ui-locales-for-idp-login.js";async function je(s){if(j.isProductionEnv)return s.newResponse(null,404,{});const{password:e,...r}=await s.req.json(),a=await k.sign({...r,name:r.username||r.email||"Unknown"},v,U.HS256);return R(s,L.AUTHORIZATION,a,{path:y()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),$(s),s.newResponse(null,200,{})}function Ke(){return async s=>{const e=s.get("logger"),r=encodeURIComponent(s.req.query("message")||"");e.error(`Login error: ${r}`);const a=`${P.LOGIN}/?error=${encodeURIComponent(r)}`;return s.newResponse(null,301,{Location:a})}}function Z(s){if(!s||!s.includes(P.MCP_CALLBACK))return null;try{const e=s.split("/"),r=e[e.length-1];if(r){const a=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(a).mcpSessionId||null}}catch{}return null}function ze(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=ge(e.req.query("state")),m=o.idpId,t=o.source==="mcp"||o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(P.MCP_CALLBACK),c=t?Z(typeof o.redirectTo=="string"?o.redirectTo:void 0):null,i=a?.[m];if(!E(i))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const d=await G(m,i);if(a&&!d.token_endpoint){const p="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${p}`),e.text(p,500)}try{const p=d.token_endpoint,u=e.req.query("code"),h=e.req.query("error");if(h)return t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:`OIDC error: ${h}`,error_details:e.req.query("error_description")||null}]),Le(e,s,{slug:"/"},403,"403OIDC");if(!u){const A="Code is expected but not present";return r.error(`OIDC login error: ${A}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:A,error_details:null}]),new Response(`Forbidden: ${A}`,{status:403})}const w=typeof o.redirectUri=="string"?o.redirectUri:new URL(_(P.OIDC_CALLBACK),e.req.url).toString(),C=e.get("cookies")?.code_verifier,l=await de(p,u,w,i,{...i.tokenRequestCustomParams,...C?{code_verifier:C}:{}});if(l.error)return r.error(`Error from OIDC provider: "${l.error}"`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:`Token exchange error: ${l.error}`,error_details:l.error_description||null}]),e.text(`Forbidden: ${l.error_description||l.error}`,403);if(!l?.id_token){const A="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${A}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:A,error_details:null}]),new Response(`Forbidden: ${A}`,{status:403})}const{payload:f,header:M}=k.decode(l.id_token),n=M.alg===U.RS256;if(i.audience?.length&&![...q(f.aud||[]),...q(f[F]||[])].some(O=>i.audience?.includes(O))){const O="No valid audience found in id_token";return r.error(`OIDC login error: ${O}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:O,error_details:null}]),new Response(`Forbidden: ${O}`)}const g=n?l.id_token:await k.sign({...f,idpId:m},v,U.HS256);me(f)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const S=i?.tokenExpirationTime?Date.now()+i.tokenExpirationTime*1e3:f.exp*1e3||Date.now()+H*1e3;if(i.introspectEndpoint){const A=await fetch(i.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:l.access_token})});if(A.ok){const b=(await A.json()).ext?.federatedIdentity;b&&(R(e,L.FEDERATED_ACCESS_TOKEN,b.access_token||"",{path:y()||"/",httpOnly:!1,expires:new Date(S)}),R(e,L.FEDERATED_ID_TOKEN,b.id_token||"",{path:y()||"/",httpOnly:!1,expires:new Date(S)}))}else r.warn(`OIDC introspect error: ${A.statusText}`)}if(R(e,L.AUTHORIZATION,g,{path:y()||"/",httpOnly:!0,expires:new Date(S)}),g!==l.id_token&&R(e,L.IDP_ID_TOKEN,l.id_token||"",{path:y()||"/",httpOnly:!0,expires:new Date(S)}),R(e,L.IDP_ACCESS_TOKEN,l.access_token||"",{path:y()||"/",httpOnly:!0,expires:new Date(S)}),Y(e,"code_verifier",{path:y()||"/"}),$(e),t&&o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(P.MCP_CALLBACK)){const O=`${e.req.url.split("?")[0].replace(P.OIDC_CALLBACK,"")}${o.redirectTo}`;return e.newResponse(null,302,{Location:O})}const V=typeof o.redirectTo=="string"?o.redirectTo:void 0;let W=B(new URL(V||"/",e.req.url).pathname);const X=e.newResponse(null,302,{Location:W});return r.updateContext({email:f.email,subject:f.sub}),r.info("OIDC login successful"),X}catch(p){const u=p instanceof Error?p.message:String(p),h=p instanceof Error?p.stack:String(p);if(r.error(`OIDC login error: ${u}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:u,error_details:h}]),p.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const I="Something went wrong";return r.error(`OIDC login error: ${I}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(c),error:I,error_details:null}]),e.text(I,500)}}function Ge(s){return async e=>{const r=e.get("logger"),o=e.get("auth").claims?.idpId,t=s.getConfig().ssoDirect?.[o];if(e.req.method==="POST")return E(t)||(K(e),z(e)),r.info("Logout successful"),e.newResponse(null,200,{});let c;if(E(t)){const i=(await G(o,t)).end_session_endpoint;if(i){const d=new URL(e.req.url),I=e.req.header("x-forwarded-proto")||d.protocol.slice(0,-1)||"https",p=e.req.header("x-forwarded-host")||d.host,u=`${I}://${p}`,h=J(u),w=h?Re(JSON.stringify({branch:J(u)})):void 0,C=h?`${Ie(u)}/${ne}/logout`:`${u}${_(P.POST_LOGOUT)}`;c=he(i,C,e.get("cookies")?.[L.IDP_ID_TOKEN]||e.get("cookies")?.[L.AUTHORIZATION]||"",w)}}return r.info("Logout successful"),K(e),z(e),e.newResponse(null,302,{Location:c||_("/")})}}function Je(s){return async e=>{const r=s.getConfig().access?.logoutReturnUrl,a=r||_("/");return e.newResponse(null,302,{Location:a})}}function Ze(s){return async e=>{const r=e.get("logger"),a=e.req.param("code"),o=j.BH_API_URL,m=(t,c,i)=>t&&c?`${t} ${c.charAt(0)}`:i;try{if(!o)throw new Error("BH_API_URL is not set");const t=s.getConfig().ssoDirect;if(!t||!Object.keys(t).length)return r.warn("Invite no sso configured to handle"),e.redirect(_("/"));const c=await te(`${o}/user-invites/public/${a}`);if(!c.ok)return c.status===404?(r.warn(`Invite ${a} not found redirect to homepage`),e.redirect(_("/"))):(r.error("Invite error",await c.text()),e.redirect(_("/")));const i=await c.json(),d=new URL(_("/invite"),e.req.url);return d.searchParams.set("code",a),d.searchParams.set("org",i.organization.name),d.searchParams.set("invitedBy",m(i.invitedBy.firstName,i.invitedBy.lastName,i.invitedBy.name)),e.newResponse(null,302,{Location:d.toString()})}catch(t){return r.error("Error processing invite",{error:t,inviteCode:a}),e.text(t.message||"Failed to process invite",400)}}}function Ve(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=new URL(e.req.url),m=e.req.query("inviteCode"),t=e.req.header("x-forwarded-proto")||o.protocol.slice(0,-1)||"https",c=e.req.header("x-forwarded-host")||o.host,i=`${t}://${c}`;let d=o.searchParams.get("idpId");const I=o.searchParams.get("redirectTo"),p=Object.keys(a||{})[0];d=d||p;const u=o.searchParams.get("mcp_redirect_uri"),h=!!u;if(!a?.[d]){const g="Invalid idpId";if(r.error(`IdP login error: ${g}`),h){const N=Z(I||void 0);T.sendMcpAuthorizationFailedMessage([{...D(N),error:g,error_details:null}])}return e.text(`Forbidden: ${g}`,403)}const C=_e({localePrefixParam:o.searchParams.get("localePrefix"),l10n:s.getGlobalData()?.l10n}),l=d&&a?await ie(d,a[d]):void 0,f={};for(const g of Object.keys(l?.extraParams||{}))f[g]=o.searchParams.get(g)||l?.extraParams?.[g]||void 0;se(e)&&(f.prompt="login",f.post_logout="1");let M,n={};if(h&&u&&l&&l.type===Q.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${u}`);const g=we("",{...l,extraParams:f},I,m,{redirectUriOverride:u,sourceOverride:"mcp",branchOverride:void 0,uiLocales:C});M=g.loginUrl,n=g.cookies||{}}else if(l){const g=ce({...l,extraParams:f},i,I,m,C);M=g.loginUrl,n=g.cookies||{}}return Object.keys(n).forEach(g=>{R(e,g,n[g].value,n[g].options)}),r.info(`IdP login initiated for ID '${d}'`),e.newResponse(null,302,{Location:M||new URL(e.req.url).pathname})}}function We(s){return async e=>{const r=e.get("logger"),a=await e.req.formData(),o=a.get("SAMLResponse"),m=a.get("RelayState");if(typeof o!="string"||typeof m!="string"){const n="SAMLResponse is required";return r.error(`SAML2 login error: ${n}`),e.text(`Bad request: ${n}`,400)}const t=le(o),{success:c,uid:i,nameFormat:d,attrs:I,issuerId:p,expiresAt:u}=pe(t),{idpId:h,redirectTo:w}=JSON.parse(m);if(!c){const n="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!u||Math.ceil(Date.now()/1e3)>=u){const n="SAML2 Token Expired";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const C=s.getConfig().ssoDirect?.[h];if(!C||!ae(C)){const n="Cannot find valid IdP";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!(C.issuerId&&p&&ee(C.issuerId,p))){const n="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!await fe(t,C.x509PublicCert)){const n="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const f=ue(i,d,I,C.teamsAttributeName??x);if(!f.sub){const n="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}if(!f.email){const n="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}const M=await k.sign({...f,idpId:h},v,U.HS256);return R(e,L.AUTHORIZATION,M,{path:y()||"/",httpOnly:!0,expires:new Date(u*1e3)}),$(e),r.updateContext({email:f.email,subject:f.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:w||"/"})}}function Xe(s){return async e=>{const r=e.get("logger"),a=new URL(e.req.query("redirectTo")||"/",e.req.url),o=_(B(a.pathname)),m=s.getConfig().ssoDirect,t=Object.entries(m||{}).find(([,w])=>E(w)&&Ae(w));if(!(m&&t))return e.newResponse(null,302,{Location:o});const i=e.req.query("token"),d=i&&await Ce(i);if(!d)return e.newResponse(null,302,{Location:o});if(!q(d[F]||[]).some(w=>w===re||w===oe))return e.newResponse(null,302,{Location:o});const u=await k.sign({...d,idpId:t?.at(0)},v,U.HS256),h=Date.now()+H*1e3;return R(e,L.AUTHORIZATION,u,{path:y()||"/",httpOnly:!0,expires:new Date(h),sameSite:"None",secure:!0}),$(e),r.info("Token login successful"),e.newResponse(null,302,{Location:o})}}export{je as authorizeHandler,Ve as idpLoginHandler,Ze as inviteHandler,Ge as logoutHandler,ze as oidcCallbackHandler,Je as postLogoutHandler,Ke as redoclyLoginCallbackHandler,Xe as redoclyTokenLoginHandler,We as samlCallbackHandler};
|
|
1
|
+
import{setCookie as L,deleteCookie as U}from"hono/cookie";import{AuthProviderType as Q,DEFAULT_TEAM_CLAIM_NAME as x}from"@redocly/config";import{withPathPrefix as O,getPathPrefix as C}from"@redocly/theme/core/utils";import{compareURIs as ee}from"../../../utils/url/compare-uris.js";import{ensureArray as N}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as H,JWT_SECRET_KEY as v,ORG_SLUG as re,ORG_ID as oe}from"../../constants/common.js";import{AUTH_SEGMENT as ne,ServerRoutes as P}from"../../../constants/api.js";import{AuthCookieNames as _,DEFAULT_COOKIE_EXPIRATION as B}from"../../../constants/common.js";import{sanitizeRedirectPathname as K}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as T}from"../../telemetry/index.js";import{envConfig as j}from"../../config/env-config.js";import{fetchWithClient as te}from"../../utils/fetch-with-client.js";import{clearAuthCookies as z,clearPostLogoutCookie as $,hasPostLogoutCookie as se,setPostLogoutCookie as G}from"../../utils/cookie.js";import{getAuthProviderLoginParams as ie,isOidcProviderConfig as b,isSaml2ProviderConfig as ae,oidcExchangeCodeForToken as de,buildLoginUrl as ce,decodeSamlResponse as le,extractUserClaims as ue,parseSamlResponse as pe,parseOidcState as ge,verifySAMLResponse as fe,getUsernameFromPayload as me,buildOidcLogoutUrl as he,getOidcMetadata as J,getRedoclyTokenPayload as Re,isRedoclySso as _e,rewritePreviewAuthRedirectUri as Ie,parsePreviewBranch as Z,buildOidcLoginUrl as Ce,createMcpSessionResource as D}from"../auth.js";import*as k from"../jwt/jwt.js";import{AlgorithmTypes as E}from"../jwt/types.js";import{handleErrorPageRender as Ae}from"../utils.js";import{encodeBase64URL as we}from"../jwt/encode.js";import{resolveUiLocalesForIdpLogin as Le}from"./helpers/resolve-ui-locales-for-idp-login.js";async function Ke(s){if(j.isProductionEnv)return s.newResponse(null,404,{});const{password:e,...r}=await s.req.json(),a=await k.sign({...r,name:r.username||r.email||"Unknown"},v,E.HS256);return L(s,_.AUTHORIZATION,a,{path:C()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),$(s),s.newResponse(null,200,{})}function je(){return async s=>{const e=s.get("logger"),r=encodeURIComponent(s.req.query("message")||"");e.error(`Login error: ${r}`);const a=`${P.LOGIN}/?error=${encodeURIComponent(r)}`;return s.newResponse(null,301,{Location:a})}}function V(s){if(!s||!s.includes(P.MCP_CALLBACK))return null;try{const e=s.split("/"),r=e[e.length-1];if(r){const a=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(a).mcpSessionId||null}}catch{}return null}function ze(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=ge(e.req.query("state")),m=o.idpId,t=o.source==="mcp"||o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(P.MCP_CALLBACK),l=t?V(typeof o.redirectTo=="string"?o.redirectTo:void 0):null,i=a?.[m];if(!b(i))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const d=await J(m,i);if(a&&!d.token_endpoint){const p="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${p}`),e.text(p,500)}try{const p=d.token_endpoint,u=e.req.query("code"),h=e.req.query("error");if(h)return t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:`OIDC error: ${h}`,error_details:e.req.query("error_description")||null}]),Ae(e,s,{slug:"/"},403,"403OIDC");if(!u){const I="Code is expected but not present";return r.error(`OIDC login error: ${I}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:I,error_details:null}]),new Response(`Forbidden: ${I}`,{status:403})}const w=typeof o.redirectUri=="string"?o.redirectUri:new URL(O(P.OIDC_CALLBACK),e.req.url).toString(),R=e.get("cookies")?.code_verifier,c=await de(p,u,w,i,{...i.tokenRequestCustomParams,...R?{code_verifier:R}:{}});if(c.error)return r.error(`Error from OIDC provider: "${c.error}"`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:`Token exchange error: ${c.error}`,error_details:c.error_description||null}]),e.text(`Forbidden: ${c.error_description||c.error}`,403);if(!c?.id_token){const I="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${I}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:I,error_details:null}]),new Response(`Forbidden: ${I}`,{status:403})}const{payload:f,header:M}=k.decode(c.id_token),n=M.alg===E.RS256;if(i.audience?.length&&![...N(f.aud||[]),...N(f[H]||[])].some(y=>i.audience?.includes(y))){const y="No valid audience found in id_token";return r.error(`OIDC login error: ${y}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:y,error_details:null}]),new Response(`Forbidden: ${y}`)}const g=n?c.id_token:await k.sign({...f,idpId:m},v,E.HS256);me(f)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const S=i?.tokenExpirationTime?Date.now()+i.tokenExpirationTime*1e3:f.exp*1e3||Date.now()+B*1e3;if(i.introspectEndpoint){const I=await fetch(i.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:c.access_token})});if(I.ok){const q=(await I.json()).ext?.federatedIdentity;q&&(L(e,_.FEDERATED_ACCESS_TOKEN,q.access_token||"",{path:C()||"/",httpOnly:!1,expires:new Date(S)}),L(e,_.FEDERATED_ID_TOKEN,q.id_token||"",{path:C()||"/",httpOnly:!1,expires:new Date(S)}))}else r.warn(`OIDC introspect error: ${I.statusText}`)}if(L(e,_.AUTHORIZATION,g,{path:C()||"/",httpOnly:!0,expires:new Date(S)}),g!==c.id_token&&L(e,_.IDP_ID_TOKEN,c.id_token||"",{path:C()||"/",httpOnly:!0,expires:new Date(S)}),L(e,_.IDP_ACCESS_TOKEN,c.access_token||"",{path:C()||"/",httpOnly:!0,expires:new Date(S)}),c.refresh_token?L(e,_.IDP_REFRESH_TOKEN,c.refresh_token,{path:C()||"/",httpOnly:!0,expires:new Date(S)}):U(e,_.IDP_REFRESH_TOKEN,{path:C()||"/"}),U(e,"code_verifier",{path:C()||"/"}),$(e),t&&o.redirectTo&&typeof o.redirectTo=="string"&&o.redirectTo.includes(P.MCP_CALLBACK)){const y=`${e.req.url.split("?")[0].replace(P.OIDC_CALLBACK,"")}${o.redirectTo}`;return e.newResponse(null,302,{Location:y})}const W=typeof o.redirectTo=="string"?o.redirectTo:void 0;let X=K(new URL(W||"/",e.req.url).pathname);const Y=e.newResponse(null,302,{Location:X});return r.updateContext({email:f.email,subject:f.sub}),r.info("OIDC login successful"),Y}catch(p){const u=p instanceof Error?p.message:String(p),h=p instanceof Error?p.stack:String(p);if(r.error(`OIDC login error: ${u}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:u,error_details:h}]),p.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const A="Something went wrong";return r.error(`OIDC login error: ${A}`),t&&T.sendMcpAuthorizationFailedMessage([{...D(l),error:A,error_details:null}]),e.text(A,500)}}function Ge(s){return async e=>{const r=e.get("logger"),o=e.get("auth").claims?.idpId,t=s.getConfig().ssoDirect?.[o];if(e.req.method==="POST")return b(t)||(z(e),G(e)),r.info("Logout successful"),e.newResponse(null,200,{});let l;if(b(t)){const i=(await J(o,t)).end_session_endpoint;if(i){const d=new URL(e.req.url),A=e.req.header("x-forwarded-proto")||d.protocol.slice(0,-1)||"https",p=e.req.header("x-forwarded-host")||d.host,u=`${A}://${p}`,h=Z(u),w=h?we(JSON.stringify({branch:Z(u)})):void 0,R=h?`${Ie(u)}/${ne}/logout`:`${u}${O(P.POST_LOGOUT)}`;l=he(i,R,e.get("cookies")?.[_.IDP_ID_TOKEN]||e.get("cookies")?.[_.AUTHORIZATION]||"",w)}}return r.info("Logout successful"),z(e),G(e),e.newResponse(null,302,{Location:l||O("/")})}}function Je(s){return async e=>{const r=s.getConfig().access?.logoutReturnUrl,a=r||O("/");return e.newResponse(null,302,{Location:a})}}function Ze(s){return async e=>{const r=e.get("logger"),a=e.req.param("code"),o=j.BH_API_URL,m=(t,l,i)=>t&&l?`${t} ${l.charAt(0)}`:i;try{if(!o)throw new Error("BH_API_URL is not set");const t=s.getConfig().ssoDirect;if(!t||!Object.keys(t).length)return r.warn("Invite no sso configured to handle"),e.redirect(O("/"));const l=await te(`${o}/public-user-invites/${a}`);if(!l.ok)return l.status===404?(r.warn(`Invite ${a} not found redirect to homepage`),e.redirect(O("/"))):(r.error("Invite error",await l.text()),e.redirect(O("/")));const i=await l.json(),d=new URL(O("/invite"),e.req.url);return d.searchParams.set("code",a),d.searchParams.set("org",i.organization.name),d.searchParams.set("invitedBy",m(i.invitedBy.firstName,i.invitedBy.lastName,i.invitedBy.name)),e.newResponse(null,302,{Location:d.toString()})}catch(t){return r.error("Error processing invite",{error:t,inviteCode:a}),e.text(t.message||"Failed to process invite",400)}}}function Ve(s){return async e=>{const r=e.get("logger"),a=s.getConfig().ssoDirect,o=new URL(e.req.url),m=e.req.query("inviteCode"),t=e.req.header("x-forwarded-proto")||o.protocol.slice(0,-1)||"https",l=e.req.header("x-forwarded-host")||o.host,i=`${t}://${l}`;let d=o.searchParams.get("idpId");const A=o.searchParams.get("redirectTo"),p=Object.keys(a||{})[0];d=d||p;const u=o.searchParams.get("mcp_redirect_uri"),h=!!u;if(!a?.[d]){const g="Invalid idpId";if(r.error(`IdP login error: ${g}`),h){const F=V(A||void 0);T.sendMcpAuthorizationFailedMessage([{...D(F),error:g,error_details:null}])}return e.text(`Forbidden: ${g}`,403)}const R=Le({localePrefixParam:o.searchParams.get("localePrefix"),l10n:s.getGlobalData()?.l10n}),c=d&&a?await ie(d,a[d]):void 0,f={};for(const g of Object.keys(c?.extraParams||{}))f[g]=o.searchParams.get(g)||c?.extraParams?.[g]||void 0;se(e)&&(f.prompt="login",f.post_logout="1");let M,n={};if(h&&u&&c&&c.type===Q.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${u}`);const g=Ce("",{...c,extraParams:f},A,m,{redirectUriOverride:u,sourceOverride:"mcp",branchOverride:void 0,uiLocales:R});M=g.loginUrl,n=g.cookies||{}}else if(c){const g=ce({...c,extraParams:f},i,A,m,R);M=g.loginUrl,n=g.cookies||{}}return Object.keys(n).forEach(g=>{L(e,g,n[g].value,n[g].options)}),r.info(`IdP login initiated for ID '${d}'`),e.newResponse(null,302,{Location:M||new URL(e.req.url).pathname})}}function We(s){return async e=>{const r=e.get("logger"),a=await e.req.formData(),o=a.get("SAMLResponse"),m=a.get("RelayState");if(typeof o!="string"||typeof m!="string"){const n="SAMLResponse is required";return r.error(`SAML2 login error: ${n}`),e.text(`Bad request: ${n}`,400)}const t=le(o),{success:l,uid:i,nameFormat:d,attrs:A,issuerId:p,expiresAt:u}=pe(t),{idpId:h,redirectTo:w}=JSON.parse(m);if(!l){const n="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!u||Math.ceil(Date.now()/1e3)>=u){const n="SAML2 Token Expired";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const R=s.getConfig().ssoDirect?.[h];if(!R||!ae(R)){const n="Cannot find valid IdP";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!(R.issuerId&&p&&ee(R.issuerId,p))){const n="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${n}`),e.text(`Permission denied: ${n}`,401)}if(!await fe(t,R.x509PublicCert)){const n="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${n}`),e.text(n,401)}const f=ue(i,d,A,R.teamsAttributeName??x);if(!f.sub){const n="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}if(!f.email){const n="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${n}`),e.text(n,400)}const M=await k.sign({...f,idpId:h},v,E.HS256);return L(e,_.AUTHORIZATION,M,{path:C()||"/",httpOnly:!0,expires:new Date(u*1e3)}),U(e,_.IDP_REFRESH_TOKEN,{path:C()||"/"}),$(e),r.updateContext({email:f.email,subject:f.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:w||"/"})}}function Xe(s){return async e=>{const r=e.get("logger"),a=new URL(e.req.query("redirectTo")||"/",e.req.url),o=O(K(a.pathname)),m=s.getConfig().ssoDirect,t=Object.entries(m||{}).find(([,w])=>b(w)&&_e(w));if(!(m&&t))return e.newResponse(null,302,{Location:o});const i=e.req.query("token"),d=i&&await Re(i);if(!d)return e.newResponse(null,302,{Location:o});if(!N(d[H]||[]).some(w=>w===re||w===oe))return e.newResponse(null,302,{Location:o});const u=await k.sign({...d,idpId:t?.at(0)},v,E.HS256),h=Date.now()+B*1e3;return L(e,_.AUTHORIZATION,u,{path:C()||"/",httpOnly:!0,expires:new Date(h),sameSite:"None",secure:!0}),U(e,_.IDP_REFRESH_TOKEN,{path:C()||"/"}),$(e),r.info("Token login successful"),e.newResponse(null,302,{Location:o})}}export{Ke as authorizeHandler,Ve as idpLoginHandler,Ze as inviteHandler,Ge as logoutHandler,ze as oidcCallbackHandler,Je as postLogoutHandler,je as redoclyLoginCallbackHandler,Xe as redoclyTokenLoginHandler,We as samlCallbackHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as
|
|
1
|
+
import{telemetryTraceStep as n}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as d}from"../../../../constants/api.js";import{ALLOWED_CATALOG_QUERY_PARAMS as y}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as E}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as g}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as b}from"../../../providers/database/pagination/schemas.js";import{ENTITY_RELATION_TO_DATABASE as A}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";import{getRbacRestrictionsDataForCatalog as f}from"../helpers/get-rbac-restrictions-data-for-catalog.js";const T=["id","key","title","type","summary","source","source_file","created_at","updated_at","relation_type","version","revision"],_=async({catalogEntitiesService:i,store:a,ctx:t})=>n("com.redocly.catalogEntities.bff.relatedEntities.getRelatedEntities",async e=>{e?.setAttribute("object","catalogEntity");try{const r=t.req.param(d);if(!r)return e?.error(new Error("Entity key is required")),t.json({message:"Entity key is required"},400);e?.setAttribute("id",r),e?.setAttribute("uri",`urn:redocly:realm:api:catalogEntity:${r}`),e?.setAttribute("pathParams",JSON.stringify({entityKey:r}));const o=t.req.query();e?.setAttribute("queryParams",JSON.stringify(E(o,y)));const l=b(T,A).parse(o),{currentRbacTeamsForRead:m,excludedTypes:u,excludedEntities:c}=f({store:a,ctx:t}),s=await i.getRelatedEntities({entityKey:r,paginationParams:l,rbacTeams:m,excludedTypes:u,excludedEntities:c});return e?.setAttribute("relatedEntitiesCount",s.items.length),t.json(s)}catch(r){return console.error(r),e?.error(r),t.json({message:r.message},500)}});function I(i){return async a=>n("com.redocly.catalogEntities.bff.relatedEntities",async t=>{t?.setAttribute("id","catalogEntityId"),t?.setAttribute("object","catalogEntity"),t?.setAttribute("uri","urn:redocly:realm:api:catalogEntity:catalogEntityId"),t?.setAttribute("method",a.req.method);const e=await g.getInstance({baseDbDir:i.serverOutDir});return _({catalogEntitiesService:e,ctx:a,store:i})})}export{I as bffCatalogRelatedEntitiesHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as y}from"../../../telemetry/helpers/trace-step.js";import{parseFilterQuery as u}from"../../../providers/database/pagination/filter.js";import{extractEqualFilterClauseValue as
|
|
1
|
+
import{telemetryTraceStep as y}from"../../../telemetry/helpers/trace-step.js";import{parseFilterQuery as u}from"../../../providers/database/pagination/filter.js";import{extractEqualFilterClauseValue as c}from"../../../providers/database/pagination/utils/extract-equal-filter-clause-value.js";import{CatalogEntitiesService as f}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";function b(a){return async e=>y("com.redocly.catalogEntities.bff.revisions.getEntityRevisions",async t=>{t?.setAttribute("object","catalogEntity");const l=await f.getInstance({baseDbDir:a.serverOutDir}),i=e.req.query("filter");let n;try{n=u(typeof i=="string"?i:"",["catalogEntityKey"])}catch{return t?.error(new Error("Invalid filter")),e.json({message:"Invalid filter"},400)}const r=c(n,"catalogEntityKey");if(!r)return t?.error(new Error("Missing catalogEntityKey in filter")),e.json({message:"The filter query must include a non-empty catalogEntityKey clause, for example filter=catalogEntityKey:my-entity."},400);t?.setAttribute("id",r),t?.setAttribute("uri",`urn:redocly:realm:api:catalogEntity:${r}`);const s=e.req.query("version")??null;t?.setAttribute("queryParams",JSON.stringify({version:s,filter:i}));const o=await l.listEntityRevisions(r,s);return t?.setAttribute("totalRevisions",o.length),e.json({items:o})})}export{b as bffCatalogRevisionsHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as
|
|
1
|
+
import{telemetryTraceStep as l}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_KEY as E}from"../../../../constants/api.js";import{ALLOWED_CATALOG_QUERY_PARAMS as b}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as f}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as A}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as v}from"../../../providers/database/pagination/schemas.js";import{isValidIsoDate as p}from"../../../utils/is-valid-iso-date.js";import{isValidSanitizedString as q}from"../../../utils/validate-and-sanitize-string.js";import{getRbacRestrictionsDataForCatalog as d}from"../helpers/get-rbac-restrictions-data-for-catalog.js";const h=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","source_file","version","revision","created_at","updated_at","domains","owners"],w=async({catalogEntitiesService:n,ctx:t,store:i})=>l("com.redocly.catalogEntities.bff.getEntities",async e=>{e?.setAttribute("id","catalogEntityId"),e?.setAttribute("object","catalogEntity"),e?.setAttribute("uri","urn:redocly:realm:api:catalogEntity:catalogEntityId");const r=t.req.query();e?.setAttribute("queryParams",JSON.stringify(f(r,b)));const a=v(h).parse(r),{currentRbacTeamsForRead:s,excludedTypes:o,excludedEntities:y}=d({store:i,ctx:t}),u=await n.getEntitiesWithRelations({paginationParams:a,rbacTeams:s,excludedTypes:o,excludedEntities:y});return e?.setAttribute("entitiesCount",u.items.length),t.json(u)}),I=async({catalogEntitiesService:n,ctx:t,store:i})=>l("com.redocly.catalogEntities.bff.getEntity",async e=>{e?.setAttribute("object","catalogEntity");const r=t.req.param(E);if(!r)return e?.error(new Error("Entity key is required")),t.json({message:"Entity key is required"},400);e?.setAttribute("id",r),e?.setAttribute("uri",`urn:redocly:realm:api:catalogEntity:${r}`);const a=t.req.query("revision");let s=null;if(a){if(!p(a))return e?.error(new Error("Invalid revision parameter")),t.json({message:"Invalid revision parameter: must be a valid ISO 8601 date-time string"},400);s=a}const o=t.req.query("version");if(!q(o,{pattern:/^[a-zA-Z0-9._-]+$/,maxLength:100,allowEmpty:!0}))return e?.error(new Error("Invalid version parameter")),t.json({message:"Invalid version parameter: version must contain only alphanumeric characters, dots, hyphens, and underscores, and must not exceed 100 characters"},400);const y=t.req.query();e?.setAttribute("queryParams",JSON.stringify(y)),e?.setAttribute("pathParams",JSON.stringify({entityKey:r}));const{currentRbacTeamsForRead:u,excludedTypes:c,excludedEntities:g}=d({store:i,ctx:t}),m=await n.getEntityWithRelationsByKey({entityKey:r,filter:{revision:s,version:o},rbacTeams:u,excludedTypes:c,excludedEntities:g});return m?(e?.setAttribute("entity",JSON.stringify(m)),t.json(m)):(e?.error(new Error("Entity not found")),t.json({message:"Entity not found"},404))});function L(n){return async t=>l("com.redocly.catalogEntities.bff",async i=>{i?.setAttribute("id","catalogEntityId"),i?.setAttribute("object","catalogEntity"),i?.setAttribute("uri","urn:redocly:realm:api:catalogEntity:catalogEntityId"),i?.setAttribute("method",t.req.method);const e=await A.getInstance({baseDbDir:n.serverOutDir});return t.req.param("entityKey")?I({catalogEntitiesService:e,ctx:t,store:n}):w({catalogEntitiesService:e,ctx:t,store:n})})}export{L as bffCatalogHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as l}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_RELATION_ID as
|
|
1
|
+
import{telemetryTraceStep as l}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_ENTITY_RELATION_ID as g}from"../../../../constants/api.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as E,ALLOWED_CATALOG_QUERY_PARAMS as c}from"../../../constants/plugins/catalog-entities.js";import{allowlistObject as m}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as R}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as A}from"../../../providers/database/pagination/schemas.js";import{ENTITY_RELATION_TO_DATABASE as b}from"../../../plugins/catalog-entities/database/mappers/field-transformations.js";import{CacheService as f}from"../../../persistence/cache/services/cache-service.js";import{parseEntityRelation as w}from"./parsers/relations/parse-entity-relation.js";import{parseEntitiesRelations as j}from"./parsers/relations/parse-entities-relations.js";import{parseEntityRelationUpdateData as h}from"./parsers/relations/parse-entity-relation-update-data.js";const O=["id","organizationId","projectId","sourceKey","targetKey","type","createdAt","updatedAt"],y=async o=>{await(await f.getInstance({baseDbDir:o,databaseType:"local"})).deleteByNamespace(E)},q=async({catalogEntitiesService:o,ctx:e})=>l("com.redocly.catalogEntities.relations.getEntityRelation",async r=>{r?.setAttribute("object","catalogEntitiesRelation");const t=e.req.param(g);if(!t)return r?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400);r?.setAttribute("id",t),r?.setAttribute("uri",`urn:redocly:realm:api:catalogEntitiesRelation:${t}`),r?.setAttribute("pathParams",JSON.stringify({entityRelationId:t}));const n=await o.getEntityRelationById(t);return n?(r?.setAttribute("entityRelation",JSON.stringify(n)),e.json(n)):(r?.error(new Error("Entity relation not found")),e.json({message:"Entity relation not found"},404))}),I=async({catalogEntitiesService:o,ctx:e})=>l("com.redocly.catalogEntities.relations.getEntitiesRelations",async r=>{r?.setAttribute("id","catalogEntitiesRelationId"),r?.setAttribute("object","catalogEntitiesRelation"),r?.setAttribute("uri","urn:redocly:realm:api:catalogEntitiesRelation:catalogEntitiesRelationId");try{const t=e.req.query();r?.setAttribute("queryParams",JSON.stringify(m(t,c)));const n=A(O,b).parse(t),i=await o.getEntitiesRelations(n);return r?.setAttribute("entitiesRelationsCount",i.items.length),e.json(i)}catch(t){return console.error(t),r?.error(new Error("Failed to get entities relations")),e.json({message:"Failed to get entities relations"},500)}}),T=async({catalogEntitiesService:o,ctx:e,serverOutDir:r})=>l("com.redocly.catalogEntities.relations.createEntityRelation",async t=>{t?.setAttribute("object","catalogEntitiesRelation");const n=e.get("logger");try{const i=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(i));const a=w(i),s=await o.createEntityRelation(a);return s?(y(r),t?.setAttribute("id",s.id),t?.setAttribute("uri",`urn:redocly:realm:api:catalogEntitiesRelation:${s.id}`),t?.setAttribute("entityRelation",JSON.stringify(s)),e.json(s)):(t?.error(new Error("Failed to create entity relation")),e.json({message:"Failed to create entity relation"},500))}catch(i){return n.error(i),i instanceof Error&&i.message.includes("validation failed")?(t?.error(new Error(i.message)),e.json({message:i.message},400)):(t?.error(i),e.json({message:"Failed to create entity relation"},500))}}),N=async({catalogEntitiesService:o,ctx:e,serverOutDir:r})=>l("com.redocly.catalogEntities.relations.bulkUpsertEntitiesRelations",async t=>{t?.setAttribute("id","catalogEntitiesRelationId"),t?.setAttribute("object","catalogEntitiesRelation"),t?.setAttribute("uri","urn:redocly:realm:api:catalogEntitiesRelation:catalogEntitiesRelationId");const n=e.get("logger");try{const i=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(i));const a=j(i),s=await o.createEntitiesRelations(a);if(!s.length)return t?.error(new Error("Failed to create entity relations")),e.json({message:"Failed to create entity relations"},500);y(r);const d=s.filter(u=>u.status==="ok");return t?.setAttribute("totalSuccess",d.length),t?.setAttribute("totalFailed",s.length-d.length),e.json(s,207)}catch(i){return n.error(i),i instanceof Error&&i.message.includes("validation failed")?(t?.error(new Error(i.message)),e.json({message:i.message},400)):(t?.error(i),e.json({message:"Failed to create entity relations"},500))}}),D=async({catalogEntitiesService:o,ctx:e,serverOutDir:r})=>l("com.redocly.catalogEntities.relations.updateEntityRelation",async t=>{t?.setAttribute("object","catalogEntitiesRelation");const n=e.get("logger"),i=e.req.param(g);if(!i)return t?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400);t?.setAttribute("id",i),t?.setAttribute("uri",`urn:redocly:realm:api:catalogEntitiesRelation:${i}`),t?.setAttribute("pathParams",JSON.stringify({entityRelationId:i}));try{const a=await e.req.json();t?.setAttribute("requestBody",JSON.stringify(a));const s=await o.getEntityRelationById(i);if(!s)return t?.error(new Error(`Entity relation with id: ${i} not found`)),e.json({message:`Entity relation with id: ${i} not found`},404);const d=h(a),u=await o.updateEntityRelation(d,s);return u?(y(r),t?.setAttribute("entityRelation",JSON.stringify(u)),e.json(u)):(t?.error(new Error("Failed to update entity relation")),e.json({message:"Failed to update entity relation"},500))}catch(a){return n.error(a),a instanceof Error&&a.message.includes("validation failed")?(t?.error(new Error(a.message)),e.json({message:a.message},400)):(t?.error(a),e.json({message:a.message},500))}}),F=async({catalogEntitiesService:o,ctx:e,serverOutDir:r})=>l("com.redocly.catalogEntities.relations.deleteEntityRelation",async t=>{t?.setAttribute("object","catalogEntitiesRelation");const n=e.req.param(g);return n?(t?.setAttribute("id",n),t?.setAttribute("uri",`urn:redocly:realm:api:catalogEntitiesRelation:${n}`),t?.setAttribute("pathParams",JSON.stringify({entityRelationId:n})),await o.deleteEntityRelation(n),y(r),new Response(null,{status:204})):(t?.error(new Error("Entity relation id is required")),e.json({message:"Entity relation id is required"},400))}),P={GET:I,POST:T,PUT:N},C={GET:q,DELETE:F,PATCH:D};function k(o){return async e=>l("com.redocly.catalogEntities.relations",async r=>{r?.setAttribute("id","catalogEntitiesRelationId"),r?.setAttribute("object","catalogEntitiesRelation"),r?.setAttribute("uri","urn:redocly:realm:api:catalogEntitiesRelation:catalogEntitiesRelationId"),r?.setAttribute("method",e.req.method);const t=await R.getInstance({baseDbDir:o.serverOutDir}),n=e.req.method,i=e.req.param(g)?C:P;return i[n]?await i[n]({catalogEntitiesService:t,ctx:e,serverOutDir:o.serverOutDir}):(r?.error(new Error("Method not allowed")),e.json({message:"Method not allowed"},405))})}export{k as catalogRelationsHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCompleteCatalogConfig as
|
|
1
|
+
import{getCompleteCatalogConfig as T}from"../../../plugins/catalog-entities/get-complete-catalog-config.js";import{telemetryTraceStep as g}from"../../../telemetry/helpers/trace-step.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as p,ALLOWED_CATALOG_QUERY_PARAMS as F}from"../../../constants/plugins/catalog-entities.js";import{CATALOG_ENTITY_ID as f}from"../../../../constants/api.js";import{allowlistObject as I}from"../../../../utils/object/allowlist-object.js";import{CatalogEntitiesService as R}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{createPaginationParamsValidator as q}from"../../../providers/database/pagination/schemas.js";import{createEntityRelationDtoFromFileSchema as O}from"../../../plugins/catalog-entities/database/mappers/create-entity-relation-dto-from-file-schema.js";import{CacheService as C}from"../../../persistence/cache/services/cache-service.js";import{hasAccessToEntity as A}from"./helpers/has-access-to-entity.js";import{getRbacRestrictionsDataForCatalog as h}from"../helpers/get-rbac-restrictions-data-for-catalog.js";import{mapEntityReadModelSchemaToEntityReadDto as m}from"./mappers/map-entity-read-model-schema-to-entity-read-dto.js";import{parseEntity as D}from"./parsers/entities/parse-entity.js";import{parseEntityUpdateData as P}from"./parsers/entities/parse-entity-update-data.js";import{parseEntities as k}from"./parsers/entities/parse-entities.js";import{upsertPagesStats as j}from"./helpers/upsert-pages-stats.js";const N=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","createdAt","updatedAt"],b=async s=>{await(await C.getInstance({baseDbDir:s,databaseType:"local"})).deleteByNamespace(p)},W=async({catalogEntitiesService:s,ctx:t,store:a})=>g("com.redocly.catalogEntities.getEntities",async o=>{o?.setAttribute("id","catalogEntityId"),o?.setAttribute("object","catalogEntity"),o?.setAttribute("uri","urn:redocly:realm:api:catalogEntity:catalogEntityId");const n=t.get("logger");try{const e=t.req.query();o?.setAttribute("queryParams",JSON.stringify(I(e,F)));const{currentRbacTeamsForRead:d,excludedTypes:r,excludedEntities:i}=h({store:a,ctx:t}),l=q(N).parse(e),y=await s.getEntities({paginationParams:l,rbacTeams:d,excludedTypes:r,excludedEntities:i});return o?.setAttribute("entitiesCount",y.items.length),t.json({...y,items:y.items.map(m)})}catch(e){return n.error(e),o?.error(e),t.json({message:"Failed to get entities"},500)}}),L=async({catalogEntitiesService:s,ctx:t,store:a})=>g("com.redocly.catalogEntities.getEntity",async o=>{o?.setAttribute("object","catalogEntity");const n=t.req.param(f);if(!n)return o?.error(new Error("Entity id is required")),t.json({message:"Entity id is required"},400);o?.setAttribute("id",n),o?.setAttribute("uri",`urn:redocly:realm:api:catalogEntity:${n}`),o?.setAttribute("pathParams",JSON.stringify({entityId:n}));const{currentRbacTeamsForRead:e,excludedTypes:d,excludedEntities:r}=h({store:a,ctx:t}),i=await s.getEntityById(n,{rbacTeams:e,excludedTypes:d,excludedEntities:r});return i?(o?.setAttribute("entity",JSON.stringify(i)),t.json(m(i))):(o?.error(new Error("Entity not found")),t.json({message:"Entity not found"},404))}),J=async({catalogEntitiesService:s,ctx:t,catalogConfig:a,serverOutDir:o,store:n})=>g("com.redocly.catalogEntities.createEntity",async e=>{e?.setAttribute("object","catalogEntity");const d=t.get("logger");try{const r=await t.req.json();e?.setAttribute("requestBody",JSON.stringify(r));const i=D(r,a);if(!A({ctx:t,store:n,accessLevel:"WRITE",entityType:i.type,entityKey:i.key}))return e?.error(new Error("Access denied")),t.json({message:"Access denied"},403);const y=await s.transaction(async()=>{const u=await s.createEntity({entity:i,source:"remote",errorOnSkip:!0}),c=i.relations?.map(E=>O(i.key,E));return await s.createEntitiesRelations(c??[]),await j({ctx:t,catalogEntitiesService:s,addedEntities:u?[u]:void 0}),u});return y?(b(o),e?.setAttribute("id",y.id),e?.setAttribute("uri",`urn:redocly:realm:api:catalogEntity:${y.id}`),e?.setAttribute("entity",JSON.stringify(y)),t.json(m(y))):(e?.error(new Error("Failed to create entity")),t.json({message:"Failed to create entity"},500))}catch(r){return d.error(r),r instanceof Error&&r.message.includes("validation failed")?(e?.error(new Error(r.message)),t.json({message:r.message},400)):(e?.error(r),t.json({message:"Failed to create entity"},500))}}),v=async({catalogEntitiesService:s,ctx:t,catalogConfig:a,serverOutDir:o,store:n})=>g("com.redocly.catalogEntities.bulkUpsertEntities",async e=>{e?.setAttribute("id","catalogEntityId"),e?.setAttribute("object","catalogEntity"),e?.setAttribute("uri","urn:redocly:realm:api:catalogEntity:catalogEntityId");const d=t.get("logger");try{const r=await t.req.json();e?.setAttribute("requestBody",JSON.stringify(r));const i=k(r,a);for(const u of i)if(!A({ctx:t,store:n,accessLevel:"WRITE",entityType:u.type,entityKey:u.key}))return e?.error(new Error("Access denied")),t.json({message:"Access denied"},403);const l=await s.transaction(async()=>{const u=await s.createEntities(i,"remote"),c=u.reduce((E,w)=>(w.status==="ok"&&w.resource!=null&&E.push(w.resource),E),[]);return await j({ctx:t,catalogEntitiesService:s,addedEntities:c}),u});if(!l.length)return e?.error(new Error("Failed to create entities")),t.json({message:"Failed to create entities"},500);b(o);const y=l.filter(u=>u.status==="ok");return e?.setAttribute("totalSuccess",y.length),e?.setAttribute("totalFailed",l.length-y.length),t.json(y.map(u=>({...u,resource:m(u.resource)})),207)}catch(r){return d.error(r),r instanceof Error&&r.message.includes("validation failed")?(e?.error(new Error(r.message)),t.json({message:r.message},400)):(e?.error(r),t.json({message:"Failed to create entities"},500))}}),B=async({catalogEntitiesService:s,ctx:t,catalogConfig:a,serverOutDir:o,store:n})=>g("com.redocly.catalogEntities.updateEntity",async e=>{e?.setAttribute("object","catalogEntity");const d=t.get("logger"),r=t.req.param(f);if(!r)return e?.error(new Error("Entity id is required")),t.json({message:"Entity id is required"},400);e?.setAttribute("id",r),e?.setAttribute("uri",`urn:redocly:realm:api:catalogEntity:${r}`),e?.setAttribute("pathParams",JSON.stringify({entityId:r}));try{const i=await t.req.json();e?.setAttribute("requestBody",JSON.stringify(i));const l=await s.getEntityById(r);if(!l)return e?.error(new Error(`Entity with id: ${r} not found`)),t.json({message:`Entity with id: ${r} not found`},404);if(l.source==="file")return e?.error(new Error("File entities cannot be updated")),t.json({message:"File entities cannot be updated"},400);if(!A({ctx:t,store:n,accessLevel:"WRITE",entityType:i.type??l.type,entityKey:i.key??l.key}))return e?.error(new Error("Access denied")),t.json({message:"Access denied"},403);const u=P(i,a,i?.type??l.type),c=await s.updateEntity(u,l);return c?(b(o),e?.setAttribute("entity",JSON.stringify(c)),t.json(m(c))):(e?.error(new Error("Failed to update entity")),t.json({message:"Failed to update entity"},500))}catch(i){return d.error(i),i instanceof Error&&i.message.includes("validation failed")?(e?.error(new Error(i.message)),t.json({message:i.message},400)):(e?.error(i),t.json({message:i.message},500))}}),U=async({catalogEntitiesService:s,ctx:t,serverOutDir:a,store:o})=>g("com.redocly.catalogEntities.deleteEntity",async n=>{n?.setAttribute("object","catalogEntity");const e=t.get("logger"),d=t.req.param(f);if(!d)return n?.error(new Error("Entity id is required")),t.json({message:"Entity id is required"},400);n?.setAttribute("id",d),n?.setAttribute("uri",`urn:redocly:realm:api:catalogEntity:${d}`),n?.setAttribute("pathParams",JSON.stringify({entityId:d}));try{const r=await s.getEntityById(d);return r?r.source==="file"?(n?.error(new Error("File entities cannot be deleted")),t.json({message:"File entities cannot be deleted"},400)):A({ctx:t,store:o,accessLevel:"WRITE",entityType:r.type,entityKey:r.key})?await s.transaction(async()=>{const y=await s.deleteEntity(r);return y?(await j({ctx:t,catalogEntitiesService:s,removedEntities:r?[r]:void 0}),y):null})?(b(a),new Response(null,{status:204})):(n?.error(new Error("Failed to delete entity")),t.json({message:"Failed to delete entity"},500)):(n?.error(new Error("Access denied")),t.json({message:"Access denied"},403)):new Response(null,{status:204})}catch(r){return e.error(r),n?.error(r),t.json({message:"Failed to delete entity"},500)}}),_={GET:W,POST:J,PUT:v},$={GET:L,DELETE:U,PATCH:B};function st(s){return async t=>g("com.redocly.catalogEntities.accessed",async a=>{a?.setAttribute("id","catalogEntityId"),a?.setAttribute("object","catalogEntity"),a?.setAttribute("uri","urn:redocly:realm:api:catalogEntity:catalogEntityId");const o=await R.getInstance({baseDbDir:s.serverOutDir}),n=t.req.method;a?.setAttribute("method",n);const e=t.req.param(f)?$:_,d=T(s.config.entitiesCatalog),r=e[n];return r?await r({catalogEntitiesService:o,ctx:t,catalogConfig:d,serverOutDir:s.serverOutDir,store:s}):(a?.error(new Error("Method not allowed")),t.json({message:"Method not allowed"},405))})}export{st as catalogHandler};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Context } from 'hono';
|
|
2
2
|
import type { Store } from '../../../../store';
|
|
3
|
-
export declare function hasAccessToEntity({ ctx, store, accessLevel, entityType, entityKey }: {
|
|
3
|
+
export declare function hasAccessToEntity({ ctx, store, accessLevel, entityType, entityKey, }: {
|
|
4
4
|
ctx: Context;
|
|
5
5
|
store: Store;
|
|
6
6
|
accessLevel: 'READ' | 'WRITE';
|