insforge 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +58 -0
- package/.env.example +49 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +83 -0
- package/.github/ISSUE_TEMPLATE/config.yml +11 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +79 -0
- package/.github/copilot-instructions.md +147 -0
- package/.github/workflows/build-image.yml +65 -0
- package/.github/workflows/ci-premerge-check.yml +24 -0
- package/.github/workflows/deploy-aws.yml +130 -0
- package/.github/workflows/lint-and-format.yml +33 -0
- package/.prettierignore +65 -0
- package/.prettierrc +9 -0
- package/CHANGELOG.md +3 -0
- package/CONTRIBUTING.md +126 -0
- package/Dockerfile +27 -0
- package/GITHUB_OAUTH_SETUP.md +49 -0
- package/GOOGLE_OAUTH_SETUP.md +148 -0
- package/LICENSE +201 -0
- package/README.md +134 -0
- package/assets/Dark.svg +23 -0
- package/assets/archDiagram.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/mcpInstallv2.png +0 -0
- package/assets/sampleResponse.png +0 -0
- package/assets/signin.png +0 -0
- package/assets/userflow.png +0 -0
- package/backend/migrations/000_create-base-tables.sql +142 -0
- package/backend/migrations/001_create-helper-functions.sql +41 -0
- package/backend/migrations/002_rename-auth-tables.sql +30 -0
- package/backend/migrations/003_create-users-table.sql +56 -0
- package/backend/migrations/004_add-reload-postgrest-func.sql +24 -0
- package/backend/migrations/005_enable-project-admin-modify-users.sql +30 -0
- package/backend/migrations/006_modify-ai-usage-table.sql +25 -0
- package/backend/migrations/007_drop-metadata-table.sql +2 -0
- package/backend/migrations/008_add-system-tables.sql +77 -0
- package/backend/migrations/009_add-function-secrets.sql +24 -0
- package/backend/migrations/010_modify-ai-config-modalities.sql +93 -0
- package/backend/migrations/011_refactor-secrets-table.sql +15 -0
- package/backend/migrations/012_add-storage-uploaded-by.sql +8 -0
- package/backend/package.json +75 -0
- package/backend/src/api/middleware/auth.ts +240 -0
- package/backend/src/api/middleware/error.ts +231 -0
- package/backend/src/api/middleware/upload.ts +59 -0
- package/backend/src/api/routes/agent.ts +29 -0
- package/backend/src/api/routes/ai.ts +472 -0
- package/backend/src/api/routes/auth.oauth.ts +482 -0
- package/backend/src/api/routes/auth.ts +386 -0
- package/backend/src/api/routes/database.advance.ts +275 -0
- package/backend/src/api/routes/database.records.ts +246 -0
- package/backend/src/api/routes/database.tables.ts +161 -0
- package/backend/src/api/routes/docs.ts +66 -0
- package/backend/src/api/routes/functions.ts +183 -0
- package/backend/src/api/routes/logs.ts +150 -0
- package/backend/src/api/routes/metadata.ts +160 -0
- package/backend/src/api/routes/openapi.ts +82 -0
- package/backend/src/api/routes/secrets.ts +199 -0
- package/backend/src/api/routes/storage.ts +547 -0
- package/backend/src/api/routes/usage.ts +96 -0
- package/backend/src/core/ai/chat.ts +207 -0
- package/backend/src/core/ai/client.ts +242 -0
- package/backend/src/core/ai/config.ts +187 -0
- package/backend/src/core/ai/image.ts +156 -0
- package/backend/src/core/ai/model.ts +117 -0
- package/backend/src/core/ai/usage.ts +290 -0
- package/backend/src/core/auth/auth.ts +781 -0
- package/backend/src/core/auth/oauth.ts +398 -0
- package/backend/src/core/database/advance.ts +1074 -0
- package/backend/src/core/database/manager.ts +178 -0
- package/backend/src/core/database/table.ts +772 -0
- package/backend/src/core/documentation/agent.ts +689 -0
- package/backend/src/core/documentation/openapi.ts +856 -0
- package/backend/src/core/functions/functions.ts +310 -0
- package/backend/src/core/logs/analytics.ts +76 -0
- package/backend/src/core/logs/audit.ts +255 -0
- package/backend/src/core/logs/providers/base.provider.ts +83 -0
- package/backend/src/core/logs/providers/cloudwatch.provider.ts +510 -0
- package/backend/src/core/logs/providers/localdb.provider.ts +246 -0
- package/backend/src/core/secrets/encryption.ts +58 -0
- package/backend/src/core/secrets/secrets.ts +410 -0
- package/backend/src/core/socket/socket.ts +388 -0
- package/backend/src/core/socket/types.ts +79 -0
- package/backend/src/core/storage/storage.ts +923 -0
- package/backend/src/server.ts +288 -0
- package/backend/src/types/ai.ts +46 -0
- package/backend/src/types/auth.ts +90 -0
- package/backend/src/types/database.ts +136 -0
- package/backend/src/types/error-constants.ts +86 -0
- package/backend/src/types/logs.ts +47 -0
- package/backend/src/types/profile.ts +55 -0
- package/backend/src/types/storage.ts +23 -0
- package/backend/src/utils/cloud-token.ts +39 -0
- package/backend/src/utils/constants.ts +1 -0
- package/backend/src/utils/environment.ts +35 -0
- package/backend/src/utils/helpers.ts +49 -0
- package/backend/src/utils/logger.ts +13 -0
- package/backend/src/utils/response.ts +62 -0
- package/backend/src/utils/seed.ts +205 -0
- package/backend/src/utils/sql-parser.ts +63 -0
- package/backend/src/utils/uuid.ts +9 -0
- package/backend/src/utils/validations.ts +129 -0
- package/backend/tests/README.md +134 -0
- package/backend/tests/cleanup-all-test-data.sh +231 -0
- package/backend/tests/cloud/test-s3-multitenant.sh +132 -0
- package/backend/tests/local/comprehensive-curl-tests.sh +156 -0
- package/backend/tests/local/test-auth-router.sh +144 -0
- package/backend/tests/local/test-database-router.sh +222 -0
- package/backend/tests/local/test-e2e.sh +241 -0
- package/backend/tests/local/test-fk-errors.sh +97 -0
- package/backend/tests/local/test-id-field.sh +201 -0
- package/backend/tests/local/test-public-bucket.sh +265 -0
- package/backend/tests/local/test-secrets.sh +248 -0
- package/backend/tests/local/test-serverless-functions.sh.disabled +325 -0
- package/backend/tests/local/test-traditional-rest.sh +209 -0
- package/backend/tests/manual/README.md +51 -0
- package/backend/tests/manual/create-large-table-simple.sql +11 -0
- package/backend/tests/manual/seed-large-table.sql +101 -0
- package/backend/tests/manual/setup-large-table-extras.sql +34 -0
- package/backend/tests/manual/test-better-auth.sh +303 -0
- package/backend/tests/manual/test-bulk-upsert.sh +410 -0
- package/backend/tests/manual/test-database-advance.sh +297 -0
- package/backend/tests/manual/test-postgrest-stability.sh +192 -0
- package/backend/tests/manual/test-rawsql-export-import.sh +412 -0
- package/backend/tests/manual/test-universal-storage.sh +264 -0
- package/backend/tests/manual/test-users.sql +18 -0
- package/backend/tests/run-all-tests.sh +140 -0
- package/backend/tests/setup.ts +22 -0
- package/backend/tests/test-config.sh +303 -0
- package/backend/tsconfig.json +23 -0
- package/backend/tsup.config.ts +18 -0
- package/backend/vitest.config.ts +22 -0
- package/docker-compose.prod.yml +145 -0
- package/docker-compose.yml +167 -0
- package/docker-init/db/db-init.sql +125 -0
- package/docker-init/db/jwt.sql +5 -0
- package/docker-init/db/logs.sql +9 -0
- package/docker-init/db/postgresql.conf +17 -0
- package/docs/deprecated/insforge-auth-api.md +215 -0
- package/docs/deprecated/insforge-auth-sdk.md +100 -0
- package/docs/deprecated/insforge-db-api.md +359 -0
- package/docs/deprecated/insforge-db-sdk.md +140 -0
- package/docs/deprecated/insforge-debug-sdk.md +157 -0
- package/docs/deprecated/insforge-debug.md +65 -0
- package/docs/deprecated/insforge-instructions.md +124 -0
- package/docs/deprecated/insforge-project.md +118 -0
- package/docs/deprecated/insforge-storage-api.md +279 -0
- package/docs/deprecated/insforge-storage-sdk.md +159 -0
- package/docs/insforge-instructions-sdk.md +407 -0
- package/eslint.config.js +317 -0
- package/examples/oauth/frontend-oauth-example.html +251 -0
- package/examples/response-examples.md +444 -0
- package/frontend/README.md +112 -0
- package/frontend/components.json +17 -0
- package/frontend/index.html +13 -0
- package/frontend/package.json +63 -0
- package/frontend/public/favicon.ico +0 -0
- package/frontend/src/App.tsx +106 -0
- package/frontend/src/assets/icons/checkbox_checked.svg +6 -0
- package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -0
- package/frontend/src/assets/icons/checked.svg +3 -0
- package/frontend/src/assets/icons/error.svg +3 -0
- package/frontend/src/assets/icons/pencil.svg +4 -0
- package/frontend/src/assets/icons/refresh.svg +4 -0
- package/frontend/src/assets/icons/step_active.svg +3 -0
- package/frontend/src/assets/icons/step_inactive.svg +11 -0
- package/frontend/src/assets/icons/warning.svg +3 -0
- package/frontend/src/assets/logos/amazon.svg +1 -0
- package/frontend/src/assets/logos/claude_code.svg +3 -0
- package/frontend/src/assets/logos/cline.svg +6 -0
- package/frontend/src/assets/logos/cursor.svg +20 -0
- package/frontend/src/assets/logos/discord.svg +9 -0
- package/frontend/src/assets/logos/gemini.svg +19 -0
- package/frontend/src/assets/logos/github.svg +5 -0
- package/frontend/src/assets/logos/google.svg +13 -0
- package/frontend/src/assets/logos/grok.svg +10 -0
- package/frontend/src/assets/logos/insforge_dark.svg +15 -0
- package/frontend/src/assets/logos/insforge_light.svg +15 -0
- package/frontend/src/assets/logos/openai.svg +10 -0
- package/frontend/src/assets/logos/roo_code.svg +9 -0
- package/frontend/src/assets/logos/trae.svg +3 -0
- package/frontend/src/assets/logos/windsurf.svg +10 -0
- package/frontend/src/components/ButtonWithLoading.tsx +27 -0
- package/frontend/src/components/Checkbox.tsx +61 -0
- package/frontend/src/components/CodeBlock.tsx +32 -0
- package/frontend/src/components/ConfirmDialog.tsx +96 -0
- package/frontend/src/components/CopyButton.tsx +69 -0
- package/frontend/src/components/DeleteActionButton.tsx +42 -0
- package/frontend/src/components/EmptyState.tsx +41 -0
- package/frontend/src/components/ErrorState.tsx +35 -0
- package/frontend/src/components/FeatureSidebar.tsx +126 -0
- package/frontend/src/components/FeatureSidebarItem.tsx +101 -0
- package/frontend/src/components/JsonHighlight.tsx +61 -0
- package/frontend/src/components/LoadingState.tsx +16 -0
- package/frontend/src/components/PaginationControls.tsx +54 -0
- package/frontend/src/components/PromptDialog.tsx +68 -0
- package/frontend/src/components/SearchInput.tsx +90 -0
- package/frontend/src/components/SelectionClearButton.tsx +26 -0
- package/frontend/src/components/Stepper.tsx +139 -0
- package/frontend/src/components/ThemeToggle.tsx +58 -0
- package/frontend/src/components/TypeBadge.tsx +20 -0
- package/frontend/src/components/datagrid/DataGrid.tsx +264 -0
- package/frontend/src/components/datagrid/DefaultCellRenderer.tsx +114 -0
- package/frontend/src/components/datagrid/IdCell.tsx +44 -0
- package/frontend/src/components/datagrid/SortableHeader.tsx +74 -0
- package/frontend/src/components/datagrid/cell-editors/BooleanCellEditor.tsx +54 -0
- package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +483 -0
- package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +362 -0
- package/frontend/src/components/datagrid/cell-editors/TextCellEditor.tsx +38 -0
- package/frontend/src/components/datagrid/cell-editors/index.ts +14 -0
- package/frontend/src/components/datagrid/cell-editors/types.ts +43 -0
- package/frontend/src/components/datagrid/datagridTypes.tsx +72 -0
- package/frontend/src/components/datagrid/index.tsx +20 -0
- package/frontend/src/components/index.ts +39 -0
- package/frontend/src/components/layout/AppHeader.tsx +146 -0
- package/frontend/src/components/layout/AppSidebar.tsx +190 -0
- package/frontend/src/components/layout/CloudLayout.tsx +95 -0
- package/frontend/src/components/layout/Layout.tsx +43 -0
- package/frontend/src/components/radix/Alert.tsx +45 -0
- package/frontend/src/components/radix/AlertDialog.tsx +115 -0
- package/frontend/src/components/radix/Avatar.tsx +45 -0
- package/frontend/src/components/radix/Badge.tsx +33 -0
- package/frontend/src/components/radix/Button.tsx +50 -0
- package/frontend/src/components/radix/Card.tsx +58 -0
- package/frontend/src/components/radix/Dialog.tsx +98 -0
- package/frontend/src/components/radix/DropdownMenu.tsx +185 -0
- package/frontend/src/components/radix/Form.tsx +167 -0
- package/frontend/src/components/radix/Input.tsx +22 -0
- package/frontend/src/components/radix/Label.tsx +19 -0
- package/frontend/src/components/radix/Popover.tsx +29 -0
- package/frontend/src/components/radix/ScrollArea.tsx +44 -0
- package/frontend/src/components/radix/Select.tsx +151 -0
- package/frontend/src/components/radix/Separator.tsx +26 -0
- package/frontend/src/components/radix/Sheet.tsx +119 -0
- package/frontend/src/components/radix/Skeleton.tsx +7 -0
- package/frontend/src/components/radix/Switch.tsx +29 -0
- package/frontend/src/components/radix/Tabs.tsx +50 -0
- package/frontend/src/components/radix/Textarea.tsx +21 -0
- package/frontend/src/components/radix/Tooltip.tsx +28 -0
- package/frontend/src/features/ai/components/AIConfigCard.tsx +154 -0
- package/frontend/src/features/ai/components/AIConfigDialog.tsx +76 -0
- package/frontend/src/features/ai/components/AIConfigForm.tsx +222 -0
- package/frontend/src/features/ai/components/AIEmptyState.tsx +18 -0
- package/frontend/src/features/ai/components/fields/ModalityField.tsx +87 -0
- package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +134 -0
- package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +33 -0
- package/frontend/src/features/ai/helpers.ts +155 -0
- package/frontend/src/features/ai/hooks/useAIConfigs.ts +221 -0
- package/frontend/src/features/ai/hooks/useAIUsage.ts +77 -0
- package/frontend/src/features/ai/page/AIPage.tsx +178 -0
- package/frontend/src/features/ai/services/ai.service.ts +148 -0
- package/frontend/src/features/auth/components/AddOAuthDialog.tsx +106 -0
- package/frontend/src/features/auth/components/AuthMethodTab.tsx +238 -0
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +303 -0
- package/frontend/src/features/auth/components/OAuthEmptyState.tsx +15 -0
- package/frontend/src/features/auth/components/UserFormDialog.tsx +248 -0
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +183 -0
- package/frontend/src/features/auth/components/UsersTab.tsx +114 -0
- package/frontend/src/features/auth/hooks/useOAuthConfig.ts +129 -0
- package/frontend/src/features/auth/hooks/useUsers.ts +57 -0
- package/frontend/src/features/auth/index.ts +9 -0
- package/frontend/src/features/auth/page/AuthenticationPage.tsx +169 -0
- package/frontend/src/features/auth/services/auth.service.ts +112 -0
- package/frontend/src/features/auth/services/oauth.service.ts +49 -0
- package/frontend/src/features/dashboard/page/DashboardPage.tsx +194 -0
- package/frontend/src/features/database/components/ColumnTypeSelect.tsx +64 -0
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +282 -0
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +187 -0
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +378 -0
- package/frontend/src/features/database/components/LinkRecordModal.tsx +288 -0
- package/frontend/src/features/database/components/RecordFormDialog.tsx +164 -0
- package/frontend/src/features/database/components/RecordFormField.tsx +568 -0
- package/frontend/src/features/database/components/TableEmptyState.tsx +21 -0
- package/frontend/src/features/database/components/TableForm.tsx +656 -0
- package/frontend/src/features/database/components/TableFormColumn.tsx +137 -0
- package/frontend/src/features/database/components/TableListSkeleton.tsx +9 -0
- package/frontend/src/features/database/components/TableSidebar.tsx +47 -0
- package/frontend/src/features/database/constants.ts +26 -0
- package/frontend/src/features/database/helpers.ts +125 -0
- package/frontend/src/features/database/hooks/UseLinkModal.tsx +78 -0
- package/frontend/src/features/database/index.ts +12 -0
- package/frontend/src/features/database/page/DatabasePage.tsx +626 -0
- package/frontend/src/features/database/schema.ts +25 -0
- package/frontend/src/features/database/services/database.service.ts +216 -0
- package/frontend/src/features/functions/components/FunctionEmptyState.tsx +15 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +71 -0
- package/frontend/src/features/functions/components/FunctionViewer.tsx +46 -0
- package/frontend/src/features/functions/components/FunctionsContent.tsx +88 -0
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -0
- package/frontend/src/features/functions/components/SecretEmptyState.tsx +23 -0
- package/frontend/src/features/functions/components/SecretRow.tsx +68 -0
- package/frontend/src/features/functions/components/SecretsContent.tsx +120 -0
- package/frontend/src/features/functions/hooks/useFunctions.ts +106 -0
- package/frontend/src/features/functions/page/FunctionsPage.tsx +28 -0
- package/frontend/src/features/functions/services/functions.service.ts +48 -0
- package/frontend/src/features/login/components/AuthErrorBoundary.tsx +87 -0
- package/frontend/src/features/login/components/PrivateRoute.tsx +24 -0
- package/frontend/src/features/login/page/CloudLoginPage.tsx +93 -0
- package/frontend/src/features/login/page/LoginPage.tsx +174 -0
- package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +313 -0
- package/frontend/src/features/logs/components/LogsTable.tsx +199 -0
- package/frontend/src/features/logs/hooks/useAuditLogs.ts +39 -0
- package/frontend/src/features/logs/index.ts +5 -0
- package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +530 -0
- package/frontend/src/features/logs/page/AuditsPage.tsx +192 -0
- package/frontend/src/features/logs/services/log.service.ts +171 -0
- package/frontend/src/features/metadata/hooks/useMetadata.ts +53 -0
- package/frontend/src/features/metadata/index.ts +0 -0
- package/frontend/src/features/metadata/page/MetadataPage.tsx +136 -0
- package/frontend/src/features/metadata/services/metadata.service.ts +17 -0
- package/frontend/src/features/onboard/components/CompletionCard.tsx +41 -0
- package/frontend/src/features/onboard/components/OnboardButton.tsx +84 -0
- package/frontend/src/features/onboard/components/StepContent.tsx +91 -0
- package/frontend/src/features/onboard/components/TestConnectionStep.tsx +53 -0
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +35 -0
- package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +144 -0
- package/frontend/src/features/onboard/components/mcp/index.ts +4 -0
- package/frontend/src/features/onboard/components/mcp/mcp-helper.tsx +98 -0
- package/frontend/src/features/onboard/index.ts +3 -0
- package/frontend/src/features/onboard/page/OnBoardPage.tsx +104 -0
- package/frontend/src/features/onboard/types.ts +8 -0
- package/frontend/src/features/secrets/hooks/useSecrets.ts +139 -0
- package/frontend/src/features/secrets/services/secrets.service.ts +57 -0
- package/frontend/src/features/storage/components/BucketEmptyState.tsx +19 -0
- package/frontend/src/features/storage/components/BucketFormDialog.tsx +194 -0
- package/frontend/src/features/storage/components/BucketListSkeleton.tsx +17 -0
- package/frontend/src/features/storage/components/FilePreviewDialog.tsx +287 -0
- package/frontend/src/features/storage/components/StorageDataGrid.tsx +239 -0
- package/frontend/src/features/storage/components/StorageManager.tsx +236 -0
- package/frontend/src/features/storage/components/StorageSidebar.tsx +44 -0
- package/frontend/src/features/storage/components/UploadToast.tsx +46 -0
- package/frontend/src/features/storage/index.ts +3 -0
- package/frontend/src/features/storage/page/StoragePage.tsx +553 -0
- package/frontend/src/features/storage/services/storage.service.ts +144 -0
- package/frontend/src/features/visualizer/components/AuthNode.tsx +107 -0
- package/frontend/src/features/visualizer/components/BucketNode.tsx +34 -0
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +359 -0
- package/frontend/src/features/visualizer/components/TableNode.tsx +152 -0
- package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +24 -0
- package/frontend/src/features/visualizer/components/index.ts +5 -0
- package/frontend/src/features/visualizer/page/VisualizerPage.tsx +127 -0
- package/frontend/src/index.css +248 -0
- package/frontend/src/lib/api/client.ts +163 -0
- package/frontend/src/lib/contexts/AuthContext.tsx +157 -0
- package/frontend/src/lib/contexts/OnboardStepContext.tsx +68 -0
- package/frontend/src/lib/contexts/SocketContext.tsx +303 -0
- package/frontend/src/lib/contexts/ThemeContext.tsx +125 -0
- package/frontend/src/lib/hooks/useAuth.ts +4 -0
- package/frontend/src/lib/hooks/useConfirm.ts +55 -0
- package/frontend/src/lib/hooks/useInterval.ts +27 -0
- package/frontend/src/lib/hooks/useMediaQuery.ts +59 -0
- package/frontend/src/lib/hooks/useOnboardingCompletion.ts +29 -0
- package/frontend/src/lib/hooks/usePagination.ts +27 -0
- package/frontend/src/lib/hooks/useTimeout.ts +27 -0
- package/frontend/src/lib/hooks/useToast.tsx +229 -0
- package/frontend/src/lib/utils/constants.ts +38 -0
- package/frontend/src/lib/utils/utils.ts +165 -0
- package/frontend/src/lib/utils/validation-schemas.ts +126 -0
- package/frontend/src/main.tsx +16 -0
- package/frontend/src/rdg.css +194 -0
- package/frontend/src/vite-env.d.ts +12 -0
- package/frontend/tailwind.config.js +97 -0
- package/frontend/tsconfig.json +26 -0
- package/frontend/tsconfig.node.json +10 -0
- package/frontend/vite.config.ts +37 -0
- package/frontend/vitest.config.ts +36 -0
- package/functions/deno.json +25 -0
- package/functions/server.ts +290 -0
- package/functions/worker-template.js +126 -0
- package/openapi/ai.yaml +689 -0
- package/openapi/auth.yaml +563 -0
- package/openapi/functions.yaml +476 -0
- package/openapi/health.yaml +30 -0
- package/openapi/logs.yaml +224 -0
- package/openapi/metadata.yaml +178 -0
- package/openapi/records.yaml +382 -0
- package/openapi/secrets.yaml +371 -0
- package/openapi/storage.yaml +876 -0
- package/openapi/tables.yaml +464 -0
- package/package.json +88 -0
- package/shared-schemas/package.json +31 -0
- package/shared-schemas/src/ai-api.schema.ts +167 -0
- package/shared-schemas/src/ai.schema.ts +54 -0
- package/shared-schemas/src/auth-api.schema.ts +193 -0
- package/shared-schemas/src/auth.schema.ts +94 -0
- package/shared-schemas/src/database-api.schema.ts +259 -0
- package/shared-schemas/src/database.schema.ts +69 -0
- package/shared-schemas/src/functions-api.schema.ts +25 -0
- package/shared-schemas/src/functions.schema.ts +16 -0
- package/shared-schemas/src/index.ts +13 -0
- package/shared-schemas/src/logs-api.schema.ts +49 -0
- package/shared-schemas/src/logs.schema.ts +14 -0
- package/shared-schemas/src/metadata.schema.ts +56 -0
- package/shared-schemas/src/storage-api.schema.ts +65 -0
- package/shared-schemas/src/storage.schema.ts +19 -0
- package/shared-schemas/tsconfig.json +21 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,482 @@
|
|
|
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;
|