insforge 0.3.2 → 1.2.10
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/.claude-plugin/marketplace.json +20 -0
- package/.cursor/rules/cursor-rules.mdc +94 -0
- package/.dockerignore +3 -0
- package/.env.example +33 -4
- package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
- package/.github/ISSUE_TEMPLATE/config.yml +2 -2
- package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
- package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
- package/.github/workflows/build-image.yml +2 -1
- package/.github/workflows/e2e.yml +63 -0
- package/CHANGELOG.md +41 -0
- package/CLAUDE_PLUGIN.md +104 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +1 -1
- package/Dockerfile +4 -1
- package/README.md +66 -18
- package/assets/mcpInstallv2.png +0 -0
- package/assets/sampleResponse.png +0 -0
- package/auth/index.html +13 -0
- package/auth/package.json +28 -0
- package/auth/public/favicon.ico +0 -0
- package/auth/src/App.tsx +33 -0
- package/auth/src/components/ErrorCard.tsx +37 -0
- package/auth/src/components/Layout.tsx +13 -0
- package/auth/src/index.css +19 -0
- package/auth/src/lib/broadcastService.ts +115 -0
- package/auth/src/lib/utils.ts +11 -0
- package/auth/src/main.tsx +22 -0
- package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
- package/auth/src/pages/ResetPasswordPage.tsx +11 -0
- package/auth/src/pages/SignInPage.tsx +57 -0
- package/auth/src/pages/SignUpPage.tsx +57 -0
- package/auth/src/pages/VerifyEmailPage.tsx +20 -0
- package/auth/src/vite-env.d.ts +10 -0
- package/auth/tsconfig.json +32 -0
- package/auth/tsconfig.node.json +11 -0
- package/auth/vite.config.ts +25 -0
- package/backend/package.json +9 -9
- package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
- package/backend/src/api/middlewares/rate-limiters.ts +127 -0
- package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
- package/backend/src/api/routes/auth/index.routes.ts +570 -0
- package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
- package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
- package/backend/src/api/routes/database/index.routes.ts +13 -0
- package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
- package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
- package/backend/src/api/routes/docs/index.routes.ts +76 -0
- package/backend/src/api/routes/functions/index.routes.ts +188 -0
- package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
- package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
- package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
- package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
- package/backend/src/api/routes/usage/index.routes.ts +89 -0
- package/backend/src/infra/config/app.config.ts +51 -0
- package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
- package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
- package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
- package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
- package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
- package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
- package/backend/src/infra/security/token.manager.ts +125 -0
- package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
- package/backend/src/providers/ai/openrouter.provider.ts +377 -0
- package/backend/src/providers/email/base.provider.ts +41 -0
- package/backend/src/providers/email/cloud.provider.ts +187 -0
- package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
- package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
- package/backend/src/providers/logs/local.provider.ts +185 -0
- package/backend/src/providers/oauth/base.provider.ts +29 -0
- package/backend/src/providers/oauth/discord.provider.ts +195 -0
- package/backend/src/providers/oauth/facebook.provider.ts +194 -0
- package/backend/src/providers/oauth/github.provider.ts +208 -0
- package/backend/src/providers/oauth/google.provider.ts +249 -0
- package/backend/src/providers/oauth/index.ts +7 -0
- package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
- package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
- package/backend/src/providers/oauth/x.provider.ts +202 -0
- package/backend/src/providers/storage/base.provider.ts +29 -0
- package/backend/src/providers/storage/local.provider.ts +103 -0
- package/backend/src/providers/storage/s3.provider.ts +313 -0
- package/backend/src/server.ts +70 -74
- package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
- package/backend/src/services/ai/ai-model.service.ts +60 -0
- package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
- package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
- package/backend/src/services/ai/helpers.ts +64 -0
- package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
- package/backend/src/services/ai/index.ts +13 -0
- package/backend/src/services/auth/auth-config.service.ts +250 -0
- package/backend/src/services/auth/auth-otp.service.ts +424 -0
- package/backend/src/services/auth/auth.service.ts +1136 -0
- package/backend/src/services/auth/index.ts +4 -0
- package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
- package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
- package/backend/src/services/database/database-table.service.ts +811 -0
- package/backend/src/services/email/email.service.ts +75 -0
- package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
- package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
- package/backend/src/services/logs/log.service.ts +73 -0
- package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
- package/backend/src/services/storage/storage.service.ts +617 -0
- package/backend/src/services/usage/usage.service.ts +149 -0
- package/backend/src/types/auth.ts +66 -2
- package/backend/src/types/email.ts +8 -0
- package/backend/src/types/error-constants.ts +4 -0
- package/backend/src/types/logs.ts +0 -29
- package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
- package/backend/src/utils/environment.ts +9 -3
- package/backend/src/utils/logger.ts +20 -2
- package/backend/src/utils/seed.ts +150 -57
- package/backend/src/utils/sql-parser.ts +1 -1
- package/backend/src/utils/utils.ts +114 -0
- package/backend/src/utils/validations.ts +40 -4
- package/backend/tests/local/test-ai-config.sh +129 -0
- package/backend/tests/local/test-ai-usage.sh +80 -0
- package/backend/tests/local/test-auth-router.sh +1 -1
- package/backend/tests/local/test-e2e.sh +1 -1
- package/backend/tests/local/test-functions.sh +123 -0
- package/backend/tests/local/test-logs.sh +132 -0
- package/backend/tests/local/test-public-bucket.sh +3 -3
- package/backend/tests/local/test-secrets.sh +14 -12
- package/backend/tests/local/test-traditional-rest.sh +2 -2
- package/backend/tests/manual/test-rawsql-modes.sh +244 -0
- package/backend/tests/test-config.sh +37 -1
- package/backend/tests/unit/cloud-token.test.ts +48 -0
- package/backend/tests/unit/constant.test.ts +8 -0
- package/backend/tests/unit/email.test.ts +372 -0
- package/backend/tests/unit/environment.test.ts +59 -0
- package/backend/tests/unit/helpers.test.ts +63 -0
- package/backend/tests/unit/logger.test.ts +22 -0
- package/backend/tests/unit/rate-limit.test.ts +154 -0
- package/backend/tests/unit/response.test.ts +58 -0
- package/backend/tests/unit/sql-parser.test.ts +74 -0
- package/backend/tests/unit/uuid.test.ts +21 -0
- package/backend/tests/unit/validations.test.ts +80 -0
- package/backend/tsconfig.json +1 -1
- package/backend/vitest.config.ts +11 -0
- package/claude-plugin/.claude-plugin/plugin.json +24 -0
- package/claude-plugin/README.md +133 -0
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
- package/docker-compose.prod.yml +60 -4
- package/docker-compose.yml +65 -4
- package/docker-init/db/db-init.sql +6 -34
- package/docker-init/logs/vector.yml +236 -0
- package/docs/README.md +44 -0
- package/docs/changelog.mdx +67 -0
- package/docs/core-concepts/ai/architecture.mdx +373 -0
- package/docs/core-concepts/ai/sdk.mdx +213 -0
- package/docs/core-concepts/authentication/architecture.mdx +278 -0
- package/docs/core-concepts/authentication/sdk.mdx +414 -0
- package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
- package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
- package/docs/core-concepts/database/architecture.mdx +256 -0
- package/docs/core-concepts/database/sdk.mdx +382 -0
- package/docs/core-concepts/functions/architecture.mdx +105 -0
- package/docs/core-concepts/functions/sdk.mdx +184 -0
- package/docs/core-concepts/storage/architecture.mdx +243 -0
- package/docs/core-concepts/storage/sdk.mdx +253 -0
- package/docs/deployment/README.md +94 -0
- package/docs/deployment/deploy-to-aws-ec2.md +565 -0
- package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
- package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
- package/docs/deployment/deploy-to-render.md +441 -0
- package/docs/docs.json +210 -0
- package/docs/examples/framework-guides/nextjs.mdx +131 -0
- package/docs/examples/framework-guides/nuxt.mdx +165 -0
- package/docs/examples/framework-guides/react.mdx +165 -0
- package/docs/examples/framework-guides/svelte.mdx +153 -0
- package/docs/examples/framework-guides/vue.mdx +159 -0
- package/docs/examples/overview.mdx +67 -0
- package/docs/favicon.svg +19 -0
- package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
- package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
- package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
- package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
- package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
- package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
- package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
- package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
- package/docs/images/checks-passed.png +0 -0
- package/docs/images/dashboard-connect-expanded.png +0 -0
- package/docs/images/dashboard-connect.png +0 -0
- package/docs/images/hero-dark.png +0 -0
- package/docs/images/hero-light.png +0 -0
- package/docs/images/icons/ai.svg +4 -0
- package/docs/images/icons/auth.svg +1 -0
- package/docs/images/icons/database.svg +1 -0
- package/docs/images/icons/function.svg +1 -0
- package/docs/images/icons/storage.svg +1 -0
- package/docs/images/logos/nextjs.svg +4 -0
- package/docs/images/logos/nuxt.svg +4 -0
- package/docs/images/logos/react.svg +5 -0
- package/docs/images/logos/svelte.svg +4 -0
- package/docs/images/logos/vue.svg +5 -0
- package/docs/images/mcp-install.png +0 -0
- package/docs/images/onboarding-mcp.png +0 -0
- package/docs/insforge-instructions-sdk.md +55 -374
- package/docs/introduction.mdx +45 -0
- package/docs/logo/dark.svg +22 -0
- package/docs/logo/light.svg +20 -0
- package/docs/partnership.mdx +647 -0
- package/docs/quickstart.mdx +83 -0
- package/docs/showcase/2048-arena.png +0 -0
- package/docs/showcase/framegen-cloud.png +0 -0
- package/docs/showcase/line-connect-race.png +0 -0
- package/docs/showcase/moment-vibe.png +0 -0
- package/docs/showcase/national-flags.png +0 -0
- package/docs/showcase/pokemon-vibe.png +0 -0
- package/docs/showcase/pure-browse-buy.png +0 -0
- package/docs/showcase.mdx +52 -0
- package/docs/snippets/sdk-installation.mdx +22 -0
- package/docs/snippets/service-icons.mdx +27 -0
- package/eslint.config.js +10 -3
- package/frontend/package.json +10 -4
- package/frontend/src/App.tsx +13 -82
- package/frontend/src/assets/icons/connected.svg +3 -0
- package/frontend/src/assets/icons/loader.svg +9 -0
- package/frontend/src/assets/logos/apple.svg +4 -0
- package/frontend/src/assets/logos/discord.svg +1 -1
- package/frontend/src/assets/logos/facebook.svg +3 -0
- package/frontend/src/assets/logos/instagram.svg +2 -0
- package/frontend/src/assets/logos/linkedin.svg +3 -0
- package/frontend/src/assets/logos/microsoft.svg +1 -0
- package/frontend/src/assets/logos/spotify.svg +17 -0
- package/frontend/src/assets/logos/tiktok.svg +6 -0
- package/frontend/src/assets/logos/x.svg +3 -0
- package/frontend/src/components/Checkbox.tsx +27 -29
- package/frontend/src/components/CodeBlock.tsx +55 -2
- package/frontend/src/components/CodeEditor.tsx +92 -0
- package/frontend/src/components/ConfirmDialog.tsx +1 -1
- package/frontend/src/components/ConnectCTA.tsx +38 -0
- package/frontend/src/components/CopyButton.tsx +52 -15
- package/frontend/src/components/ErrorState.tsx +1 -2
- package/frontend/src/components/FeatureSidebar.tsx +6 -6
- package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
- package/frontend/src/components/JsonHighlight.tsx +21 -9
- package/frontend/src/components/ProjectInfoModal.tsx +128 -0
- package/frontend/src/components/PromptDialog.tsx +1 -4
- package/frontend/src/components/SearchInput.tsx +1 -2
- package/frontend/src/components/Stepper.tsx +53 -0
- package/frontend/src/components/ThemeToggle.tsx +3 -3
- package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
- package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
- package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
- package/frontend/src/components/datagrid/index.ts +23 -0
- package/frontend/src/components/index.ts +23 -30
- package/frontend/src/components/layout/AppHeader.tsx +133 -92
- package/frontend/src/components/layout/AppSidebar.tsx +80 -170
- package/frontend/src/components/layout/Layout.tsx +12 -23
- package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
- package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
- package/frontend/src/components/layout/index.ts +5 -0
- package/frontend/src/components/radix/Tooltip.tsx +24 -13
- package/frontend/src/components/radix/index.ts +22 -0
- package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
- package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
- package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
- package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
- package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
- package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
- package/frontend/src/features/ai/components/index.ts +6 -0
- package/frontend/src/features/ai/helpers.ts +57 -71
- package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
- package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
- package/frontend/src/features/ai/page/AIPage.tsx +67 -79
- package/frontend/src/features/ai/services/ai.service.ts +5 -5
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
- package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
- package/frontend/src/features/auth/components/index.ts +5 -0
- package/frontend/src/features/auth/helpers.tsx +200 -0
- package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
- package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
- package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
- package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
- package/frontend/src/features/auth/index.ts +3 -2
- package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
- package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
- package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
- package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
- package/frontend/src/features/auth/services/config.service.ts +19 -0
- package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
- package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
- package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
- package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
- package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
- package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
- package/frontend/src/features/dashboard/components/index.ts +4 -0
- package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
- package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
- package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
- package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
- package/frontend/src/features/dashboard/prompts/index.ts +31 -0
- package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
- package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
- package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
- package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
- package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
- package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
- package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
- package/frontend/src/features/database/components/TableForm.tsx +28 -15
- package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
- package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
- package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
- package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
- package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
- package/frontend/src/features/database/components/index.ts +19 -0
- package/frontend/src/features/database/constants.ts +28 -2
- package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
- package/frontend/src/features/database/helpers.ts +2 -2
- package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
- package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
- package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
- package/frontend/src/features/database/hooks/useRecords.ts +139 -0
- package/frontend/src/features/database/hooks/useTables.ts +131 -0
- package/frontend/src/features/database/index.ts +6 -1
- package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
- package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
- package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
- package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
- package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
- package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
- package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
- package/frontend/src/features/database/services/advance.service.ts +66 -0
- package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
- package/frontend/src/features/database/services/table.service.ts +64 -0
- package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
- package/frontend/src/features/database/templates/crm-system.ts +528 -0
- package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
- package/frontend/src/features/database/templates/index.ts +34 -0
- package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
- package/frontend/src/features/database/templates/notion-clone.ts +483 -0
- package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
- package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
- package/frontend/src/features/functions/components/index.ts +5 -0
- package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
- package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
- package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
- package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
- package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
- package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
- package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
- package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
- package/frontend/src/features/login/page/LoginPage.tsx +16 -23
- package/frontend/src/features/login/services/partnership.service.ts +65 -0
- package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
- package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
- package/frontend/src/features/logs/components/index.ts +2 -0
- package/frontend/src/features/logs/helpers.ts +24 -0
- package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
- package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
- package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
- package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
- package/frontend/src/features/logs/index.ts +8 -2
- package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
- package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
- package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
- package/frontend/src/features/logs/services/audit.service.ts +63 -0
- package/frontend/src/features/logs/services/log.service.ts +15 -110
- package/frontend/src/features/logs/services/usage.service.ts +31 -0
- package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
- package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
- package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
- package/frontend/src/features/onboard/components/index.ts +4 -0
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
- package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
- package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
- package/frontend/src/features/onboard/index.ts +13 -3
- package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
- package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
- package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
- package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
- package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
- package/frontend/src/features/storage/components/index.ts +12 -0
- package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
- package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
- package/frontend/src/features/storage/services/storage.service.ts +22 -1
- package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
- package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
- package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
- package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
- package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
- package/frontend/src/index.css +1 -0
- package/frontend/src/lib/analytics/posthog.tsx +27 -0
- package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
- package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
- package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
- package/frontend/src/lib/hooks/useToast.tsx +6 -2
- package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
- package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
- package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
- package/frontend/src/lib/utils/menuItems.ts +183 -0
- package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
- package/frontend/src/lib/utils/utils.ts +19 -1
- package/frontend/src/vite-env.d.ts +1 -0
- package/frontend/vite.config.ts +5 -3
- package/functions/server.ts +28 -3
- package/functions/worker-template.js +15 -4
- package/i18n/README.ar.md +130 -0
- package/i18n/README.de.md +130 -0
- package/i18n/README.es.md +154 -0
- package/i18n/README.fr.md +134 -0
- package/i18n/README.hi.md +129 -0
- package/i18n/README.ja.md +174 -0
- package/i18n/README.ko.md +137 -0
- package/i18n/README.pt-BR.md +131 -0
- package/i18n/README.ru.md +129 -0
- package/i18n/README.zh-CN.md +133 -0
- package/openapi/ai.yaml +31 -4
- package/openapi/auth.yaml +827 -146
- package/package.json +16 -7
- package/shared-schemas/package.json +1 -1
- package/shared-schemas/src/ai-api.schema.ts +34 -58
- package/shared-schemas/src/ai.schema.ts +5 -0
- package/shared-schemas/src/auth-api.schema.ts +154 -8
- package/shared-schemas/src/auth.schema.ts +42 -6
- package/shared-schemas/src/cloud-events.schema.ts +57 -0
- package/shared-schemas/src/database-api.schema.ts +3 -3
- package/shared-schemas/src/database.schema.ts +1 -1
- package/shared-schemas/src/index.ts +1 -0
- package/shared-schemas/src/logs-api.schema.ts +7 -1
- package/shared-schemas/src/logs.schema.ts +26 -0
- package/shared-schemas/src/metadata.schema.ts +9 -4
- package/test-gemini.sh +35 -0
- package/test-usage-admin.sh +57 -0
- package/test-usage.sh +50 -0
- package/zeabur/README.md +13 -0
- package/zeabur/template.yml +1032 -0
- package/.github/workflows/deploy-aws.yml +0 -130
- package/backend/src/api/routes/agent.ts +0 -29
- package/backend/src/api/routes/auth.oauth.ts +0 -482
- package/backend/src/api/routes/auth.ts +0 -386
- package/backend/src/api/routes/docs.ts +0 -66
- package/backend/src/api/routes/functions.ts +0 -183
- package/backend/src/api/routes/openapi.ts +0 -82
- package/backend/src/api/routes/usage.ts +0 -96
- package/backend/src/core/ai/client.ts +0 -242
- package/backend/src/core/ai/model.ts +0 -117
- package/backend/src/core/auth/auth.ts +0 -781
- package/backend/src/core/database/table.ts +0 -772
- package/backend/src/core/documentation/agent.ts +0 -689
- package/backend/src/core/documentation/openapi.ts +0 -856
- package/backend/src/core/logs/analytics.ts +0 -76
- package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
- package/backend/src/core/storage/storage.ts +0 -923
- package/backend/src/utils/cloud-token.ts +0 -39
- package/backend/src/utils/helpers.ts +0 -49
- package/backend/src/utils/uuid.ts +0 -9
- package/backend/tests/manual/test-better-auth.sh +0 -303
- package/docker-init/db/logs.sql +0 -9
- package/frontend/README.md +0 -112
- package/frontend/src/components/datagrid/index.tsx +0 -20
- package/frontend/src/components/layout/CloudLayout.tsx +0 -95
- package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
- package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
- package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
- package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
- package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
- package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
- package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
- package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
- package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
- package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
- package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
- package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
- package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
- package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
- package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
- package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
- package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
- package/frontend/src/features/metadata/index.ts +0 -0
- package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
- package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
- package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
- package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
- package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
- package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
- package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
- package/frontend/src/features/onboard/types.ts +0 -8
- package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
- package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
- /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
- /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
- /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import { MoreHorizontal, Plus, Trash2, Pencil, Mail, ChevronDown } from 'lucide-react';
|
|
3
|
+
import { OAuthConfigDialog, AuthPreview } from '@/features/auth/components';
|
|
4
|
+
import { useOAuthConfig } from '@/features/auth/hooks/useOAuthConfig';
|
|
5
|
+
import { useConfirm } from '@/lib/hooks/useConfirm';
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
ConfirmDialog,
|
|
9
|
+
CopyButton,
|
|
10
|
+
DropdownMenu,
|
|
11
|
+
DropdownMenuContent,
|
|
12
|
+
DropdownMenuItem,
|
|
13
|
+
DropdownMenuTrigger,
|
|
14
|
+
DropdownMenuSeparator,
|
|
15
|
+
} from '@/components';
|
|
16
|
+
import type { OAuthProvidersSchema } from '@insforge/shared-schemas';
|
|
17
|
+
import {
|
|
18
|
+
oauthProviders,
|
|
19
|
+
type OAuthProviderInfo,
|
|
20
|
+
getAuthImplementationPrompt,
|
|
21
|
+
} from '@/features/auth/helpers';
|
|
22
|
+
import { getBackendUrl } from '@/lib/utils/utils';
|
|
23
|
+
|
|
24
|
+
export default function AuthMethodsPage() {
|
|
25
|
+
const [selectedProvider, setSelectedProvider] = useState<OAuthProviderInfo>();
|
|
26
|
+
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
27
|
+
const { confirm, confirmDialogProps } = useConfirm();
|
|
28
|
+
const {
|
|
29
|
+
configs,
|
|
30
|
+
isLoadingConfigs,
|
|
31
|
+
deleteConfig,
|
|
32
|
+
refetchConfigs,
|
|
33
|
+
getProviderConfig,
|
|
34
|
+
isProviderConfigured,
|
|
35
|
+
} = useOAuthConfig();
|
|
36
|
+
|
|
37
|
+
const handleConfigureProvider = (provider: OAuthProviderInfo) => {
|
|
38
|
+
setSelectedProvider(provider);
|
|
39
|
+
setIsDialogOpen(true);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const deleteOAuthConfig = async (providerId: OAuthProvidersSchema, providerName: string) => {
|
|
43
|
+
const shouldDelete = await confirm({
|
|
44
|
+
title: `Delete ${providerName} OAuth`,
|
|
45
|
+
description: `Are you sure you want to delete the ${providerName} configuration? This action cannot be undone.`,
|
|
46
|
+
confirmText: 'Delete',
|
|
47
|
+
cancelText: 'Cancel',
|
|
48
|
+
destructive: true,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (shouldDelete) {
|
|
52
|
+
deleteConfig(providerId);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleCloseDialog = () => {
|
|
57
|
+
setIsDialogOpen(false);
|
|
58
|
+
setSelectedProvider(undefined);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const hasAuthMethods = useMemo(() => {
|
|
62
|
+
return !!configs.length;
|
|
63
|
+
}, [configs]);
|
|
64
|
+
|
|
65
|
+
const enabledProviders = useMemo(() => {
|
|
66
|
+
const enabled: Record<OAuthProvidersSchema, boolean> = {} as Record<
|
|
67
|
+
OAuthProvidersSchema,
|
|
68
|
+
boolean
|
|
69
|
+
>;
|
|
70
|
+
oauthProviders.forEach((provider) => {
|
|
71
|
+
enabled[provider.id] = isProviderConfigured(provider.id);
|
|
72
|
+
});
|
|
73
|
+
return enabled;
|
|
74
|
+
}, [isProviderConfigured]);
|
|
75
|
+
|
|
76
|
+
// Check if all providers are enabled
|
|
77
|
+
const allProvidersEnabled = useMemo(() => {
|
|
78
|
+
return oauthProviders.every((provider) => enabledProviders[provider.id]);
|
|
79
|
+
}, [enabledProviders]);
|
|
80
|
+
|
|
81
|
+
const handleSuccess = useCallback(() => {
|
|
82
|
+
// Refresh configuration after successful update
|
|
83
|
+
void refetchConfigs();
|
|
84
|
+
}, [refetchConfigs]);
|
|
85
|
+
|
|
86
|
+
if (isLoadingConfigs) {
|
|
87
|
+
return (
|
|
88
|
+
<div className="h-full bg-slate-50 dark:bg-neutral-800 flex flex-col overflow-hidden">
|
|
89
|
+
<div className="flex-1 flex items-center justify-center">
|
|
90
|
+
<div className="text-center">
|
|
91
|
+
<div className="text-sm text-gray-500 dark:text-zinc-400">
|
|
92
|
+
Loading OAuth configuration...
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div className="h-full flex flex-col overflow-hidden">
|
|
102
|
+
{/* Two column layout */}
|
|
103
|
+
<div className="h-full flex overflow-hidden">
|
|
104
|
+
{/* Left Section - Auth Methods List */}
|
|
105
|
+
<div className="flex-1 bg-slate-50 dark:bg-[#2d2d2d] flex flex-col overflow-hidden">
|
|
106
|
+
{/* Header */}
|
|
107
|
+
<div className="flex items-center justify-between px-4 py-6 gap-3">
|
|
108
|
+
<h2 className="px-4 text-xl font-semibold text-gray-900 dark:text-white tracking-tight">
|
|
109
|
+
Auth Methods
|
|
110
|
+
</h2>
|
|
111
|
+
{!allProvidersEnabled && (
|
|
112
|
+
<DropdownMenu>
|
|
113
|
+
<DropdownMenuTrigger asChild>
|
|
114
|
+
<Button className="h-8 px-2 py-0 gap-2 bg-black text-white dark:bg-neutral-600 dark:text-white hover:bg-gray-800 dark:hover:bg-neutral-500 text-sm font-medium rounded">
|
|
115
|
+
<Plus className="w-5 h-5" />
|
|
116
|
+
Add Provider
|
|
117
|
+
<ChevronDown className="w-4 h-4" />
|
|
118
|
+
</Button>
|
|
119
|
+
</DropdownMenuTrigger>
|
|
120
|
+
<DropdownMenuContent align="end" className="w-80">
|
|
121
|
+
{/* Available providers (not enabled) */}
|
|
122
|
+
{oauthProviders
|
|
123
|
+
.filter((provider) => !enabledProviders[provider.id])
|
|
124
|
+
.map((provider) => (
|
|
125
|
+
<DropdownMenuItem
|
|
126
|
+
key={provider.id}
|
|
127
|
+
onClick={() => handleConfigureProvider(provider)}
|
|
128
|
+
className="py-2 px-3 flex items-center gap-3 cursor-pointer"
|
|
129
|
+
>
|
|
130
|
+
{provider.icon}
|
|
131
|
+
<span className="text-sm">{provider.name}</span>
|
|
132
|
+
</DropdownMenuItem>
|
|
133
|
+
))}
|
|
134
|
+
|
|
135
|
+
{/* Separator if there are both enabled and disabled providers */}
|
|
136
|
+
{oauthProviders.some((p) => enabledProviders[p.id]) &&
|
|
137
|
+
oauthProviders.some((p) => !enabledProviders[p.id]) && (
|
|
138
|
+
<DropdownMenuSeparator />
|
|
139
|
+
)}
|
|
140
|
+
|
|
141
|
+
{/* Enabled providers (disabled from selection) */}
|
|
142
|
+
{oauthProviders
|
|
143
|
+
.filter((provider) => enabledProviders[provider.id])
|
|
144
|
+
.map((provider) => (
|
|
145
|
+
<DropdownMenuItem
|
|
146
|
+
key={provider.id}
|
|
147
|
+
disabled
|
|
148
|
+
className="py-2 px-3 flex items-center justify-between gap-3 opacity-50 cursor-not-allowed"
|
|
149
|
+
>
|
|
150
|
+
<div className="flex items-center gap-3">
|
|
151
|
+
{provider.icon}
|
|
152
|
+
<span className="text-sm">{provider.name}</span>
|
|
153
|
+
</div>
|
|
154
|
+
<span className="text-xs px-2 py-0.5 bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-400 rounded border border-emerald-300 dark:border-emerald-700">
|
|
155
|
+
Enabled
|
|
156
|
+
</span>
|
|
157
|
+
</DropdownMenuItem>
|
|
158
|
+
))}
|
|
159
|
+
</DropdownMenuContent>
|
|
160
|
+
</DropdownMenu>
|
|
161
|
+
)}
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
{/* Auth Methods List */}
|
|
165
|
+
<div className="flex-1 overflow-y-auto p-4">
|
|
166
|
+
<div className="flex flex-col gap-3">
|
|
167
|
+
{/* Email Auth Card */}
|
|
168
|
+
<div className="flex items-center justify-between px-6 py-4 bg-white dark:bg-neutral-800 rounded-lg border border-gray-200 dark:border-transparent">
|
|
169
|
+
<div className="flex items-center gap-3">
|
|
170
|
+
<Mail className="w-6 h-6 text-gray-700 dark:text-white" />
|
|
171
|
+
<div className="text-sm font-medium text-black dark:text-white">Email Auth</div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
{/* OAuth Providers */}
|
|
176
|
+
{hasAuthMethods &&
|
|
177
|
+
oauthProviders.map((provider) => {
|
|
178
|
+
const providerConfig = getProviderConfig(provider.id);
|
|
179
|
+
if (!providerConfig) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<div
|
|
185
|
+
key={provider.id}
|
|
186
|
+
className="flex items-center justify-between px-6 py-4 bg-white dark:bg-neutral-800 rounded-lg border border-gray-200 dark:border-transparent"
|
|
187
|
+
>
|
|
188
|
+
<div className="flex items-center gap-3">
|
|
189
|
+
{provider.icon}
|
|
190
|
+
<div className="text-sm font-medium text-black dark:text-white">
|
|
191
|
+
{provider.name}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
|
|
195
|
+
<div className="flex items-center gap-3">
|
|
196
|
+
{providerConfig.useSharedKey && (
|
|
197
|
+
<span className="px-2 py-0.5 text-xs font-medium text-neutral-500 dark:text-neutral-400 border border-neutral-500 dark:border-neutral-400 rounded">
|
|
198
|
+
Shared Keys
|
|
199
|
+
</span>
|
|
200
|
+
)}
|
|
201
|
+
|
|
202
|
+
<DropdownMenu>
|
|
203
|
+
<DropdownMenuTrigger asChild>
|
|
204
|
+
<Button
|
|
205
|
+
className="h-7 w-7 p-1 text-gray-500 dark:text-neutral-400 hover:bg-gray-100 dark:hover:bg-neutral-700"
|
|
206
|
+
variant="ghost"
|
|
207
|
+
size="sm"
|
|
208
|
+
>
|
|
209
|
+
<MoreHorizontal className="w-5 h-5" />
|
|
210
|
+
</Button>
|
|
211
|
+
</DropdownMenuTrigger>
|
|
212
|
+
<DropdownMenuContent align="end" className="w-40 py-1 px-2">
|
|
213
|
+
<DropdownMenuItem
|
|
214
|
+
onClick={() => handleConfigureProvider(provider)}
|
|
215
|
+
className="py-2 px-3 flex items-center gap-3 cursor-pointer"
|
|
216
|
+
>
|
|
217
|
+
<Pencil className="w-5 h-5" />
|
|
218
|
+
Edit
|
|
219
|
+
</DropdownMenuItem>
|
|
220
|
+
<DropdownMenuItem
|
|
221
|
+
onClick={() => void deleteOAuthConfig(provider.id, provider.name)}
|
|
222
|
+
className="py-2 px-3 flex items-center gap-3 cursor-pointer text-red-600 dark:text-red-400"
|
|
223
|
+
>
|
|
224
|
+
<Trash2 className="w-5 h-5" />
|
|
225
|
+
Delete
|
|
226
|
+
</DropdownMenuItem>
|
|
227
|
+
</DropdownMenuContent>
|
|
228
|
+
</DropdownMenu>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
);
|
|
232
|
+
})}
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
{/* Right Section - Preview */}
|
|
238
|
+
<div className="w-[688px] bg-slate-50 dark:bg-[#2d2d2d] p-3 flex flex-col overflow-hidden">
|
|
239
|
+
<div className="h-full bg-gray-200 dark:bg-neutral-700 rounded-xl overflow-hidden flex flex-col">
|
|
240
|
+
{/* Preview Header */}
|
|
241
|
+
<div className="flex items-center justify-end px-6 py-3 gap-3">
|
|
242
|
+
<p className="text-sm font-medium text-gray-700 dark:text-white">
|
|
243
|
+
Integrate Authentication to Your Application
|
|
244
|
+
</p>
|
|
245
|
+
<CopyButton
|
|
246
|
+
text={getAuthImplementationPrompt(getBackendUrl())}
|
|
247
|
+
copyText="Copy Prompt"
|
|
248
|
+
variant="primary"
|
|
249
|
+
className="w-34"
|
|
250
|
+
/>
|
|
251
|
+
</div>
|
|
252
|
+
|
|
253
|
+
{/* Preview Content */}
|
|
254
|
+
<div className="flex-1 overflow-y-auto py-8 flex flex-col items-center justify-center gap-4">
|
|
255
|
+
<AuthPreview />
|
|
256
|
+
<p className="text-xs text-gray-500 dark:text-neutral-400 text-center">
|
|
257
|
+
Preview Mode
|
|
258
|
+
</p>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
<OAuthConfigDialog
|
|
265
|
+
provider={selectedProvider}
|
|
266
|
+
isOpen={isDialogOpen}
|
|
267
|
+
onClose={handleCloseDialog}
|
|
268
|
+
onSuccess={handleSuccess}
|
|
269
|
+
/>
|
|
270
|
+
|
|
271
|
+
{/* Confirm Dialog */}
|
|
272
|
+
<ConfirmDialog {...confirmDialogProps} />
|
|
273
|
+
</div>
|
|
274
|
+
);
|
|
275
|
+
}
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useForm, Controller } from 'react-hook-form';
|
|
3
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
Input,
|
|
7
|
+
Switch,
|
|
8
|
+
Checkbox,
|
|
9
|
+
Select,
|
|
10
|
+
SelectContent,
|
|
11
|
+
SelectItem,
|
|
12
|
+
SelectTrigger,
|
|
13
|
+
} from '@/components';
|
|
14
|
+
import {
|
|
15
|
+
updateAuthConfigRequestSchema,
|
|
16
|
+
type UpdateAuthConfigRequest,
|
|
17
|
+
} from '@insforge/shared-schemas';
|
|
18
|
+
import { useAuthConfig } from '@/features/auth/hooks/useAuthConfig';
|
|
19
|
+
import { isInsForgeCloudProject } from '@/lib/utils/utils';
|
|
20
|
+
|
|
21
|
+
export default function ConfigurationPage() {
|
|
22
|
+
const { config, isLoading, isUpdating, updateConfig } = useAuthConfig();
|
|
23
|
+
|
|
24
|
+
const form = useForm<UpdateAuthConfigRequest>({
|
|
25
|
+
resolver: zodResolver(updateAuthConfigRequestSchema),
|
|
26
|
+
defaultValues: {
|
|
27
|
+
requireEmailVerification: false,
|
|
28
|
+
passwordMinLength: 6,
|
|
29
|
+
requireNumber: false,
|
|
30
|
+
requireLowercase: false,
|
|
31
|
+
requireUppercase: false,
|
|
32
|
+
requireSpecialChar: false,
|
|
33
|
+
verifyEmailMethod: 'code',
|
|
34
|
+
resetPasswordMethod: 'code',
|
|
35
|
+
signInRedirectTo: null,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Load configuration when config changes
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (config) {
|
|
42
|
+
form.reset({
|
|
43
|
+
requireEmailVerification: config.requireEmailVerification,
|
|
44
|
+
passwordMinLength: config.passwordMinLength,
|
|
45
|
+
requireNumber: config.requireNumber,
|
|
46
|
+
requireLowercase: config.requireLowercase,
|
|
47
|
+
requireUppercase: config.requireUppercase,
|
|
48
|
+
requireSpecialChar: config.requireSpecialChar,
|
|
49
|
+
verifyEmailMethod: config.verifyEmailMethod,
|
|
50
|
+
resetPasswordMethod: config.resetPasswordMethod,
|
|
51
|
+
signInRedirectTo: config.signInRedirectTo ?? null,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}, [config, form]);
|
|
55
|
+
|
|
56
|
+
const handleSubmitData = (data: UpdateAuthConfigRequest) => {
|
|
57
|
+
updateConfig(data);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleSubmit = () => {
|
|
61
|
+
void form.handleSubmit(handleSubmitData)();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const handleReset = () => {
|
|
65
|
+
if (config) {
|
|
66
|
+
form.reset({
|
|
67
|
+
requireEmailVerification: config.requireEmailVerification,
|
|
68
|
+
passwordMinLength: config.passwordMinLength,
|
|
69
|
+
requireNumber: config.requireNumber,
|
|
70
|
+
requireLowercase: config.requireLowercase,
|
|
71
|
+
requireUppercase: config.requireUppercase,
|
|
72
|
+
requireSpecialChar: config.requireSpecialChar,
|
|
73
|
+
verifyEmailMethod: config.verifyEmailMethod,
|
|
74
|
+
resetPasswordMethod: config.resetPasswordMethod,
|
|
75
|
+
signInRedirectTo: config.signInRedirectTo ?? null,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
if (isLoading) {
|
|
81
|
+
return (
|
|
82
|
+
<div className="h-full bg-slate-50 dark:bg-neutral-800 flex flex-col overflow-hidden">
|
|
83
|
+
<div className="flex-1 flex items-center justify-center">
|
|
84
|
+
<div className="text-center">
|
|
85
|
+
<div className="text-sm text-gray-500 dark:text-zinc-400">Loading configuration...</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div className="h-full bg-slate-50 dark:bg-neutral-800 flex flex-col overflow-hidden">
|
|
94
|
+
<div className="flex-1 flex flex-col overflow-y-auto">
|
|
95
|
+
<div className="p-6 w-full max-w-[1080px] mx-auto">
|
|
96
|
+
<div className="flex flex-col gap-8">
|
|
97
|
+
<div>
|
|
98
|
+
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white">
|
|
99
|
+
Configuration
|
|
100
|
+
</h2>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<form onSubmit={(e) => e.preventDefault()} className="flex flex-col gap-8">
|
|
104
|
+
{/* Sign In Redirect URL */}
|
|
105
|
+
<div className="space-y-6">
|
|
106
|
+
<div className="bg-white dark:bg-[#333333] rounded-lg p-6 flex items-center gap-10">
|
|
107
|
+
<div className="w-100 flex flex-col gap-1">
|
|
108
|
+
<label className="text-sm font-medium text-gray-900 dark:text-white">
|
|
109
|
+
Redirect URL After Sign In
|
|
110
|
+
</label>
|
|
111
|
+
<span className="text-xs text-zinc-500 dark:text-neutral-400">
|
|
112
|
+
Your app url after successful authentication
|
|
113
|
+
</span>
|
|
114
|
+
</div>
|
|
115
|
+
<div className="w-full max-w-[320px]">
|
|
116
|
+
<Input
|
|
117
|
+
type="url"
|
|
118
|
+
placeholder="https://yourapp.com/dashboard"
|
|
119
|
+
{...form.register('signInRedirectTo')}
|
|
120
|
+
className={`bg-white dark:bg-neutral-900 dark:placeholder:text-neutral-400 dark:border-neutral-700 dark:text-white ${
|
|
121
|
+
form.formState.errors.signInRedirectTo
|
|
122
|
+
? 'border-red-500 dark:border-red-500'
|
|
123
|
+
: ''
|
|
124
|
+
}`}
|
|
125
|
+
/>
|
|
126
|
+
{form.formState.errors.signInRedirectTo && (
|
|
127
|
+
<span className="text-xs text-red-500">
|
|
128
|
+
{form.formState.errors.signInRedirectTo.message ||
|
|
129
|
+
'Please enter a valid URL'}
|
|
130
|
+
</span>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
{isInsForgeCloudProject() && (
|
|
137
|
+
<div className="space-y-6">
|
|
138
|
+
<div>
|
|
139
|
+
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-3">
|
|
140
|
+
Email Verification
|
|
141
|
+
</h3>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div className="bg-white dark:bg-[#333333] rounded-lg p-6 space-y-6">
|
|
145
|
+
{/* Email Verification Toggle */}
|
|
146
|
+
<div className="flex items-center gap-10">
|
|
147
|
+
<div className="w-100 flex flex-col gap-1">
|
|
148
|
+
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
|
149
|
+
Require Email Verification
|
|
150
|
+
</span>
|
|
151
|
+
<span className="text-xs text-zinc-500 dark:text-neutral-400">
|
|
152
|
+
Users must verify their email address before they can sign in
|
|
153
|
+
</span>
|
|
154
|
+
</div>
|
|
155
|
+
<Controller
|
|
156
|
+
name="requireEmailVerification"
|
|
157
|
+
control={form.control}
|
|
158
|
+
render={({ field }) => (
|
|
159
|
+
<div className="w-full max-w-[320px]">
|
|
160
|
+
<Switch
|
|
161
|
+
checked={field.value}
|
|
162
|
+
onCheckedChange={(value) => {
|
|
163
|
+
field.onChange(value);
|
|
164
|
+
}}
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
)}
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
170
|
+
|
|
171
|
+
{/* Verify Email Method - Only shown when email verification is enabled */}
|
|
172
|
+
{form.watch('requireEmailVerification') && (
|
|
173
|
+
<div className="flex items-center gap-10">
|
|
174
|
+
<div className="w-100 flex flex-col gap-1">
|
|
175
|
+
<label className="text-sm font-medium text-gray-900 dark:text-white">
|
|
176
|
+
Email Verification Method
|
|
177
|
+
</label>
|
|
178
|
+
<span className="text-xs text-zinc-500 dark:text-neutral-400">
|
|
179
|
+
Choose between 6-digit verification code or verification link
|
|
180
|
+
</span>
|
|
181
|
+
</div>
|
|
182
|
+
<Controller
|
|
183
|
+
name="verifyEmailMethod"
|
|
184
|
+
control={form.control}
|
|
185
|
+
render={({ field }) => (
|
|
186
|
+
<Select
|
|
187
|
+
value={field.value}
|
|
188
|
+
onValueChange={(value) => {
|
|
189
|
+
if (value) {
|
|
190
|
+
field.onChange(value);
|
|
191
|
+
}
|
|
192
|
+
}}
|
|
193
|
+
>
|
|
194
|
+
<SelectTrigger className="w-full max-w-[320px] dark:bg-neutral-700 dark:border-neutral-700">
|
|
195
|
+
<span className="text-black dark:text-white">
|
|
196
|
+
{field.value === 'code' ? 'Code' : 'Link'}
|
|
197
|
+
</span>
|
|
198
|
+
</SelectTrigger>
|
|
199
|
+
<SelectContent>
|
|
200
|
+
<SelectItem value="code">Code</SelectItem>
|
|
201
|
+
<SelectItem value="link">Link</SelectItem>
|
|
202
|
+
</SelectContent>
|
|
203
|
+
</Select>
|
|
204
|
+
)}
|
|
205
|
+
/>
|
|
206
|
+
</div>
|
|
207
|
+
)}
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
)}
|
|
211
|
+
|
|
212
|
+
{/* Password Requirements Section */}
|
|
213
|
+
<div className="space-y-6">
|
|
214
|
+
<div>
|
|
215
|
+
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-3">
|
|
216
|
+
Password Requirements
|
|
217
|
+
</h3>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<div className="bg-white dark:bg-[#333333] rounded-lg p-6 space-y-6">
|
|
221
|
+
{/* Password Length */}
|
|
222
|
+
<div className="flex items-center gap-10">
|
|
223
|
+
<div className="w-100 flex flex-col gap-1">
|
|
224
|
+
<label className="text-sm font-medium text-gray-900 dark:text-white">
|
|
225
|
+
Minimum Password Length
|
|
226
|
+
</label>
|
|
227
|
+
<span className="text-xs text-zinc-500 dark:text-neutral-400">
|
|
228
|
+
Must be between 4 and 128 characters
|
|
229
|
+
</span>
|
|
230
|
+
</div>
|
|
231
|
+
<div className="w-full max-w-[320px]">
|
|
232
|
+
<Input
|
|
233
|
+
type="number"
|
|
234
|
+
min="4"
|
|
235
|
+
max="128"
|
|
236
|
+
{...form.register('passwordMinLength', { valueAsNumber: true })}
|
|
237
|
+
className={`bg-white dark:bg-neutral-900 dark:placeholder:text-neutral-400 dark:border-neutral-700 dark:text-white ${
|
|
238
|
+
form.formState.errors.passwordMinLength
|
|
239
|
+
? 'border-red-500 dark:border-red-500'
|
|
240
|
+
: ''
|
|
241
|
+
}`}
|
|
242
|
+
/>
|
|
243
|
+
{form.formState.errors.passwordMinLength && (
|
|
244
|
+
<span className="text-xs text-red-500">
|
|
245
|
+
{form.formState.errors.passwordMinLength.message ||
|
|
246
|
+
'Must be between 4 and 128 characters'}
|
|
247
|
+
</span>
|
|
248
|
+
)}
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
{/* Password Strength Checkboxes */}
|
|
253
|
+
<div className="flex items-start gap-10">
|
|
254
|
+
<div className="w-100 flex flex-col gap-1 justify-center">
|
|
255
|
+
<label className="text-sm font-medium text-gray-900 dark:text-white">
|
|
256
|
+
Password Strength Requirements
|
|
257
|
+
</label>
|
|
258
|
+
</div>
|
|
259
|
+
<div className="w-full max-w-[320px] flex flex-col gap-3 justify-center">
|
|
260
|
+
<Controller
|
|
261
|
+
name="requireNumber"
|
|
262
|
+
control={form.control}
|
|
263
|
+
render={({ field }) => (
|
|
264
|
+
<label className="flex items-center gap-2 cursor-pointer">
|
|
265
|
+
<Checkbox
|
|
266
|
+
checked={field.value ?? false}
|
|
267
|
+
onChange={(checked) => field.onChange(checked)}
|
|
268
|
+
/>
|
|
269
|
+
<span className="text-sm text-gray-700 dark:text-white">
|
|
270
|
+
At least 1 number
|
|
271
|
+
</span>
|
|
272
|
+
</label>
|
|
273
|
+
)}
|
|
274
|
+
/>
|
|
275
|
+
|
|
276
|
+
<Controller
|
|
277
|
+
name="requireSpecialChar"
|
|
278
|
+
control={form.control}
|
|
279
|
+
render={({ field }) => (
|
|
280
|
+
<label className="flex items-center gap-2 cursor-pointer">
|
|
281
|
+
<Checkbox
|
|
282
|
+
checked={field.value ?? false}
|
|
283
|
+
onChange={(checked) => field.onChange(checked)}
|
|
284
|
+
/>
|
|
285
|
+
<span className="text-sm text-gray-700 dark:text-white">
|
|
286
|
+
At least 1 special character
|
|
287
|
+
</span>
|
|
288
|
+
</label>
|
|
289
|
+
)}
|
|
290
|
+
/>
|
|
291
|
+
|
|
292
|
+
<Controller
|
|
293
|
+
name="requireLowercase"
|
|
294
|
+
control={form.control}
|
|
295
|
+
render={({ field }) => (
|
|
296
|
+
<label className="flex items-center gap-2 cursor-pointer">
|
|
297
|
+
<Checkbox
|
|
298
|
+
checked={field.value ?? false}
|
|
299
|
+
onChange={(checked) => field.onChange(checked)}
|
|
300
|
+
/>
|
|
301
|
+
<span className="text-sm text-gray-700 dark:text-white">
|
|
302
|
+
At least 1 lowercase character
|
|
303
|
+
</span>
|
|
304
|
+
</label>
|
|
305
|
+
)}
|
|
306
|
+
/>
|
|
307
|
+
|
|
308
|
+
<Controller
|
|
309
|
+
name="requireUppercase"
|
|
310
|
+
control={form.control}
|
|
311
|
+
render={({ field }) => (
|
|
312
|
+
<label className="flex items-center gap-2 cursor-pointer">
|
|
313
|
+
<Checkbox
|
|
314
|
+
checked={field.value ?? false}
|
|
315
|
+
onChange={(checked) => field.onChange(checked)}
|
|
316
|
+
/>
|
|
317
|
+
<span className="text-sm text-gray-700 dark:text-white">
|
|
318
|
+
At least 1 uppercase character
|
|
319
|
+
</span>
|
|
320
|
+
</label>
|
|
321
|
+
)}
|
|
322
|
+
/>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
|
|
326
|
+
{/* Reset Password Method */}
|
|
327
|
+
{isInsForgeCloudProject() && (
|
|
328
|
+
<div className="flex items-center gap-10">
|
|
329
|
+
<div className="w-100 flex flex-col gap-1">
|
|
330
|
+
<label className="text-sm font-medium text-gray-900 dark:text-white">
|
|
331
|
+
Password Reset Method
|
|
332
|
+
</label>
|
|
333
|
+
<span className="text-xs text-zinc-500 dark:text-neutral-400">
|
|
334
|
+
Choose between 6-digit reset code or reset link
|
|
335
|
+
</span>
|
|
336
|
+
</div>
|
|
337
|
+
<Controller
|
|
338
|
+
name="resetPasswordMethod"
|
|
339
|
+
control={form.control}
|
|
340
|
+
render={({ field }) => (
|
|
341
|
+
<Select
|
|
342
|
+
value={field.value}
|
|
343
|
+
onValueChange={(value) => {
|
|
344
|
+
if (value) {
|
|
345
|
+
field.onChange(value);
|
|
346
|
+
}
|
|
347
|
+
}}
|
|
348
|
+
>
|
|
349
|
+
<SelectTrigger className="w-full max-w-[320px] dark:bg-neutral-700 dark:border-neutral-700">
|
|
350
|
+
<span className="text-black dark:text-white">
|
|
351
|
+
{field.value === 'code' ? 'Code' : 'Link'}
|
|
352
|
+
</span>
|
|
353
|
+
</SelectTrigger>
|
|
354
|
+
<SelectContent>
|
|
355
|
+
<SelectItem value="code">Code</SelectItem>
|
|
356
|
+
<SelectItem value="link">Link</SelectItem>
|
|
357
|
+
</SelectContent>
|
|
358
|
+
</Select>
|
|
359
|
+
)}
|
|
360
|
+
/>
|
|
361
|
+
</div>
|
|
362
|
+
)}
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
{/* Action Buttons - Reserve space even when hidden */}
|
|
367
|
+
<div className="flex justify-end gap-3 min-h-10">
|
|
368
|
+
{form.formState.isDirty && (
|
|
369
|
+
<>
|
|
370
|
+
<Button
|
|
371
|
+
type="button"
|
|
372
|
+
onClick={handleReset}
|
|
373
|
+
disabled={isUpdating}
|
|
374
|
+
className="h-10 px-6 bg-white border border-zinc-200 shadow-[0px_1px_2px_0px_rgba(0,0,0,0.1)] text-zinc-950 hover:bg-zinc-50 dark:bg-neutral-600 dark:border-neutral-600 dark:text-white dark:hover:bg-neutral-700"
|
|
375
|
+
>
|
|
376
|
+
Cancel
|
|
377
|
+
</Button>
|
|
378
|
+
<Button
|
|
379
|
+
type="button"
|
|
380
|
+
onClick={handleSubmit}
|
|
381
|
+
disabled={isUpdating}
|
|
382
|
+
className="h-10 px-6 dark:bg-emerald-300 dark:text-black dark:hover:bg-emerald-400"
|
|
383
|
+
>
|
|
384
|
+
{isUpdating ? 'Saving...' : 'Save Changes'}
|
|
385
|
+
</Button>
|
|
386
|
+
</>
|
|
387
|
+
)}
|
|
388
|
+
</div>
|
|
389
|
+
</form>
|
|
390
|
+
</div>
|
|
391
|
+
</div>
|
|
392
|
+
</div>
|
|
393
|
+
</div>
|
|
394
|
+
);
|
|
395
|
+
}
|