Browse Source

Merge pull request #5727 from nocodb/develop

pull/5728/head 0.107.4
github-actions[bot] 1 year ago committed by GitHub
parent
commit
890123c854
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 64
      packages/nc-gui/package-lock.json
  2. 2
      packages/nc-gui/package.json
  3. 10
      packages/noco-docs/content/en/engineering/development-setup.md
  4. 4
      packages/nocodb-sdk/package-lock.json
  5. 4
      packages/nocodb/Dockerfile
  6. 4
      packages/nocodb/Dockerfile.local
  7. 42
      packages/nocodb/package-lock.json
  8. 6
      packages/nocodb/package.json
  9. 2
      packages/nocodb/src/Noco.ts
  10. 3
      packages/nocodb/src/app.module.ts
  11. 281
      packages/nocodb/src/helpers/initAdminFromEnv.ts
  12. 7
      packages/nocodb/src/middlewares/public/public.middleware.spec.ts
  13. 23
      packages/nocodb/src/middlewares/public/public.middleware.ts
  14. 4
      packages/nocodb/src/models/Base.ts
  15. 34
      packages/nocodb/src/models/Model.ts
  16. 0
      packages/nocodb/src/public/css/fonts.montserrat.css
  17. 0
      packages/nocodb/src/public/css/fonts.roboto.css
  18. 0
      packages/nocodb/src/public/css/materialdesignicons.5.x.min.css
  19. 0
      packages/nocodb/src/public/css/swagger-ui-bundle.4.5.2.min.css
  20. 0
      packages/nocodb/src/public/css/vuetify.2.x.min.css
  21. 0
      packages/nocodb/src/public/favicon.ico
  22. 0
      packages/nocodb/src/public/icon.png
  23. 0
      packages/nocodb/src/public/js/axios.0.19.2.min.js
  24. 0
      packages/nocodb/src/public/js/redoc.standalone.min.js
  25. 0
      packages/nocodb/src/public/js/swagger-ui-bundle.4.5.2.min.js
  26. 0
      packages/nocodb/src/public/js/vue.2.6.14.min.js
  27. 0
      packages/nocodb/src/public/js/vue.global.js
  28. 0
      packages/nocodb/src/public/js/vuetify.2.x.min.js
  29. 15
      packages/nocodb/src/services/app-init.service.ts
  30. 5
      packages/nocodb/src/strategies/authtoken.strategy/authtoken.strategy.ts
  31. 2
      packages/nocodb/src/version-upgrader/NcUpgrader.ts
  32. 48
      packages/nocodb/src/version-upgrader/ncProjectConfigUpgrader.ts
  33. 2
      packages/nocodb/webpack.config.js

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

@ -30,7 +30,7 @@
"leaflet.markercluster": "^1.5.3",
"locale-codes": "^1.3.1",
"monaco-editor": "^0.33.0",
"nocodb-sdk": "0.107.3",
"nocodb-sdk": "file:../nocodb-sdk",
"papaparse": "^5.3.2",
"pinia": "^2.0.33",
"qrcode": "^1.5.1",
@ -111,7 +111,6 @@
},
"../nocodb-sdk": {
"version": "0.107.3",
"extraneous": true,
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
@ -8776,6 +8775,7 @@
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true,
"funding": [
{
"type": "individual",
@ -12294,21 +12294,8 @@
}
},
"node_modules/nocodb-sdk": {
"version": "0.107.3",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.107.3.tgz",
"integrity": "sha512-82gi9BcGOtNnwR4zmLVSyNXzIen4ZN0hMnzW4E52dlxFzBteezGd+DYiLyoqJba1rPlA11QMLgqOscl5SPy7fw==",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
},
"node_modules/nocodb-sdk/node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
"resolved": "../nocodb-sdk",
"link": true
},
"node_modules/node-abi": {
"version": "3.23.0",
@ -15258,9 +15245,9 @@
}
},
"node_modules/socket.io-parser": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
@ -24810,7 +24797,8 @@
"follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true
},
"form-data": {
"version": "4.0.0",
@ -27360,22 +27348,22 @@
}
},
"nocodb-sdk": {
"version": "0.107.3",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.107.3.tgz",
"integrity": "sha512-82gi9BcGOtNnwR4zmLVSyNXzIen4ZN0hMnzW4E52dlxFzBteezGd+DYiLyoqJba1rPlA11QMLgqOscl5SPy7fw==",
"version": "file:../nocodb-sdk",
"requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1",
"jsep": "^1.3.6"
},
"dependencies": {
"axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
"follow-redirects": "^1.14.0"
}
}
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
}
},
"node-abi": {
@ -29560,9 +29548,9 @@
}
},
"socket.io-parser": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"

2
packages/nc-gui/package.json

@ -54,7 +54,7 @@
"leaflet.markercluster": "^1.5.3",
"locale-codes": "^1.3.1",
"monaco-editor": "^0.33.0",
"nocodb-sdk": "0.107.3",
"nocodb-sdk": "file:../nocodb-sdk",
"papaparse": "^5.3.2",
"pinia": "^2.0.33",
"qrcode": "^1.5.1",

10
packages/noco-docs/content/en/engineering/development-setup.md

@ -51,4 +51,14 @@ For Playwright tests, screenshots are captured on the tests. These will provide
![Screenshot 2022-09-29 at 12 43 37 PM](https://user-images.githubusercontent.com/86527202/192965070-dc04b952-70fb-4197-b4bd-ca7eda066e60.png)
## Accessing 'Easter egg' menu
Double click twice on empty space between `View list` & `Share` button to the left top of Grid view; following options become accessible
1. Export Cache
2. Delete Cache
3. Debug Meta
4. Toggle Beta Features
![Screenshot 2023-05-23 at 8 35 14 PM](https://github.com/nocodb/nocodb/assets/86527202/fe2765fa-5796-4d26-8c12-e71b8226872e)

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

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

4
packages/nocodb/Dockerfile

@ -31,9 +31,7 @@ COPY ./package*.json ./
COPY ./docker/main.js ./docker/main.js
#COPY ./docker/start.sh /usr/src/appEntry/start.sh
COPY ./docker/start-litestream.sh /usr/src/appEntry/start.sh
COPY ./public/css/*.css ./docker/public/css/
COPY ./public/js/*.js ./docker/public/js/
COPY ./public/favicon.ico ./docker/public/
COPY src/public/ ./docker/public/
# install production dependencies,
# reduce node_module size with modclean & removing sqlite deps,

4
packages/nocodb/Dockerfile.local

@ -14,9 +14,7 @@ COPY ./package*.json ./
COPY ./docker/nc-gui/ ./docker/nc-gui/
COPY ./docker/main.js ./docker/index.js
COPY ./docker/start-local.sh /usr/src/appEntry/start.sh
COPY ./public/css/*.css ./docker/public/css/
COPY ./public/js/*.js ./docker/public/js/
COPY ./public/favicon.ico ./docker/public/
COPY src/public/ ./docker/public/
# install production dependencies,
# reduce node_module size with modclean & removing sqlite deps,

42
packages/nocodb/package-lock.json generated

@ -83,7 +83,7 @@
"nc-lib-gui": "0.107.3",
"nc-plugin": "^0.1.3",
"ncp": "^2.0.0",
"nocodb-sdk": "0.107.3",
"nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10",
"object-hash": "^3.0.0",
"os-locale": "^6.0.2",
@ -191,7 +191,6 @@
},
"../nocodb-sdk": {
"version": "0.107.3",
"extraneous": true,
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
@ -13207,13 +13206,8 @@
}
},
"node_modules/nocodb-sdk": {
"version": "0.107.3",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.107.3.tgz",
"integrity": "sha512-82gi9BcGOtNnwR4zmLVSyNXzIen4ZN0hMnzW4E52dlxFzBteezGd+DYiLyoqJba1rPlA11QMLgqOscl5SPy7fw==",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
"resolved": "../nocodb-sdk",
"link": true
},
"node_modules/node-abort-controller": {
"version": "3.1.1",
@ -15803,9 +15797,9 @@
}
},
"node_modules/socket.io-parser": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz",
"integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
@ -28485,12 +28479,22 @@
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="
},
"nocodb-sdk": {
"version": "0.107.3",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.107.3.tgz",
"integrity": "sha512-82gi9BcGOtNnwR4zmLVSyNXzIen4ZN0hMnzW4E52dlxFzBteezGd+DYiLyoqJba1rPlA11QMLgqOscl5SPy7fw==",
"version": "file:../nocodb-sdk",
"requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1",
"jsep": "^1.3.6"
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
}
},
"node-abort-controller": {
@ -30440,9 +30444,9 @@
}
},
"socket.io-parser": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz",
"integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"

6
packages/nocodb/package.json

@ -32,6 +32,8 @@
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"watch:run": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/docker --log-error --project tsconfig.json\"",
"watch:run:mysql": "cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/dockerRunMysql --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\"",
"watch:run:playwright": "rm -f ./test_noco.db; cross-env DATABASE_URL=sqlite:./test_noco.db PLAYWRIGHT_TEST=true NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/testDocker --log-error --project tsconfig.json\"",
"watch:run:playwright:quick": "rm -f ./test_noco.db; cp ../../tests/playwright/fixtures/noco_0_91_7.db ./test_noco.db; cross-env DATABASE_URL=sqlite:./test_noco.db NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/docker --log-error --project tsconfig.json\"",
"watch:run:playwright:pg:cyquick": "rm -f ./test_noco.db; cp ../../tests/playwright/fixtures/noco_0_91_7.db ./test_noco.db; cross-env NC_DISABLE_TELE=true EE=true nodemon -e ts,js -w ./src -x \"ts-node src/run/dockerRunPG_CyQuick.ts --log-error --project tsconfig.json\"",
@ -114,7 +116,7 @@
"nc-lib-gui": "0.107.3",
"nc-plugin": "^0.1.3",
"ncp": "^2.0.0",
"nocodb-sdk": "0.107.3",
"nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10",
"object-hash": "^3.0.0",
"os-locale": "^6.0.2",
@ -201,4 +203,4 @@
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
}

2
packages/nocodb/src/Noco.ts

@ -1,5 +1,6 @@
import Sentry, { Handlers } from '@sentry/node';
import { Logger } from '@nestjs/common';
import path from 'path';
import { NestFactory } from '@nestjs/core';
import clear from 'clear';
import * as express from 'express';
@ -122,6 +123,7 @@ export default class Noco {
const dashboardPath = process.env.NC_DASHBOARD_URL || '/dashboard';
server.use(NcToolGui.expressMiddleware(dashboardPath));
server.use(express.static(path.join(__dirname, 'public')));
server.get('/', (_req, res) => res.redirect(dashboardPath));
this.initSentryErrorHandler(server);

3
packages/nocodb/src/app.module.ts

@ -5,7 +5,6 @@ import { EventEmitterModule as NestJsEventEmitter } from '@nestjs/event-emitter'
import { GlobalExceptionFilter } from './filters/global-exception/global-exception.filter';
import { GlobalMiddleware } from './middlewares/global/global.middleware';
import { GuiMiddleware } from './middlewares/gui/gui.middleware';
import { PublicMiddleware } from './middlewares/public/public.middleware';
import { DatasModule } from './modules/datas/datas.module';
import { EventEmitterModule } from './modules/event-emitter/event-emitter.module';
import { AuthService } from './services/auth.service';
@ -59,8 +58,6 @@ export class AppModule {
consumer
.apply(GuiMiddleware)
.forRoutes({ path: '*', method: RequestMethod.GET })
.apply(PublicMiddleware)
.forRoutes({ path: '*', method: RequestMethod.GET })
.apply(GlobalMiddleware)
.forRoutes({ path: '*', method: RequestMethod.ALL });
}

281
packages/nocodb/src/helpers/initAdminFromEnv.ts

@ -0,0 +1,281 @@
import { promisify } from 'util';
import { v4 as uuidv4 } from 'uuid';
import bcrypt from 'bcryptjs';
import { validatePassword } from 'nocodb-sdk';
import boxen from 'boxen';
import { T } from 'nc-help';
import { isEmail } from 'validator';
import NocoCache from '../cache/NocoCache';
import { ProjectUser, User } from '../models';
import Noco from '../Noco';
import { CacheScope, MetaTable } from '../utils/globals';
const rolesLevel = { owner: 0, creator: 1, editor: 2, commenter: 3, viewer: 4 };
export default async function initAdminFromEnv(_ncMeta = Noco.ncMeta) {
if (process.env.NC_ADMIN_EMAIL && process.env.NC_ADMIN_PASSWORD) {
if (!isEmail(process.env.NC_ADMIN_EMAIL?.trim())) {
console.log(
'\n',
boxen(
`Provided admin email '${process.env.NC_ADMIN_EMAIL}' is not valid`,
{
title: 'Invalid admin email',
padding: 1,
borderStyle: 'double',
titleAlignment: 'center',
borderColor: 'red',
},
),
'\n',
);
process.exit(1);
}
const { valid, error, hint } = validatePassword(
process.env.NC_ADMIN_PASSWORD,
);
if (!valid) {
console.log(
'\n',
boxen(`${error}${hint ? `\n\n${hint}` : ''}`, {
title: 'Invalid admin password',
padding: 1,
borderStyle: 'double',
titleAlignment: 'center',
borderColor: 'red',
}),
'\n',
);
process.exit(1);
}
let ncMeta;
try {
ncMeta = await _ncMeta.startTransaction();
const email = process.env.NC_ADMIN_EMAIL.toLowerCase().trim();
const salt = await promisify(bcrypt.genSalt)(10);
const password = await promisify(bcrypt.hash)(
process.env.NC_ADMIN_PASSWORD,
salt,
);
const email_verification_token = uuidv4();
const roles = 'user,super';
// if super admin not present
if (await User.isFirst(ncMeta)) {
// roles = 'owner,creator,editor'
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});
await User.insert(
{
firstname: '',
lastname: '',
email,
salt,
password,
email_verification_token,
roles,
},
ncMeta,
);
} else {
const salt = await promisify(bcrypt.genSalt)(10);
const password = await promisify(bcrypt.hash)(
process.env.NC_ADMIN_PASSWORD,
salt,
);
const email_verification_token = uuidv4();
const superUser = await ncMeta.metaGet2(null, null, MetaTable.USERS, {
roles: 'user,super',
});
if (!superUser?.id) {
const existingUserWithNewEmail = await User.getByEmail(email, ncMeta);
if (existingUserWithNewEmail?.id) {
// clear cache
await NocoCache.delAll(
CacheScope.USER,
`${existingUserWithNewEmail.email}___*`,
);
await NocoCache.del(
`${CacheScope.USER}:${existingUserWithNewEmail.id}`,
);
await NocoCache.del(
`${CacheScope.USER}:${existingUserWithNewEmail.email}`,
);
// Update email and password of super admin account
await User.update(
existingUserWithNewEmail.id,
{
salt,
email,
password,
email_verification_token,
token_version: null,
refresh_token: null,
roles,
},
ncMeta,
);
} else {
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});
await User.insert(
{
firstname: '',
lastname: '',
email,
salt,
password,
email_verification_token,
roles,
},
ncMeta,
);
}
} else if (email !== superUser.email) {
// update admin email and password and migrate projects
// if user already present and associated with some project
// check user account already present with the new admin email
const existingUserWithNewEmail = await User.getByEmail(email, ncMeta);
if (existingUserWithNewEmail?.id) {
// get all project access belongs to the existing account
// and migrate to the admin account
const existingUserProjects = await ncMeta.metaList2(
null,
null,
MetaTable.PROJECT_USERS,
{
condition: { fk_user_id: existingUserWithNewEmail.id },
},
);
for (const existingUserProject of existingUserProjects) {
const userProject = await ProjectUser.get(
existingUserProject.project_id,
superUser.id,
ncMeta,
);
// if admin user already have access to the project
// then update role based on the highest access level
if (userProject) {
if (
rolesLevel[userProject.roles] >
rolesLevel[existingUserProject.roles]
) {
await ProjectUser.update(
userProject.project_id,
superUser.id,
existingUserProject.roles,
ncMeta,
);
}
} else {
// if super doesn't have access then add the access
await ProjectUser.insert(
{
...existingUserProject,
fk_user_id: superUser.id,
},
ncMeta,
);
}
// delete the old project access entry from DB
await ProjectUser.delete(
existingUserProject.project_id,
existingUserProject.fk_user_id,
ncMeta,
);
}
// delete existing user
await ncMeta.metaDelete(
null,
null,
MetaTable.USERS,
existingUserWithNewEmail.id,
);
// clear cache
await NocoCache.delAll(
CacheScope.USER,
`${existingUserWithNewEmail.email}___*`,
);
await NocoCache.del(
`${CacheScope.USER}:${existingUserWithNewEmail.id}`,
);
await NocoCache.del(
`${CacheScope.USER}:${existingUserWithNewEmail.email}`,
);
// Update email and password of super admin account
await User.update(
superUser.id,
{
salt,
email,
password,
email_verification_token,
token_version: null,
refresh_token: null,
},
ncMeta,
);
} else {
// if email's are not different update the password and hash
await User.update(
superUser.id,
{
salt,
email,
password,
email_verification_token,
token_version: null,
refresh_token: null,
},
ncMeta,
);
}
} else {
const newPasswordHash = await promisify(bcrypt.hash)(
process.env.NC_ADMIN_PASSWORD,
superUser.salt,
);
if (newPasswordHash !== superUser.password) {
// if email's are same and passwords are different
// then update the password and token version
await User.update(
superUser.id,
{
salt,
password,
email_verification_token,
token_version: null,
refresh_token: null,
},
ncMeta,
);
}
}
}
await ncMeta.commit();
} catch (e) {
console.log('Error occurred while updating/creating admin user');
console.log(e);
await ncMeta.rollback(e);
}
}
}

7
packages/nocodb/src/middlewares/public/public.middleware.spec.ts

@ -1,7 +0,0 @@
import { PublicMiddleware } from './public.middleware';
describe('PublicMiddleware', () => {
it('should be defined', () => {
expect(new PublicMiddleware()).toBeDefined();
});
});

23
packages/nocodb/src/middlewares/public/public.middleware.ts

@ -1,23 +0,0 @@
import path, { join } from 'path';
import { Injectable } from '@nestjs/common';
import express from 'express';
import isDocker from 'is-docker';
import type { NestMiddleware } from '@nestjs/common';
@Injectable()
export class PublicMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
// redirect root to dashboard
if (req.path === '/') {
const dashboardPath = process.env.NC_DASHBOARD_URL || '/dashboard';
return res.redirect(dashboardPath);
}
// serve static files from public folder
if (isDocker()) {
express.static(join(process.cwd(), 'docker', 'public'))(req, res, next);
} else {
express.static(join(process.cwd(), 'public'))(req, res, next);
}
}
}

4
packages/nocodb/src/models/Base.ts

@ -91,6 +91,7 @@ export default class Base implements BaseType {
base: BaseType & {
id: string;
projectId: string;
skipReorder?: boolean;
},
ncMeta = Noco.ncMeta,
) {
@ -144,7 +145,8 @@ export default class Base implements BaseType {
// call before reorder to update cache
const returnBase = await this.get(oldBase.id, ncMeta);
await this.reorderBases(base.projectId, returnBase.id, ncMeta);
if (!base.skipReorder)
await this.reorderBases(base.projectId, returnBase.id, ncMeta);
return returnBase;
}

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

@ -135,7 +135,15 @@ export default class Model implements TableType {
MetaTable.MODELS,
insertObj,
);
if (baseId) {
await NocoCache.appendToList(
CacheScope.MODEL,
[projectId, baseId],
`${CacheScope.MODEL}:${id}`,
);
}
// cater cases where baseId is not required
// e.g. xcVisibilityMetaGet
await NocoCache.appendToList(
CacheScope.MODEL,
[projectId],
@ -169,7 +177,10 @@ export default class Model implements TableType {
},
ncMeta = Noco.ncMeta,
): Promise<Model[]> {
const cachedList = await NocoCache.getList(CacheScope.MODEL, [project_id]);
const cachedList = await NocoCache.getList(CacheScope.MODEL, [
project_id,
base_id,
]);
let { list: modelList } = cachedList;
const { isNoneList } = cachedList;
if (!isNoneList && !modelList.length) {
@ -189,7 +200,11 @@ export default class Model implements TableType {
model.meta = parseMetaProp(model);
}
await NocoCache.setList(CacheScope.MODEL, [project_id], modelList);
await NocoCache.setList(
CacheScope.MODEL,
[project_id, base_id],
modelList,
);
}
modelList.sort(
(a, b) =>
@ -683,13 +698,13 @@ export default class Model implements TableType {
},
ncMeta = Noco.ncMeta,
) {
const cacheKey = base_id
? `${CacheScope.MODEL}:${project_id}:${base_id}:${aliasOrId}`
: `${CacheScope.MODEL}:${project_id}:${aliasOrId}`;
const modelId =
project_id &&
aliasOrId &&
(await NocoCache.get(
`${CacheScope.MODEL}:${project_id}:${aliasOrId}`,
CacheGetType.TYPE_OBJECT,
));
(await NocoCache.get(cacheKey, CacheGetType.TYPE_OBJECT));
if (!modelId) {
const model = base_id
? await ncMeta.metaGet2(
@ -735,10 +750,7 @@ export default class Model implements TableType {
},
);
if (model) {
await NocoCache.set(
`${CacheScope.MODEL}:${project_id}:${aliasOrId}`,
model.id,
);
await NocoCache.set(cacheKey, model.id);
await NocoCache.set(`${CacheScope.MODEL}:${model.id}`, model);
}
return model && new Model(model);

0
packages/nocodb/public/css/fonts.montserrat.css → packages/nocodb/src/public/css/fonts.montserrat.css

0
packages/nocodb/public/css/fonts.roboto.css → packages/nocodb/src/public/css/fonts.roboto.css

0
packages/nocodb/public/css/materialdesignicons.5.x.min.css → packages/nocodb/src/public/css/materialdesignicons.5.x.min.css vendored

0
packages/nocodb/public/css/swagger-ui-bundle.4.5.2.min.css → packages/nocodb/src/public/css/swagger-ui-bundle.4.5.2.min.css vendored

0
packages/nocodb/public/css/vuetify.2.x.min.css → packages/nocodb/src/public/css/vuetify.2.x.min.css vendored

0
packages/nocodb/public/favicon.ico → packages/nocodb/src/public/favicon.ico

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

0
packages/nocodb/public/icon.png → packages/nocodb/src/public/icon.png

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

0
packages/nocodb/public/js/axios.0.19.2.min.js → packages/nocodb/src/public/js/axios.0.19.2.min.js vendored

0
packages/nocodb/public/js/redoc.standalone.min.js → packages/nocodb/src/public/js/redoc.standalone.min.js vendored

0
packages/nocodb/public/js/swagger-ui-bundle.4.5.2.min.js → packages/nocodb/src/public/js/swagger-ui-bundle.4.5.2.min.js vendored

0
packages/nocodb/public/js/vue.2.6.14.min.js → packages/nocodb/src/public/js/vue.2.6.14.min.js vendored

0
packages/nocodb/public/js/vue.global.js → packages/nocodb/src/public/js/vue.global.js

0
packages/nocodb/public/js/vuetify.2.x.min.js → packages/nocodb/src/public/js/vuetify.2.x.min.js vendored

15
packages/nocodb/src/services/app-init.service.ts

@ -1,9 +1,12 @@
import { Inject, Injectable } from '@nestjs/common';
import { T } from 'nc-help';
import NocoCache from '../cache/NocoCache';
import { Connection } from '../connection/connection';
import initAdminFromEnv from '../helpers/initAdminFromEnv';
import NcPluginMgrv2 from '../helpers/NcPluginMgrv2';
import { MetaService } from '../meta/meta.service';
import { User } from '../models'
import Noco from '../Noco';
import getInstance from '../utils/getInstance';
import NcConfigFactory from '../utils/NcConfigFactory';
import NcUpgrader from '../version-upgrader/NcUpgrader';
import type { IEventEmitter } from '../modules/event-emitter/event-emitter.interface';
@ -35,7 +38,7 @@ export const appInitServiceProvider: Provider = {
metaService: MetaService,
eventEmitter: IEventEmitter,
) => {
process.env.NC_VERSION = '0105004';
process.env.NC_VERSION = '0107004';
await NocoCache.init();
@ -54,6 +57,9 @@ export const appInitServiceProvider: Provider = {
// init jwt secret
await Noco.initJwt();
// load super admin user from env if env is set
await initAdminFromEnv(metaService);
// init plugin manager
await NcPluginMgrv2.init(Noco.ncMeta);
await Noco.loadEEState();
@ -61,6 +67,11 @@ export const appInitServiceProvider: Provider = {
// run upgrader
await NcUpgrader.upgrade({ ncMeta: Noco._ncMeta });
T.init({
instance: getInstance,
});
T.emit('evt_app_started', await User.count());
// todo: move app config to app-init service
return new AppInitService(connection.config);
},

5
packages/nocodb/src/strategies/authtoken.strategy/authtoken.strategy.ts

@ -26,6 +26,11 @@ export class AuthTokenStrategy extends PassportStrategy(Strategy, 'authtoken') {
return callback({ msg: 'User not found' });
}
Object.assign(user, {
id: dbUser.id,
roles: dbUser.roles,
});
dbUser.is_api_token = true;
if (req['ncProjectId']) {
const projectUser = await ProjectUser.get(

2
packages/nocodb/src/version-upgrader/NcUpgrader.ts

@ -13,6 +13,7 @@ import ncProjectUpgraderV2_0090000 from './ncProjectUpgraderV2_0090000';
import ncProjectEnvUpgrader0011045 from './ncProjectEnvUpgrader0011045';
import ncProjectEnvUpgrader from './ncProjectEnvUpgrader';
import ncHookUpgrader from './ncHookUpgrader';
import ncProjectConfigUpgrader from './ncProjectConfigUpgrader';
import type { MetaService } from '../meta/meta.service';
import type { NcConfig } from '../interface/config';
@ -48,6 +49,7 @@ export default class NcUpgrader {
{ name: '0105002', handler: ncStickyColumnUpgrader },
{ name: '0105003', handler: ncFilterUpgrader_0105003 },
{ name: '0105004', handler: ncHookUpgrader },
{ name: '0107004', handler: ncProjectConfigUpgrader },
];
if (!(await ctx.ncMeta.knexConnection?.schema?.hasTable?.('nc_store'))) {
return;

48
packages/nocodb/src/version-upgrader/ncProjectConfigUpgrader.ts

@ -0,0 +1,48 @@
import CryptoJS from 'crypto-js';
import { Base } from '../models';
import { MetaTable } from '../utils/globals';
import type { NcUpgraderCtx } from './NcUpgrader';
const TEMP_KEY = 'temporary-key';
// In version 0.107.0 we were used a temporary fallback secret key for JWT token encryption and project base config encryption.
// So any project created in version 0.107.0 won't be able to decrypt the project base config.
// So we need to update the project base config with the new secret key.
// Get all the project bases and update the project config with the new secret key.
export default async function ({ ncMeta }: NcUpgraderCtx) {
const actions = [];
// Get all the project bases
const bases = await ncMeta.metaList2(null, null, MetaTable.BASES);
// Update the base config with the new secret key if we could decrypt the base config with the fallback secret key
for (const base of bases) {
let config;
// Try to decrypt the base config with the fallback secret key
// if we could decrypt the base config with the fallback secret key then we will update the base config with the new secret key
// otherwise we will skip the base config update since it is already encrypted with the new secret key
try {
config = JSON.parse(
CryptoJS.AES.decrypt(base.config, TEMP_KEY).toString(CryptoJS.enc.Utf8),
);
// Update the base config with the new secret key
actions.push(
Base.updateBase(
base.id,
{
id: base.id,
projectId: base.project_id,
config,
skipReorder: true,
},
ncMeta,
),
);
} catch (e) {
// ignore the error
}
}
await Promise.all(actions);
}

2
packages/nocodb/webpack.config.js

@ -44,7 +44,7 @@ module.exports = {
plugins: [
new webpack.EnvironmentPlugin(['EE']),
new CopyPlugin({
patterns: [{ from: 'public', to: 'public' }],
patterns: [{ from: 'src/public', to: 'public' }],
}),
],

Loading…
Cancel
Save