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

teableio / teable / 20065394908

09 Dec 2025 01:36PM UTC coverage: 71.858%. First build
20065394908

Pull #2168

github

web-flow
Merge b9dc7a0f8 into 6fd609a47
Pull Request #2168: feat: base node

22892 of 25545 branches covered (89.61%)

1916 of 2478 new or added lines in 35 files covered. (77.32%)

57741 of 80354 relevant lines covered (71.86%)

4259.47 hits per line

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

91.84
/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, IDeleteBaseNodeVo } 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 { EmitControllerEvent } from '../../event-emitter/decorators/emit-controller-event.decorator';
16
import { Events } from '../../event-emitter/events';
17
import type { IClsStore } from '../../types/cls';
18
import { ZodValidationPipe } from '../../zod.validation.pipe';
19
import { BaseNodePermissions } from '../auth/decorators/base-node-permissions.decorator';
20
import { Permissions } from '../auth/decorators/permissions.decorator';
21
import { BaseNodePermissionGuard } from '../auth/guard/base-node-permission.guard';
22
import { checkBaseNodePermission } from './base-node.permission.helper';
23
import { BaseNodeService } from './base-node.service';
24
import { BaseNodeAction } from './types';
25

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

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

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

65
  @Get(':nodeId')
123✔
66
  @Permissions('base|read')
67
  @BaseNodePermissions(BaseNodeAction.Read)
8✔
68
  async getNode(
8✔
69
    @Param('baseId') baseId: string,
8✔
70
    @Param('nodeId') nodeId: string
8✔
71
  ): Promise<IBaseNodeVo> {
8✔
72
    return this.baseNodeService.getNodeVo(baseId, nodeId);
8✔
73
  }
8✔
74

75
  @Post()
123✔
76
  @Permissions('base|read')
77
  @BaseNodePermissions(BaseNodeAction.Create)
110✔
78
  @EmitControllerEvent(Events.BASE_NODE_CREATE)
110✔
79
  async create(
110✔
80
    @Param('baseId') baseId: string,
110✔
81
    @Body(new ZodValidationPipe(createBaseNodeRoSchema)) ro: ICreateBaseNodeRo
110✔
82
  ): Promise<IBaseNodeVo> {
110✔
83
    return this.baseNodeService.create(baseId, ro);
110✔
84
  }
110✔
85

86
  @Post(':nodeId/duplicate')
123✔
87
  @Permissions('base|read')
88
  @BaseNodePermissions(BaseNodeAction.Read, BaseNodeAction.Create)
5✔
89
  @EmitControllerEvent(Events.BASE_NODE_CREATE)
5✔
90
  async duplicate(
5✔
91
    @Param('baseId') baseId: string,
5✔
92
    @Param('nodeId') nodeId: string,
5✔
93
    @Body(new ZodValidationPipe(duplicateBaseNodeRoSchema)) ro: IDuplicateBaseNodeRo
5✔
94
  ): Promise<IBaseNodeVo> {
5✔
95
    return this.baseNodeService.duplicate(baseId, nodeId, ro);
5✔
96
  }
5✔
97

98
  @Put(':nodeId')
123✔
99
  @Permissions('base|read')
100
  @BaseNodePermissions(BaseNodeAction.Update)
7✔
101
  @EmitControllerEvent(Events.BASE_NODE_UPDATE)
7✔
102
  async update(
7✔
103
    @Param('baseId') baseId: string,
7✔
104
    @Param('nodeId') nodeId: string,
7✔
105
    @Body(new ZodValidationPipe(updateBaseNodeRoSchema)) ro: IUpdateBaseNodeRo
7✔
106
  ): Promise<IBaseNodeVo> {
7✔
107
    return this.baseNodeService.update(baseId, nodeId, ro);
7✔
108
  }
7✔
109

110
  @Put(':nodeId/move')
123✔
111
  @Permissions('base|update')
112
  async move(
20✔
113
    @Param('baseId') baseId: string,
20✔
114
    @Param('nodeId') nodeId: string,
20✔
115
    @Body(new ZodValidationPipe(moveBaseNodeRoSchema)) ro: IMoveBaseNodeRo
20✔
116
  ): Promise<IBaseNodeVo> {
20✔
117
    return this.baseNodeService.move(baseId, nodeId, ro);
20✔
118
  }
20✔
119

120
  @Delete(':nodeId')
123✔
121
  @Permissions('base|read')
122
  @BaseNodePermissions(BaseNodeAction.Delete)
99✔
123
  @EmitControllerEvent(Events.BASE_NODE_DELETE)
99✔
124
  async delete(
99✔
125
    @Param('baseId') baseId: string,
99✔
126
    @Param('nodeId') nodeId: string
99✔
127
  ): Promise<IDeleteBaseNodeVo> {
99✔
128
    return this.baseNodeService.delete(baseId, nodeId);
99✔
129
  }
99✔
130

131
  @Delete(':nodeId/permanent')
123✔
132
  @Permissions('base|read')
NEW
133
  @BaseNodePermissions(BaseNodeAction.Delete)
×
NEW
134
  @EmitControllerEvent(Events.BASE_NODE_DELETE)
×
NEW
135
  async permanentDelete(
×
NEW
136
    @Param('baseId') baseId: string,
×
NEW
137
    @Param('nodeId') nodeId: string
×
NEW
138
  ): Promise<IDeleteBaseNodeVo> {
×
NEW
139
    return this.baseNodeService.delete(baseId, nodeId, true);
×
NEW
140
  }
×
141

142
  protected async getPermissionContext(_baseId: string) {
123✔
143
    const permissions = this.cls.get('permissions');
16✔
144
    const permissionSet = new Set(permissions);
16✔
145
    return { permissionSet };
16✔
146
  }
16✔
147
}
123✔
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