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

teableio / teable / 10297377414

08 Aug 2024 06:53AM UTC coverage: 81.982% (+64.3%) from 17.728%
10297377414

Pull #802

github

web-flow
Merge e299a248f into 4854acca2
Pull Request #802: fix: restrict the encoding format of attachment names to utf-8

4274 of 4473 branches covered (95.55%)

8 of 11 new or added lines in 2 files covered. (72.73%)

28269 of 34482 relevant lines covered (81.98%)

1219.9 hits per line

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

88.76
/apps/nestjs-backend/src/features/attachments/attachments.controller.ts
1
/* eslint-disable @typescript-eslint/naming-convention */
4✔
2
import {
4✔
3
  Body,
4✔
4
  Controller,
4✔
5
  Get,
4✔
6
  Param,
4✔
7
  Post,
4✔
8
  Put,
4✔
9
  Query,
4✔
10
  Req,
4✔
11
  Res,
4✔
12
  StreamableFile,
4✔
13
  UseGuards,
4✔
14
} from '@nestjs/common';
4✔
15
import { SignatureRo, signatureRoSchema } from '@teable/openapi';
4✔
16
import type { INotifyVo, SignatureVo } from '@teable/openapi';
4✔
17
import { Response, Request } from 'express';
4✔
18
import { ZodValidationPipe } from '../../zod.validation.pipe';
4✔
19
import { Public } from '../auth/decorators/public.decorator';
4✔
20
import { TokenAccess } from '../auth/decorators/token.decorator';
4✔
21
import { AuthGuard } from '../auth/guard/auth.guard';
4✔
22
import { AttachmentsService } from './attachments.service';
4✔
23
import { DynamicAuthGuardFactory } from './guard/auth.guard';
4✔
24

4✔
25
@Controller('api/attachments')
4✔
26
@Public()
4✔
27
@TokenAccess()
4✔
28
export class AttachmentsController {
4✔
29
  constructor(private readonly attachmentsService: AttachmentsService) {}
72✔
30

72✔
31
  @Put('/upload/:token')
72✔
32
  async uploadFilePut(@Req() req: Request, @Param('token') token: string) {
10✔
33
    await this.attachmentsService.upload(req, token);
10✔
34
    return null;
10✔
35
  }
10✔
36

72✔
37
  @Post('/upload/:token')
72✔
38
  async uploadFilePost(@Req() req: Request, @Param('token') token: string) {
×
39
    await this.attachmentsService.upload(req, token);
×
40
    return null;
×
41
  }
×
42

72✔
43
  @Get('/read/:path(*)')
72✔
44
  async read(
20✔
45
    @Res({ passthrough: true }) res: Response,
20✔
46
    @Req() req: Request,
20✔
47
    @Param('path') path: string,
20✔
48
    @Query('token') token: string,
20✔
49
    @Query('response-content-disposition') responseContentDisposition?: string
20✔
50
  ) {
20✔
51
    const hasCache = this.attachmentsService.localFileConditionalCaching(path, req.headers, res);
20✔
52
    if (hasCache) {
20✔
53
      res.status(304);
×
54
      return;
×
55
    }
×
56
    const { fileStream, headers } = await this.attachmentsService.readLocalFile(path, token);
20✔
57
    if (responseContentDisposition) {
20✔
58
      const fileNameMatch =
20✔
59
        responseContentDisposition.match(/filename\*=UTF-8''([^;]+)/) ||
20✔
NEW
60
        responseContentDisposition.match(/filename="?([^"]+)"?/);
×
61
      if (fileNameMatch) {
20✔
62
        const fileName = fileNameMatch[1] as string;
20✔
63
        headers['Content-Disposition'] =
20✔
64
          `attachment; filename*=UTF-8''${encodeURIComponent(fileName)}`;
20✔
65
      } else {
20✔
NEW
66
        headers['Content-Disposition'] = responseContentDisposition;
×
NEW
67
      }
×
68
    }
20✔
69
    res.set(headers);
20✔
70
    return new StreamableFile(fileStream);
20✔
71
  }
20✔
72

72✔
73
  @UseGuards(AuthGuard, DynamicAuthGuardFactory)
72✔
74
  @Post('/signature')
10✔
75
  async signature(
10✔
76
    @Body(new ZodValidationPipe(signatureRoSchema)) body: SignatureRo
10✔
77
  ): Promise<SignatureVo> {
10✔
78
    return await this.attachmentsService.signature(body);
10✔
79
  }
10✔
80

72✔
81
  @UseGuards(AuthGuard, DynamicAuthGuardFactory)
72✔
82
  @Post('/notify/:token')
10✔
83
  async notify(
10✔
84
    @Param('token') token: string,
10✔
85
    @Query('filename') filename?: string
10✔
86
  ): Promise<INotifyVo> {
10✔
87
    return await this.attachmentsService.notify(token, filename);
10✔
88
  }
10✔
89
}
72✔
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

© 2025 Coveralls, Inc