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

supabase / storage / 27746145680

18 Jun 2026 08:14AM UTC coverage: 45.155% (-33.2%) from 78.328%
27746145680

Pull #1160

github

web-flow
Merge f3f72b209 into 77bc6ab87
Pull Request #1160: fix: limit for delete objects and sign urls

2799 of 6771 branches covered (41.34%)

Branch coverage included in aggregate %.

13 of 17 new or added lines in 4 files covered. (76.47%)

4061 existing lines in 171 files now uncovered.

5551 of 11721 relevant lines covered (47.36%)

35.34 hits per line

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

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

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

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

31
export const db = fastifyPlugin(
4✔
32
  async function db(fastify) {
UNCOV
33
    fastify.register(migrations)
×
34

UNCOV
35
    fastify.decorateRequest('db')
×
36

UNCOV
37
    fastify.addHook('preHandler', async (request) => {
×
UNCOV
38
      const adminUser = await getServiceKeyUser(request.tenantId)
×
UNCOV
39
      const userPayload = request.jwtPayload
×
40

UNCOV
41
      if (!userPayload) {
×
42
        throw ERRORS.AccessDenied('JWT payload is missing')
×
43
      }
44

UNCOV
45
      request.db = await getPostgresConnection({
×
46
        user: {
47
          payload: userPayload,
48
          jwt: request.jwt,
49
        },
50
        superUser: adminUser,
51
        tenantId: request.tenantId,
52
        host: request.headers['x-forwarded-host'] as string,
53
        headers: request.headers,
54
        path: request.url,
55
        method: request.method,
UNCOV
56
        operation: () => request.operation?.type,
×
57
      })
58

59
      // Connect abort signal to DB connection for query cancellation
UNCOV
60
      if (request.signals?.disconnect?.signal && databaseEnableQueryCancellation) {
×
61
        request.db.setAbortSignal(request.signals.disconnect.signal)
×
62
      }
63
    })
64

UNCOV
65
    fastify.addHook('onSend', async (request, reply, payload) => {
×
UNCOV
66
      disposeRequestConnections(request)
×
UNCOV
67
      return payload
×
68
    })
69

UNCOV
70
    fastify.addHook('onTimeout', async (request) => {
×
71
      disposeRequestConnections(request)
×
72
    })
73

UNCOV
74
    fastify.addHook('onRequestAbort', async (request) => {
×
75
      disposeRequestConnections(request)
×
76
    })
77
  },
78
  { name: 'db-init' }
79
)
80

81
interface DbSuperUserPluginOptions {
82
  disableHostCheck?: boolean
83
}
84

85
export const dbSuperUser = fastifyPlugin<DbSuperUserPluginOptions>(
4✔
86
  async function dbSuperUser(fastify, opts) {
87
    fastify.register(migrations)
5✔
88
    fastify.decorateRequest('db')
5✔
89

90
    fastify.addHook('preHandler', async (request) => {
5✔
91
      const adminUser = await getServiceKeyUser(request.tenantId)
1✔
92

93
      request.db = await getPostgresConnection({
1✔
94
        user: adminUser,
95
        superUser: adminUser,
96
        tenantId: request.tenantId,
97
        host: request.headers['x-forwarded-host'] as string,
98
        path: request.url,
99
        method: request.method,
100
        headers: request.headers,
101
        disableHostCheck: opts.disableHostCheck,
UNCOV
102
        operation: () => request.operation?.type,
×
103
      })
104

105
      // Connect abort signal to DB connection for query cancellation
106
      if (request.signals?.disconnect?.signal && databaseEnableQueryCancellation) {
1!
107
        request.db.setAbortSignal(request.signals.disconnect.signal)
×
108
      }
109
    })
110

111
    fastify.addHook('onSend', async (request, reply, payload) => {
5✔
112
      disposeRequestConnections(request)
1✔
113
      return payload
1✔
114
    })
115

116
    fastify.addHook('onTimeout', async (request) => {
5✔
117
      disposeRequestConnections(request)
×
118
    })
119

120
    fastify.addHook('onRequestAbort', async (request) => {
5✔
UNCOV
121
      disposeRequestConnections(request)
×
122
    })
123
  },
124
  { name: 'db-superuser-init' }
125
)
126

127
function disposeRequestConnections(request: {
128
  db?: PgTenantConnection
129
  log: Parameters<typeof logSchema.error>[0]
130
  tenantId: string
131
  id: string
132
  sbReqId?: string
133
}) {
134
  request.db?.dispose().catch((e) => {
1✔
135
    logSchema.error(request.log, 'Error disposing db connection', {
×
136
      type: 'db-connection',
137
      tenantId: request.tenantId,
138
      project: request.tenantId,
139
      reqId: request.id,
140
      sbReqId: request.sbReqId,
141
      error: e,
142
    })
143
  })
144
}
145

146
/**
147
 * Handle database migration for multitenant applications when a request is made
148
 */
149
export const migrations = fastifyPlugin(
4✔
150
  async function migrations(fastify) {
151
    fastify.addHook('preHandler', async (req) => {
5✔
152
      if (isMultitenant) {
1!
UNCOV
153
        const { migrationVersion } = await getTenantConfig(req.tenantId)
×
UNCOV
154
        req.latestMigration = migrationVersion
×
UNCOV
155
        return
×
156
      }
157

158
      req.latestMigration = await lastLocalMigrationName()
1✔
159
    })
160

161
    if (dbMigrationStrategy === MultitenantMigrationStrategy.ON_REQUEST) {
5!
162
      const migrationsMutex = createMutexByKey<void>()
5✔
163

164
      fastify.addHook('preHandler', async (request) => {
5✔
165
        // migrations are handled via async migrations
166
        if (!isMultitenant) {
1!
167
          return
1✔
168
        }
169

UNCOV
170
        const tenant = await getTenantConfig(request.tenantId)
×
UNCOV
171
        const migrationsUpToDate = await areMigrationsUpToDate(request.tenantId)
×
172

UNCOV
173
        if (tenant.syncMigrationsDone || migrationsUpToDate) {
×
174
          return
×
175
        }
176

UNCOV
177
        await migrationsMutex(request.tenantId, async () => {
×
UNCOV
178
          const tenant = await getTenantConfig(request.tenantId)
×
179

UNCOV
180
          if (tenant.syncMigrationsDone) {
×
181
            return
×
182
          }
183

UNCOV
184
          await runMigrationsOnTenant({
×
185
            databaseUrl: tenant.databaseUrl,
186
            tenantId: request.tenantId,
187
            upToMigration: dbMigrationFreezeAt,
188
          })
UNCOV
189
          await updateTenantMigrationsState(request.tenantId)
×
UNCOV
190
          tenant.syncMigrationsDone = true
×
191
        })
192
      })
193
    }
194

195
    if (dbMigrationStrategy === MultitenantMigrationStrategy.PROGRESSIVE) {
5!
196
      fastify.addHook('preHandler', async (request) => {
×
197
        if (!isMultitenant) {
×
198
          return
×
199
        }
200

201
        const tenant = await getTenantConfig(request.tenantId)
×
202
        const migrationsUpToDate = await areMigrationsUpToDate(request.tenantId)
×
203

204
        // migrations are up to date
205
        if (tenant.syncMigrationsDone || migrationsUpToDate) {
×
206
          return
×
207
        }
208

209
        progressiveMigrations.addTenant(request.tenantId)
×
210
      })
211
    }
212
  },
213
  { name: 'db-migrations' }
214
)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc