Browse Source

Merge pull request #5222 from nocodb/feat/ajv-validation-followup

refactor: ajv validation & swagger
pull/5273/head
Pranav C 2 years ago committed by GitHub
parent
commit
cdafba4c49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue
  2. 20
      packages/noco-docs/content/en/developer-resources/rest-apis.md
  3. 4387
      packages/nocodb-sdk/src/lib/Api.ts
  4. 2
      packages/nocodb-sdk/src/lib/globals.ts
  5. 25
      packages/nocodb/package-lock.json
  6. 4
      packages/nocodb/package.json
  7. 4
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelectv2.ts
  8. 2
      packages/nocodb/src/lib/meta/api/helpers/apiHelpers.ts
  9. 16
      packages/nocodb/src/lib/meta/helpers/getColumnPropsFromUIDT.ts
  10. 5
      packages/nocodb/src/lib/models/ApiToken.ts
  11. 47
      packages/nocodb/src/lib/models/Audit.ts
  12. 22
      packages/nocodb/src/lib/models/Base.ts
  13. 6
      packages/nocodb/src/lib/models/Filter.ts
  14. 1
      packages/nocodb/src/lib/models/FormView.ts
  15. 28
      packages/nocodb/src/lib/models/FormViewColumn.ts
  16. 3
      packages/nocodb/src/lib/models/GalleryViewColumn.ts
  17. 4
      packages/nocodb/src/lib/models/GridViewColumn.ts
  18. 2
      packages/nocodb/src/lib/models/Hook.ts
  19. 2
      packages/nocodb/src/lib/models/HookFilter.ts
  20. 3
      packages/nocodb/src/lib/models/KanbanViewColumn.ts
  21. 3
      packages/nocodb/src/lib/models/LookupColumn.ts
  22. 4
      packages/nocodb/src/lib/models/MapViewColumn.ts
  23. 10
      packages/nocodb/src/lib/models/Model.ts
  24. 4
      packages/nocodb/src/lib/models/Project.ts
  25. 4
      packages/nocodb/src/lib/models/ProjectUser.ts
  26. 19
      packages/nocodb/src/lib/models/RollupColumn.ts
  27. 6
      packages/nocodb/src/lib/models/SelectOption.ts
  28. 4
      packages/nocodb/src/lib/models/View.ts
  29. 2
      packages/nocodb/src/lib/services/attachmentService.ts
  30. 2
      packages/nocodb/src/lib/services/formViewService.ts
  31. 1
      packages/nocodb/src/lib/services/projectUserService.ts
  32. 2
      packages/nocodb/src/lib/services/syncService/helpers/job.ts
  33. 15
      packages/nocodb/src/lib/services/viewColumnService.ts
  34. 14
      packages/nocodb/src/lib/services/viewService.ts
  35. 40
      packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts
  36. 45
      packages/nocodb/src/run/redoc.ts
  37. 12043
      packages/nocodb/src/schema/swagger.json
  38. 12
      packages/nocodb/tests/unit/factory/project.ts
  39. 10
      packages/nocodb/tests/unit/rest/tests/project.test.ts

4
packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue

@ -90,7 +90,7 @@ const filterUpdateCondition = (filter: FilterType, i: number) => {
// since `blank`, `empty`, `null` doesn't require value, // since `blank`, `empty`, `null` doesn't require value,
// hence remove the previous value // hence remove the previous value
filter.value = null filter.value = null
filter.comparison_sub_op = '' filter.comparison_sub_op = null
} else if ([UITypes.Date, UITypes.DateTime].includes(col.uidt as UITypes)) { } else if ([UITypes.Date, UITypes.DateTime].includes(col.uidt as UITypes)) {
// for date / datetime, // for date / datetime,
// the input type could be decimal or datepicker / datetime picker // the input type could be decimal or datepicker / datetime picker
@ -177,7 +177,7 @@ const selectFilterField = (filter: Filter, index: number) => {
} }
} else { } else {
// reset // reset
filter.comparison_sub_op = '' filter.comparison_sub_op = null
} }
// reset filter value as well // reset filter value as well

20
packages/noco-docs/content/en/developer-resources/rest-apis.md

@ -120,14 +120,20 @@ Currently, the default value for {orgs} is <b>noco</b>. Users will be able to ch
| Meta | Patch | dbView | update | /api/v1/db/meta/tables/{tableId} | | Meta | Patch | dbView | update | /api/v1/db/meta/tables/{tableId} |
| Meta | Delete| dbView | delete | /api/v1/db/meta/tables/{tableId} | | Meta | Delete| dbView | delete | /api/v1/db/meta/tables/{tableId} |
| Meta | Post | dbView | reorder | /api/v1/db/meta/tables/{tableId}/reorder | | Meta | Post | dbView | reorder | /api/v1/db/meta/tables/{tableId}/reorder |
| Meta | Post | dbView | formCreate | /api/v1/db/meta/forms | | Meta | Post | dbView | formCreate | /api/v1/db/meta/tables/{tableId}/forms |
| Meta | Patch | dbView | formUpdate | /api/v1/db/meta/forms/{formId} | | Meta | Patch | dbView | formUpdate | /api/v1/db/meta/forms/{formViewId} |
| Meta | Get | dbView | formRead | /api/v1/db/meta/forms/{formId} | | Meta | Get | dbView | formRead | /api/v1/db/meta/forms/{formViewId} |
| Meta | Patch | dbView | formColumnUpdate | /api/v1/db/meta/form-columns/{formViewColumnId} | | Meta | Patch | dbView | formColumnUpdate | /api/v1/db/meta/form-columns/{formViewColumnId} |
| Meta | Post | dbView | galleryCreate | /api/v1/db/meta/galleries | | Meta | Post | dbView | galleryCreate | /api/v1/db/meta/tables/{tableId}/galleries |
| Meta | Patch | dbView | galleryUpdate | /api/v1/db/meta/galleries/{galleriesId} | | Meta | Patch | dbView | galleryUpdate | /api/v1/db/meta/galleries/{galleryViewId} |
| Meta | Get | dbView | galleryRead | /api/v1/db/meta/galleries/{galleriesId} | | Meta | Get | dbView | galleryRead | /api/v1/db/meta/galleries/{galleryViewId} |
| Meta | Post | dbView | gridCreate | /api/v1/db/meta/tables/${tableId}/grids | | Meta | Post | dbView | kanbanCreate | /api/v1/db/meta/tables/{tableId}/kanbans |
| Meta | Patch | dbView | kanbanUpdate | /api/v1/db/meta/kanban/{kanbanViewId} |
| Meta | Get | dbView | kanbanRead | /api/v1/db/meta/kanbans/{kanbanViewId} |
| Meta | Post | dbView | mapCreate | /api/v1/db/meta/tables/{tableId}/maps |
| Meta | Patch | dbView | mapUpdate | /api/v1/db/meta/maps/{mapViewId} |
| Meta | Get | dbView | mapRead | /api/v1/db/meta/maps/{mapViewId} |
| Meta | Post | dbView | gridCreate | /api/v1/db/meta/tables/{tableId}/grids |
| Meta | Get | dbView | gridColumnsList | /api/v1/db/meta/grids/{gridId}/grid-columns | | Meta | Get | dbView | gridColumnsList | /api/v1/db/meta/grids/{gridId}/grid-columns |
| Meta | Patch | dbView | gridColumnUpdate | /api/v1/db/meta/grid-columns/{columnId} | | Meta | Patch | dbView | gridColumnUpdate | /api/v1/db/meta/grid-columns/{columnId} |
| Meta | Patch | dbView | update | /api/v1/db/meta/views/{viewId} | | Meta | Patch | dbView | update | /api/v1/db/meta/views/{viewId} |

4387
packages/nocodb-sdk/src/lib/Api.ts

File diff suppressed because it is too large Load Diff

2
packages/nocodb-sdk/src/lib/globals.ts

@ -55,7 +55,7 @@ export enum AuditOperationSubTypes {
EXPORT_TO_ZIP = 'EXPORT_TO_ZIP', EXPORT_TO_ZIP = 'EXPORT_TO_ZIP',
UPDATED = 'UPDATED', UPDATED = 'UPDATED',
SIGNIN = 'SIGNIN', SIGNIN = 'SIGNIN',
SIGN = 'SIGN', SIGNUP = 'SIGNUP',
PASSWORD_RESET = 'PASSWORD_RESET', PASSWORD_RESET = 'PASSWORD_RESET',
PASSWORD_FORGOT = 'PASSWORD_FORGOT', PASSWORD_FORGOT = 'PASSWORD_FORGOT',
PASSWORD_CHANGE = 'PASSWORD_CHANGE', PASSWORD_CHANGE = 'PASSWORD_CHANGE',

25
packages/nocodb/package-lock.json generated

@ -14,6 +14,7 @@
"@sentry/node": "^6.3.5", "@sentry/node": "^6.3.5",
"airtable": "^0.11.3", "airtable": "^0.11.3",
"ajv": "^8.12.0", "ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"archiver": "^5.0.2", "archiver": "^5.0.2",
"auto-bind": "^4.0.0", "auto-bind": "^4.0.0",
"aws-sdk": "^2.829.0", "aws-sdk": "^2.829.0",
@ -2261,6 +2262,22 @@
"ajv": ">=5.0.0" "ajv": ">=5.0.0"
} }
}, },
"node_modules/ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dependencies": {
"ajv": "^8.0.0"
},
"peerDependencies": {
"ajv": "^8.0.0"
},
"peerDependenciesMeta": {
"ajv": {
"optional": true
}
}
},
"node_modules/amdefine": { "node_modules/amdefine": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
@ -20919,6 +20936,14 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"requires": {
"ajv": "^8.0.0"
}
},
"amdefine": { "amdefine": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",

4
packages/nocodb/package.json

@ -43,7 +43,8 @@
"watch:run:pg": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/dockerRunPG --log-error --project tsconfig.json\"", "watch:run:pg": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/dockerRunPG --log-error --project tsconfig.json\"",
"run": "ts-node src/run/docker", "run": "ts-node src/run/docker",
"watch:try": "nodemon -e ts,js -w ./src -x \"ts-node src/run/try --log-error --project tsconfig.json\"", "watch:try": "nodemon -e ts,js -w ./src -x \"ts-node src/run/try --log-error --project tsconfig.json\"",
"example:docker": "ts-node src/run/docker.ts" "example:docker": "ts-node src/run/docker.ts",
"redoc": "nodemon -e ts,json -w ./src/schema -x \"ts-node src/run/redoc --log-error --project tsconfig.json\""
}, },
"engines": { "engines": {
"node": ">=8.9" "node": ">=8.9"
@ -54,6 +55,7 @@
"@sentry/node": "^6.3.5", "@sentry/node": "^6.3.5",
"airtable": "^0.11.3", "airtable": "^0.11.3",
"ajv": "^8.12.0", "ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"archiver": "^5.0.2", "archiver": "^5.0.2",
"auto-bind": "^4.0.0", "auto-bind": "^4.0.0",
"aws-sdk": "^2.829.0", "aws-sdk": "^2.829.0",

4
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelectv2.ts

@ -29,7 +29,7 @@ export default async function ({
case RelationTypes.HAS_MANY: case RelationTypes.HAS_MANY:
return { return {
builder: knex(`${childModel?.table_name} as ${refTableAlias}`) builder: knex(`${childModel?.table_name} as ${refTableAlias}`)
[columnOptions.rollup_function]?.( [columnOptions.rollup_function as string]?.(
knex.ref(`${refTableAlias}.${rollupColumn.column_name}`) knex.ref(`${refTableAlias}.${rollupColumn.column_name}`)
) )
.where( .where(
@ -47,7 +47,7 @@ export default async function ({
return { return {
builder: knex(`${parentModel?.table_name} as ${refTableAlias}`) builder: knex(`${parentModel?.table_name} as ${refTableAlias}`)
[columnOptions.rollup_function]?.( [columnOptions.rollup_function as string]?.(
knex.ref(`${refTableAlias}.${rollupColumn.column_name}`) knex.ref(`${refTableAlias}.${rollupColumn.column_name}`)
) )
.innerJoin( .innerJoin(

2
packages/nocodb/src/lib/meta/api/helpers/apiHelpers.ts

@ -1,5 +1,6 @@
import { NextFunction, Request, Response } from 'express'; import { NextFunction, Request, Response } from 'express';
import Ajv, { ErrorObject } from 'ajv'; import Ajv, { ErrorObject } from 'ajv';
import addFormats from 'ajv-formats';
// @ts-ignore // @ts-ignore
import swagger from '../../../../schema/swagger.json'; import swagger from '../../../../schema/swagger.json';
import { NcError } from '../../helpers/catchError'; import { NcError } from '../../helpers/catchError';
@ -12,6 +13,7 @@ export function parseHrtimeToSeconds(hrtime) {
const ajv = new Ajv({ strictSchema: false, strict: false }); // Initialize AJV const ajv = new Ajv({ strictSchema: false, strict: false }); // Initialize AJV
ajv.addSchema(swagger, 'swagger.json'); ajv.addSchema(swagger, 'swagger.json');
addFormats(ajv);
// A middleware generator to validate the request body // A middleware generator to validate the request body
export const getAjvValidatorMw = (schema) => { export const getAjvValidatorMw = (schema) => {

16
packages/nocodb/src/lib/meta/helpers/getColumnPropsFromUIDT.ts

@ -1,14 +1,20 @@
import { ColumnReqType, SqlUIColumn, SqlUiFactory, UITypes } from 'nocodb-sdk'; import {
ColumnReqType,
NormalColumnRequestType,
SqlUiFactory,
UITypes,
} from 'nocodb-sdk';
import Base from '../../models/Base'; import Base from '../../models/Base';
import Column from '../../models/Column';
export default function getColumnPropsFromUIDT( export default function getColumnPropsFromUIDT(
column: SqlUIColumn & { uidt: UITypes } & ColumnReqType, column: ColumnReqType & { altered?: number },
base: Base base: Base
) { ) {
const sqlUi = SqlUiFactory.create(base.getConnectionConfig()); const sqlUi = SqlUiFactory.create(base.getConnectionConfig());
const colProp = sqlUi.getDataTypeForUiType( const colProp = sqlUi.getDataTypeForUiType(
column, column as Column,
column?.['meta']?.['ag'] ? 'AG' : 'AI' column?.['meta']?.['ag'] ? 'AG' : 'AI'
); );
const newColumn = { const newColumn = {
@ -28,9 +34,9 @@ export default function getColumnPropsFromUIDT(
if ( if (
column && column &&
selectTypes.includes(newColumn.uidt) && selectTypes.includes(newColumn.uidt) &&
selectTypes.includes(column.uidt) selectTypes.includes(column.uidt as UITypes)
) { ) {
newColumn.dtxp = column.dtxp; newColumn.dtxp = (column as NormalColumnRequestType).dtxp;
} }
newColumn.altered = column.altered || 2; newColumn.altered = column.altered || 2;

5
packages/nocodb/src/lib/models/ApiToken.ts

@ -7,8 +7,9 @@ import {
import Noco from '../Noco'; import Noco from '../Noco';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import type { ApiTokenType } from 'nocodb-sdk';
export default class ApiToken { export default class ApiToken implements ApiTokenType {
project_id?: string; project_id?: string;
db_alias?: string; db_alias?: string;
fk_user_id?: string; fk_user_id?: string;
@ -18,7 +19,7 @@ export default class ApiToken {
expiry?: string; expiry?: string;
enabled?: boolean; enabled?: boolean;
constructor(audit: Partial<ApiToken>) { constructor(audit: Partial<ApiToken | ApiTokenType>) {
Object.assign(this, audit); Object.assign(this, audit);
} }

47
packages/nocodb/src/lib/models/Audit.ts

@ -4,6 +4,49 @@ import Noco from '../Noco';
import Model from './Model'; import Model from './Model';
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps';
const opTypes = <const>[
'COMMENT',
'DATA',
'PROJECT',
'VIRTUAL_RELATION',
'RELATION',
'TABLE_VIEW',
'TABLE',
'VIEW',
'META',
'WEBHOOKS',
'AUTHENTICATION',
'TABLE_COLUMN',
'ORG_USER',
];
const opSubTypes = <const>[
'UPDATE',
'INSERT',
'BULK_INSERT',
'BULK_UPDATE',
'BULK_DELETE',
'LINK_RECORD',
'UNLINK_RECORD',
'DELETE',
'CREATED',
'DELETED',
'RENAMED',
'IMPORT_FROM_ZIP',
'EXPORT_TO_FS',
'EXPORT_TO_ZIP',
'UPDATED',
'SIGNIN',
'SIGNUP',
'PASSWORD_RESET',
'PASSWORD_FORGOT',
'PASSWORD_CHANGE',
'EMAIL_VERIFICATION',
'ROLES_MANAGEMENT',
'INVITE',
'RESEND_INVITE',
];
export default class Audit implements AuditType { export default class Audit implements AuditType {
id?: string; id?: string;
user?: string; user?: string;
@ -12,8 +55,8 @@ export default class Audit implements AuditType {
project_id?: string; project_id?: string;
fk_model_id?: string; fk_model_id?: string;
row_id?: string; row_id?: string;
op_type?: string; op_type?: typeof opTypes[number];
op_sub_type?: string; op_sub_type?: typeof opSubTypes[number];
status?: string; status?: string;
description?: string; description?: string;
details?: string; details?: string;

22
packages/nocodb/src/lib/models/Base.ts

@ -14,16 +14,24 @@ import { extractProps } from '../meta/helpers/extractProps';
import { NcError } from '../meta/helpers/catchError'; import { NcError } from '../meta/helpers/catchError';
import SyncSource from './SyncSource'; import SyncSource from './SyncSource';
export const DB_TYPES = <const>[
'mysql2',
'sqlite3',
'mysql',
'mssql',
'snowflake',
'oracledb',
'pg',
];
// todo: hide credentials // todo: hide credentials
export default class Base implements BaseType { export default class Base implements BaseType {
id?: string; id?: string;
project_id?: string; project_id?: string;
alias?: string; alias?: string;
type?: string; type?: typeof DB_TYPES[number];
is_meta?: BoolType; is_meta?: BoolType;
config?: any; config?: string;
created_at?: any;
updated_at?: any;
inflection_column?: string; inflection_column?: string;
inflection_table?: string; inflection_table?: string;
order?: number; order?: number;
@ -43,8 +51,6 @@ export default class Base implements BaseType {
'config', 'config',
'type', 'type',
'is_meta', 'is_meta',
'created_at',
'updated_at',
'inflection_column', 'inflection_column',
'inflection_table', 'inflection_table',
'order', 'order',
@ -81,8 +87,6 @@ export default class Base implements BaseType {
base: BaseType & { base: BaseType & {
id: string; id: string;
projectId: string; projectId: string;
created_at?;
updated_at?;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
@ -101,8 +105,6 @@ export default class Base implements BaseType {
'config', 'config',
'type', 'type',
'is_meta', 'is_meta',
'created_at',
'updated_at',
'inflection_column', 'inflection_column',
'inflection_table', 'inflection_table',
'order', 'order',

6
packages/nocodb/src/lib/models/Filter.ts

@ -71,7 +71,7 @@ export const COMPARISON_SUB_OPS = <const>[
...IS_WITHIN_COMPARISON_SUB_OPS, ...IS_WITHIN_COMPARISON_SUB_OPS,
]; ];
export default class Filter { export default class Filter implements FilterType {
id: string; id: string;
fk_model_id?: string; fk_model_id?: string;
@ -85,7 +85,7 @@ export default class Filter {
value?: string; value?: string;
logical_op?: string; logical_op?: 'and' | 'or' | 'not';
is_group?: BoolType; is_group?: BoolType;
children?: Filter[]; children?: Filter[];
project_id?: string; project_id?: string;
@ -383,7 +383,7 @@ export default class Filter {
const result: FilterType = { const result: FilterType = {
is_group: true, is_group: true,
children: [], children: [],
logical_op: 'AND', logical_op: 'and',
}; };
const grouped = {}; const grouped = {};

1
packages/nocodb/src/lib/models/FormView.ts

@ -25,7 +25,6 @@ export default class FormView implements FormType {
fk_view_id: string; fk_view_id: string;
columns?: FormViewColumn[]; columns?: FormViewColumn[];
project_id?: string; project_id?: string;
base_id?: string; base_id?: string;
meta?: string | Record<string, any>; meta?: string | Record<string, any>;

28
packages/nocodb/src/lib/models/FormViewColumn.ts

@ -1,6 +1,11 @@
import Noco from '../Noco'; import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import { FormColumnType } from 'nocodb-sdk'; import {
BoolType,
FormColumnType,
MetaType,
StringOrNullType,
} from 'nocodb-sdk';
import { deserializeJSON, serializeJSON } from '../utils/serialize'; import { deserializeJSON, serializeJSON } from '../utils/serialize';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
@ -8,25 +13,23 @@ import { extractProps } from '../meta/helpers/extractProps';
export default class FormViewColumn implements FormColumnType { export default class FormViewColumn implements FormColumnType {
id?: string; id?: string;
label?: string;
help?: string;
description?: string;
required?: boolean;
show?: boolean;
order?: number;
fk_view_id?: string; fk_view_id?: string;
fk_column_id?: string; fk_column_id?: string;
project_id?: string; project_id?: string;
base_id?: string; base_id?: string;
meta?: string | Record<string, any>; label?: StringOrNullType;
help?: StringOrNullType;
description?: StringOrNullType;
required?: BoolType;
uuid?: StringOrNullType;
show?: BoolType;
order?: number;
meta?: MetaType;
constructor(data: FormViewColumn) { constructor(data: FormViewColumn) {
Object.assign(this, data); Object.assign(this, data);
} }
uuid?: any;
public static async get(formViewColumnId: string, ncMeta = Noco.ncMeta) { public static async get(formViewColumnId: string, ncMeta = Noco.ncMeta) {
let viewColumn = let viewColumn =
formViewColumnId && formViewColumnId &&
@ -187,7 +190,4 @@ export default class FormViewColumn implements FormColumnType {
columnId columnId
); );
} }
created_at?: string;
updated_at?: string;
} }

3
packages/nocodb/src/lib/models/GalleryViewColumn.ts

@ -3,11 +3,12 @@ import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps';
import { BoolType } from 'nocodb-sdk';
export default class GalleryViewColumn { export default class GalleryViewColumn {
id: string; id: string;
title?: string; title?: string;
show?: boolean; show?: BoolType;
order?: number; order?: number;
fk_view_id: string; fk_view_id: string;

4
packages/nocodb/src/lib/models/GridViewColumn.ts

@ -1,13 +1,13 @@
import Noco from '../Noco'; import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import { GridColumnType } from 'nocodb-sdk'; import { BoolType, GridColumnType } from 'nocodb-sdk';
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
export default class GridViewColumn implements GridColumnType { export default class GridViewColumn implements GridColumnType {
id: string; id: string;
show: boolean; show: BoolType;
order: number; order: number;
width?: string; width?: string;

2
packages/nocodb/src/lib/models/Hook.ts

@ -26,7 +26,7 @@ export default class Hook implements HookType {
url?: string; url?: string;
headers?: string; headers?: string;
condition?: BoolType; condition?: BoolType;
notification?: string; notification?: string | object;
retries?: number; retries?: number;
retry_interval?: number; retry_interval?: number;
timeout?: number; timeout?: number;

2
packages/nocodb/src/lib/models/HookFilter.ts

@ -254,7 +254,7 @@ export default class Filter {
const result: FilterType = { const result: FilterType = {
is_group: true, is_group: true,
children: [], children: [],
logical_op: 'AND', logical_op: 'and',
}; };
const grouped = {}; const grouped = {};

3
packages/nocodb/src/lib/models/KanbanViewColumn.ts

@ -3,11 +3,12 @@ import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps';
import { BoolType } from 'nocodb-sdk';
export default class KanbanViewColumn { export default class KanbanViewColumn {
id: string; id: string;
title?: string; title?: string;
show?: boolean; show?: BoolType;
order?: number; order?: number;
fk_view_id: string; fk_view_id: string;

3
packages/nocodb/src/lib/models/LookupColumn.ts

@ -3,8 +3,9 @@ import Column from './Column';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps';
import type { LookupType } from 'nocodb-sdk';
export default class LookupColumn { export default class LookupColumn implements LookupType {
fk_relation_column_id: string; fk_relation_column_id: string;
fk_lookup_column_id: string; fk_lookup_column_id: string;
fk_column_id: string; fk_column_id: string;

4
packages/nocodb/src/lib/models/MapViewColumn.ts

@ -2,11 +2,11 @@ import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { BoolType } from 'nocodb-sdk';
export default class MapViewColumn { export default class MapViewColumn {
id: string; id: string;
title?: string; show?: BoolType;
show?: boolean;
order?: number; order?: number;
fk_view_id: string; fk_view_id: string;

10
packages/nocodb/src/lib/models/Model.ts

@ -5,9 +5,9 @@ import NocoCache from '../cache/NocoCache';
import { XKnex } from '../db/sql-data-mapper'; import { XKnex } from '../db/sql-data-mapper';
import { BaseModelSqlv2 } from '../db/sql-data-mapper/lib/sql/BaseModelSqlv2'; import { BaseModelSqlv2 } from '../db/sql-data-mapper/lib/sql/BaseModelSqlv2';
import { import {
BoolType,
isVirtualCol, isVirtualCol,
ModelTypes, ModelTypes,
BoolType,
TableReqType, TableReqType,
TableType, TableType,
UITypes, UITypes,
@ -27,7 +27,6 @@ import { extractProps } from '../meta/helpers/extractProps';
export default class Model implements TableType { export default class Model implements TableType {
copy_enabled: BoolType; copy_enabled: BoolType;
created_at: Date | number | string;
base_id: 'db' | string; base_id: 'db' | string;
deleted: BoolType; deleted: BoolType;
enabled: BoolType; enabled: BoolType;
@ -42,7 +41,6 @@ export default class Model implements TableType {
show_all_fields: boolean; show_all_fields: boolean;
tags: string; tags: string;
type: ModelTypes; type: ModelTypes;
updated_at: Date | number | string;
table_name: string; table_name: string;
title: string; title: string;
@ -100,8 +98,6 @@ export default class Model implements TableType {
baseId, baseId,
model: Partial<TableReqType> & { model: Partial<TableReqType> & {
mm?: BoolType; mm?: BoolType;
created_at?: any;
updated_at?: any;
type?: ModelTypes; type?: ModelTypes;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
@ -112,8 +108,6 @@ export default class Model implements TableType {
'mm', 'mm',
'order', 'order',
'type', 'type',
'created_at',
'updated_at',
'id', 'id',
]); ]);
@ -152,8 +146,6 @@ export default class Model implements TableType {
title: model.title || model.table_name, title: model.title || model.table_name,
is_default: true, is_default: true,
type: ViewTypes.GRID, type: ViewTypes.GRID,
created_at: model.created_at,
updated_at: model.updated_at,
}, },
ncMeta ncMeta
); );

4
packages/nocodb/src/lib/models/Project.ts

@ -1,4 +1,4 @@
import Base from './/Base'; import Base, { DB_TYPES } from './/Base';
import Noco from '../Noco'; import Noco from '../Noco';
import { BoolType, MetaType, ProjectType } from 'nocodb-sdk'; import { BoolType, MetaType, ProjectType } from 'nocodb-sdk';
import { import {
@ -68,7 +68,7 @@ export default class Project implements ProjectType {
for (const base of project.bases) { for (const base of project.bases) {
await Base.createBase( await Base.createBase(
{ {
type: base.config?.client, type: base.config?.client as typeof DB_TYPES[number],
...base, ...base,
projectId, projectId,
}, },

4
packages/nocodb/src/lib/models/ProjectUser.ts

@ -20,15 +20,13 @@ export default class ProjectUser {
} }
public static async insert( public static async insert(
projectUser: Partial<ProjectUser & { created_at?: any; updated_at?: any }>, projectUser: Partial<ProjectUser>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = extractProps(projectUser, [ const insertObj = extractProps(projectUser, [
'fk_user_id', 'fk_user_id',
'project_id', 'project_id',
'roles', 'roles',
'created_at',
'updated_at',
]); ]);
const { project_id, fk_user_id } = await ncMeta.metaInsert2( const { project_id, fk_user_id } = await ncMeta.metaInsert2(

19
packages/nocodb/src/lib/models/RollupColumn.ts

@ -3,15 +3,24 @@ import Column from './Column';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps';
import type { RollupType } from 'nocodb-sdk';
export default class RollupColumn { export const ROLLUP_FUNCTIONS = <const>[
'count',
'min',
'max',
'avg',
'countDistinct',
'sumDistinct',
'avgDistinct',
];
export default class RollupColumn implements RollupType {
id: string;
fk_column_id; fk_column_id;
fk_relation_column_id; fk_relation_column_id;
fk_rollup_column_id; fk_rollup_column_id;
rollup_function: typeof ROLLUP_FUNCTIONS[number];
rollup_function: string;
id: string;
constructor(data: Partial<RollupColumn>) { constructor(data: Partial<RollupColumn>) {
Object.assign(this, data); Object.assign(this, data);

6
packages/nocodb/src/lib/models/SelectOption.ts

@ -2,8 +2,10 @@ import Noco from '../Noco';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps';
import type { SelectOptionType } from 'nocodb-sdk';
export default class SelectOption { export default class SelectOption implements SelectOptionType {
id: string;
title: string; title: string;
fk_column_id: string; fk_column_id: string;
color: string; color: string;
@ -110,6 +112,4 @@ export default class SelectOption {
return data && new SelectOption(data); return data && new SelectOption(data);
} }
id: string;
} }

4
packages/nocodb/src/lib/models/View.ts

@ -741,8 +741,8 @@ export default class View implements ViewType {
viewId: string, viewId: string,
fkColId: string, fkColId: string,
colData: { colData: {
order: number; order?: number;
show: boolean; show?: BoolType;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
): Promise< ): Promise<

2
packages/nocodb/src/lib/services/attachmentService.ts

@ -11,6 +11,7 @@ export async function upload(param: {
// todo: proper type // todo: proper type
files: unknown[]; files: unknown[];
}) { }) {
// TODO: add getAjvValidatorMw
const filePath = sanitizeUrlPath(param.path?.toString()?.split('/') || ['']); const filePath = sanitizeUrlPath(param.path?.toString()?.split('/') || ['']);
const destPath = path.join('nc', 'uploads', ...filePath); const destPath = path.join('nc', 'uploads', ...filePath);
@ -59,6 +60,7 @@ export async function uploadViaURL(param: {
size?: string | number; size?: string | number;
}[]; }[];
}) { }) {
// TODO: add getAjvValidatorMw
const filePath = sanitizeUrlPath(param?.path?.toString()?.split('/') || ['']); const filePath = sanitizeUrlPath(param?.path?.toString()?.split('/') || ['']);
const destPath = path.join('nc', 'uploads', ...filePath); const destPath = path.join('nc', 'uploads', ...filePath);

2
packages/nocodb/src/lib/services/formViewService.ts

@ -12,7 +12,7 @@ export async function formViewCreate(param: {
tableId: string; tableId: string;
body: FormReqType; body: FormReqType;
}) { }) {
validatePayload('swagger.json#/components/schemas/FormCreateReq', param.body); validatePayload('swagger.json#/components/schemas/FormReq', param.body);
T.emit('evt', { evt_type: 'vtable:created', show_as: 'form' }); T.emit('evt', { evt_type: 'vtable:created', show_as: 'form' });
const view = await View.insert({ const view = await View.insert({

1
packages/nocodb/src/lib/services/projectUserService.ts

@ -252,7 +252,6 @@ export async function projectUserInviteResend(param: {
NcError.badRequest(`User with id '${param.userId}' not found`); NcError.badRequest(`User with id '${param.userId}' not found`);
} }
param.projectUser.roles = user.roles;
const invite_token = uuidv4(); const invite_token = uuidv4();
await User.update(user.id, { await User.update(user.id, {

2
packages/nocodb/src/lib/services/syncService/helpers/job.ts

@ -2078,7 +2078,7 @@ export default async (
const _perfStart = recordPerfStart(); const _perfStart = recordPerfStart();
await api.dbTableSort.create(viewId, { await api.dbTableSort.create(viewId, {
fk_column_id: columnId, fk_column_id: columnId,
direction: s.sortSet[i].ascending ? 'asc' : 'dsc', direction: s.sortSet[i].ascending ? 'asc' : 'desc',
}); });
recordPerfStats(_perfStart, 'dbTableSort.create'); recordPerfStats(_perfStart, 'dbTableSort.create');
} }

15
packages/nocodb/src/lib/services/viewColumnService.ts

@ -1,5 +1,7 @@
import { T } from 'nc-help'; import { T } from 'nc-help';
import { validatePayload } from '../meta/api/helpers';
import { View } from '../models'; import { View } from '../models';
import type { ViewColumnReqType } from 'nocodb-sdk';
export async function columnList(param: { viewId: string }) { export async function columnList(param: { viewId: string }) {
return await View.getColumns(param.viewId); return await View.getColumns(param.viewId);
@ -7,16 +9,17 @@ export async function columnList(param: { viewId: string }) {
export async function columnAdd(param: { export async function columnAdd(param: {
viewId: string; viewId: string;
columnId: string; columnId: string;
// todo: add proper type for grid column in swagger column: ViewColumnReqType;
column: any;
}) { }) {
validatePayload(
'swagger.json#/components/schemas/ViewColumnReq',
param.column
);
const viewColumn = await View.insertOrUpdateColumn( const viewColumn = await View.insertOrUpdateColumn(
param.viewId, param.viewId,
param.columnId, param.columnId,
{ param.column
...param.column,
view_id: param.viewId,
}
); );
T.emit('evt', { evt_type: 'viewColumn:inserted' }); T.emit('evt', { evt_type: 'viewColumn:inserted' });

14
packages/nocodb/src/lib/services/viewService.ts

@ -1,4 +1,5 @@
import { SharedViewType, ViewType } from 'nocodb-sdk'; import { SharedViewReqType, ViewReqType } from 'nocodb-sdk';
import { validatePayload } from '../meta/api/helpers';
import { Model, View } from '../models'; import { Model, View } from '../models';
import { T } from 'nc-help'; import { T } from 'nc-help';
import { xcVisibilityMetaGet } from './modelVisibilityService'; import { xcVisibilityMetaGet } from './modelVisibilityService';
@ -33,8 +34,8 @@ export async function shareView(param: { viewId: string }) {
return await View.share(param.viewId); return await View.share(param.viewId);
} }
// todo: type correctly export async function viewUpdate(param: { viewId: string; view: ViewReqType }) {
export async function viewUpdate(param: { viewId: string; view: ViewType }) { validatePayload('swagger.json#/components/schemas/ViewReq', param.view);
const result = await View.update(param.viewId, param.view); const result = await View.update(param.viewId, param.view);
T.emit('evt', { evt_type: 'vtable:updated', show_as: result.type }); T.emit('evt', { evt_type: 'vtable:updated', show_as: result.type });
return result; return result;
@ -48,9 +49,12 @@ export async function viewDelete(param: { viewId: string }) {
export async function shareViewUpdate(param: { export async function shareViewUpdate(param: {
viewId: string; viewId: string;
// todo: type correctly sharedView: SharedViewReqType;
sharedView: SharedViewType;
}) { }) {
validatePayload(
'swagger.json#/components/schemas/SharedViewReq',
param.sharedView
);
T.emit('evt', { evt_type: 'sharedView:updated' }); T.emit('evt', { evt_type: 'sharedView:updated' });
return await View.update(param.viewId, param.sharedView); return await View.update(param.viewId, param.sharedView);
} }

40
packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts

@ -14,7 +14,7 @@ import {
import Column from '../models/Column'; import Column from '../models/Column';
import LinkToAnotherRecordColumn from '../models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../models/LinkToAnotherRecordColumn';
import NcHelp from '../utils/NcHelp'; import NcHelp from '../utils/NcHelp';
import RollupColumn from '../models/RollupColumn'; import RollupColumn, { ROLLUP_FUNCTIONS } from '../models/RollupColumn';
import View from '../models/View'; import View from '../models/View';
import GridView from '../models/GridView'; import GridView from '../models/GridView';
import KanbanView from '../models/KanbanView'; import KanbanView from '../models/KanbanView';
@ -92,14 +92,10 @@ async function migrateProjects(
is_meta: !!projectConfig.prefix, is_meta: !!projectConfig.prefix,
type: d.client, type: d.client,
config: d, config: d,
created_at: project.created_at,
updated_at: project.updated_at,
inflection_column: inflection.cn, inflection_column: inflection.cn,
inflection_table: inflection.tn, inflection_table: inflection.tn,
}; };
}), }),
created_at: project.created_at,
updated_at: project.updated_at,
}; };
const p = await Project.createProject(projectBody, ncMeta); const p = await Project.createProject(projectBody, ncMeta);
projectsObj[p.id] = p; projectsObj[p.id] = p;
@ -126,8 +122,6 @@ async function migrateProjectUsers(
project_id: projectUser.project_id, project_id: projectUser.project_id,
fk_user_id: projectUser.user_id, fk_user_id: projectUser.user_id,
roles: projectUser.roles, roles: projectUser.roles,
created_at: projectUser.created_at,
updated_at: projectUser.updated_at,
}, },
ncMeta ncMeta
); );
@ -268,8 +262,6 @@ interface ModelMetav1 {
m_to_m_meta: string; m_to_m_meta: string;
order: number; order: number;
view_order: number; view_order: number;
created_at;
updated_at;
} }
type ObjModelColumnRefv1 = { type ObjModelColumnRefv1 = {
@ -406,8 +398,6 @@ async function migrateProjectModels(
title: modelData.alias, title: modelData.alias,
// todo: sanitize // todo: sanitize
type: modelData.type === 'table' ? ModelTypes.TABLE : ModelTypes.VIEW, type: modelData.type === 'table' ? ModelTypes.TABLE : ModelTypes.VIEW,
created_at: modelData.created_at,
updated_at: modelData.updated_at,
mm: !!modelData.mm, mm: !!modelData.mm,
}, },
ncMeta ncMeta
@ -613,7 +603,8 @@ async function migrateProjectModels(
const colBody: Partial<RollupColumn & Column> = { const colBody: Partial<RollupColumn & Column> = {
title: columnMeta._cn, title: columnMeta._cn,
rollup_function: columnMeta.rl.fn, rollup_function: columnMeta.rl
.fn as typeof ROLLUP_FUNCTIONS[number],
}; };
colBody.fk_rollup_column_id = colBody.fk_rollup_column_id =
@ -883,14 +874,7 @@ async function migrateProjectModelViews(
queryParams; queryParams;
const insertObj: Partial< const insertObj: Partial<
View & View & GridView & KanbanView & FormView & GalleryView
GridView &
KanbanView &
FormView &
GalleryView & {
created_at;
updated_at;
}
> = { > = {
title: viewData.title, title: viewData.title,
show: true, show: true,
@ -898,8 +882,6 @@ async function migrateProjectModelViews(
fk_model_id: objModelRef[project.id][viewData.parent_model_title].id, fk_model_id: objModelRef[project.id][viewData.parent_model_title].id,
project_id: project.id, project_id: project.id,
base_id: baseId, base_id: baseId,
created_at: viewData.created_at,
updated_at: viewData.updated_at,
}; };
if (viewData.show_as === 'grid') { if (viewData.show_as === 'grid') {
@ -1082,8 +1064,6 @@ async function migrateUIAcl(ctx: MigrateCtxV1, ncMeta: any) {
tn: string; tn: string;
parent_model_title: string; parent_model_title: string;
project_id: string; project_id: string;
created_at?;
updated_at?;
}> = await ncMeta.metaList(null, null, 'nc_disabled_models_for_role'); }> = await ncMeta.metaList(null, null, 'nc_disabled_models_for_role');
for (const acl of uiAclList) { for (const acl of uiAclList) {
@ -1116,8 +1096,6 @@ async function migrateUIAcl(ctx: MigrateCtxV1, ncMeta: any) {
role: acl.role, role: acl.role,
fk_view_id, fk_view_id,
disabled: acl.disabled, disabled: acl.disabled,
created_at: acl.created_at,
updated_at: acl.updated_at,
}, },
ncMeta ncMeta
); );
@ -1216,8 +1194,6 @@ async function migratePlugins(ncMeta: any) {
creator: plugin.creator, creator: plugin.creator,
creator_website: plugin.creator_website, creator_website: plugin.creator_website,
price: plugin.price, price: plugin.price,
created_at: plugin.created_at,
updated_at: plugin.updated_at,
}); });
} }
} }
@ -1243,8 +1219,6 @@ async function migrateWebhooks(ctx: MigrateCtxV1, ncMeta: any) {
retry_interval: number; retry_interval: number;
timeout: number; timeout: number;
active: boolean; active: boolean;
created_at?;
updated_at?;
}> = await ncMeta.metaList(null, null, 'nc_hooks'); }> = await ncMeta.metaList(null, null, 'nc_hooks');
for (const hookMeta of hooks) { for (const hookMeta of hooks) {
@ -1274,8 +1248,6 @@ async function migrateWebhooks(ctx: MigrateCtxV1, ncMeta: any) {
retry_interval: hookMeta.retry_interval, retry_interval: hookMeta.retry_interval,
timeout: hookMeta.timeout, timeout: hookMeta.timeout,
active: hookMeta.active, active: hookMeta.active,
created_at: hookMeta.created_at,
updated_at: hookMeta.updated_at,
}, },
ncMeta ncMeta
); );
@ -1325,8 +1297,6 @@ async function migrateAutitLog(
status: string; status: string;
description: string; description: string;
details: string; details: string;
created_at: any;
updated_at: any;
}> = await ncMeta.metaList(null, null, 'nc_audit'); }> = await ncMeta.metaList(null, null, 'nc_audit');
for (const audit of audits) { for (const audit of audits) {
@ -1343,8 +1313,6 @@ async function migrateAutitLog(
status: audit.status, status: audit.status,
description: audit.description, description: audit.description,
details: audit.details, details: audit.details,
created_at: audit.created_at,
updated_at: audit.updated_at,
}; };
if (audit.model_name) { if (audit.model_name) {

45
packages/nocodb/src/run/redoc.ts

@ -0,0 +1,45 @@
import express from 'express';
import path from 'path';
const pageContent = `<!DOCTYPE html>
<html>
<head>
<title>NocoDB API Documentation</title>
<!-- needed for adaptive design -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<!--
Redoc doesn't change outer page styles
-->
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<img src="https://static.scarf.sh/a.png?x-pxid=c12a77cc-855e-4602-8a0f-614b2d0da56a"/>
<redoc spec-url='./swagger.json'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@latest/bundles/redoc.standalone.js"></script>
</script>
</body>
</html>`;
const app = express();
app.get('/', function (_req, res) {
res.send(pageContent);
});
app.use(
'/swagger.json',
express.static(path.join(__dirname, '../schema/swagger.json'))
);
app.listen(3001, function () {
console.log(
'Example app listening on port 3001! Go to http://localhost:3001'
);
});

12043
packages/nocodb/src/schema/swagger.json

File diff suppressed because it is too large Load Diff

12
packages/nocodb/tests/unit/factory/project.ts

@ -4,13 +4,13 @@ import Project from '../../../src/lib/models/Project';
const sakilaProjectConfig = (context) => { const sakilaProjectConfig = (context) => {
let base; let base;
if(context.sakilaDbConfig.client === 'mysql2'){ if (context.sakilaDbConfig.client === 'mysql2') {
base = { base = {
type: context.sakilaDbConfig.client, type: context.sakilaDbConfig.client,
config: { config: {
client: context.sakilaDbConfig.client, client: context.sakilaDbConfig.client,
connection: context.sakilaDbConfig.connection connection: context.sakilaDbConfig.connection,
} },
}; };
} else { } else {
base = { base = {
@ -26,7 +26,7 @@ const sakilaProjectConfig = (context) => {
} }
base = { base = {
...base, ...base,
inflection_column: 'camelize', inflection_column: 'camelize',
inflection_table: 'camelize', inflection_table: 'camelize',
}; };
@ -35,7 +35,7 @@ const sakilaProjectConfig = (context) => {
title: 'sakila', title: 'sakila',
bases: [base], bases: [base],
external: true, external: true,
} };
}; };
const defaultProjectValue = { const defaultProjectValue = {
@ -44,7 +44,7 @@ const defaultProjectValue = {
const defaultSharedBaseValue = { const defaultSharedBaseValue = {
roles: 'viewer', roles: 'viewer',
password: 'test', password: 'password123',
}; };
const createSharedBase = async (app, token, project, sharedBaseArgs = {}) => { const createSharedBase = async (app, token, project, sharedBaseArgs = {}) => {

10
packages/nocodb/tests/unit/rest/tests/project.test.ts

@ -159,7 +159,7 @@ function projectTest() {
.set('xc-auth', context.token) .set('xc-auth', context.token)
.send({ .send({
roles: 'viewer', roles: 'viewer',
password: 'test', password: 'password123',
}) })
.expect(200); .expect(200);
@ -168,7 +168,7 @@ function projectTest() {
if ( if (
!updatedProject.uuid || !updatedProject.uuid ||
updatedProject.roles !== 'viewer' || updatedProject.roles !== 'viewer' ||
updatedProject.password !== 'test' updatedProject.password !== 'password123'
) { ) {
return new Error('Shared base not configured properly'); return new Error('Shared base not configured properly');
} }
@ -180,7 +180,7 @@ function projectTest() {
.set('xc-auth', context.token) .set('xc-auth', context.token)
.send({ .send({
roles: 'commenter', roles: 'commenter',
password: 'test', password: 'password123',
}) })
.expect(200); .expect(200);
@ -199,7 +199,7 @@ function projectTest() {
.set('xc-auth', context.token) .set('xc-auth', context.token)
.send({ .send({
roles: 'commenter', roles: 'commenter',
password: 'test', password: 'password123',
}) })
.expect(200); .expect(200);
@ -218,7 +218,7 @@ function projectTest() {
.set('xc-auth', context.token) .set('xc-auth', context.token)
.send({ .send({
roles: 'editor', roles: 'editor',
password: 'test', password: 'password123',
}) })
.expect(200); .expect(200);
const updatedProject = await Project.getByTitleOrId(project.id); const updatedProject = await Project.getByTitleOrId(project.id);

Loading…
Cancel
Save