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

supabase / storage / 16223502981

11 Jul 2025 03:16PM UTC coverage: 77.08% (-0.9%) from 77.981%
16223502981

push

github

web-flow
fix: analytic bucket support

1623 of 2339 branches covered (69.39%)

Branch coverage included in aggregate %.

3010 of 3976 new or added lines in 64 files covered. (75.7%)

84 existing lines in 10 files now uncovered.

20321 of 26130 relevant lines covered (77.77%)

102.97 hits per line

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

83.78
/src/http/plugins/jwt.ts
1
import fastifyPlugin from 'fastify-plugin'
1✔
2
import { JWTPayload } from 'jose'
1✔
3

1✔
4
import { verifyJWTWithCache, verifyJWT } from '@internal/auth'
1✔
5
import { getJwtSecret } from '@internal/database'
1✔
6
import { ERRORS } from '@internal/errors'
1✔
7
import { getConfig } from '../../config'
1✔
8

1✔
9
declare module 'fastify' {
1✔
10
  interface FastifyRequest {
1✔
11
    isAuthenticated: boolean
1✔
12
    jwt: string
1✔
13
    jwtPayload?: JWTPayload & { role?: string }
1✔
14
    owner?: string
1✔
15
  }
1✔
16

1✔
17
  interface FastifyContextConfig {
1✔
18
    allowInvalidJwt?: boolean
1✔
19
  }
1✔
20
}
1✔
21

1✔
22
interface JWTPluginOptions {
1✔
23
  enforceJwtRoles?: string[]
1✔
24
}
1✔
25

1✔
26
const { jwtCachingEnabled } = getConfig()
1✔
27

1✔
28
const BEARER = /^Bearer\s+/i
1✔
29

1✔
30
export const jwt = fastifyPlugin<JWTPluginOptions>(
1✔
31
  async (fastify, opts) => {
1✔
32
    fastify.decorateRequest('jwt', '')
854✔
33
    fastify.decorateRequest('jwtPayload', undefined)
854✔
34

854✔
35
    fastify.addHook('preHandler', async (request) => {
854✔
36
      request.jwt = (request.headers.authorization || '').replace(BEARER, '')
100✔
37

100✔
38
      if (!request.jwt && request.routeOptions.config.allowInvalidJwt) {
100✔
39
        request.jwtPayload = { role: 'anon' }
4✔
40
        request.isAuthenticated = false
4✔
41
        return
4✔
42
      }
4✔
43

96✔
44
      const { secret, jwks } = await getJwtSecret(request.tenantId)
96✔
45

96✔
46
      try {
96✔
47
        const payload = await (jwtCachingEnabled
96✔
48
          ? verifyJWTWithCache(request.jwt, secret, jwks || null)
100!
49
          : verifyJWT(request.jwt, secret, jwks || null))
100!
50

96✔
51
        request.jwtPayload = payload
96✔
52
        request.owner = payload.sub
96✔
53
        request.isAuthenticated = true
96✔
54
      } catch (e) {
100!
55
        request.jwtPayload = { role: 'anon' }
×
56
        request.isAuthenticated = false
×
57

×
58
        if (request.routeOptions.config.allowInvalidJwt) {
×
59
          return
×
60
        }
×
61
        const err = e as Error
×
62
        throw ERRORS.AccessDenied(err.message, err)
×
63
      }
×
64
    })
854✔
65

854✔
66
    if (opts.enforceJwtRoles && opts.enforceJwtRoles.length > 0) {
854✔
67
      fastify.register(enforceJwtRole, {
244✔
68
        roles: opts.enforceJwtRoles,
244✔
69
      })
244✔
70
    }
244✔
71
  },
854✔
72
  { name: 'auth-jwt' }
1✔
73
)
1✔
74

1✔
75
interface EnforceJWTRoleOptions {
1✔
76
  roles: string[]
1✔
77
}
1✔
78

1✔
79
export const enforceJwtRole = fastifyPlugin<EnforceJWTRoleOptions>(
1✔
80
  async (fastify, opts) => {
1✔
81
    fastify.addHook('preHandler', async (request) => {
244✔
82
      if (!request.isAuthenticated) {
11!
NEW
83
        throw ERRORS.AccessDenied('Access denied: JWT is not authenticated').withStatusCode(403)
×
NEW
84
      }
×
85

11✔
86
      const hasRoles = request.jwtPayload?.role && opts.roles.includes(request.jwtPayload.role)
11✔
87

11✔
88
      if (!hasRoles) {
11!
NEW
89
        throw ERRORS.AccessDenied(`Access denied: Invalid role`).withStatusCode(403)
×
NEW
90
      }
×
91
    })
244✔
92
  },
244✔
93
  { name: 'allow-invalid-jwt' }
1✔
94
)
1✔
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