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.
Files changed (507) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.cursor/rules/cursor-rules.mdc +94 -0
  3. package/.dockerignore +3 -0
  4. package/.env.example +33 -4
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
  6. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
  8. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  9. package/.github/workflows/build-image.yml +2 -1
  10. package/.github/workflows/e2e.yml +63 -0
  11. package/CHANGELOG.md +41 -0
  12. package/CLAUDE_PLUGIN.md +104 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/Dockerfile +4 -1
  16. package/README.md +66 -18
  17. package/assets/mcpInstallv2.png +0 -0
  18. package/assets/sampleResponse.png +0 -0
  19. package/auth/index.html +13 -0
  20. package/auth/package.json +28 -0
  21. package/auth/public/favicon.ico +0 -0
  22. package/auth/src/App.tsx +33 -0
  23. package/auth/src/components/ErrorCard.tsx +37 -0
  24. package/auth/src/components/Layout.tsx +13 -0
  25. package/auth/src/index.css +19 -0
  26. package/auth/src/lib/broadcastService.ts +115 -0
  27. package/auth/src/lib/utils.ts +11 -0
  28. package/auth/src/main.tsx +22 -0
  29. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  30. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  31. package/auth/src/pages/SignInPage.tsx +57 -0
  32. package/auth/src/pages/SignUpPage.tsx +57 -0
  33. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  34. package/auth/src/vite-env.d.ts +10 -0
  35. package/auth/tsconfig.json +32 -0
  36. package/auth/tsconfig.node.json +11 -0
  37. package/auth/vite.config.ts +25 -0
  38. package/backend/package.json +9 -9
  39. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  40. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  41. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
  42. package/backend/src/api/routes/auth/index.routes.ts +570 -0
  43. package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
  44. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
  45. package/backend/src/api/routes/database/index.routes.ts +13 -0
  46. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
  47. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
  48. package/backend/src/api/routes/docs/index.routes.ts +76 -0
  49. package/backend/src/api/routes/functions/index.routes.ts +188 -0
  50. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  51. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
  52. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  53. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
  54. package/backend/src/api/routes/usage/index.routes.ts +89 -0
  55. package/backend/src/infra/config/app.config.ts +51 -0
  56. package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
  57. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  58. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  59. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  60. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  61. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  62. package/backend/src/infra/security/token.manager.ts +125 -0
  63. package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
  64. package/backend/src/providers/ai/openrouter.provider.ts +377 -0
  65. package/backend/src/providers/email/base.provider.ts +41 -0
  66. package/backend/src/providers/email/cloud.provider.ts +187 -0
  67. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  68. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  69. package/backend/src/providers/logs/local.provider.ts +185 -0
  70. package/backend/src/providers/oauth/base.provider.ts +29 -0
  71. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  72. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  73. package/backend/src/providers/oauth/github.provider.ts +208 -0
  74. package/backend/src/providers/oauth/google.provider.ts +249 -0
  75. package/backend/src/providers/oauth/index.ts +7 -0
  76. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  77. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  78. package/backend/src/providers/oauth/x.provider.ts +202 -0
  79. package/backend/src/providers/storage/base.provider.ts +29 -0
  80. package/backend/src/providers/storage/local.provider.ts +103 -0
  81. package/backend/src/providers/storage/s3.provider.ts +313 -0
  82. package/backend/src/server.ts +70 -74
  83. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  84. package/backend/src/services/ai/ai-model.service.ts +60 -0
  85. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  86. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  87. package/backend/src/services/ai/helpers.ts +64 -0
  88. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  89. package/backend/src/services/ai/index.ts +13 -0
  90. package/backend/src/services/auth/auth-config.service.ts +250 -0
  91. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  92. package/backend/src/services/auth/auth.service.ts +1136 -0
  93. package/backend/src/services/auth/index.ts +4 -0
  94. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  95. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  96. package/backend/src/services/database/database-table.service.ts +811 -0
  97. package/backend/src/services/email/email.service.ts +75 -0
  98. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  99. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  100. package/backend/src/services/logs/log.service.ts +73 -0
  101. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  102. package/backend/src/services/storage/storage.service.ts +617 -0
  103. package/backend/src/services/usage/usage.service.ts +149 -0
  104. package/backend/src/types/auth.ts +66 -2
  105. package/backend/src/types/email.ts +8 -0
  106. package/backend/src/types/error-constants.ts +4 -0
  107. package/backend/src/types/logs.ts +0 -29
  108. package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
  109. package/backend/src/utils/environment.ts +9 -3
  110. package/backend/src/utils/logger.ts +20 -2
  111. package/backend/src/utils/seed.ts +150 -57
  112. package/backend/src/utils/sql-parser.ts +1 -1
  113. package/backend/src/utils/utils.ts +114 -0
  114. package/backend/src/utils/validations.ts +40 -4
  115. package/backend/tests/local/test-ai-config.sh +129 -0
  116. package/backend/tests/local/test-ai-usage.sh +80 -0
  117. package/backend/tests/local/test-auth-router.sh +1 -1
  118. package/backend/tests/local/test-e2e.sh +1 -1
  119. package/backend/tests/local/test-functions.sh +123 -0
  120. package/backend/tests/local/test-logs.sh +132 -0
  121. package/backend/tests/local/test-public-bucket.sh +3 -3
  122. package/backend/tests/local/test-secrets.sh +14 -12
  123. package/backend/tests/local/test-traditional-rest.sh +2 -2
  124. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  125. package/backend/tests/test-config.sh +37 -1
  126. package/backend/tests/unit/cloud-token.test.ts +48 -0
  127. package/backend/tests/unit/constant.test.ts +8 -0
  128. package/backend/tests/unit/email.test.ts +372 -0
  129. package/backend/tests/unit/environment.test.ts +59 -0
  130. package/backend/tests/unit/helpers.test.ts +63 -0
  131. package/backend/tests/unit/logger.test.ts +22 -0
  132. package/backend/tests/unit/rate-limit.test.ts +154 -0
  133. package/backend/tests/unit/response.test.ts +58 -0
  134. package/backend/tests/unit/sql-parser.test.ts +74 -0
  135. package/backend/tests/unit/uuid.test.ts +21 -0
  136. package/backend/tests/unit/validations.test.ts +80 -0
  137. package/backend/tsconfig.json +1 -1
  138. package/backend/vitest.config.ts +11 -0
  139. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  140. package/claude-plugin/README.md +133 -0
  141. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  142. package/docker-compose.prod.yml +60 -4
  143. package/docker-compose.yml +65 -4
  144. package/docker-init/db/db-init.sql +6 -34
  145. package/docker-init/logs/vector.yml +236 -0
  146. package/docs/README.md +44 -0
  147. package/docs/changelog.mdx +67 -0
  148. package/docs/core-concepts/ai/architecture.mdx +373 -0
  149. package/docs/core-concepts/ai/sdk.mdx +213 -0
  150. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  151. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  152. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  153. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  154. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  155. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  156. package/docs/core-concepts/database/architecture.mdx +256 -0
  157. package/docs/core-concepts/database/sdk.mdx +382 -0
  158. package/docs/core-concepts/functions/architecture.mdx +105 -0
  159. package/docs/core-concepts/functions/sdk.mdx +184 -0
  160. package/docs/core-concepts/storage/architecture.mdx +243 -0
  161. package/docs/core-concepts/storage/sdk.mdx +253 -0
  162. package/docs/deployment/README.md +94 -0
  163. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  164. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  165. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  166. package/docs/deployment/deploy-to-render.md +441 -0
  167. package/docs/docs.json +210 -0
  168. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  169. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  170. package/docs/examples/framework-guides/react.mdx +165 -0
  171. package/docs/examples/framework-guides/svelte.mdx +153 -0
  172. package/docs/examples/framework-guides/vue.mdx +159 -0
  173. package/docs/examples/overview.mdx +67 -0
  174. package/docs/favicon.svg +19 -0
  175. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  176. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  177. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  178. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  179. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  180. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  181. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  182. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  183. package/docs/images/checks-passed.png +0 -0
  184. package/docs/images/dashboard-connect-expanded.png +0 -0
  185. package/docs/images/dashboard-connect.png +0 -0
  186. package/docs/images/hero-dark.png +0 -0
  187. package/docs/images/hero-light.png +0 -0
  188. package/docs/images/icons/ai.svg +4 -0
  189. package/docs/images/icons/auth.svg +1 -0
  190. package/docs/images/icons/database.svg +1 -0
  191. package/docs/images/icons/function.svg +1 -0
  192. package/docs/images/icons/storage.svg +1 -0
  193. package/docs/images/logos/nextjs.svg +4 -0
  194. package/docs/images/logos/nuxt.svg +4 -0
  195. package/docs/images/logos/react.svg +5 -0
  196. package/docs/images/logos/svelte.svg +4 -0
  197. package/docs/images/logos/vue.svg +5 -0
  198. package/docs/images/mcp-install.png +0 -0
  199. package/docs/images/onboarding-mcp.png +0 -0
  200. package/docs/insforge-instructions-sdk.md +55 -374
  201. package/docs/introduction.mdx +45 -0
  202. package/docs/logo/dark.svg +22 -0
  203. package/docs/logo/light.svg +20 -0
  204. package/docs/partnership.mdx +647 -0
  205. package/docs/quickstart.mdx +83 -0
  206. package/docs/showcase/2048-arena.png +0 -0
  207. package/docs/showcase/framegen-cloud.png +0 -0
  208. package/docs/showcase/line-connect-race.png +0 -0
  209. package/docs/showcase/moment-vibe.png +0 -0
  210. package/docs/showcase/national-flags.png +0 -0
  211. package/docs/showcase/pokemon-vibe.png +0 -0
  212. package/docs/showcase/pure-browse-buy.png +0 -0
  213. package/docs/showcase.mdx +52 -0
  214. package/docs/snippets/sdk-installation.mdx +22 -0
  215. package/docs/snippets/service-icons.mdx +27 -0
  216. package/eslint.config.js +10 -3
  217. package/frontend/package.json +10 -4
  218. package/frontend/src/App.tsx +13 -82
  219. package/frontend/src/assets/icons/connected.svg +3 -0
  220. package/frontend/src/assets/icons/loader.svg +9 -0
  221. package/frontend/src/assets/logos/apple.svg +4 -0
  222. package/frontend/src/assets/logos/discord.svg +1 -1
  223. package/frontend/src/assets/logos/facebook.svg +3 -0
  224. package/frontend/src/assets/logos/instagram.svg +2 -0
  225. package/frontend/src/assets/logos/linkedin.svg +3 -0
  226. package/frontend/src/assets/logos/microsoft.svg +1 -0
  227. package/frontend/src/assets/logos/spotify.svg +17 -0
  228. package/frontend/src/assets/logos/tiktok.svg +6 -0
  229. package/frontend/src/assets/logos/x.svg +3 -0
  230. package/frontend/src/components/Checkbox.tsx +27 -29
  231. package/frontend/src/components/CodeBlock.tsx +55 -2
  232. package/frontend/src/components/CodeEditor.tsx +92 -0
  233. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  234. package/frontend/src/components/ConnectCTA.tsx +38 -0
  235. package/frontend/src/components/CopyButton.tsx +52 -15
  236. package/frontend/src/components/ErrorState.tsx +1 -2
  237. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  238. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  239. package/frontend/src/components/JsonHighlight.tsx +21 -9
  240. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  241. package/frontend/src/components/PromptDialog.tsx +1 -4
  242. package/frontend/src/components/SearchInput.tsx +1 -2
  243. package/frontend/src/components/Stepper.tsx +53 -0
  244. package/frontend/src/components/ThemeToggle.tsx +3 -3
  245. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  246. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  247. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  248. package/frontend/src/components/datagrid/index.ts +23 -0
  249. package/frontend/src/components/index.ts +23 -30
  250. package/frontend/src/components/layout/AppHeader.tsx +133 -92
  251. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  252. package/frontend/src/components/layout/Layout.tsx +12 -23
  253. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  254. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  255. package/frontend/src/components/layout/index.ts +5 -0
  256. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  257. package/frontend/src/components/radix/index.ts +22 -0
  258. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  259. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  260. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  261. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  262. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  263. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  264. package/frontend/src/features/ai/components/index.ts +6 -0
  265. package/frontend/src/features/ai/helpers.ts +57 -71
  266. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  267. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  268. package/frontend/src/features/ai/page/AIPage.tsx +67 -79
  269. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  270. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  271. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
  272. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  273. package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
  274. package/frontend/src/features/auth/components/index.ts +5 -0
  275. package/frontend/src/features/auth/helpers.tsx +200 -0
  276. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  277. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  278. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  279. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  280. package/frontend/src/features/auth/index.ts +3 -2
  281. package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
  282. package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
  283. package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
  284. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  285. package/frontend/src/features/auth/services/config.service.ts +19 -0
  286. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  287. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  288. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  289. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  290. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  291. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  292. package/frontend/src/features/dashboard/components/index.ts +4 -0
  293. package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
  294. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  295. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  296. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  297. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  298. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  299. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  300. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  301. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  302. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  303. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  304. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  305. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  306. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  307. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  308. package/frontend/src/features/database/components/TableForm.tsx +28 -15
  309. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  310. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  311. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  312. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  313. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  314. package/frontend/src/features/database/components/index.ts +19 -0
  315. package/frontend/src/features/database/constants.ts +28 -2
  316. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  317. package/frontend/src/features/database/helpers.ts +2 -2
  318. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  319. package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
  320. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  321. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  322. package/frontend/src/features/database/hooks/useTables.ts +131 -0
  323. package/frontend/src/features/database/index.ts +6 -1
  324. package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
  325. package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
  326. package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
  327. package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
  328. package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
  329. package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
  330. package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
  331. package/frontend/src/features/database/services/advance.service.ts +66 -0
  332. package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
  333. package/frontend/src/features/database/services/table.service.ts +64 -0
  334. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  335. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  336. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  337. package/frontend/src/features/database/templates/index.ts +34 -0
  338. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  339. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  340. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  341. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  342. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  343. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  344. package/frontend/src/features/functions/components/index.ts +5 -0
  345. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  346. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  347. package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
  348. package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
  349. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  350. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  351. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  352. package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
  353. package/frontend/src/features/login/page/LoginPage.tsx +16 -23
  354. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  355. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  356. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  357. package/frontend/src/features/logs/components/index.ts +2 -0
  358. package/frontend/src/features/logs/helpers.ts +24 -0
  359. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  360. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  361. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  362. package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
  363. package/frontend/src/features/logs/index.ts +8 -2
  364. package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
  365. package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
  366. package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
  367. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  368. package/frontend/src/features/logs/services/log.service.ts +15 -110
  369. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  370. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  371. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  372. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  373. package/frontend/src/features/onboard/components/index.ts +4 -0
  374. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  375. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  376. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  377. package/frontend/src/features/onboard/index.ts +13 -3
  378. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  379. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  380. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  381. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  382. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  383. package/frontend/src/features/storage/components/index.ts +12 -0
  384. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  385. package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
  386. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  387. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  388. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  389. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  390. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  391. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  392. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
  393. package/frontend/src/index.css +1 -0
  394. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  395. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  396. package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
  397. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  398. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  399. package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
  400. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  401. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  402. package/frontend/src/lib/utils/menuItems.ts +183 -0
  403. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  404. package/frontend/src/lib/utils/utils.ts +19 -1
  405. package/frontend/src/vite-env.d.ts +1 -0
  406. package/frontend/vite.config.ts +5 -3
  407. package/functions/server.ts +28 -3
  408. package/functions/worker-template.js +15 -4
  409. package/i18n/README.ar.md +130 -0
  410. package/i18n/README.de.md +130 -0
  411. package/i18n/README.es.md +154 -0
  412. package/i18n/README.fr.md +134 -0
  413. package/i18n/README.hi.md +129 -0
  414. package/i18n/README.ja.md +174 -0
  415. package/i18n/README.ko.md +137 -0
  416. package/i18n/README.pt-BR.md +131 -0
  417. package/i18n/README.ru.md +129 -0
  418. package/i18n/README.zh-CN.md +133 -0
  419. package/openapi/ai.yaml +31 -4
  420. package/openapi/auth.yaml +827 -146
  421. package/package.json +16 -7
  422. package/shared-schemas/package.json +1 -1
  423. package/shared-schemas/src/ai-api.schema.ts +34 -58
  424. package/shared-schemas/src/ai.schema.ts +5 -0
  425. package/shared-schemas/src/auth-api.schema.ts +154 -8
  426. package/shared-schemas/src/auth.schema.ts +42 -6
  427. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  428. package/shared-schemas/src/database-api.schema.ts +3 -3
  429. package/shared-schemas/src/database.schema.ts +1 -1
  430. package/shared-schemas/src/index.ts +1 -0
  431. package/shared-schemas/src/logs-api.schema.ts +7 -1
  432. package/shared-schemas/src/logs.schema.ts +26 -0
  433. package/shared-schemas/src/metadata.schema.ts +9 -4
  434. package/test-gemini.sh +35 -0
  435. package/test-usage-admin.sh +57 -0
  436. package/test-usage.sh +50 -0
  437. package/zeabur/README.md +13 -0
  438. package/zeabur/template.yml +1032 -0
  439. package/.github/workflows/deploy-aws.yml +0 -130
  440. package/backend/src/api/routes/agent.ts +0 -29
  441. package/backend/src/api/routes/auth.oauth.ts +0 -482
  442. package/backend/src/api/routes/auth.ts +0 -386
  443. package/backend/src/api/routes/docs.ts +0 -66
  444. package/backend/src/api/routes/functions.ts +0 -183
  445. package/backend/src/api/routes/openapi.ts +0 -82
  446. package/backend/src/api/routes/usage.ts +0 -96
  447. package/backend/src/core/ai/client.ts +0 -242
  448. package/backend/src/core/ai/model.ts +0 -117
  449. package/backend/src/core/auth/auth.ts +0 -781
  450. package/backend/src/core/database/table.ts +0 -772
  451. package/backend/src/core/documentation/agent.ts +0 -689
  452. package/backend/src/core/documentation/openapi.ts +0 -856
  453. package/backend/src/core/logs/analytics.ts +0 -76
  454. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  455. package/backend/src/core/storage/storage.ts +0 -923
  456. package/backend/src/utils/cloud-token.ts +0 -39
  457. package/backend/src/utils/helpers.ts +0 -49
  458. package/backend/src/utils/uuid.ts +0 -9
  459. package/backend/tests/manual/test-better-auth.sh +0 -303
  460. package/docker-init/db/logs.sql +0 -9
  461. package/frontend/README.md +0 -112
  462. package/frontend/src/components/datagrid/index.tsx +0 -20
  463. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  464. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  465. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  466. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  467. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  468. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  469. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  470. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  471. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  472. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  473. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  474. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  475. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  476. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  477. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  478. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  479. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  480. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  481. package/frontend/src/features/metadata/index.ts +0 -0
  482. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  483. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  484. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  485. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  486. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  487. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  488. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  489. package/frontend/src/features/onboard/types.ts +0 -8
  490. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  491. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  492. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  493. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  494. /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
  495. /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
  496. /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
  497. /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
  498. /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
  499. /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
  500. /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
  501. /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
  502. /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
  503. /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
  504. /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
  505. /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
  506. /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
  507. /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;