• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / storage / 30825450288

03 Aug 2026 03:00PM UTC coverage: 60.991% (-19.4%) from 80.366%
30825450288

Pull #1293

github

web-flow
Merge 838eef931 into 1e33d8708
Pull Request #1293: fix: hardening for non-json object reply

3709 of 6900 branches covered (53.75%)

Branch coverage included in aggregate %.

22 of 32 new or added lines in 5 files covered. (68.75%)

2204 existing lines in 109 files now uncovered.

7686 of 11783 relevant lines covered (65.23%)

384.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.57
/src/http/plugins/db.ts
1
import { createSingleFlightByKey } from '@internal/concurrency'
2
import {
3
  getPostgresConnection,
4
  getServiceKeyUser,
5
  getTenantConfig,
6
  type TenantConnection,
7
  TenantMigrationStatus,
8
} from '@internal/database'
9
import {
10
  areMigrationsUpToDate,
11
  DBMigration,
12
  lastLocalMigrationName,
13
  progressiveMigrations,
14
  runMigrationsOnTenant,
15
  updateTenantMigrationsState,
16
} from '@internal/database/migrations'
17
import { ERRORS } from '@internal/errors'
18
import type { FastifyInstance } from 'fastify'
19
import fastifyPlugin from 'fastify-plugin'
20
import { getConfig, MultitenantMigrationStrategy } from '../../config'
21

22
declare module 'fastify' {
23
  interface FastifyRequest {
24
    db: TenantConnection
25
    latestMigration?: keyof typeof DBMigration
26
  }
27
}
28

29
const { databaseEnableQueryCancellation, dbMigrationStrategy, isMultitenant, dbMigrationFreezeAt } =
30
  getConfig()
29✔
31

32
const migrationSingleFlight = createSingleFlightByKey<keyof typeof DBMigration>()
29✔
33

34
function resolveLatestMigration(
35
  localLatest: keyof typeof DBMigration,
36
  applied: keyof typeof DBMigration | undefined
37
): keyof typeof DBMigration {
38
  if (
8!
39
    applied &&
12✔
40
    DBMigration[applied] !== undefined &&
41
    DBMigration[applied] > DBMigration[localLatest]
42
  ) {
UNCOV
43
    return applied
×
44
  }
45
  return localLatest
8✔
46
}
47

48
export const db = fastifyPlugin(
29✔
49
  async function db(fastify) {
50
    fastify.register(migrations)
4,704✔
51

52
    fastify.decorateRequest('db')
4,704✔
53

54
    fastify.addHook('preHandler', async (request) => {
4,704✔
55
      const adminUser = await getServiceKeyUser(request.tenantId)
1,094✔
56
      const userPayload = request.jwtPayload
1,094✔
57

58
      if (!userPayload) {
1,094!
59
        throw ERRORS.AccessDenied('JWT payload is missing')
×
60
      }
61

62
      request.db = await getPostgresConnection({
1,094✔
63
        user: {
64
          payload: userPayload,
65
          jwt: request.jwt,
66
        },
67
        superUser: adminUser,
68
        tenantId: request.tenantId,
69
        host: request.headers['x-forwarded-host'] as string,
70
        headers: request.headers,
71
        path: request.url,
72
        method: request.method,
73
        operation: () => request.operation,
2,413✔
74
      })
75

76
      // Connect abort signal to DB connection for query cancellation
77
      if (databaseEnableQueryCancellation && request.signals) {
1,092!
UNCOV
78
        request.db.setAbortSignal(request.signals.disconnect.signal)
×
79
      }
80
    })
81

82
    registerConnectionCleanupHooks(fastify)
4,704✔
83
  },
84
  { name: 'db-init' }
85
)
86

87
interface DbSuperUserPluginOptions {
88
  disableHostCheck?: boolean
89
}
90

91
export const dbSuperUser = fastifyPlugin<DbSuperUserPluginOptions>(
29✔
92
  async function dbSuperUser(fastify, opts) {
93
    fastify.register(migrations)
1,787✔
94
    fastify.decorateRequest('db')
1,787✔
95

96
    fastify.addHook('preHandler', async (request) => {
1,787✔
97
      const adminUser = await getServiceKeyUser(request.tenantId)
200✔
98

99
      request.db = await getPostgresConnection({
200✔
100
        user: adminUser,
101
        superUser: adminUser,
102
        tenantId: request.tenantId,
103
        host: request.headers['x-forwarded-host'] as string,
104
        path: request.url,
105
        method: request.method,
106
        headers: request.headers,
107
        disableHostCheck: opts.disableHostCheck,
108
        operation: () => request.operation,
65✔
109
      })
110

111
      // Connect abort signal to DB connection for query cancellation
112
      if (databaseEnableQueryCancellation && request.signals) {
200!
UNCOV
113
        request.db.setAbortSignal(request.signals.disconnect.signal)
×
114
      }
115
    })
116

117
    registerConnectionCleanupHooks(fastify)
1,787✔
118
  },
119
  { name: 'db-superuser-init' }
120
)
121

122
function registerConnectionCleanupHooks(fastify: FastifyInstance) {
123
  fastify.addHook('onSend', (request, _reply, payload, done) => {
6,491✔
124
    request.db?.dispose()
1,357✔
125
    done(null, payload)
1,357✔
126
  })
127

128
  fastify.addHook('onTimeout', (request, _reply, done) => {
6,491✔
NEW
129
    request.db?.dispose()
×
NEW
130
    done()
×
131
  })
132

133
  fastify.addHook('onRequestAbort', (request, done) => {
6,491✔
134
    request.db?.dispose()
1✔
135
    done()
1✔
136
  })
137
}
138

139
/**
140
 * Handle database migration for multitenant applications when a request is made
141
 */
142
export const migrations = fastifyPlugin(
29✔
143
  async function migrations(fastify) {
144
    fastify.addHook('preHandler', async (req) => {
6,491✔
145
      if (isMultitenant) {
1,294✔
146
        const { migrationVersion } = await getTenantConfig(req.tenantId)
4✔
147
        req.latestMigration = migrationVersion
4✔
148
        return
4✔
149
      }
150

151
      req.latestMigration = await lastLocalMigrationName()
1,290✔
152
    })
153

154
    if (dbMigrationStrategy === MultitenantMigrationStrategy.ON_REQUEST) {
6,491!
155
      fastify.addHook('preHandler', async (request) => {
6,491✔
156
        // migrations are handled via async migrations
157
        if (!isMultitenant) {
1,294✔
158
          return
1,290✔
159
        }
160

161
        const tenant = await getTenantConfig(request.tenantId)
4✔
162
        if (tenant.syncMigrationsDone) {
4!
UNCOV
163
          request.latestMigration = resolveLatestMigration(
×
164
            await lastLocalMigrationName(),
165
            tenant.migrationVersion
166
          )
UNCOV
167
          return
×
168
        }
169

170
        const latestMigration = await migrationSingleFlight(request.tenantId, async () => {
4✔
171
          const localLatest = await lastLocalMigrationName()
4✔
172
          const migrationsUpToDate = await areMigrationsUpToDate(request.tenantId)
4✔
173

174
          if (!migrationsUpToDate) {
4!
175
            await runMigrationsOnTenant({
4✔
176
              databaseUrl: tenant.databaseUrl,
177
              tenantId: request.tenantId,
178
              upToMigration: dbMigrationFreezeAt,
179
            })
180
          }
181

182
          const refreshedTenant = await getTenantConfig(request.tenantId)
4✔
183
          const resolvedMigration = resolveLatestMigration(
4✔
184
            resolveLatestMigration(localLatest, tenant.migrationVersion),
185
            refreshedTenant.migrationVersion
186
          )
187

188
          if (!migrationsUpToDate) {
4!
189
            await updateTenantMigrationsState(request.tenantId, {
4✔
190
              migration: resolvedMigration,
191
              state: TenantMigrationStatus.COMPLETED,
192
            })
193
          }
194

195
          refreshedTenant.migrationVersion = resolvedMigration
4✔
196
          refreshedTenant.migrationStatus = TenantMigrationStatus.COMPLETED
4✔
197
          refreshedTenant.syncMigrationsDone = true
4✔
198

199
          return resolvedMigration
4✔
200
        })
201

202
        tenant.migrationVersion = latestMigration
4✔
203
        tenant.migrationStatus = TenantMigrationStatus.COMPLETED
4✔
204
        tenant.syncMigrationsDone = true
4✔
205
        request.latestMigration = latestMigration
4✔
206
      })
207
    }
208

209
    if (dbMigrationStrategy === MultitenantMigrationStrategy.PROGRESSIVE) {
6,491!
UNCOV
210
      fastify.addHook('preHandler', async (request) => {
×
UNCOV
211
        if (!isMultitenant) {
×
UNCOV
212
          return
×
213
        }
214

215
        const tenant = await getTenantConfig(request.tenantId)
×
216
        if (tenant.syncMigrationsDone) {
×
217
          return
×
218
        }
219

220
        // migrations are up to date
221
        if (await areMigrationsUpToDate(request.tenantId)) {
×
222
          tenant.syncMigrationsDone = true
×
223
          return
×
224
        }
225

226
        progressiveMigrations.addTenant(request.tenantId)
×
227
      })
228
    }
229
  },
230
  { name: 'db-migrations' }
231
)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc