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

teableio / teable / 15039567037

15 May 2025 07:49AM UTC coverage: 80.625% (-0.4%) from 81.043%
15039567037

push

github

web-flow
feat: base chat UI (#1524)

* feat: add base sql executor services

* feat: chatbot ui

* feat: chat loading

* feat: full chat ui

* fix: build error

* feat: support add context for messages

* feat: add reason message part render

* fix: reason part expand

* chore: update pnpm lock

* feat: preview html

* feat: memo ai markdown block

* chore: update pnpm lock

* feat: ai message add consumed credits and time

* fix: meta content is empty display

* fix: import url

* chore: update pnpm-lock.yaml

* fix: display token usage

* fix: magic ai icons

* feat: chat model only display model name

* fix: missing import

* feat: message rerender

* Update apps/nestjs-backend/src/features/base-sql-executor/utils.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Boris <boris2code@outlook.com>

* chore: lint code

* chore: update i18n

---------

Signed-off-by: Boris <boris2code@outlook.com>
Co-authored-by: tea artist <artist@teable.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

7869 of 8373 branches covered (93.98%)

53 of 297 new or added lines in 4 files covered. (17.85%)

5 existing lines in 2 files now uncovered.

37339 of 46312 relevant lines covered (80.62%)

1762.75 hits per line

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

96.36
/apps/nestjs-backend/src/features/base-sql-executor/utils.ts
1
import { BadRequestException } from '@nestjs/common';
2✔
2
import { DriverClient } from '@teable/core';
3
import type { AST } from 'node-sql-parser';
4
import { Parser } from 'node-sql-parser';
5

6
export const validateRoleOperations = (sql: string) => {
2✔
7
  const removeQuotedContent = (sql: string) => {
16✔
8
    return sql.replace(/'[^']*'|"[^"]*"/g, ' ');
16✔
9
  };
16✔
10

11
  const normalizedSql = sql.toLowerCase().replace(/\s+/g, ' ');
16✔
12
  const sqlWithoutQuotes = removeQuotedContent(normalizedSql);
16✔
13

14
  const roleOperationPatterns = [/set\s+role/, /reset\s+role/, /set\s+session/];
16✔
15

16
  for (const pattern of roleOperationPatterns) {
16✔
17
    if (pattern.test(sqlWithoutQuotes)) {
28✔
18
      throw new BadRequestException(`not allowed to execute sql with keyword: ${pattern.source}`);
12✔
19
    }
12✔
20
  }
28✔
21
};
4✔
22

23
const databaseTypeMap = {
2✔
24
  [DriverClient.Pg]: 'postgresql',
2✔
25
  [DriverClient.Sqlite]: 'sqlite',
2✔
26
};
2✔
27

28
const collectWithNames = (ast: AST) => {
2✔
29
  const withNames: string[] = [];
8✔
30
  if (ast.type === 'select' && ast.with) {
8✔
31
    ast.with.forEach((withItem) => {
6✔
32
      withNames.push(withItem.name.value);
6✔
33
    });
6✔
34
  }
6✔
35
  return withNames;
8✔
36
};
8✔
37

38
export const checkTableAccess = (
2✔
39
  sql: string,
8✔
40
  {
8✔
41
    tableNames,
8✔
42
    database,
8✔
43
  }: {
44
    tableNames: string[];
45
    database: DriverClient;
46
  }
8✔
47
) => {
48
  const parser = new Parser();
8✔
49
  const opt = {
8✔
50
    database: databaseTypeMap[database],
8✔
51
  };
8✔
52
  const { ast } = parser.parse(sql, opt);
8✔
53
  const withNames = Array.isArray(ast) ? ast.map(collectWithNames).flat() : collectWithNames(ast);
8!
54
  const allWithNames = new Set([...withNames, ...tableNames]);
8✔
55
  const whiteColumnList = Array.from(allWithNames).map((table) => {
8✔
56
    const [schema, tableName] = table.includes('.') ? table.split('.') : [null, table];
18✔
57
    return `select::${schema}::${tableName}`;
18✔
58
  });
18✔
59
  try {
8✔
60
    const error = parser.whiteListCheck(sql, whiteColumnList, opt);
8✔
61
    if (error) {
8!
NEW
62
      throw error;
×
NEW
63
    }
×
64
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
8✔
65
  } catch (error: any) {
8✔
66
    throw new BadRequestException(
2✔
67
      error?.message || 'An error occurred while checking table access.'
2!
68
    );
69
  }
2✔
70
};
8✔
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