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
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
name: Deploy to AWS EC2
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main, master]
|
|
6
|
-
workflow_dispatch:
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
deploy:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: Checkout code
|
|
14
|
-
uses: actions/checkout@v4
|
|
15
|
-
|
|
16
|
-
- name: Deploy to EC2
|
|
17
|
-
uses: appleboy/ssh-action@v1.0.0
|
|
18
|
-
with:
|
|
19
|
-
host: ${{ secrets.EC2_HOST }}
|
|
20
|
-
username: ec2-user
|
|
21
|
-
key: ${{ secrets.EC2_SSH_KEY }}
|
|
22
|
-
port: 22
|
|
23
|
-
script: |
|
|
24
|
-
# Install required dependencies if not present
|
|
25
|
-
if ! command -v git &> /dev/null; then
|
|
26
|
-
echo "Installing git..."
|
|
27
|
-
sudo yum update -y
|
|
28
|
-
sudo yum install -y git
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
if ! command -v docker &> /dev/null; then
|
|
32
|
-
echo "Installing Docker..."
|
|
33
|
-
sudo yum update -y
|
|
34
|
-
sudo yum install -y docker
|
|
35
|
-
sudo systemctl start docker
|
|
36
|
-
sudo systemctl enable docker
|
|
37
|
-
sudo usermod -aG docker ec2-user
|
|
38
|
-
|
|
39
|
-
# Install docker-compose plugin
|
|
40
|
-
sudo mkdir -p /usr/local/lib/docker/cli-plugins
|
|
41
|
-
sudo curl -SL https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
|
|
42
|
-
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
|
|
43
|
-
|
|
44
|
-
# Also install standalone docker-compose for compatibility
|
|
45
|
-
sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
|
46
|
-
sudo chmod +x /usr/local/bin/docker-compose
|
|
47
|
-
fi
|
|
48
|
-
|
|
49
|
-
# Navigate to application directory
|
|
50
|
-
mkdir -p ~/insforge
|
|
51
|
-
cd ~/insforge
|
|
52
|
-
|
|
53
|
-
# Pull latest code or fresh clone
|
|
54
|
-
if [ -d ".git" ]; then
|
|
55
|
-
# Clean up old branches and reset to latest
|
|
56
|
-
git remote prune origin
|
|
57
|
-
git fetch --all --prune
|
|
58
|
-
# Use the branch that triggered the workflow
|
|
59
|
-
git checkout ${{ github.ref_name }} || git checkout main || git checkout master
|
|
60
|
-
git reset --hard origin/${{ github.ref_name }} || git reset --hard origin/main || git reset --hard origin/master
|
|
61
|
-
else
|
|
62
|
-
# Remove existing non-git directory if it exists
|
|
63
|
-
if [ -d ~/insforge ] && [ ! -d ~/insforge/.git ]; then
|
|
64
|
-
rm -rf ~/insforge/*
|
|
65
|
-
rm -rf ~/insforge/.*
|
|
66
|
-
fi
|
|
67
|
-
# Clone using SSH (since we set up SSH key)
|
|
68
|
-
git clone git@github.com:InsForge/insforge.git ~/insforge
|
|
69
|
-
cd ~/insforge
|
|
70
|
-
# Stay on default branch instead of detached HEAD
|
|
71
|
-
# git checkout ${{ github.sha }} # Commented out to avoid detached HEAD
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
# Create .env file matching .env.example structure
|
|
75
|
-
cat > .env << EOF
|
|
76
|
-
# Server Configuration
|
|
77
|
-
PORT=7130
|
|
78
|
-
|
|
79
|
-
# PostgreSQL Configuration
|
|
80
|
-
POSTGRES_USER=postgres
|
|
81
|
-
POSTGRES_PASSWORD=postgres
|
|
82
|
-
POSTGRES_DB=insforge
|
|
83
|
-
|
|
84
|
-
API_BASE_URL=http://localhost:7130
|
|
85
|
-
VITE_API_BASE_URL=http://localhost:7130
|
|
86
|
-
|
|
87
|
-
# Authentication
|
|
88
|
-
JWT_SECRET=your-secret-jwt-key-must-be-32-characters-minimum
|
|
89
|
-
ADMIN_EMAIL=admin@example.com
|
|
90
|
-
ADMIN_PASSWORD=change-this-password
|
|
91
|
-
|
|
92
|
-
# Logflare
|
|
93
|
-
LOGFLARE_PUBLIC_ACCESS_TOKEN=your-super-secret-and-long-logflare-key-public
|
|
94
|
-
LOGFLARE_PRIVATE_ACCESS_TOKEN=your-super-secret-and-long-logflare-key-private
|
|
95
|
-
|
|
96
|
-
# Docker
|
|
97
|
-
DOCKER_SOCKET_LOCATION=/var/run/docker.sock
|
|
98
|
-
|
|
99
|
-
EOF
|
|
100
|
-
|
|
101
|
-
# Ensure we're in the right directory with docker-compose.yml
|
|
102
|
-
cd ~/insforge
|
|
103
|
-
|
|
104
|
-
# Stop ALL containers regardless of which compose file started them
|
|
105
|
-
# This ensures clean slate even if previous deploy used different compose file
|
|
106
|
-
sudo docker stop $(sudo docker ps -aq) || true
|
|
107
|
-
sudo docker rm $(sudo docker ps -aq) || true
|
|
108
|
-
|
|
109
|
-
# Also try to stop using both compose files (in case either was used)
|
|
110
|
-
# IMPORTANT: Specify -f for dev file too, to avoid default file selection
|
|
111
|
-
sudo /usr/local/bin/docker-compose -f docker-compose.yml down -v || true
|
|
112
|
-
sudo /usr/local/bin/docker-compose -f docker-compose.prod.yml down -v || true
|
|
113
|
-
|
|
114
|
-
# Clean up any orphaned volumes and networks
|
|
115
|
-
sudo docker volume prune -f || true
|
|
116
|
-
sudo docker network prune -f || true
|
|
117
|
-
|
|
118
|
-
# Build fresh image with no cache and latest base images
|
|
119
|
-
sudo /usr/local/bin/docker-compose -f docker-compose.prod.yml build --no-cache --pull
|
|
120
|
-
|
|
121
|
-
# Now start fresh with production compose
|
|
122
|
-
sudo /usr/local/bin/docker-compose -f docker-compose.prod.yml up -d
|
|
123
|
-
|
|
124
|
-
# Clean up old images
|
|
125
|
-
sudo docker image prune -af
|
|
126
|
-
|
|
127
|
-
# Check deployment status
|
|
128
|
-
sleep 10
|
|
129
|
-
sudo /usr/local/bin/docker-compose -f docker-compose.prod.yml ps
|
|
130
|
-
sudo /usr/local/bin/docker-compose -f docker-compose.prod.yml logs --tail=50
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Router, Request, Response } from 'express';
|
|
2
|
-
import { AgentAPIDocService } from '@/core/documentation/agent.js';
|
|
3
|
-
import { AppError } from '@/api/middleware/error.js';
|
|
4
|
-
import { ERROR_CODES } from '@/types/error-constants.js';
|
|
5
|
-
import { successResponse } from '@/utils/response.js';
|
|
6
|
-
import logger from '@/utils/logger.js';
|
|
7
|
-
|
|
8
|
-
const router = Router();
|
|
9
|
-
const agentAPIDocService = AgentAPIDocService.getInstance();
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* GET /api/agent-docs
|
|
13
|
-
* Get AI-native API documentation optimized for LLMs
|
|
14
|
-
*/
|
|
15
|
-
router.get('/', async (_req: Request, res: Response, next) => {
|
|
16
|
-
try {
|
|
17
|
-
const agentDocs = await agentAPIDocService.generateAgentDocumentation();
|
|
18
|
-
successResponse(res, agentDocs);
|
|
19
|
-
} catch (error) {
|
|
20
|
-
logger.error('Failed to generate agent API documentation', {
|
|
21
|
-
error: error instanceof Error ? error.message : String(error),
|
|
22
|
-
});
|
|
23
|
-
next(
|
|
24
|
-
new AppError('Failed to generate agent API documentation', 500, ERROR_CODES.INTERNAL_ERROR)
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
export { router as agentDocsRouter };
|
|
@@ -1,482 +0,0 @@
|
|
|
1
|
-
import { Router, Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { AuthService } from '@/core/auth/auth.js';
|
|
3
|
-
import { OAuthConfigService } from '@/core/auth/oauth.js';
|
|
4
|
-
import { AuditService } from '@/core/logs/audit.js';
|
|
5
|
-
import { AppError } from '@/api/middleware/error.js';
|
|
6
|
-
import { ERROR_CODES } from '@/types/error-constants.js';
|
|
7
|
-
import { successResponse } from '@/utils/response.js';
|
|
8
|
-
import { AuthRequest, verifyAdmin } from '@/api/middleware/auth.js';
|
|
9
|
-
import logger from '@/utils/logger.js';
|
|
10
|
-
import jwt from 'jsonwebtoken';
|
|
11
|
-
import { SocketService } from '@/core/socket/socket.js';
|
|
12
|
-
import { DataUpdateResourceType, ServerEvents } from '@/core/socket/types.js';
|
|
13
|
-
import {
|
|
14
|
-
createOAuthConfigRequestSchema,
|
|
15
|
-
updateOAuthConfigRequestSchema,
|
|
16
|
-
type ListOAuthConfigsResponse,
|
|
17
|
-
} from '@insforge/shared-schemas';
|
|
18
|
-
import { isOAuthSharedKeysAvailable } from '@/utils/environment.js';
|
|
19
|
-
|
|
20
|
-
const router = Router();
|
|
21
|
-
const authService = AuthService.getInstance();
|
|
22
|
-
const oauthConfigService = OAuthConfigService.getInstance();
|
|
23
|
-
const auditService = AuditService.getInstance();
|
|
24
|
-
|
|
25
|
-
// GET /api/auth/oauth/google - Initialize Google OAuth flow
|
|
26
|
-
router.get('/google', async (req: Request, res: Response, next: NextFunction) => {
|
|
27
|
-
try {
|
|
28
|
-
const { redirect_uri } = req.query;
|
|
29
|
-
if (!redirect_uri) {
|
|
30
|
-
throw new AppError('Redirect URI is required', 400, ERROR_CODES.INVALID_INPUT);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const jwtPayload = {
|
|
34
|
-
provider: 'google',
|
|
35
|
-
redirectUri: redirect_uri ? (redirect_uri as string) : undefined,
|
|
36
|
-
createdAt: Date.now(),
|
|
37
|
-
};
|
|
38
|
-
const state = jwt.sign(jwtPayload, process.env.JWT_SECRET || 'default_secret', {
|
|
39
|
-
algorithm: 'HS256',
|
|
40
|
-
expiresIn: '1h', // Set expiration time for the state token
|
|
41
|
-
});
|
|
42
|
-
const authUrl = await authService.generateGoogleAuthUrl(state);
|
|
43
|
-
|
|
44
|
-
res.json({ authUrl });
|
|
45
|
-
} catch (error) {
|
|
46
|
-
logger.error('Google OAuth error', { error });
|
|
47
|
-
next(
|
|
48
|
-
new AppError(
|
|
49
|
-
'Google OAuth is not properly configured. Please check your oauth configurations.',
|
|
50
|
-
500,
|
|
51
|
-
ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
|
|
52
|
-
)
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// GET /api/auth/oauth/github - Initialize GitHub OAuth flow
|
|
58
|
-
router.get('/github', async (req: Request, res: Response, next: NextFunction) => {
|
|
59
|
-
try {
|
|
60
|
-
const { redirect_uri } = req.query;
|
|
61
|
-
if (!redirect_uri) {
|
|
62
|
-
throw new AppError('Redirect URI is required', 400, ERROR_CODES.INVALID_INPUT);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const jwtPayload = {
|
|
66
|
-
provider: 'github',
|
|
67
|
-
redirectUri: redirect_uri ? (redirect_uri as string) : undefined,
|
|
68
|
-
createdAt: Date.now(),
|
|
69
|
-
};
|
|
70
|
-
const state = jwt.sign(jwtPayload, process.env.JWT_SECRET || 'default_secret', {
|
|
71
|
-
algorithm: 'HS256',
|
|
72
|
-
expiresIn: '1h', // Set expiration time for the state token
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const authUrl = await authService.generateGitHubAuthUrl(state);
|
|
76
|
-
|
|
77
|
-
res.json({ authUrl });
|
|
78
|
-
} catch (error) {
|
|
79
|
-
logger.error('GitHub OAuth error', { error });
|
|
80
|
-
next(
|
|
81
|
-
new AppError(
|
|
82
|
-
'GitHub OAuth is not properly configured. Please check your oauth configurations.',
|
|
83
|
-
500,
|
|
84
|
-
ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
|
|
85
|
-
)
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// GET /api/auth/oauth/shared/callback/:state - Shared callback for OAuth providers
|
|
91
|
-
router.get('/shared/callback/:state', async (req: Request, res: Response, next: NextFunction) => {
|
|
92
|
-
try {
|
|
93
|
-
const { state } = req.params;
|
|
94
|
-
const { success, error, payload } = req.query;
|
|
95
|
-
|
|
96
|
-
if (!state) {
|
|
97
|
-
logger.warn('Shared OAuth callback called without state parameter');
|
|
98
|
-
throw new AppError('State parameter is required', 400, ERROR_CODES.INVALID_INPUT);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
let redirectUri: string;
|
|
102
|
-
let provider: string;
|
|
103
|
-
try {
|
|
104
|
-
const decodedState = jwt.verify(state, process.env.JWT_SECRET || 'default_secret') as {
|
|
105
|
-
provider: string;
|
|
106
|
-
redirectUri: string;
|
|
107
|
-
};
|
|
108
|
-
redirectUri = decodedState.redirectUri || '/';
|
|
109
|
-
provider = decodedState.provider || '';
|
|
110
|
-
} catch {
|
|
111
|
-
logger.warn('Invalid state parameter', { state });
|
|
112
|
-
throw new AppError('Invalid state parameter', 400, ERROR_CODES.INVALID_INPUT);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (!['google', 'github'].includes(provider)) {
|
|
116
|
-
logger.warn('Invalid provider in state', { provider });
|
|
117
|
-
throw new AppError('Invalid provider in state', 400, ERROR_CODES.INVALID_INPUT);
|
|
118
|
-
}
|
|
119
|
-
if (!redirectUri) {
|
|
120
|
-
throw new AppError('Redirect URL is required', 400, ERROR_CODES.INVALID_INPUT);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (success !== 'true') {
|
|
124
|
-
const errorMessage = error || 'OAuth authentication failed';
|
|
125
|
-
logger.warn('Shared OAuth callback failed', { error: errorMessage, provider });
|
|
126
|
-
return res.redirect(`${redirectUri}?error=${encodeURIComponent(String(errorMessage))}`);
|
|
127
|
-
}
|
|
128
|
-
if (!payload) {
|
|
129
|
-
throw new AppError('No payload provided in callback', 400, ERROR_CODES.INVALID_INPUT);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const payloadData = JSON.parse(Buffer.from(payload as string, 'base64').toString('utf8'));
|
|
133
|
-
let result;
|
|
134
|
-
if (provider === 'google') {
|
|
135
|
-
// Handle Google OAuth payload
|
|
136
|
-
const googleUserInfo = {
|
|
137
|
-
sub: payloadData.providerId,
|
|
138
|
-
email: payloadData.email,
|
|
139
|
-
name: payloadData.name || '',
|
|
140
|
-
userName: payloadData.userName || '',
|
|
141
|
-
picture: payloadData.avatar || '',
|
|
142
|
-
};
|
|
143
|
-
result = await authService.findOrCreateGoogleUser(googleUserInfo);
|
|
144
|
-
} else if (provider === 'github') {
|
|
145
|
-
// Handle GitHub OAuth payload
|
|
146
|
-
const githubUserInfo = {
|
|
147
|
-
id: payloadData.providerId,
|
|
148
|
-
login: payloadData.login || '',
|
|
149
|
-
email: payloadData.email,
|
|
150
|
-
name: payloadData.name || '',
|
|
151
|
-
avatar_url: payloadData.avatar || '',
|
|
152
|
-
};
|
|
153
|
-
result = await authService.findOrCreateGitHubUser(githubUserInfo);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const finalredirectUri = new URL(redirectUri);
|
|
157
|
-
finalredirectUri.searchParams.set('access_token', result?.accessToken ?? '');
|
|
158
|
-
finalredirectUri.searchParams.set('user_id', result?.user.id ?? '');
|
|
159
|
-
finalredirectUri.searchParams.set('email', result?.user.email ?? '');
|
|
160
|
-
finalredirectUri.searchParams.set('name', result?.user.name ?? '');
|
|
161
|
-
res.redirect(finalredirectUri.toString());
|
|
162
|
-
} catch (error) {
|
|
163
|
-
logger.error('Shared OAuth callback error', { error });
|
|
164
|
-
next(error);
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// GET /api/auth/oauth/:provider/callback - OAuth provider callback
|
|
169
|
-
router.get('/:provider/callback', async (req: Request, res: Response, _: NextFunction) => {
|
|
170
|
-
try {
|
|
171
|
-
const { provider } = req.params;
|
|
172
|
-
const { code, state, token } = req.query;
|
|
173
|
-
|
|
174
|
-
let redirectUri = '/';
|
|
175
|
-
|
|
176
|
-
if (state) {
|
|
177
|
-
try {
|
|
178
|
-
const stateData = jwt.verify(
|
|
179
|
-
state as string,
|
|
180
|
-
process.env.JWT_SECRET || 'default_secret'
|
|
181
|
-
) as {
|
|
182
|
-
provider: string;
|
|
183
|
-
redirectUri: string;
|
|
184
|
-
};
|
|
185
|
-
redirectUri = stateData.redirectUri || '/';
|
|
186
|
-
} catch {
|
|
187
|
-
// Invalid state
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (!['google', 'github'].includes(provider)) {
|
|
192
|
-
throw new AppError('Invalid provider', 400, ERROR_CODES.INVALID_INPUT);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
let result;
|
|
196
|
-
|
|
197
|
-
if (provider === 'google') {
|
|
198
|
-
let id_token: string;
|
|
199
|
-
|
|
200
|
-
if (token) {
|
|
201
|
-
id_token = token as string;
|
|
202
|
-
} else if (code) {
|
|
203
|
-
const tokens = await authService.exchangeCodeToTokenByGoogle(code as string);
|
|
204
|
-
id_token = tokens.id_token;
|
|
205
|
-
} else {
|
|
206
|
-
throw new AppError(
|
|
207
|
-
'No authorization code or token provided',
|
|
208
|
-
400,
|
|
209
|
-
ERROR_CODES.INVALID_INPUT
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const googleUserInfo = await authService.verifyGoogleToken(id_token);
|
|
214
|
-
result = await authService.findOrCreateGoogleUser(googleUserInfo);
|
|
215
|
-
} else if (provider === 'github') {
|
|
216
|
-
if (!code) {
|
|
217
|
-
throw new AppError('No authorization code provided', 400, ERROR_CODES.INVALID_INPUT);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const accessToken = await authService.exchangeGitHubCodeForToken(code as string);
|
|
221
|
-
const githubUserInfo = await authService.getGitHubUserInfo(accessToken);
|
|
222
|
-
result = await authService.findOrCreateGitHubUser(githubUserInfo);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Create URL with JWT token and user info (like the working example)
|
|
226
|
-
const finalredirectUri = new URL(redirectUri);
|
|
227
|
-
finalredirectUri.searchParams.set('access_token', result?.accessToken ?? '');
|
|
228
|
-
finalredirectUri.searchParams.set('user_id', result?.user.id ?? '');
|
|
229
|
-
finalredirectUri.searchParams.set('email', result?.user.email ?? '');
|
|
230
|
-
finalredirectUri.searchParams.set('name', result?.user.name ?? '');
|
|
231
|
-
|
|
232
|
-
logger.info('OAuth callback successful, redirecting with token', {
|
|
233
|
-
redirectUri: finalredirectUri.toString(),
|
|
234
|
-
hasAccessToken: !!result?.accessToken,
|
|
235
|
-
userId: result?.user.id,
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// Redirect directly to the app with token in URL
|
|
239
|
-
return res.redirect(finalredirectUri.toString());
|
|
240
|
-
} catch (error) {
|
|
241
|
-
logger.error('OAuth callback error', {
|
|
242
|
-
error: error instanceof Error ? error.message : error,
|
|
243
|
-
stack: error instanceof Error ? error.stack : undefined,
|
|
244
|
-
provider: req.params.provider,
|
|
245
|
-
hasCode: !!req.query.code,
|
|
246
|
-
hasState: !!req.query.state,
|
|
247
|
-
hasToken: !!req.query.token,
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// Redirect to app with error message
|
|
251
|
-
const { state } = req.query;
|
|
252
|
-
const redirectUri = state
|
|
253
|
-
? (() => {
|
|
254
|
-
try {
|
|
255
|
-
const stateData = JSON.parse(Buffer.from(state as string, 'base64').toString());
|
|
256
|
-
return stateData.redirectUri || '/';
|
|
257
|
-
} catch {
|
|
258
|
-
return '/';
|
|
259
|
-
}
|
|
260
|
-
})()
|
|
261
|
-
: '/';
|
|
262
|
-
|
|
263
|
-
const errorMessage = error instanceof Error ? error.message : 'OAuth authentication failed';
|
|
264
|
-
|
|
265
|
-
// Redirect with error in URL parameters
|
|
266
|
-
const errorredirectUri = new URL(redirectUri);
|
|
267
|
-
errorredirectUri.searchParams.set('error', errorMessage);
|
|
268
|
-
|
|
269
|
-
return res.redirect(errorredirectUri.toString());
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// ============= OAuth Configuration Management Endpoints =============
|
|
274
|
-
|
|
275
|
-
// GET /api/auth/oauth/configs - List all OAuth configurations (admin only)
|
|
276
|
-
router.get('/configs', verifyAdmin, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
277
|
-
try {
|
|
278
|
-
const configs = await oauthConfigService.getAllConfigs();
|
|
279
|
-
|
|
280
|
-
const response: ListOAuthConfigsResponse = {
|
|
281
|
-
data: configs,
|
|
282
|
-
count: configs.length,
|
|
283
|
-
};
|
|
284
|
-
successResponse(res, response);
|
|
285
|
-
} catch (error) {
|
|
286
|
-
logger.error('Failed to list OAuth configurations', { error });
|
|
287
|
-
next(error);
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
// GET /api/auth/oauth/configs/:provider - Get specific OAuth configuration (admin only)
|
|
292
|
-
router.get(
|
|
293
|
-
'/configs/:provider',
|
|
294
|
-
verifyAdmin,
|
|
295
|
-
async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
296
|
-
try {
|
|
297
|
-
const provider = req.params.provider;
|
|
298
|
-
if (!provider || provider.length === 0 || provider.length > 50) {
|
|
299
|
-
throw new AppError('Invalid provider name', 400, ERROR_CODES.INVALID_INPUT);
|
|
300
|
-
}
|
|
301
|
-
const config = await oauthConfigService.getConfigByProvider(provider);
|
|
302
|
-
const clientSecret = await oauthConfigService.getClientSecretByProvider(provider);
|
|
303
|
-
|
|
304
|
-
if (!config) {
|
|
305
|
-
throw new AppError(
|
|
306
|
-
`OAuth configuration for ${provider} not found`,
|
|
307
|
-
404,
|
|
308
|
-
ERROR_CODES.NOT_FOUND
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
successResponse(res, { ...config, clientSecret });
|
|
313
|
-
} catch (error) {
|
|
314
|
-
logger.error('Failed to get OAuth configuration', { error, provider: req.params.provider });
|
|
315
|
-
next(error);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
);
|
|
319
|
-
|
|
320
|
-
// POST /api/auth/oauth/configs - Create new OAuth configuration (admin only)
|
|
321
|
-
router.post(
|
|
322
|
-
'/configs',
|
|
323
|
-
verifyAdmin,
|
|
324
|
-
async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
325
|
-
try {
|
|
326
|
-
const validationResult = createOAuthConfigRequestSchema.safeParse(req.body);
|
|
327
|
-
if (!validationResult.success) {
|
|
328
|
-
throw new AppError(
|
|
329
|
-
validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
|
|
330
|
-
400,
|
|
331
|
-
ERROR_CODES.INVALID_INPUT
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
const input = validationResult.data;
|
|
336
|
-
|
|
337
|
-
// Check if using shared keys when not allowed
|
|
338
|
-
if (input.useSharedKey && !isOAuthSharedKeysAvailable()) {
|
|
339
|
-
throw new AppError(
|
|
340
|
-
'Shared OAuth keys are not enabled in this environment',
|
|
341
|
-
400,
|
|
342
|
-
ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const config = await oauthConfigService.createConfig(input);
|
|
347
|
-
|
|
348
|
-
await auditService.log({
|
|
349
|
-
actor: req.user?.email || 'api-key',
|
|
350
|
-
action: 'CREATE_OAUTH_CONFIG',
|
|
351
|
-
module: 'AUTH',
|
|
352
|
-
details: {
|
|
353
|
-
provider: input.provider,
|
|
354
|
-
useSharedKey: input.useSharedKey || false,
|
|
355
|
-
},
|
|
356
|
-
ip_address: req.ip,
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
// Broadcast configuration change
|
|
360
|
-
const socket = SocketService.getInstance();
|
|
361
|
-
socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
|
|
362
|
-
resource: DataUpdateResourceType.AUTH_SCHEMA,
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
successResponse(res, config);
|
|
366
|
-
} catch (error) {
|
|
367
|
-
logger.error('Failed to create OAuth configuration', { error });
|
|
368
|
-
next(error);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
// PUT /api/auth/oauth/configs/:provider - Update OAuth configuration (admin only)
|
|
374
|
-
router.put(
|
|
375
|
-
'/configs/:provider',
|
|
376
|
-
verifyAdmin,
|
|
377
|
-
async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
378
|
-
try {
|
|
379
|
-
const provider = req.params.provider;
|
|
380
|
-
if (!provider || provider.length === 0 || provider.length > 50) {
|
|
381
|
-
throw new AppError('Invalid provider name', 400, ERROR_CODES.INVALID_INPUT);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const validationResult = updateOAuthConfigRequestSchema.safeParse(req.body);
|
|
385
|
-
if (!validationResult.success) {
|
|
386
|
-
throw new AppError(
|
|
387
|
-
validationResult.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', '),
|
|
388
|
-
400,
|
|
389
|
-
ERROR_CODES.INVALID_INPUT
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const input = validationResult.data;
|
|
394
|
-
|
|
395
|
-
// Check if using shared keys when not allowed
|
|
396
|
-
if (input.useSharedKey && !isOAuthSharedKeysAvailable()) {
|
|
397
|
-
throw new AppError(
|
|
398
|
-
'Shared OAuth keys are not enabled in this environment',
|
|
399
|
-
400,
|
|
400
|
-
ERROR_CODES.AUTH_OAUTH_CONFIG_ERROR
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const config = await oauthConfigService.updateConfig(provider, input);
|
|
405
|
-
|
|
406
|
-
await auditService.log({
|
|
407
|
-
actor: req.user?.email || 'api-key',
|
|
408
|
-
action: 'UPDATE_OAUTH_CONFIG',
|
|
409
|
-
module: 'AUTH',
|
|
410
|
-
details: {
|
|
411
|
-
provider,
|
|
412
|
-
updatedFields: Object.keys(input),
|
|
413
|
-
},
|
|
414
|
-
ip_address: req.ip,
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
// Broadcast configuration change
|
|
418
|
-
const socket = SocketService.getInstance();
|
|
419
|
-
socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
|
|
420
|
-
resource: DataUpdateResourceType.AUTH_SCHEMA,
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
successResponse(res, config);
|
|
424
|
-
} catch (error) {
|
|
425
|
-
logger.error('Failed to update OAuth configuration', {
|
|
426
|
-
error,
|
|
427
|
-
provider: req.params.provider,
|
|
428
|
-
});
|
|
429
|
-
next(error);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
);
|
|
433
|
-
|
|
434
|
-
// DELETE /api/auth/oauth/configs/:provider - Delete OAuth configuration (admin only)
|
|
435
|
-
router.delete(
|
|
436
|
-
'/configs/:provider',
|
|
437
|
-
verifyAdmin,
|
|
438
|
-
async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
439
|
-
try {
|
|
440
|
-
const provider = req.params.provider;
|
|
441
|
-
if (!provider || provider.length === 0 || provider.length > 50) {
|
|
442
|
-
throw new AppError('Invalid provider name', 400, ERROR_CODES.INVALID_INPUT);
|
|
443
|
-
}
|
|
444
|
-
const deleted = await oauthConfigService.deleteConfig(provider);
|
|
445
|
-
|
|
446
|
-
if (!deleted) {
|
|
447
|
-
throw new AppError(
|
|
448
|
-
`OAuth configuration for ${provider} not found`,
|
|
449
|
-
404,
|
|
450
|
-
ERROR_CODES.NOT_FOUND
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
await auditService.log({
|
|
455
|
-
actor: req.user?.email || 'api-key',
|
|
456
|
-
action: 'DELETE_OAUTH_CONFIG',
|
|
457
|
-
module: 'AUTH',
|
|
458
|
-
details: { provider },
|
|
459
|
-
ip_address: req.ip,
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
// Broadcast configuration change
|
|
463
|
-
const socket = SocketService.getInstance();
|
|
464
|
-
socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
|
|
465
|
-
resource: DataUpdateResourceType.AUTH_SCHEMA,
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
successResponse(res, {
|
|
469
|
-
success: true,
|
|
470
|
-
message: `OAuth configuration for ${provider} deleted successfully`,
|
|
471
|
-
});
|
|
472
|
-
} catch (error) {
|
|
473
|
-
logger.error('Failed to delete OAuth configuration', {
|
|
474
|
-
error,
|
|
475
|
-
provider: req.params.provider,
|
|
476
|
-
});
|
|
477
|
-
next(error);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
);
|
|
481
|
-
|
|
482
|
-
export default router;
|