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

supabase / storage / 25739744753

12 May 2026 02:05PM UTC coverage: 39.493% (-34.9%) from 74.366%
25739744753

Pull #1102

github

web-flow
Merge 8db6e774f into defbbb616
Pull Request #1102: fix: add more acceptance test coverage

2113 of 5922 branches covered (35.68%)

Branch coverage included in aggregate %.

4230 of 10139 relevant lines covered (41.72%)

35.36 hits per line

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

10.0
/src/http/routes/render/renderSignedImage.ts
1
import { SignedToken, verifyJWT } from '@internal/auth'
2
import { getJwtSecret, getTenantConfig } from '@internal/database'
3
import { ERRORS } from '@internal/errors'
4
import { ImageRenderer } from '@storage/renderer'
5
import { FastifyInstance } from 'fastify'
6
import { FromSchema } from 'json-schema-to-ts'
7
import { getConfig } from '../../../config'
8
import { ROUTE_OPERATIONS } from '../operations'
9

10
const { storageS3Bucket, isMultitenant } = getConfig()
2✔
11

12
const renderAuthenticatedImageParamsSchema = {
2✔
13
  type: 'object',
14
  properties: {
15
    bucketName: { type: 'string', examples: ['avatars'] },
16
    '*': { type: 'string', examples: ['folder/cat.png'] },
17
  },
18
  required: ['bucketName', '*'],
19
} as const
20

21
const renderImageQuerySchema = {
2✔
22
  type: 'object',
23
  properties: {
24
    token: {
25
      type: 'string',
26
      examples: [
27
        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJidWNrZXQyL3B1YmxpYy9zYWRjYXQtdXBsb2FkMjMucG5nIiwiaWF0IjoxNjE3NzI2MjczLCJleHAiOjE2MTc3MjcyNzN9.uBQcXzuvXxfw-9WgzWMBfE_nR3VOgpvfZe032sfLSSk',
28
      ],
29
    },
30
    download: { type: 'string', examples: ['filename.png'] },
31
  },
32
  required: ['token'],
33
} as const
34

35
interface renderImageRequestInterface {
36
  Params: FromSchema<typeof renderAuthenticatedImageParamsSchema>
37
  Querystring: FromSchema<typeof renderImageQuerySchema>
38
}
39

40
export default async function routes(fastify: FastifyInstance) {
41
  const summary = 'Render an authenticated image with the given transformations'
×
42
  fastify.get<renderImageRequestInterface>(
×
43
    '/sign/:bucketName/*',
44
    {
45
      schema: {
46
        params: renderAuthenticatedImageParamsSchema,
47
        querystring: renderImageQuerySchema,
48
        summary,
49
        response: { '4xx': { $ref: 'errorSchema#', description: 'Error response' } },
50
        tags: ['transformation'],
51
      },
52
      config: {
53
        operation: { type: ROUTE_OPERATIONS.RENDER_SIGNED_IMAGE },
54
      },
55
    },
56
    async (request, response) => {
57
      const { token } = request.query
×
58
      const { download } = request.query
×
59

60
      let payload: SignedToken
61
      const { secret: jwtSecret, jwks } = await getJwtSecret(request.tenantId)
×
62

63
      try {
×
64
        payload = (await verifyJWT(token, jwtSecret, jwks)) as SignedToken
×
65
      } catch (e) {
66
        const err = e as Error
×
67
        throw ERRORS.InvalidJWT(err)
×
68
      }
69

70
      const { url, transformations, exp } = payload
×
71

72
      const path = `${request.params.bucketName}/${request.params['*']}`
×
73

74
      if (url !== path) {
×
75
        throw ERRORS.InvalidSignature()
×
76
      }
77

78
      const s3Key = `${request.tenantId}/${url}`
×
79

80
      const [bucketName, ...objParts] = url.split('/')
×
81
      const obj = await request.storage
×
82
        .asSuperUser()
83
        .from(bucketName)
84
        .findObject(objParts.join('/'), 'id,version,metadata')
85

86
      const renderer = request.storage.renderer('image') as ImageRenderer
×
87

88
      if (isMultitenant) {
×
89
        const tenantConfig = await getTenantConfig(request.tenantId)
×
90
        renderer.setLimits({
×
91
          maxResolution: tenantConfig.features.imageTransformation.maxResolution,
92
        })
93
      }
94

95
      return renderer
×
96
        .setTransformationsFromString(transformations || '')
×
97
        .render(request, response, {
98
          bucket: storageS3Bucket,
99
          key: s3Key,
100
          version: obj.version,
101
          download,
102
          expires: new Date(exp * 1000).toUTCString(),
103
          xRobotsTag: obj.metadata?.['xRobotsTag'] as string | undefined,
104
          signal: request.signals.disconnect.signal,
105
        })
106
    }
107
  )
108
}
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