insforge 1.2.10 → 1.3.0

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 (335) hide show
  1. package/.claude-plugin/marketplace.json +20 -20
  2. package/.dockerignore +60 -60
  3. package/.env.example +83 -77
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +65 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -63
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +44 -44
  15. package/CLAUDE_PLUGIN.md +104 -104
  16. package/CODE_OF_CONDUCT.md +128 -128
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -30
  19. package/GITHUB_OAUTH_SETUP.md +49 -49
  20. package/GOOGLE_OAUTH_SETUP.md +148 -148
  21. package/LICENSE +201 -201
  22. package/README.md +182 -182
  23. package/assets/Dark.svg +23 -23
  24. package/auth/package.json +28 -28
  25. package/auth/src/lib/broadcastService.ts +117 -115
  26. package/auth/src/pages/SignInPage.tsx +60 -57
  27. package/auth/src/pages/SignUpPage.tsx +60 -57
  28. package/auth/tsconfig.json +32 -32
  29. package/auth/tsconfig.node.json +11 -11
  30. package/backend/package.json +78 -75
  31. package/backend/src/api/routes/ai/index.routes.ts +3 -3
  32. package/backend/src/api/routes/auth/index.routes.ts +667 -570
  33. package/backend/src/api/routes/auth/oauth.routes.ts +473 -448
  34. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  35. package/backend/src/api/routes/database/index.routes.ts +78 -1
  36. package/backend/src/api/routes/database/records.routes.ts +10 -10
  37. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  38. package/backend/src/api/routes/docs/index.routes.ts +75 -76
  39. package/backend/src/api/routes/email/index.routes.ts +35 -0
  40. package/backend/src/api/routes/functions/index.routes.ts +18 -12
  41. package/backend/src/api/routes/metadata/index.routes.ts +12 -0
  42. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  43. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  44. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  45. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  46. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  47. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  48. package/backend/src/infra/database/database.manager.ts +14 -1
  49. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  50. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  51. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  52. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  53. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  54. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  55. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  56. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  57. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  58. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  59. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  60. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  61. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  62. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  63. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  64. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  65. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  66. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  67. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  68. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  69. package/backend/src/infra/security/token.manager.ts +219 -125
  70. package/backend/src/infra/socket/socket.manager.ts +198 -64
  71. package/backend/src/providers/ai/openrouter.provider.ts +12 -9
  72. package/backend/src/providers/email/base.provider.ts +4 -7
  73. package/backend/src/providers/email/cloud.provider.ts +84 -0
  74. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  75. package/backend/src/providers/oauth/index.ts +1 -0
  76. package/backend/src/server.ts +317 -284
  77. package/backend/src/services/ai/ai-model.service.ts +5 -5
  78. package/backend/src/services/ai/chat-completion.service.ts +4 -4
  79. package/backend/src/services/ai/image-generation.service.ts +3 -3
  80. package/backend/src/services/auth/auth.service.ts +14 -0
  81. package/backend/src/services/database/database-table.service.ts +0 -9
  82. package/backend/src/services/database/database.service.ts +127 -0
  83. package/backend/src/services/email/email.service.ts +5 -7
  84. package/backend/src/services/realtime/index.ts +3 -0
  85. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  86. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  87. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  88. package/backend/src/types/auth.ts +11 -0
  89. package/backend/src/types/realtime.ts +18 -0
  90. package/backend/src/types/socket.ts +7 -31
  91. package/backend/src/utils/cookies.ts +35 -0
  92. package/backend/src/utils/s3-config-loader.ts +64 -0
  93. package/backend/src/utils/seed.ts +301 -298
  94. package/backend/src/utils/sql-parser.ts +90 -0
  95. package/backend/tests/README.md +133 -133
  96. package/backend/tests/cleanup-all-test-data.sh +230 -230
  97. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  98. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  99. package/backend/tests/local/test-ai-config.sh +129 -129
  100. package/backend/tests/local/test-ai-usage.sh +80 -80
  101. package/backend/tests/local/test-auth-router.sh +143 -143
  102. package/backend/tests/local/test-database-router.sh +222 -222
  103. package/backend/tests/local/test-e2e.sh +240 -240
  104. package/backend/tests/local/test-fk-errors.sh +96 -96
  105. package/backend/tests/local/test-functions.sh +123 -123
  106. package/backend/tests/local/test-id-field.sh +200 -200
  107. package/backend/tests/local/test-logs.sh +132 -132
  108. package/backend/tests/local/test-public-bucket.sh +264 -264
  109. package/backend/tests/local/test-secrets.sh +249 -249
  110. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  111. package/backend/tests/local/test-traditional-rest.sh +208 -208
  112. package/backend/tests/manual/README.md +50 -50
  113. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  114. package/backend/tests/manual/seed-large-table.sql +100 -100
  115. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  116. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  117. package/backend/tests/manual/test-database-advance.sh +296 -296
  118. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  119. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  120. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  121. package/backend/tests/manual/test-universal-storage.sh +263 -263
  122. package/backend/tests/manual/test-users.sql +17 -17
  123. package/backend/tests/run-all-tests.sh +139 -139
  124. package/backend/tests/setup.ts +0 -0
  125. package/backend/tests/test-config.sh +338 -338
  126. package/backend/tests/unit/analyze-query.test.ts +697 -0
  127. package/backend/tsconfig.json +22 -22
  128. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  129. package/claude-plugin/README.md +133 -133
  130. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -270
  131. package/docker-compose.prod.yml +204 -200
  132. package/docker-compose.yml +232 -228
  133. package/docker-init/db/db-init.sql +97 -97
  134. package/docker-init/db/jwt.sql +5 -5
  135. package/docker-init/db/postgresql.conf +16 -16
  136. package/docker-init/logs/vector.yml +236 -236
  137. package/docs/README.md +44 -44
  138. package/docs/agent-docs/real-time.md +269 -0
  139. package/docs/changelog.mdx +119 -67
  140. package/docs/core-concepts/ai/architecture.mdx +372 -372
  141. package/docs/core-concepts/ai/sdk.mdx +213 -213
  142. package/docs/core-concepts/authentication/architecture.mdx +278 -278
  143. package/docs/core-concepts/authentication/sdk.mdx +414 -414
  144. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -529
  145. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -221
  146. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -184
  147. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -129
  148. package/docs/core-concepts/database/architecture.mdx +255 -255
  149. package/docs/core-concepts/database/sdk.mdx +382 -382
  150. package/docs/core-concepts/email/architecture.mdx +101 -0
  151. package/docs/core-concepts/email/sdk.mdx +53 -0
  152. package/docs/core-concepts/functions/architecture.mdx +105 -105
  153. package/docs/core-concepts/functions/sdk.mdx +184 -184
  154. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  155. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  156. package/docs/core-concepts/storage/architecture.mdx +243 -243
  157. package/docs/core-concepts/storage/sdk.mdx +253 -253
  158. package/docs/deployment/README.md +94 -94
  159. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  160. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  161. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  162. package/docs/deployment/deploy-to-render.md +441 -441
  163. package/docs/deprecated/insforge-auth-api.md +214 -214
  164. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  165. package/docs/deprecated/insforge-db-api.md +358 -358
  166. package/docs/deprecated/insforge-db-sdk.md +139 -139
  167. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  168. package/docs/deprecated/insforge-debug.md +64 -64
  169. package/docs/deprecated/insforge-instructions.md +123 -123
  170. package/docs/deprecated/insforge-project.md +117 -117
  171. package/docs/deprecated/insforge-storage-api.md +278 -278
  172. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  173. package/docs/docs.json +232 -210
  174. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  175. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  176. package/docs/examples/framework-guides/react.mdx +165 -165
  177. package/docs/examples/framework-guides/svelte.mdx +153 -153
  178. package/docs/examples/framework-guides/vue.mdx +159 -159
  179. package/docs/examples/overview.mdx +67 -67
  180. package/docs/favicon.svg +19 -19
  181. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  182. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  183. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  184. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  185. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  186. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  187. package/docs/images/icons/ai.svg +4 -4
  188. package/docs/images/logos/nextjs.svg +4 -4
  189. package/docs/images/logos/nuxt.svg +4 -4
  190. package/docs/images/logos/react.svg +5 -5
  191. package/docs/images/logos/svelte.svg +4 -4
  192. package/docs/images/logos/vue.svg +5 -5
  193. package/docs/insforge-instructions-sdk.md +89 -88
  194. package/docs/introduction.mdx +45 -45
  195. package/docs/logo/dark.svg +22 -22
  196. package/docs/logo/light.svg +20 -20
  197. package/docs/partnership.mdx +651 -646
  198. package/docs/quickstart.mdx +82 -82
  199. package/docs/showcase.mdx +52 -52
  200. package/docs/snippets/sdk-installation.mdx +21 -21
  201. package/docs/snippets/service-icons.mdx +27 -27
  202. package/examples/oauth/frontend-oauth-example.html +250 -250
  203. package/examples/response-examples.md +443 -443
  204. package/frontend/components.json +17 -17
  205. package/frontend/package.json +69 -69
  206. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  207. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  208. package/frontend/src/assets/icons/checked.svg +3 -3
  209. package/frontend/src/assets/icons/connected.svg +3 -3
  210. package/frontend/src/assets/icons/error.svg +3 -3
  211. package/frontend/src/assets/icons/loader.svg +9 -9
  212. package/frontend/src/assets/icons/pencil.svg +4 -4
  213. package/frontend/src/assets/icons/refresh.svg +4 -4
  214. package/frontend/src/assets/icons/step_active.svg +3 -3
  215. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  216. package/frontend/src/assets/icons/warning.svg +3 -3
  217. package/frontend/src/assets/logos/apple.svg +3 -3
  218. package/frontend/src/assets/logos/claude_code.svg +3 -3
  219. package/frontend/src/assets/logos/cline.svg +6 -6
  220. package/frontend/src/assets/logos/cursor.svg +20 -20
  221. package/frontend/src/assets/logos/discord.svg +8 -8
  222. package/frontend/src/assets/logos/facebook.svg +3 -3
  223. package/frontend/src/assets/logos/gemini.svg +19 -19
  224. package/frontend/src/assets/logos/github.svg +5 -5
  225. package/frontend/src/assets/logos/google.svg +13 -13
  226. package/frontend/src/assets/logos/grok.svg +10 -10
  227. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  228. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  229. package/frontend/src/assets/logos/instagram.svg +1 -1
  230. package/frontend/src/assets/logos/linkedin.svg +3 -3
  231. package/frontend/src/assets/logos/openai.svg +10 -10
  232. package/frontend/src/assets/logos/roo_code.svg +9 -9
  233. package/frontend/src/assets/logos/spotify.svg +16 -16
  234. package/frontend/src/assets/logos/tiktok.svg +5 -5
  235. package/frontend/src/assets/logos/trae.svg +3 -3
  236. package/frontend/src/assets/logos/windsurf.svg +10 -10
  237. package/frontend/src/assets/logos/x.svg +3 -3
  238. package/frontend/src/components/layout/AppHeader.tsx +9 -10
  239. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  240. package/frontend/src/features/auth/components/UsersDataGrid.tsx +6 -0
  241. package/frontend/src/features/auth/helpers.tsx +8 -0
  242. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  243. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  244. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  245. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  246. package/frontend/src/features/database/hooks/useTables.ts +32 -28
  247. package/frontend/src/features/database/index.ts +1 -0
  248. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -37
  249. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +35 -47
  250. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +43 -54
  251. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  252. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +35 -47
  253. package/frontend/src/features/database/services/advance.service.ts +0 -26
  254. package/frontend/src/features/database/services/database.service.ts +55 -0
  255. package/frontend/src/features/database/services/table.service.ts +0 -6
  256. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  257. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +11 -9
  258. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  259. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  260. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  261. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  262. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  263. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  264. package/frontend/src/features/realtime/index.ts +11 -0
  265. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  266. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  267. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  268. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  269. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  270. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +3 -3
  271. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +1 -35
  272. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  273. package/frontend/src/lib/routing/AppRoutes.tsx +35 -20
  274. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  275. package/frontend/src/lib/utils/menuItems.ts +24 -0
  276. package/frontend/src/lib/utils/utils.ts +14 -1
  277. package/frontend/tsconfig.json +25 -25
  278. package/frontend/tsconfig.node.json +9 -9
  279. package/functions/deno.json +24 -24
  280. package/functions/server.ts +315 -315
  281. package/i18n/README.ar.md +130 -130
  282. package/i18n/README.de.md +130 -130
  283. package/i18n/README.es.md +154 -154
  284. package/i18n/README.fr.md +134 -134
  285. package/i18n/README.hi.md +129 -129
  286. package/i18n/README.ja.md +174 -174
  287. package/i18n/README.ko.md +136 -136
  288. package/i18n/README.pt-BR.md +131 -131
  289. package/i18n/README.ru.md +129 -129
  290. package/i18n/README.zh-CN.md +133 -133
  291. package/openapi/ai.yaml +715 -715
  292. package/openapi/auth.yaml +1244 -1244
  293. package/openapi/email.yaml +158 -0
  294. package/openapi/functions.yaml +475 -475
  295. package/openapi/health.yaml +29 -29
  296. package/openapi/logs.yaml +223 -223
  297. package/openapi/metadata.yaml +177 -177
  298. package/openapi/realtime.yaml +699 -0
  299. package/openapi/records.yaml +381 -381
  300. package/openapi/secrets.yaml +370 -370
  301. package/openapi/storage.yaml +875 -875
  302. package/openapi/tables.yaml +463 -463
  303. package/package.json +97 -97
  304. package/shared-schemas/package.json +31 -31
  305. package/shared-schemas/src/ai.schema.ts +63 -59
  306. package/shared-schemas/src/auth-api.schema.ts +352 -339
  307. package/shared-schemas/src/auth.schema.ts +1 -1
  308. package/shared-schemas/src/database-api.schema.ts +32 -1
  309. package/shared-schemas/src/database.schema.ts +39 -0
  310. package/shared-schemas/src/docs.schema.ts +26 -0
  311. package/shared-schemas/src/email-api.schema.ts +30 -0
  312. package/shared-schemas/src/index.ts +4 -0
  313. package/shared-schemas/src/metadata.schema.ts +9 -0
  314. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  315. package/shared-schemas/src/realtime.schema.ts +143 -0
  316. package/shared-schemas/tsconfig.json +21 -21
  317. package/tsconfig.json +7 -7
  318. package/zeabur/README.md +13 -13
  319. package/zeabur/template.yml +1032 -1032
  320. package/.cursor/rules/cursor-rules.mdc +0 -94
  321. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  322. package/test-gemini.sh +0 -35
  323. package/test-usage-admin.sh +0 -57
  324. package/test-usage.sh +0 -50
  325. /package/frontend/src/features/ai/{page → pages}/AIPage.tsx +0 -0
  326. /package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +0 -0
  327. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  328. /package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +0 -0
  329. /package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +0 -0
  330. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  331. /package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +0 -0
  332. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  333. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  334. /package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +0 -0
  335. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -0,0 +1,19 @@
1
+ import { Router, Response, NextFunction } from 'express';
2
+ import { verifyAdmin, AuthRequest } from '@/api/middlewares/auth.js';
3
+ import { RealtimeChannelService } from '@/services/realtime/realtime-channel.service.js';
4
+ import { successResponse } from '@/utils/response.js';
5
+
6
+ const router = Router();
7
+ const channelService = RealtimeChannelService.getInstance();
8
+
9
+ // Get realtime RLS permissions (subscribe on channels, publish on messages)
10
+ router.get('/', verifyAdmin, async (_req: AuthRequest, res: Response, next: NextFunction) => {
11
+ try {
12
+ const permissions = await channelService.getPermissions();
13
+ successResponse(res, permissions);
14
+ } catch (error) {
15
+ next(error);
16
+ }
17
+ });
18
+
19
+ export { router as permissionsRouter };
@@ -79,9 +79,12 @@ router.post(
79
79
  });
80
80
 
81
81
  const socket = SocketManager.getInstance();
82
- socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
83
- resource: DataUpdateResourceType.BUCKETS,
84
- });
82
+ socket.broadcastToRoom(
83
+ 'role:project_admin',
84
+ ServerEvents.DATA_UPDATE,
85
+ { resource: DataUpdateResourceType.BUCKETS },
86
+ 'system'
87
+ );
85
88
 
86
89
  const accessInfo = isPublic
87
90
  ? 'This is a PUBLIC bucket - objects can be accessed without authentication.'
@@ -150,12 +153,12 @@ router.patch(
150
153
  });
151
154
 
152
155
  const socket = SocketManager.getInstance();
153
- socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
154
- resource: DataUpdateResourceType.BUCKETS,
155
- data: {
156
- bucketName,
157
- },
158
- });
156
+ socket.broadcastToRoom(
157
+ 'role:project_admin',
158
+ ServerEvents.DATA_UPDATE,
159
+ { resource: DataUpdateResourceType.BUCKETS, data: { bucketName } },
160
+ 'system'
161
+ );
159
162
 
160
163
  const accessInfo = isPublic
161
164
  ? 'Bucket is now PUBLIC - objects can be accessed without authentication.'
@@ -379,9 +382,12 @@ router.delete(
379
382
  });
380
383
 
381
384
  const socket = SocketManager.getInstance();
382
- socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
383
- resource: DataUpdateResourceType.BUCKETS,
384
- });
385
+ socket.broadcastToRoom(
386
+ 'role:project_admin',
387
+ ServerEvents.DATA_UPDATE,
388
+ { resource: DataUpdateResourceType.BUCKETS },
389
+ 'system'
390
+ );
385
391
 
386
392
  successResponse(
387
393
  res,
@@ -33,10 +33,12 @@ usageRouter.post(
33
33
  // Broadcast MCP tool usage to frontend via socket
34
34
  const socketService = SocketManager.getInstance();
35
35
 
36
- socketService.broadcastToRoom('role:project_admin', ServerEvents.MCP_CONNECTED, {
37
- tool_name,
38
- created_at: result.created_at,
39
- });
36
+ socketService.broadcastToRoom(
37
+ 'role:project_admin',
38
+ ServerEvents.MCP_CONNECTED,
39
+ { tool_name, created_at: result.created_at },
40
+ 'system'
41
+ );
40
42
 
41
43
  successResponse(res, { success: true });
42
44
  } catch (error) {
@@ -1,4 +1,4 @@
1
- import { Pool } from 'pg';
1
+ import { Pool, Client } from 'pg';
2
2
  import path from 'path';
3
3
  import fs from 'fs/promises';
4
4
  import { fileURLToPath } from 'url';
@@ -163,6 +163,19 @@ export class DatabaseManager {
163
163
  return this.pool;
164
164
  }
165
165
 
166
+ /**
167
+ * Create a dedicated client for operations that can't use pooled connections (e.g., LISTEN/NOTIFY)
168
+ */
169
+ createClient(): Client {
170
+ return new Client({
171
+ host: process.env.POSTGRES_HOST || 'localhost',
172
+ port: parseInt(process.env.POSTGRES_PORT || '5432'),
173
+ database: process.env.POSTGRES_DB || 'insforge',
174
+ user: process.env.POSTGRES_USER || 'postgres',
175
+ password: process.env.POSTGRES_PASSWORD || 'postgres',
176
+ });
177
+ }
178
+
166
179
  async close(): Promise<void> {
167
180
  await this.pool.end();
168
181
  }
@@ -1,142 +1,142 @@
1
- -- Migration: 000 - Create base system tables
2
- -- This migration creates all the initial tables that the application needs
3
-
4
- -- System configuration
5
- CREATE TABLE IF NOT EXISTS _config (
6
- key TEXT PRIMARY KEY,
7
- value TEXT NOT NULL,
8
- created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
9
- updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
10
- );
11
-
12
- -- App metadata
13
- CREATE TABLE IF NOT EXISTS _metadata (
14
- key TEXT PRIMARY KEY,
15
- value TEXT,
16
- created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
17
- updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
18
- );
19
-
20
- -- Storage buckets table to track bucket-level settings
21
- CREATE TABLE IF NOT EXISTS _storage_buckets (
22
- name TEXT PRIMARY KEY,
23
- public BOOLEAN DEFAULT TRUE,
24
- created_at TIMESTAMPTZ DEFAULT NOW(),
25
- updated_at TIMESTAMPTZ DEFAULT NOW()
26
- );
27
-
28
- -- Storage files table
29
- CREATE TABLE IF NOT EXISTS _storage (
30
- bucket TEXT NOT NULL,
31
- key TEXT NOT NULL,
32
- size INTEGER NOT NULL,
33
- mime_type TEXT,
34
- uploaded_at TIMESTAMPTZ DEFAULT NOW(),
35
- PRIMARY KEY (bucket, key),
36
- FOREIGN KEY (bucket) REFERENCES _storage_buckets(name) ON DELETE CASCADE
37
- );
38
-
39
- -- MCP usage tracking table
40
- CREATE TABLE IF NOT EXISTS _mcp_usage (
41
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
42
- tool_name VARCHAR(255) NOT NULL,
43
- success BOOLEAN DEFAULT true,
44
- created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
45
- );
46
-
47
- -- AI configurations table
48
- CREATE TABLE IF NOT EXISTS _ai_configs (
49
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
50
- modality VARCHAR(255) NOT NULL,
51
- provider VARCHAR(255) NOT NULL,
52
- model_id VARCHAR(255) UNIQUE NOT NULL,
53
- system_prompt TEXT,
54
- created_at TIMESTAMPTZ DEFAULT NOW(),
55
- updated_at TIMESTAMPTZ DEFAULT NOW()
56
- );
57
-
58
- CREATE TABLE IF NOT EXISTS _ai_usage (
59
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
60
- config_id UUID NOT NULL,
61
- input_tokens INT,
62
- output_tokens INT,
63
- image_count INT,
64
- image_resolution TEXT,
65
- created_at TIMESTAMPTZ DEFAULT NOW(),
66
- FOREIGN KEY (config_id) REFERENCES _ai_configs(id) ON DELETE NO ACTION
67
- );
68
-
69
- -- Indexes for AI tables
70
- CREATE INDEX IF NOT EXISTS idx_ai_usage_config_id ON _ai_usage(config_id);
71
- CREATE INDEX IF NOT EXISTS idx_ai_usage_created_at ON _ai_usage(created_at DESC);
72
-
73
- -- Index for efficient date range queries
74
- CREATE INDEX IF NOT EXISTS idx_mcp_usage_created_at ON _mcp_usage(created_at DESC);
75
-
76
- -- Edge functions
77
- CREATE TABLE IF NOT EXISTS _edge_functions (
78
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
79
- slug VARCHAR(255) UNIQUE NOT NULL,
80
- name VARCHAR(255) NOT NULL,
81
- description TEXT,
82
- code TEXT NOT NULL,
83
- status VARCHAR(50) DEFAULT 'draft',
84
- created_at TIMESTAMPTZ DEFAULT NOW(),
85
- updated_at TIMESTAMPTZ DEFAULT NOW(),
86
- deployed_at TIMESTAMPTZ
87
- );
88
-
89
- -- Auth Tables (2-table structure)
90
- -- User table
91
- CREATE TABLE IF NOT EXISTS _user (
92
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
93
- email TEXT UNIQUE NOT NULL,
94
- password TEXT, -- NULL for OAuth-only users
95
- name TEXT,
96
- email_verified BOOLEAN DEFAULT false,
97
- created_at TIMESTAMPTZ DEFAULT NOW(),
98
- updated_at TIMESTAMPTZ DEFAULT NOW()
99
- );
100
-
101
- -- Account table (for OAuth connections)
102
- CREATE TABLE IF NOT EXISTS _account (
103
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
104
- user_id UUID NOT NULL REFERENCES _user(id) ON DELETE CASCADE,
105
- provider TEXT NOT NULL, -- OAuth provider name: 'google', 'github', etc.
106
- provider_account_id TEXT NOT NULL, -- User's unique ID on the provider's system
107
- access_token TEXT, -- OAuth access token for making API calls to provider
108
- refresh_token TEXT, -- OAuth refresh token for renewing access
109
- provider_data JSONB, -- OAuth provider's user profile
110
- created_at TIMESTAMPTZ DEFAULT NOW(),
111
- updated_at TIMESTAMPTZ DEFAULT NOW(),
112
- UNIQUE(provider, provider_account_id)
113
- );
114
-
115
- -- Create update timestamp function
116
- CREATE OR REPLACE FUNCTION update_updated_at_column()
117
- RETURNS TRIGGER AS $$
118
- BEGIN
119
- NEW.updated_at = NOW();
120
- RETURN NEW;
121
- END;
122
- $$ language 'plpgsql';
123
-
124
- -- Create triggers for updated_at
125
- DROP TRIGGER IF EXISTS update__config_updated_at ON _config;
126
- CREATE TRIGGER update__config_updated_at BEFORE UPDATE ON _config
127
- FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
128
-
129
- DROP TRIGGER IF EXISTS update__metadata_updated_at ON _metadata;
130
- CREATE TRIGGER update__metadata_updated_at BEFORE UPDATE ON _metadata
131
- FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
132
-
133
- DROP TRIGGER IF EXISTS update__edge_functions_updated_at ON _edge_functions;
134
- CREATE TRIGGER update__edge_functions_updated_at BEFORE UPDATE ON _edge_functions
135
- FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
136
-
137
- -- Insert initial metadata
138
- INSERT INTO _metadata (key, value) VALUES ('version', '1.0.0')
139
- ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
140
-
141
- INSERT INTO _metadata (key, value) VALUES ('created_at', NOW()::TEXT)
1
+ -- Migration: 000 - Create base system tables
2
+ -- This migration creates all the initial tables that the application needs
3
+
4
+ -- System configuration
5
+ CREATE TABLE IF NOT EXISTS _config (
6
+ key TEXT PRIMARY KEY,
7
+ value TEXT NOT NULL,
8
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
9
+ updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
10
+ );
11
+
12
+ -- App metadata
13
+ CREATE TABLE IF NOT EXISTS _metadata (
14
+ key TEXT PRIMARY KEY,
15
+ value TEXT,
16
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
17
+ updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
18
+ );
19
+
20
+ -- Storage buckets table to track bucket-level settings
21
+ CREATE TABLE IF NOT EXISTS _storage_buckets (
22
+ name TEXT PRIMARY KEY,
23
+ public BOOLEAN DEFAULT TRUE,
24
+ created_at TIMESTAMPTZ DEFAULT NOW(),
25
+ updated_at TIMESTAMPTZ DEFAULT NOW()
26
+ );
27
+
28
+ -- Storage files table
29
+ CREATE TABLE IF NOT EXISTS _storage (
30
+ bucket TEXT NOT NULL,
31
+ key TEXT NOT NULL,
32
+ size INTEGER NOT NULL,
33
+ mime_type TEXT,
34
+ uploaded_at TIMESTAMPTZ DEFAULT NOW(),
35
+ PRIMARY KEY (bucket, key),
36
+ FOREIGN KEY (bucket) REFERENCES _storage_buckets(name) ON DELETE CASCADE
37
+ );
38
+
39
+ -- MCP usage tracking table
40
+ CREATE TABLE IF NOT EXISTS _mcp_usage (
41
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
42
+ tool_name VARCHAR(255) NOT NULL,
43
+ success BOOLEAN DEFAULT true,
44
+ created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
45
+ );
46
+
47
+ -- AI configurations table
48
+ CREATE TABLE IF NOT EXISTS _ai_configs (
49
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
50
+ modality VARCHAR(255) NOT NULL,
51
+ provider VARCHAR(255) NOT NULL,
52
+ model_id VARCHAR(255) UNIQUE NOT NULL,
53
+ system_prompt TEXT,
54
+ created_at TIMESTAMPTZ DEFAULT NOW(),
55
+ updated_at TIMESTAMPTZ DEFAULT NOW()
56
+ );
57
+
58
+ CREATE TABLE IF NOT EXISTS _ai_usage (
59
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
60
+ config_id UUID NOT NULL,
61
+ input_tokens INT,
62
+ output_tokens INT,
63
+ image_count INT,
64
+ image_resolution TEXT,
65
+ created_at TIMESTAMPTZ DEFAULT NOW(),
66
+ FOREIGN KEY (config_id) REFERENCES _ai_configs(id) ON DELETE NO ACTION
67
+ );
68
+
69
+ -- Indexes for AI tables
70
+ CREATE INDEX IF NOT EXISTS idx_ai_usage_config_id ON _ai_usage(config_id);
71
+ CREATE INDEX IF NOT EXISTS idx_ai_usage_created_at ON _ai_usage(created_at DESC);
72
+
73
+ -- Index for efficient date range queries
74
+ CREATE INDEX IF NOT EXISTS idx_mcp_usage_created_at ON _mcp_usage(created_at DESC);
75
+
76
+ -- Edge functions
77
+ CREATE TABLE IF NOT EXISTS _edge_functions (
78
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
79
+ slug VARCHAR(255) UNIQUE NOT NULL,
80
+ name VARCHAR(255) NOT NULL,
81
+ description TEXT,
82
+ code TEXT NOT NULL,
83
+ status VARCHAR(50) DEFAULT 'draft',
84
+ created_at TIMESTAMPTZ DEFAULT NOW(),
85
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
86
+ deployed_at TIMESTAMPTZ
87
+ );
88
+
89
+ -- Auth Tables (2-table structure)
90
+ -- User table
91
+ CREATE TABLE IF NOT EXISTS _user (
92
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
93
+ email TEXT UNIQUE NOT NULL,
94
+ password TEXT, -- NULL for OAuth-only users
95
+ name TEXT,
96
+ email_verified BOOLEAN DEFAULT false,
97
+ created_at TIMESTAMPTZ DEFAULT NOW(),
98
+ updated_at TIMESTAMPTZ DEFAULT NOW()
99
+ );
100
+
101
+ -- Account table (for OAuth connections)
102
+ CREATE TABLE IF NOT EXISTS _account (
103
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
104
+ user_id UUID NOT NULL REFERENCES _user(id) ON DELETE CASCADE,
105
+ provider TEXT NOT NULL, -- OAuth provider name: 'google', 'github', etc.
106
+ provider_account_id TEXT NOT NULL, -- User's unique ID on the provider's system
107
+ access_token TEXT, -- OAuth access token for making API calls to provider
108
+ refresh_token TEXT, -- OAuth refresh token for renewing access
109
+ provider_data JSONB, -- OAuth provider's user profile
110
+ created_at TIMESTAMPTZ DEFAULT NOW(),
111
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
112
+ UNIQUE(provider, provider_account_id)
113
+ );
114
+
115
+ -- Create update timestamp function
116
+ CREATE OR REPLACE FUNCTION update_updated_at_column()
117
+ RETURNS TRIGGER AS $$
118
+ BEGIN
119
+ NEW.updated_at = NOW();
120
+ RETURN NEW;
121
+ END;
122
+ $$ language 'plpgsql';
123
+
124
+ -- Create triggers for updated_at
125
+ DROP TRIGGER IF EXISTS update__config_updated_at ON _config;
126
+ CREATE TRIGGER update__config_updated_at BEFORE UPDATE ON _config
127
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
128
+
129
+ DROP TRIGGER IF EXISTS update__metadata_updated_at ON _metadata;
130
+ CREATE TRIGGER update__metadata_updated_at BEFORE UPDATE ON _metadata
131
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
132
+
133
+ DROP TRIGGER IF EXISTS update__edge_functions_updated_at ON _edge_functions;
134
+ CREATE TRIGGER update__edge_functions_updated_at BEFORE UPDATE ON _edge_functions
135
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
136
+
137
+ -- Insert initial metadata
138
+ INSERT INTO _metadata (key, value) VALUES ('version', '1.0.0')
139
+ ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
140
+
141
+ INSERT INTO _metadata (key, value) VALUES ('created_at', NOW()::TEXT)
142
142
  ON CONFLICT (key) DO NOTHING;
@@ -1,41 +1,41 @@
1
- -- Migration: 001 - Create helper functions for RLS
2
- -- These functions extract user information from JWT claims
3
-
4
- -- Function to get current user ID from JWT
5
- CREATE OR REPLACE FUNCTION public.uid()
6
- RETURNS uuid
7
- LANGUAGE sql STABLE
8
- AS $$
9
- SELECT
10
- nullif(
11
- coalesce(
12
- current_setting('request.jwt.claim.sub', true),
13
- (current_setting('request.jwt.claims', true)::jsonb ->> 'sub')
14
- ),
15
- ''
16
- )::uuid
17
- $$;
18
-
19
- -- Function to get current user role from JWT
20
- CREATE OR REPLACE FUNCTION public.role()
21
- RETURNS text
22
- LANGUAGE sql STABLE
23
- AS $$
24
- SELECT
25
- coalesce(
26
- current_setting('request.jwt.claim.role', true),
27
- (current_setting('request.jwt.claims', true)::jsonb ->> 'role')
28
- )::text
29
- $$;
30
-
31
- -- Function to get current user email from JWT
32
- CREATE OR REPLACE FUNCTION public.email()
33
- RETURNS text
34
- LANGUAGE sql STABLE
35
- AS $$
36
- SELECT
37
- coalesce(
38
- current_setting('request.jwt.claim.email', true),
39
- (current_setting('request.jwt.claims', true)::jsonb ->> 'email')
40
- )::text
1
+ -- Migration: 001 - Create helper functions for RLS
2
+ -- These functions extract user information from JWT claims
3
+
4
+ -- Function to get current user ID from JWT
5
+ CREATE OR REPLACE FUNCTION public.uid()
6
+ RETURNS uuid
7
+ LANGUAGE sql STABLE
8
+ AS $$
9
+ SELECT
10
+ nullif(
11
+ coalesce(
12
+ current_setting('request.jwt.claim.sub', true),
13
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'sub')
14
+ ),
15
+ ''
16
+ )::uuid
17
+ $$;
18
+
19
+ -- Function to get current user role from JWT
20
+ CREATE OR REPLACE FUNCTION public.role()
21
+ RETURNS text
22
+ LANGUAGE sql STABLE
23
+ AS $$
24
+ SELECT
25
+ coalesce(
26
+ current_setting('request.jwt.claim.role', true),
27
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'role')
28
+ )::text
29
+ $$;
30
+
31
+ -- Function to get current user email from JWT
32
+ CREATE OR REPLACE FUNCTION public.email()
33
+ RETURNS text
34
+ LANGUAGE sql STABLE
35
+ AS $$
36
+ SELECT
37
+ coalesce(
38
+ current_setting('request.jwt.claim.email', true),
39
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'email')
40
+ )::text
41
41
  $$;
@@ -1,30 +1,30 @@
1
- -- Migration: 002 - Rename authentication tables to better auth naming convention
2
-
3
- DO $$
4
- BEGIN
5
- -- Handle _account to _oauth_connections
6
- IF EXISTS (SELECT FROM information_schema.tables
7
- WHERE table_name = '_account' AND table_schema = 'public') THEN
8
- IF EXISTS (SELECT FROM information_schema.tables
9
- WHERE table_name = '_oauth_connections' AND table_schema = 'public') THEN
10
- -- Both exist, drop the old one
11
- DROP TABLE _account CASCADE;
12
- ELSE
13
- -- Only old exists, rename it
14
- ALTER TABLE _account RENAME TO _oauth_connections;
15
- END IF;
16
- END IF;
17
-
18
- -- Handle _user to _accounts
19
- IF EXISTS (SELECT FROM information_schema.tables
20
- WHERE table_name = '_user' AND table_schema = 'public') THEN
21
- IF EXISTS (SELECT FROM information_schema.tables
22
- WHERE table_name = '_accounts' AND table_schema = 'public') THEN
23
- -- Both exist, drop the old one
24
- DROP TABLE _user CASCADE;
25
- ELSE
26
- -- Only old exists, rename it
27
- ALTER TABLE _user RENAME TO _accounts;
28
- END IF;
29
- END IF;
1
+ -- Migration: 002 - Rename authentication tables to better auth naming convention
2
+
3
+ DO $$
4
+ BEGIN
5
+ -- Handle _account to _oauth_connections
6
+ IF EXISTS (SELECT FROM information_schema.tables
7
+ WHERE table_name = '_account' AND table_schema = 'public') THEN
8
+ IF EXISTS (SELECT FROM information_schema.tables
9
+ WHERE table_name = '_oauth_connections' AND table_schema = 'public') THEN
10
+ -- Both exist, drop the old one
11
+ DROP TABLE _account CASCADE;
12
+ ELSE
13
+ -- Only old exists, rename it
14
+ ALTER TABLE _account RENAME TO _oauth_connections;
15
+ END IF;
16
+ END IF;
17
+
18
+ -- Handle _user to _accounts
19
+ IF EXISTS (SELECT FROM information_schema.tables
20
+ WHERE table_name = '_user' AND table_schema = 'public') THEN
21
+ IF EXISTS (SELECT FROM information_schema.tables
22
+ WHERE table_name = '_accounts' AND table_schema = 'public') THEN
23
+ -- Both exist, drop the old one
24
+ DROP TABLE _user CASCADE;
25
+ ELSE
26
+ -- Only old exists, rename it
27
+ ALTER TABLE _user RENAME TO _accounts;
28
+ END IF;
29
+ END IF;
30
30
  END $$;
@@ -1,56 +1,56 @@
1
- -- Migration: 003 - Create users table for user profiles
2
-
3
- DO $$
4
- BEGIN
5
- CREATE TABLE IF NOT EXISTS users (
6
- id UUID PRIMARY KEY REFERENCES _accounts(id) ON DELETE CASCADE,
7
- nickname TEXT,
8
- avatar_url TEXT,
9
- bio TEXT,
10
- birthday DATE,
11
- created_at TIMESTAMPTZ DEFAULT NOW(),
12
- updated_at TIMESTAMPTZ DEFAULT NOW()
13
- );
14
-
15
- -- Check and create policies only if they don't exist
16
- -- Allow everyone to read users table
17
- IF NOT EXISTS (
18
- SELECT 1 FROM pg_policies
19
- WHERE tablename = 'users'
20
- AND policyname = 'Enable read access for all users'
21
- ) THEN
22
- CREATE POLICY "Enable read access for all users" ON users
23
- FOR SELECT
24
- USING (true); -- Allow all reads
25
- END IF;
26
-
27
- IF NOT EXISTS (
28
- SELECT 1 FROM pg_policies
29
- WHERE tablename = 'users'
30
- AND policyname = 'Disable delete for users'
31
- ) THEN
32
- CREATE POLICY "Disable delete for users" ON users
33
- FOR DELETE
34
- TO authenticated
35
- USING (false);
36
- END IF;
37
-
38
- IF NOT EXISTS (
39
- SELECT 1 FROM pg_policies
40
- WHERE tablename = 'users'
41
- AND policyname = 'Enable update for users based on user_id'
42
- ) THEN
43
- CREATE POLICY "Enable update for users based on user_id" ON users
44
- FOR UPDATE
45
- TO authenticated
46
- USING (uid() = id)
47
- WITH CHECK (uid() = id); -- make sure only the owner can update
48
- END IF;
49
-
50
- -- Enable Row Level Security on the users table
51
- ALTER TABLE users ENABLE ROW LEVEL SECURITY;
52
-
53
- -- Grant permissions to anon and authenticated roles
54
- GRANT SELECT ON users TO anon;
55
- GRANT SELECT, UPDATE ON users TO authenticated;
1
+ -- Migration: 003 - Create users table for user profiles
2
+
3
+ DO $$
4
+ BEGIN
5
+ CREATE TABLE IF NOT EXISTS users (
6
+ id UUID PRIMARY KEY REFERENCES _accounts(id) ON DELETE CASCADE,
7
+ nickname TEXT,
8
+ avatar_url TEXT,
9
+ bio TEXT,
10
+ birthday DATE,
11
+ created_at TIMESTAMPTZ DEFAULT NOW(),
12
+ updated_at TIMESTAMPTZ DEFAULT NOW()
13
+ );
14
+
15
+ -- Check and create policies only if they don't exist
16
+ -- Allow everyone to read users table
17
+ IF NOT EXISTS (
18
+ SELECT 1 FROM pg_policies
19
+ WHERE tablename = 'users'
20
+ AND policyname = 'Enable read access for all users'
21
+ ) THEN
22
+ CREATE POLICY "Enable read access for all users" ON users
23
+ FOR SELECT
24
+ USING (true); -- Allow all reads
25
+ END IF;
26
+
27
+ IF NOT EXISTS (
28
+ SELECT 1 FROM pg_policies
29
+ WHERE tablename = 'users'
30
+ AND policyname = 'Disable delete for users'
31
+ ) THEN
32
+ CREATE POLICY "Disable delete for users" ON users
33
+ FOR DELETE
34
+ TO authenticated
35
+ USING (false);
36
+ END IF;
37
+
38
+ IF NOT EXISTS (
39
+ SELECT 1 FROM pg_policies
40
+ WHERE tablename = 'users'
41
+ AND policyname = 'Enable update for users based on user_id'
42
+ ) THEN
43
+ CREATE POLICY "Enable update for users based on user_id" ON users
44
+ FOR UPDATE
45
+ TO authenticated
46
+ USING (uid() = id)
47
+ WITH CHECK (uid() = id); -- make sure only the owner can update
48
+ END IF;
49
+
50
+ -- Enable Row Level Security on the users table
51
+ ALTER TABLE users ENABLE ROW LEVEL SECURITY;
52
+
53
+ -- Grant permissions to anon and authenticated roles
54
+ GRANT SELECT ON users TO anon;
55
+ GRANT SELECT, UPDATE ON users TO authenticated;
56
56
  END $$;