Browse Source

Merge branch 'develop' into feat/data-apis

pull/5747/head
Pranav C 1 year ago committed by GitHub
parent
commit
8bd1590b44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      packages/nc-gui/components/smartsheet/Pagination.vue
  2. 4
      packages/nc-gui/components/smartsheet/header/Icon.vue
  3. 2
      packages/nc-gui/components/tabs/Smartsheet.vue
  4. 1
      packages/nc-gui/components/virtual-cell/components/ItemChip.vue
  5. 1
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  6. 1
      packages/nc-gui/components/virtual-cell/components/ListItems.vue
  7. 4
      packages/nc-gui/composables/useMultiSelect/index.ts
  8. 2
      packages/nc-gui/package-lock.json
  9. 2
      packages/nc-lib-gui/package.json
  10. 4
      packages/nocodb-sdk/package-lock.json
  11. 2
      packages/nocodb-sdk/package.json
  12. 20
      packages/nocodb/package-lock.json
  13. 4
      packages/nocodb/package.json
  14. 2
      packages/nocodb/src/controllers/test/TestResetService/index.ts
  15. 178
      packages/nocodb/src/db/BaseModelSqlv2.ts
  16. 41
      packages/nocodb/src/db/sql-client/lib/mssql/MssqlClient.ts
  17. 2
      packages/nocodb/src/db/sql-client/lib/oracle/OracleClient.ts
  18. 2
      packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts
  19. 73
      packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts
  20. 1
      packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts
  21. 43
      packages/nocodb/src/db/sql-data-mapper/lib/BaseModel.ts
  22. 2
      packages/nocodb/src/db/sql-migrator/lib/KnexMigrator.ts
  23. 1
      packages/nocodb/src/db/sql-migrator/lib/KnexMigratorv2.ts
  24. 2
      packages/nocodb/src/helpers/apiMetrics.ts
  25. 2
      packages/nocodb/src/helpers/webhookHelpers.ts
  26. 2
      packages/nocodb/src/meta/migrations/v1/nc_011_remove_old_ses_plugin.ts
  27. 1
      packages/nocodb/src/models/Model.ts
  28. 1
      packages/nocodb/src/models/View.ts
  29. 2
      packages/nocodb/src/modules/jobs/jobs/at-import/at-import.controller.ts
  30. 69
      packages/nocodb/src/modules/jobs/jobs/at-import/at-import.processor.ts
  31. 1
      packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts
  32. 38
      packages/nocodb/src/plugins/storage/Local.ts
  33. 4
      packages/nocodb/src/services/auth.service.ts
  34. 8
      packages/nocodb/src/services/tables.service.ts
  35. 1
      packages/nocodb/src/utils/common/XcAudit.ts

6
packages/nc-gui/components/smartsheet/Pagination.vue

@ -2,9 +2,11 @@
import { ChangePageInj, PaginationDataInj, computed, iconMap, inject, isRtlLang, useI18n } from '#imports'
import type { Language } from '~/lib'
const props = defineProps<{
interface Props {
alignCountOnRight?: boolean
}>()
}
const { alignCountOnRight } = defineProps<Props>()
const { locale } = useI18n()

4
packages/nc-gui/components/smartsheet/header/Icon.vue

@ -1,8 +1,8 @@
<script lang="ts" setup>
import { ColumnType, isVirtualCol } from 'nocodb-sdk'
import type { ColumnType } from 'nocodb-sdk'
import { isVirtualCol } from 'nocodb-sdk'
const { column } = defineProps<{ column: ColumnType }>()
</script>
<template>

2
packages/nc-gui/components/tabs/Smartsheet.vue

@ -72,7 +72,7 @@ const onDrop = async (event: DragEvent) => {
event.preventDefault()
try {
// Access the dropped data
const data = JSON.parse(event.dataTransfer?.getData('text/json')!)
const data = JSON.parse(event.dataTransfer!.getData('text/json'))
// Do something with the received data
// if dragged item is not from the same base, return

1
packages/nc-gui/components/virtual-cell/components/ItemChip.vue

@ -9,7 +9,6 @@ import {
inject,
isAttachment,
ref,
renderValue,
useExpandedFormDetached,
useLTARStoreOrThrow,
} from '#imports'

1
packages/nc-gui/components/virtual-cell/components/ListChildItems.vue

@ -13,7 +13,6 @@ import {
iconMap,
inject,
ref,
renderValue,
useLTARStoreOrThrow,
useSmartsheetRowStoreOrThrow,
useVModel,

1
packages/nc-gui/components/virtual-cell/components/ListItems.vue

@ -12,7 +12,6 @@ import {
inject,
isDrawerExist,
ref,
renderValue,
useLTARStoreOrThrow,
useSelectedCellKeyupListener,
useSmartsheetRowStoreOrThrow,

4
packages/nc-gui/composables/useMultiSelect/index.ts

@ -26,7 +26,6 @@ import {
useI18n,
useMetas,
useProject,
useUIPermission,
} from '#imports'
const MAIN_MOUSE_PRESSED = 0
@ -80,9 +79,6 @@ export function useMultiSelect(
() => !(activeCell.row === null || activeCell.col === null || isNaN(activeCell.row) || isNaN(activeCell.col)),
)
const { isUIAllowed } = useUIPermission()
const hasEditPermission = $computed(() => isUIAllowed('xcDatatableEditable'))
function makeActive(row: number, col: number) {
if (activeCell.row === row && activeCell.col === col) {
return

2
packages/nc-gui/package-lock.json generated

@ -110,7 +110,7 @@
}
},
"../nocodb-sdk": {
"version": "0.109.5",
"version": "0.109.6",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",

2
packages/nc-lib-gui/package.json

@ -1,6 +1,6 @@
{
"name": "nc-lib-gui",
"version": "0.109.5",
"version": "0.109.6",
"description": "NocoDB GUI",
"author": {
"name": "NocoDB",

4
packages/nocodb-sdk/package-lock.json generated

@ -1,12 +1,12 @@
{
"name": "nocodb-sdk",
"version": "0.109.5",
"version": "0.109.6",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "nocodb-sdk",
"version": "0.109.5",
"version": "0.109.6",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",

2
packages/nocodb-sdk/package.json

@ -1,6 +1,6 @@
{
"name": "nocodb-sdk",
"version": "0.109.5",
"version": "0.109.6",
"description": "NocoDB SDK",
"main": "build/main/index.js",
"typings": "build/main/index.d.ts",

20
packages/nocodb/package-lock.json generated

@ -1,12 +1,12 @@
{
"name": "nocodb",
"version": "0.109.5",
"version": "0.109.6",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "nocodb",
"version": "0.109.5",
"version": "0.109.6",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@google-cloud/storage": "^5.7.2",
@ -80,7 +80,7 @@
"mysql2": "^3.2.0",
"nanoid": "^3.1.20",
"nc-help": "^0.2.87",
"nc-lib-gui": "0.109.5",
"nc-lib-gui": "0.109.6",
"nc-plugin": "^0.1.3",
"ncp": "^2.0.0",
"nocodb-sdk": "file:../nocodb-sdk",
@ -191,7 +191,7 @@
}
},
"../nocodb-sdk": {
"version": "0.109.5",
"version": "0.109.6",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
@ -13158,9 +13158,9 @@
}
},
"node_modules/nc-lib-gui": {
"version": "0.109.5",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.109.5.tgz",
"integrity": "sha512-A6za8yFO167OVd2MnGrzEFAOQ5Nx9UJ5zpk1iH7FC427TEHJOAbvlOYMVa3s7Pb8wjYKhZ5Mr4sBldtY0cKaHA==",
"version": "0.109.6",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.109.6.tgz",
"integrity": "sha512-HX0JuimDTgpliJowNDctjHGvsbkO8SZ1dq/i+WEIce1nlgxdBrOM+/79UlGMaeLWMb3RuU7zNLxpxYvvdoFs4w==",
"dependencies": {
"express": "^4.17.1"
}
@ -28474,9 +28474,9 @@
}
},
"nc-lib-gui": {
"version": "0.109.5",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.109.5.tgz",
"integrity": "sha512-A6za8yFO167OVd2MnGrzEFAOQ5Nx9UJ5zpk1iH7FC427TEHJOAbvlOYMVa3s7Pb8wjYKhZ5Mr4sBldtY0cKaHA==",
"version": "0.109.6",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.109.6.tgz",
"integrity": "sha512-HX0JuimDTgpliJowNDctjHGvsbkO8SZ1dq/i+WEIce1nlgxdBrOM+/79UlGMaeLWMb3RuU7zNLxpxYvvdoFs4w==",
"requires": {
"express": "^4.17.1"
}

4
packages/nocodb/package.json

@ -1,6 +1,6 @@
{
"name": "nocodb",
"version": "0.109.5",
"version": "0.109.6",
"description": "NocoDB Backend",
"main": "dist/bundle.js",
"author": {
@ -113,7 +113,7 @@
"mysql2": "^3.2.0",
"nanoid": "^3.1.20",
"nc-help": "^0.2.87",
"nc-lib-gui": "0.109.5",
"nc-lib-gui": "0.109.6",
"nc-plugin": "^0.1.3",
"ncp": "^2.0.0",
"nocodb-sdk": "file:../nocodb-sdk",

2
packages/nocodb/src/controllers/test/TestResetService/index.ts

@ -1,6 +1,6 @@
import axios from 'axios';
import Project from '../../../models/Project';
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';
// import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';
import Noco from '../../../Noco';
import User from '../../../models/User';
import NocoCache from '../../../cache/NocoCache';

178
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -44,6 +44,7 @@ import genRollupSelectv2 from './genRollupSelectv2';
import conditionV2 from './conditionV2';
import sortV2 from './sortV2';
import { customValidators } from './util/customValidators';
import Transaction = Knex.Transaction;
import type { XKnex } from './CustomKnex';
import type {
XcFilter,
@ -59,7 +60,6 @@ import type {
SelectOption,
} from '../models';
import type { SortType } from 'nocodb-sdk';
import Transaction = Knex.Transaction;
dayjs.extend(utc);
dayjs.extend(timezone);
@ -2710,7 +2710,83 @@ class BaseModelSqlv2 {
qb.del();
const count = (await qb) as any;
const childColumn = await colOptions.getChildColumn();
const parentColumn = await colOptions.getParentColumn();
const parentTable = await parentColumn.getModel();
const childTable = await childColumn.getModel();
await childTable.getColumns();
await parentTable.getColumns();
const childTn = this.getTnPath(childTable);
switch (colOptions.type) {
case 'mm':
{
const vChildCol = await colOptions.getMMChildColumn();
const vTable = await colOptions.getMMModel();
const vTn = this.getTnPath(vTable);
execQueries.push(() =>
this.dbDriver(vTn)
.where({
[vChildCol.column_name]: this.dbDriver(childTn)
.select(childColumn.column_name)
.first(),
})
.delete(),
);
}
break;
case 'hm':
{
// skip if it's an mm table column
const relatedTable = await colOptions.getRelatedTable();
if (relatedTable.mm) {
break;
}
const childColumn = await Column.get({
colId: colOptions.fk_child_column_id,
});
execQueries.push((trx, qb) =>
trx(childTn)
.where({
[childColumn.column_name]: this.dbDriver.from(
qb
.select(parentColumn.column_name)
// .where(_wherePk(parentTable.primaryKeys, rowId))
.first()
.as('___cn_alias'),
),
})
.update({
[childColumn.column_name]: null,
}),
);
}
break;
}
}
const base = await Base.get(this.model.base_id);
trx = await this.dbDriver.transaction();
// unlink LTAR data
if (base.is_meta) {
for (const execQuery of execQueries) {
await execQuery(trx, qb.clone());
}
}
const deleteQb = qb.clone().transacting(trx).del();
const count = (await deleteQb) as any;
await trx.commit();
await this.afterBulkDelete(count, this.dbDriver, cookie, true);
@ -2911,104 +2987,12 @@ class BaseModelSqlv2 {
modelId: this.model.id,
tnPath: this.tnPath,
});
/*
const view = await View.get(this.viewId);
// handle form view data submission
if (
(hookName === 'after.insert' || hookName === 'after.bulkInsert') &&
view.type === ViewTypes.FORM
) {
try {
const formView = await view.getView<FormView>();
const { columns } = await FormView.getWithInfo(formView.fk_view_id);
const allColumns = await this.model.getColumns();
const fieldById = columns.reduce(
(o: Record<string, any>, f: Record<string, any>) => ({
...o,
[f.fk_column_id]: f,
}),
{},
);
let order = 1;
const filteredColumns = allColumns
?.map((c: Record<string, any>) => ({
...c,
fk_column_id: c.id,
fk_view_id: formView.fk_view_id,
...(fieldById[c.id] ? fieldById[c.id] : {}),
order: (fieldById[c.id] && fieldById[c.id].order) || order++,
id: fieldById[c.id] && fieldById[c.id].id,
}))
.sort(
(a: Record<string, any>, b: Record<string, any>) =>
a.order - b.order,
)
.filter(
(f: Record<string, any>) =>
f.show &&
f.uidt !== UITypes.Rollup &&
f.uidt !== UITypes.Lookup &&
f.uidt !== UITypes.Formula &&
f.uidt !== UITypes.QrCode &&
f.uidt !== UITypes.Barcode &&
f.uidt !== UITypes.SpecificDBType,
)
.sort(
(a: Record<string, any>, b: Record<string, any>) =>
a.order - b.order,
)
.map((c: Record<string, any>) => ({
...c,
required: !!(c.required || 0),
}));
const emails = Object.entries(JSON.parse(formView?.email) || {})
.filter((a) => a[1])
.map((a) => a[0]);
if (emails?.length) {
const transformedData = _transformSubmittedFormDataForEmail(
newData,
formView,
filteredColumns,
);
(await NcPluginMgrv2.emailAdapter(false))?.mailSend({
to: emails.join(','),
subject: 'NocoDB Form',
html: ejs.render(formSubmissionEmailTemplate, {
data: transformedData,
tn: this.tnPath,
_tn: this.model.title,
}),
});
}
} catch (e) {
console.log(e);
}
}
try {
const [event, operation] = hookName.split('.');
const hooks = await Hook.list({
fk_model_id: this.model.id,
event,
operation,
});
for (const hook of hooks) {
if (hook.active) {
invokeWebhook(hook, this.model, view, prevData, newData, req?.user);
}
}
} catch (e) {
console.log('hooks :: error', hookName, e);
}*/
}
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected async errorInsert(e, data, trx, cookie) {}
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected async errorUpdate(e, data, trx, cookie) {}
// todo: handle composite primary key
@ -3022,7 +3006,7 @@ class BaseModelSqlv2 {
);
}
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected async errorDelete(e, id, trx, cookie) {}
async validate(columns) {

41
packages/nocodb/src/db/sql-client/lib/mssql/MssqlClient.ts

@ -2101,7 +2101,7 @@ class MssqlClient extends KnexClient {
table = table.onUpdate(relation.ur);
}
if (relation.dr) {
table = table.onDelete(relation.dr);
table.onDelete(relation.dr);
}
})
.toQuery());
@ -2192,28 +2192,31 @@ class MssqlClient extends KnexClient {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table = table.onDelete(args.onDelete);
table.onDelete(args.onDelete);
}
},
);
const upStatement =
this.querySeparator() +
(await this.sqlClient.schema
.table(this.getTnPath(args.childTable), function (table) {
table = table
.foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn)
.on(self.getTnPath(args.parentTable));
const upQb = this.sqlClient.schema.table(
this.getTnPath(args.childTable),
function (table) {
table = table
.foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn)
.on(self.getTnPath(args.parentTable));
if (args.onUpdate) {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table = table.onDelete(args.onDelete);
}
})
.toQuery());
if (args.onUpdate) {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table.onDelete(args.onDelete);
}
},
);
await upQb;
const upStatement = this.querySeparator() + upQb.toQuery();
this.emit(`Success : ${upStatement}`);
@ -2221,7 +2224,7 @@ class MssqlClient extends KnexClient {
this.querySeparator() +
this.sqlClient.schema
.table(this.getTnPath(args.childTable), function (table) {
table = table.dropForeign(args.childColumn, foreignKeyName);
table.dropForeign(args.childColumn, foreignKeyName);
})
.toQuery();

2
packages/nocodb/src/db/sql-client/lib/oracle/OracleClient.ts

@ -1914,7 +1914,7 @@ class OracleClient extends KnexClient {
* @returns {String} message
*/
async totalRecords(_args: any = {}): Promise<Result> {
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const func = this.totalRecords.name;
throw new Error('Function not supported for oracle yet');
}

2
packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts

@ -2359,7 +2359,7 @@ class PGClient extends KnexClient {
table = table.onUpdate(relation.ur);
}
if (relation.dr) {
table = table.onDelete(relation.dr);
table.onDelete(relation.dr);
}
})
.toQuery());

73
packages/nocodb/src/db/sql-client/lib/snowflake/SnowflakeClient.ts

@ -1970,23 +1970,24 @@ class SnowflakeClient extends KnexClient {
relationsList = relationsList.data.list;
for (const relation of relationsList) {
downQuery +=
this.querySeparator() +
(await this.sqlClient.schema
.table(relation.tn, function (table) {
table = table
.foreign(relation.cn, null)
.references(relation.rcn)
.on(relation.rtn);
if (relation.ur) {
table = table.onUpdate(relation.ur);
}
if (relation.dr) {
table = table.onDelete(relation.dr);
}
})
.toQuery());
const downQb = this.sqlClient.schema.table(
relation.tn,
function (table) {
table = table
.foreign(relation.cn, null)
.references(relation.rcn)
.on(relation.rtn);
if (relation.ur) {
table = table.onUpdate(relation.ur);
}
if (relation.dr) {
table.onDelete(relation.dr);
}
},
);
await downQb;
downQuery += this.querySeparator() + downQb.toQuery();
}
let indexList: any = await this.indexList(args);
@ -2060,8 +2061,6 @@ class SnowflakeClient extends KnexClient {
const foreignKeyName = args.foreignKeyName || null;
try {
// s = await this.sqlClient.schema.index(Object.keys(args.columns));
await this.sqlClient.schema.table(args.childTable, (table) => {
table = table
.foreign(args.childColumn, foreignKeyName)
@ -2072,27 +2071,27 @@ class SnowflakeClient extends KnexClient {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table = table.onDelete(args.onDelete);
table.onDelete(args.onDelete);
}
});
const upStatement =
this.querySeparator() +
(await this.sqlClient.schema
.table(args.childTable, (table) => {
table = table
.foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn)
.on(this.getTnPath(args.parentTable));
const upQb = this.sqlClient.schema.table(args.childTable, (table) => {
table = table
.foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn)
.on(this.getTnPath(args.parentTable));
if (args.onUpdate) {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table = table.onDelete(args.onDelete);
}
})
.toQuery());
if (args.onUpdate) {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table.onDelete(args.onDelete);
}
});
await upQb;
const upStatement = this.querySeparator() + upQb.toQuery();
this.emit(`Success : ${upStatement}`);
@ -2100,7 +2099,7 @@ class SnowflakeClient extends KnexClient {
this.querySeparator() +
this.sqlClient.schema
.table(args.childTable, (table) => {
table = table.dropForeign(args.childColumn, foreignKeyName);
table.dropForeign(args.childColumn, foreignKeyName);
})
.toQuery();

1
packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts

@ -1866,6 +1866,7 @@ class SqliteClient extends KnexClient {
/* Filter relations for current table */
if (args.tn) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
relations = relations.filter(
(r) => r.tn === args.tn || r.rtn === args.tn,
);

43
packages/nocodb/src/db/sql-data-mapper/lib/BaseModel.ts

@ -321,7 +321,7 @@ abstract class BaseModel {
* @returns {Object} Table row data
*/
// @ts-ignore
async readByPk(id, { conditionGraph }) {
async readByPk(id) {
try {
return await this._run(
this.$db.select().where(this._wherePk(id)).first(),
@ -704,10 +704,7 @@ abstract class BaseModel {
*/
async exists(id, _) {
try {
return (
Object.keys(await this.readByPk(id, { conditionGraph: null }))
.length !== 0
);
return Object.keys(await this.readByPk(id)).length !== 0;
} catch (e) {
console.log(e);
throw e;
@ -1341,7 +1338,7 @@ abstract class BaseModel {
* @param {Object} data - insert data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async beforeInsert(data, trx?: any, cookie?: {}) {}
/**
@ -1350,7 +1347,7 @@ abstract class BaseModel {
* @param {Object} response - inserted data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async afterInsert(response, trx?: any, cookie?: {}) {}
/**
@ -1360,7 +1357,7 @@ abstract class BaseModel {
* @param {Object} data - insert data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async errorInsert(err, data, trx?: any, cookie?: {}) {}
/**
@ -1369,7 +1366,7 @@ abstract class BaseModel {
* @param {Object} data - update data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async beforeUpdate(data, trx?: any, cookie?: {}) {}
/**
@ -1378,7 +1375,7 @@ abstract class BaseModel {
* @param {Object} response - updated data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async afterUpdate(response, trx?: any, cookie?: {}) {}
/**
@ -1388,7 +1385,7 @@ abstract class BaseModel {
* @param {Object} data - update data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async errorUpdate(err, data, trx?: any, cookie?: {}) {}
/**
@ -1397,7 +1394,7 @@ abstract class BaseModel {
* @param {Object} data - delete data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async beforeDelete(data, trx?: any, cookie?: {}) {}
/**
@ -1406,7 +1403,7 @@ abstract class BaseModel {
* @param {Object} response - Deleted data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async afterDelete(response, trx?: any, cookie?: {}) {}
/**
@ -1416,7 +1413,7 @@ abstract class BaseModel {
* @param {Object} data - delete data
* @param {Object} trx? - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async errorDelete(err, data, trx?: any, cookie?: {}) {}
/**
@ -1425,7 +1422,7 @@ abstract class BaseModel {
* @param {Object[]} data - insert data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async beforeInsertb(data, trx?: any) {}
/**
@ -1434,7 +1431,7 @@ abstract class BaseModel {
* @param {Object[]} response - inserted data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async afterInsertb(response, trx?: any) {}
/**
@ -1444,7 +1441,7 @@ abstract class BaseModel {
* @param {Object} data - delete data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async errorInsertb(err, data, trx?: any) {}
/**
@ -1453,7 +1450,7 @@ abstract class BaseModel {
* @param {Object[]} data - update data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async beforeUpdateb(data, trx?: any) {}
/**
@ -1462,7 +1459,7 @@ abstract class BaseModel {
* @param {Object[]} response - updated data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async afterUpdateb(response, trx?: any) {}
/**
@ -1472,7 +1469,7 @@ abstract class BaseModel {
* @param {Object[]} data - delete data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async errorUpdateb(err, data, trx?: any) {}
/**
@ -1481,7 +1478,7 @@ abstract class BaseModel {
* @param {Object[]} data - delete data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async beforeDeleteb(data, trx?: any) {}
/**
@ -1490,7 +1487,7 @@ abstract class BaseModel {
* @param {Object[]} response - deleted data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async afterDeleteb(response, trx?: any) {}
/**
@ -1500,7 +1497,7 @@ abstract class BaseModel {
* @param {Object[]} data - delete data
* @param {Object} trx - knex transaction reference
*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async errorDeleteb(err, data, trx?: any) {}
}

2
packages/nocodb/src/db/sql-migrator/lib/KnexMigrator.ts

@ -137,6 +137,7 @@ export default class KnexMigrator extends SqlMigrator {
),
);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const dirStat = await promisify(fs.stat)(
path.join(
this.toolDir,
@ -232,6 +233,7 @@ export default class KnexMigrator extends SqlMigrator {
);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const metaStat = await promisify(fs.stat)(
path.join(
this.toolDir,

1
packages/nocodb/src/db/sql-migrator/lib/KnexMigratorv2.ts

@ -114,6 +114,7 @@ export default class KnexMigratorv2 {
}*/
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async _initDbOnFs(base: Base) {
// this.emit(
// 'Creating folder: ',

2
packages/nocodb/src/helpers/apiMetrics.ts

@ -3,7 +3,7 @@ import type { Request } from 'express';
const countMap = {};
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const metrics = async (req: Request, c = 150) => {
if (!req?.route?.path) return;
const event = `a:api:${req.route.path}:${req.method}`;

2
packages/nocodb/src/helpers/webhookHelpers.ts

@ -271,7 +271,7 @@ export async function invokeWebhook(
return;
}
if (hook.condition) {
if (hook.condition && !testHook) {
if (isBulkOperation) {
const filteredData = [];
for (const data of newData) {

2
packages/nocodb/src/meta/migrations/v1/nc_011_remove_old_ses_plugin.ts

@ -5,7 +5,7 @@ const up = async (knex: Knex) => {
await knex('nc_plugins').del().where({ title: 'SES' });
};
const down = async (knex: Knex) => {
const down = async (_: Knex) => {
// await knex('nc_plugins').insert([ses]);
};

1
packages/nocodb/src/models/Model.ts

@ -65,6 +65,7 @@ export default class Model implements TableType {
}
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async getViews(force = false, ncMeta = Noco.ncMeta): Promise<View[]> {
this.views = await View.listWithInfo(this.id, ncMeta);
return this.views;

1
packages/nocodb/src/models/View.ts

@ -1,4 +1,3 @@
import { title } from 'process';
import { isSystemColumn, UITypes, ViewTypes } from 'nocodb-sdk';
import Noco from '../Noco';
import {

2
packages/nocodb/src/modules/jobs/jobs/at-import/at-import.controller.ts

@ -65,7 +65,7 @@ export class AtImportController {
@Post('/api/v1/db/meta/syncs/:syncId/abort')
@HttpCode(200)
async abortImport(@Request() req) {
async abortImport(@Request() _) {
return {};
}
}

69
packages/nocodb/src/modules/jobs/jobs/at-import/at-import.processor.ts

@ -348,32 +348,6 @@ export class AtImportProcessor {
}
};
const nc_DumpTableSchema = async () => {
console.log('[');
// const ncTblList = await api.base.tableList(
// ncCreatedProjectSchema.id,
// syncDB.baseId
// );
const ncTblList = { list: [] };
ncTblList['list'] = await this.tablesService.getAccessibleTables({
projectId: ncCreatedProjectSchema.id,
baseId: syncDB.baseId,
roles: userRole,
});
for (let i = 0; i < ncTblList.list.length; i++) {
// const ncTbl = await api.dbTable.read(ncTblList.list[i].id);
const ncTbl = await this.tablesService.getTableWithAccessibleViews({
tableId: ncTblList.list[i].id,
user: syncDB.user,
});
console.log(JSON.stringify(ncTbl, null, 2));
console.log(',');
}
console.log(']');
};
// retrieve nc column schema from using aTbl field ID as reference
//
const nc_getColumnSchema = async (aTblFieldId) => {
@ -1563,45 +1537,6 @@ export class AtImportProcessor {
return rec;
};
const nocoReadDataSelected = async (projName, table, callback, fields) => {
return new Promise((resolve, reject) => {
base(table.title)
.select({
pageSize: 100,
// maxRecords: 100,
fields: fields,
})
.eachPage(
async function page(records, fetchNextPage) {
// This function (`page`) will get called for each page of records.
// records.forEach(record => callback(table, record));
logBasic(
`:: ${table.title} / ${fields} : ${
recordCnt + 1
} ~ ${(recordCnt += 100)}`,
);
await Promise.all(
records.map((r) => callback(projName, table, r, fields)),
);
// To fetch the next page of records, call `fetchNextPage`.
// If there are more records, `page` will get called again.
// If there are no more records, `done` will get called.
fetchNextPage();
},
function done(err) {
if (err) {
console.error(err);
reject(err);
}
resolve(null);
},
);
});
};
//////////
const nc_isLinkExists = (airtableFieldId) => {
return !!ncLinkMappingTable.find(
(x) => x.aTbl.typeOptions.symmetricColumnId === airtableFieldId,
@ -2294,7 +2229,6 @@ export class AtImportProcessor {
};
///////////////////////////////////////////////////////////////////////////////
let recordCnt = 0;
try {
logBasic('SDK initialized');
logDetailed('Project initialization started');
@ -2374,7 +2308,6 @@ export class AtImportProcessor {
if (syncDB.options.syncData) {
try {
// await nc_DumpTableSchema();
const _perfStart = recordPerfStart();
const ncTblList = { list: [] };
ncTblList['list'] = await this.tablesService.getAccessibleTables({
@ -2404,8 +2337,6 @@ export class AtImportProcessor {
});
recordPerfStats(_perfStart, 'dbTable.read');
recordCnt = 0;
recordsMap[ncTbl.id] = await importData({
projectName: syncDB.projectName,
table: ncTbl,

1
packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts

@ -1214,6 +1214,7 @@ export class ImportService {
storageAdapter as any
).fileReadByStream(linkFile);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
handledLinks = await this.importLinkFromCsvStream({
idMap,
linkStream: linkReadStream,

38
packages/nocodb/src/plugins/storage/Local.ts

@ -3,6 +3,7 @@ import path from 'path';
import { promisify } from 'util';
import mkdirp from 'mkdirp';
import axios from 'axios';
import { NcError } from '../../helpers/catchError';
import { getToolDir } from '../../utils/nc-config';
import type { IStorageAdapterV2, XcFile } from 'nc-plugin';
import type { Readable } from 'stream';
@ -11,7 +12,7 @@ export default class Local implements IStorageAdapterV2 {
constructor() {}
public async fileCreate(key: string, file: XcFile): Promise<any> {
const destPath = path.join(getToolDir(), ...key.split('/'));
const destPath = this.validateAndNormalisePath(key);
try {
await mkdirp(path.dirname(destPath));
const data = await promisify(fs.readFile)(file.path);
@ -24,7 +25,7 @@ export default class Local implements IStorageAdapterV2 {
}
async fileCreateByUrl(key: string, url: string): Promise<any> {
const destPath = path.join(getToolDir(), ...key.split('/'));
const destPath = this.validateAndNormalisePath(key);
return new Promise((resolve, reject) => {
axios
.get(url, {
@ -71,7 +72,7 @@ export default class Local implements IStorageAdapterV2 {
stream: Readable,
): Promise<void> {
return new Promise((resolve, reject) => {
const destPath = path.join(getToolDir(), ...key.split('/'));
const destPath = this.validateAndNormalisePath(key);
try {
mkdirp(path.dirname(destPath)).then(() => {
const writableStream = fs.createWriteStream(destPath);
@ -86,12 +87,12 @@ export default class Local implements IStorageAdapterV2 {
}
public async fileReadByStream(key: string): Promise<Readable> {
const srcPath = path.join(getToolDir(), ...key.split('/'));
const srcPath = this.validateAndNormalisePath(key);
return fs.createReadStream(srcPath, { encoding: 'utf8' });
}
public async getDirectoryList(key: string): Promise<string[]> {
const destDir = path.join(getToolDir(), ...key.split('/'));
const destDir = this.validateAndNormalisePath(key);
return fs.promises.readdir(destDir);
}
@ -103,7 +104,7 @@ export default class Local implements IStorageAdapterV2 {
public async fileRead(filePath: string): Promise<any> {
try {
const fileData = await fs.promises.readFile(
path.join(getToolDir(), ...filePath.split('/')),
this.validateAndNormalisePath(filePath, true),
);
return fileData;
} catch (e) {
@ -118,4 +119,29 @@ export default class Local implements IStorageAdapterV2 {
test(): Promise<boolean> {
return Promise.resolve(false);
}
// method for validate/normalise the path for avoid path traversal attack
protected validateAndNormalisePath(
fileOrFolderPath: string,
throw404 = false,
): string {
// Get the absolute path to the base directory
const absoluteBasePath = path.resolve(getToolDir(), 'nc');
// Get the absolute path to the file
const absolutePath = path.resolve(
path.join(getToolDir(), ...fileOrFolderPath.split('/')),
);
// Check if the resolved path is within the intended directory
if (!absolutePath.startsWith(absoluteBasePath)) {
if (throw404) {
NcError.notFound();
} else {
NcError.badRequest('Invalid path');
}
}
return absolutePath;
}
}

4
packages/nocodb/src/services/auth.service.ts

@ -40,8 +40,8 @@ export class AuthService {
email: _email,
firstname,
lastname,
token,
ignore_subscribe,
// token,
// ignore_subscribe,
} = createUserDto as any;
let { password } = createUserDto;

8
packages/nocodb/src/services/tables.service.ts

@ -14,13 +14,7 @@ import getColumnPropsFromUIDT from '../helpers/getColumnPropsFromUIDT';
import getColumnUiType from '../helpers/getColumnUiType';
import getTableNameAlias, { getColumnNameAlias } from '../helpers/getTableName';
import mapDefaultDisplayValue from '../helpers/mapDefaultDisplayValue';
import {
Audit,
Column,
Model,
ModelRoleVisibility,
Project,
} from '../models';
import { Audit, Column, Model, ModelRoleVisibility, Project } from '../models';
import Noco from '../Noco';
import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2';
import { validatePayload } from '../helpers';

1
packages/nocodb/src/utils/common/XcAudit.ts

@ -9,5 +9,6 @@ export default class XcAudit {
private static app: Noco;
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public static async log(data: { project }) {}
}

Loading…
Cancel
Save