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

teableio / teable / 19916241702

04 Dec 2025 03:04AM UTC coverage: 71.774%. First build
19916241702

Pull #2168

github

web-flow
Merge d927191d3 into 2e3b12704
Pull Request #2168: feat: base node

22774 of 25482 branches covered (89.37%)

1811 of 2360 new or added lines in 32 files covered. (76.74%)

57177 of 79663 relevant lines covered (71.77%)

4248.07 hits per line

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

92.86
/apps/nestjs-backend/src/features/base-node/base-node.controller.ts
1
/* eslint-disable sonarjs/no-duplicate-string */
5✔
2
import { Body, Controller, Delete, Get, Param, Post, Put, UseGuards } from '@nestjs/common';
3
import type { IBaseNodeTreeVo, IBaseNodeVo } from '@teable/openapi';
4
import {
5
  moveBaseNodeRoSchema,
6
  createBaseNodeRoSchema,
7
  duplicateBaseNodeRoSchema,
8
  ICreateBaseNodeRo,
9
  IDuplicateBaseNodeRo,
10
  IMoveBaseNodeRo,
11
  updateBaseNodeRoSchema,
12
  IUpdateBaseNodeRo,
13
} from '@teable/openapi';
14
import { ClsService } from 'nestjs-cls';
15
import type { IClsStore } from '../../types/cls';
16
import { ZodValidationPipe } from '../../zod.validation.pipe';
17
import { BaseNodePermissions } from '../auth/decorators/base-node-permissions.decorator';
18
import { Permissions } from '../auth/decorators/permissions.decorator';
19
import { BaseNodePermissionGuard } from '../auth/guard/base-node-permission.guard';
20
import { checkBaseNodePermission } from './base-node.permission.helper';
21
import { BaseNodeService } from './base-node.service';
22

23
@Controller('api/base/:baseId/node')
24
@UseGuards(BaseNodePermissionGuard)
25
export class BaseNodeController {
5✔
26
  constructor(
117✔
27
    private readonly baseNodeService: BaseNodeService,
117✔
28
    private readonly cls: ClsService<IClsStore>
117✔
29
  ) {}
117✔
30

31
  @Get('list')
117✔
32
  @Permissions('base|read')
33
  async getList(@Param('baseId') baseId: string): Promise<IBaseNodeVo[]> {
3✔
34
    const permissionContext = await this.getPermissionContext(baseId);
3✔
35
    const nodeList = await this.baseNodeService.getList(baseId);
3✔
36
    return nodeList.filter((node) =>
3✔
37
      checkBaseNodePermission(
11✔
38
        { resourceType: node.resourceType, resourceId: node.resourceId },
11✔
39
        'base_node|read',
11✔
40
        permissionContext
11✔
41
      )
42
    );
43
  }
3✔
44

45
  @Get('tree')
117✔
46
  @Permissions('base|read')
47
  async getTree(@Param('baseId') baseId: string): Promise<IBaseNodeTreeVo> {
13✔
48
    const permissionContext = await this.getPermissionContext(baseId);
13✔
49
    const tree = await this.baseNodeService.getTree(baseId);
13✔
50
    return {
13✔
51
      ...tree,
13✔
52
      nodes: tree.nodes.filter((node) =>
13✔
53
        checkBaseNodePermission(
53✔
54
          { resourceType: node.resourceType, resourceId: node.resourceId },
53✔
55
          'base_node|read',
53✔
56
          permissionContext
53✔
57
        )
58
      ),
59
    };
13✔
60
  }
13✔
61

62
  @Get(':nodeId')
117✔
63
  @Permissions('base|read')
64
  @BaseNodePermissions('base_node|read')
65
  async getNode(
8✔
66
    @Param('baseId') baseId: string,
8✔
67
    @Param('nodeId') nodeId: string
8✔
68
  ): Promise<IBaseNodeVo> {
8✔
69
    return this.baseNodeService.getNodeVo(baseId, nodeId);
8✔
70
  }
8✔
71

72
  @Post()
117✔
73
  @Permissions('base|read')
74
  @BaseNodePermissions('base_node|create')
75
  async create(
110✔
76
    @Param('baseId') baseId: string,
110✔
77
    @Body(new ZodValidationPipe(createBaseNodeRoSchema)) ro: ICreateBaseNodeRo
110✔
78
  ): Promise<IBaseNodeVo> {
110✔
79
    return this.baseNodeService.create(baseId, ro);
110✔
80
  }
110✔
81

82
  @Post(':nodeId/duplicate')
117✔
83
  @Permissions('base|read')
84
  @BaseNodePermissions('base_node|read', 'base_node|create')
85
  async duplicate(
5✔
86
    @Param('baseId') baseId: string,
5✔
87
    @Param('nodeId') nodeId: string,
5✔
88
    @Body(new ZodValidationPipe(duplicateBaseNodeRoSchema)) ro: IDuplicateBaseNodeRo
5✔
89
  ): Promise<IBaseNodeVo> {
5✔
90
    return this.baseNodeService.duplicate(baseId, nodeId, ro);
5✔
91
  }
5✔
92

93
  @Put(':nodeId')
117✔
94
  @Permissions('base|read')
95
  @BaseNodePermissions('base_node|update')
96
  async update(
7✔
97
    @Param('baseId') baseId: string,
7✔
98
    @Param('nodeId') nodeId: string,
7✔
99
    @Body(new ZodValidationPipe(updateBaseNodeRoSchema)) ro: IUpdateBaseNodeRo
7✔
100
  ): Promise<IBaseNodeVo> {
7✔
101
    return this.baseNodeService.update(baseId, nodeId, ro);
7✔
102
  }
7✔
103

104
  @Put(':nodeId/move')
117✔
105
  @Permissions('base|update')
106
  async move(
20✔
107
    @Param('baseId') baseId: string,
20✔
108
    @Param('nodeId') nodeId: string,
20✔
109
    @Body(new ZodValidationPipe(moveBaseNodeRoSchema)) ro: IMoveBaseNodeRo
20✔
110
  ): Promise<IBaseNodeVo> {
20✔
111
    return this.baseNodeService.move(baseId, nodeId, ro);
20✔
112
  }
20✔
113

114
  @Delete(':nodeId')
117✔
115
  @Permissions('base|read')
116
  @BaseNodePermissions('base_node|delete')
117
  async delete(@Param('baseId') baseId: string, @Param('nodeId') nodeId: string): Promise<void> {
99✔
118
    return this.baseNodeService.delete(baseId, nodeId);
99✔
119
  }
99✔
120

121
  @Delete(':nodeId/permanent')
117✔
122
  @Permissions('base|read')
123
  @BaseNodePermissions('base_node|delete')
NEW
124
  async permanentDelete(
×
NEW
125
    @Param('baseId') baseId: string,
×
NEW
126
    @Param('nodeId') nodeId: string
×
NEW
127
  ): Promise<void> {
×
NEW
128
    return this.baseNodeService.delete(baseId, nodeId, true);
×
NEW
129
  }
×
130

131
  protected async getPermissionContext(_baseId: string) {
117✔
132
    const permissions = this.cls.get('permissions');
16✔
133
    const permissionSet = new Set(permissions);
16✔
134
    return { permissionSet };
16✔
135
  }
16✔
136
}
117✔
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