diff --git a/packages/nocodb/src/lib/migrator/SqlMigrator/lib/KnexMigrator.ts b/packages/nocodb/src/lib/migrator/SqlMigrator/lib/KnexMigrator.ts index 4aa9e78623..b2d35c7dad 100644 --- a/packages/nocodb/src/lib/migrator/SqlMigrator/lib/KnexMigrator.ts +++ b/packages/nocodb/src/lib/migrator/SqlMigrator/lib/KnexMigrator.ts @@ -375,7 +375,7 @@ export default class KnexMigrator extends SqlMigrator { // await sqlClient.createTableIfNotExists({tn: connectionConfig.meta.tn}); } - async _initEnvDbsWithSql(env, dbAlias = null, sqlClient =null) { + async _initEnvDbsWithSql(env, dbAlias = null, sqlClient = null) { const {envs} = this.project; @@ -470,8 +470,8 @@ export default class KnexMigrator extends SqlMigrator { if (!migrationSteps && !args.file) { result.code = -1; result.message = - "Neither num of steps nor file is specified for migartion"; - log.debug("Neither num of steps nor file is specified for migartion"); + "Neither num of steps nor file is specified for migration"; + log.debug("Neither num of steps nor file is specified for migration"); log.debug("See help"); return result; } @@ -501,7 +501,13 @@ export default class KnexMigrator extends SqlMigrator { args.env ); const sqlClient = args.sqlClient || SqlClientFactory.create(connection); - const migrations = await sqlClient.selectAll(sqlClient.getTnPath(connection.meta.tn)); + + let migrations = await sqlClient.selectAll(sqlClient.getTnPath(connection.meta.tn)); + + if (this.suffix) { + migrations = migrations.filter(m => m.title.includes(this.suffix)) + } + /** ************** END : get files and migrations *************** */ if (files.length === migrations.length) { @@ -971,7 +977,7 @@ export default class KnexMigrator extends SqlMigrator { // } // create filenames - const prefix = fileHelp.getUniqFilenamePrefix(); + const prefix = `${fileHelp.getUniqFilenamePrefix()}${this.suffix}`; const upFileName = fileHelp.getFilenameForUp(prefix); const downFileName = fileHelp.getFilenameForDown(prefix); if (this.metaDb) { @@ -1069,7 +1075,7 @@ export default class KnexMigrator extends SqlMigrator { * and only filenames are migrated to _evolution table * @memberof KnexMigrator */ - async migrationsUp(args: any = {}) { + async migrationsUp(args: any = {}) { const func = this.migrationsUp.name; // const result = new Result(); @@ -1623,6 +1629,13 @@ export default class KnexMigrator extends SqlMigrator { return 'nc_evolutions'; } + + private get suffix(): string { + if (this.project?.prefix) + return `_${this.project?.prefix.slice(3,7)}` + return ''; + } + } /** diff --git a/packages/nocodb/src/lib/noco/meta/NcMetaIO.ts b/packages/nocodb/src/lib/noco/meta/NcMetaIO.ts index fb97714b2d..6ba3253c26 100644 --- a/packages/nocodb/src/lib/noco/meta/NcMetaIO.ts +++ b/packages/nocodb/src/lib/noco/meta/NcMetaIO.ts @@ -102,7 +102,8 @@ export default abstract class NcMetaIO { public abstract projectCreate(projectName: string, config: any, - description?: string): Promise; + description?: string, + meta?:boolean): Promise; public abstract projectUpdate(projectId: string, config: any): Promise; diff --git a/packages/nocodb/src/lib/noco/meta/NcMetaIOImpl.ts b/packages/nocodb/src/lib/noco/meta/NcMetaIOImpl.ts index 3f00500c70..2e3cfef602 100644 --- a/packages/nocodb/src/lib/noco/meta/NcMetaIOImpl.ts +++ b/packages/nocodb/src/lib/noco/meta/NcMetaIOImpl.ts @@ -1,5 +1,5 @@ import CryptoJS from 'crypto-js'; -import {nanoid} from 'nanoid'; +import {customAlphabet} from 'nanoid' import {NcConfig} from "../../../interface/config"; import {Knex, XKnex} from "../../dataMapper"; @@ -10,6 +10,9 @@ import NcMetaIO, {META_TABLES} from "./NcMetaIO"; import NcConnectionMgr from "../common/NcConnectionMgr"; +const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 4) + + export default class NcMetaIOImpl extends NcMetaIO { @@ -258,14 +261,14 @@ export default class NcMetaIOImpl extends NcMetaIO { async commit() { if (this.trx) { - await this.trx.commit(); + await this.trx.commit(); } this.trx = null; } async rollback(e?) { if (this.trx) { - await this.trx.rollback(e); + await this.trx.rollback(e); } this.trx = null; } @@ -294,9 +297,17 @@ export default class NcMetaIOImpl extends NcMetaIO { } } - public async projectCreate(projectName: string, config: any, description?: string): Promise { + public async projectCreate(projectName: string, config: any, description?: string, + meta?: boolean): Promise { try { - const id = this.getProjectId(projectName); + const ranId = this.getNanoId(); + const id = `${projectName.toLowerCase().replace(/\W+/g, '_')}_${ranId}`; + if (meta) { + config.prefix = `nc_${ranId}__` + // if(config.envs._noco?.db?.[0]?.meta?.tn){ + // config.envs._noco.db[0].meta.tn += `_${prefix}` + // } + } config.id = id; const project = { id, @@ -435,8 +446,8 @@ export default class NcMetaIOImpl extends NcMetaIO { return this.knexConnection; } - private getProjectId(projectName: string) { - return `${projectName.toLowerCase().replace(/\W+/g, '_')}_${nanoid(4)}` + private getNanoId() { + return nanoid() } public async audit(project_id: string, dbAlias: string, target: string, data: any): Promise { diff --git a/packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts b/packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts index 61e5ebbca6..aa3b86d78a 100644 --- a/packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts +++ b/packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts @@ -353,6 +353,10 @@ export default class NcMetaMgr { const data = JSON.parse(fs.readFileSync(path.join(metaFolder, `${tn}.json`), 'utf8')); for (const row of data) { delete row.id; + + row.created_at = row.created_at ? new Date(row.created_at) : null; + row.updated_at = row.updated_at ? new Date(row.updated_at) : null; + await this.xcMeta.metaInsert(projectId, dbAlias, tn, { ...row, db_alias: dbAlias, @@ -361,7 +365,7 @@ export default class NcMetaMgr { } } } - this.xcMeta.commit(); + await this.xcMeta.commit(); this.xcMeta.audit(projectId, dbAlias, 'nc_audit', { // created_at: (Knex as any).fn.now(), @@ -374,7 +378,7 @@ export default class NcMetaMgr { } catch (e) { console.log(e); - this.xcMeta.rollback(e); + await this.xcMeta.rollback(e); } } @@ -410,6 +414,14 @@ export default class NcMetaMgr { } else { // decrypt with old key and encrypt again with latest key const projectConfig = JSON.parse(CryptoJS.AES.decrypt(projectDetails.config, projectDetails.key).toString(CryptoJS.enc.Utf8)) + + + if (projectConfig?.prefix) { + const metaProjConfig = NcConfigFactory.makeProjectConfigFromConnection(this.config?.meta?.db, args.args.projectType); + projectConfig.envs._noco = metaProjConfig.envs._noco + } + + // delete projectDetails.key; projectDetails.config = projectConfig; @@ -708,9 +720,9 @@ export default class NcMetaMgr { id: row.id }) } - trx.commit(); + await trx.commit(); } catch (e) { - trx.rollback(); + await trx.rollback(); throw e; } } @@ -1315,28 +1327,30 @@ export default class NcMetaMgr { config.title = args.args.title; config.projectType = args.args.projectType; - const metaProjectsCount = await this.xcMeta.metaGet(null, null, 'nc_store', { - key: 'NC_PROJECT_COUNT' - }); - // todo: populate unique prefix dynamically - config.prefix = `xb${Object.keys(this.projectConfigs).length}__`; - if (metaProjectsCount) { - // todo: populate unique prefix dynamically - config.prefix = `xa${(+metaProjectsCount.value || 0) + 1}__`; - } + // const metaProjectsCount = await this.xcMeta.metaGet(null, null, 'nc_store', { + // key: 'NC_PROJECT_COUNT' + // }); + // // todo: populate unique prefix dynamically + // config.prefix = `xb${Object.keys(this.projectConfigs).length}__`; + // if (metaProjectsCount) { + // // todo: populate unique prefix dynamically + // config.prefix = `xa${(+metaProjectsCount.value || 0) + 1}__`; + // } - result = await this.xcMeta.projectCreate(config.title, config); + result = await this.xcMeta.projectCreate(config.title, config, null, true); await this.xcMeta.projectAddUser(result.id, req?.session?.passport?.user?.id, 'owner,creator'); await this.projectMgr.getSqlMgr({ ...result, config, metaDb: this.xcMeta?.knex }).projectOpenByWeb(config); + + this.projectConfigs[result.id] = config; - this.xcMeta.metaUpdate(null, null, 'nc_store', { - value: ((metaProjectsCount && +metaProjectsCount.value) || 0) + 1 - }, {key: 'NC_PROJECT_COUNT'}) + // this.xcMeta.metaUpdate(null, null, 'nc_store', { + // value: ((metaProjectsCount && +metaProjectsCount.value) || 0) + 1 + // }, {key: 'NC_PROJECT_COUNT'}) this.xcMeta.audit(result?.id, null, 'nc_audit', { op_type: 'PROJECT', @@ -1352,7 +1366,7 @@ export default class NcMetaMgr { case 'projectList': result = await this.xcMeta.userProjectList(req?.session?.passport?.user?.id); result.forEach(p => { - const config =JSON.parse(p.config); + const config = JSON.parse(p.config); p.projectType = config?.projectType; p.prefix = config?.prefix delete p.config diff --git a/packages/nocodb/src/lib/noco/rest/RestAuthCtrl.ts b/packages/nocodb/src/lib/noco/rest/RestAuthCtrl.ts index 3a9a4e686f..6a4e926734 100644 --- a/packages/nocodb/src/lib/noco/rest/RestAuthCtrl.ts +++ b/packages/nocodb/src/lib/noco/rest/RestAuthCtrl.ts @@ -30,7 +30,16 @@ import axios from 'axios'; import IEmailAdapter from "../../../interface/IEmailAdapter"; import XcCache from "../plugins/adapters/cache/XcCache"; -passport.serializeUser(function ({id, email, email_verified, roles, provider, firstname, lastname, isAuthorized}, done) { +passport.serializeUser(function ({ + id, + email, + email_verified, + roles, + provider, + firstname, + lastname, + isAuthorized + }, done) { done(null, { isAuthorized, id, @@ -651,7 +660,7 @@ export default class RestAuthCtrl { console.log('token refresh') try { - if(!req?.cookies?.refresh_token){ + if (!req?.cookies?.refresh_token) { return res.status(400).json({msg: 'Missing refresh token'}); } @@ -682,7 +691,7 @@ export default class RestAuthCtrl { roles: user.roles }, this.config.auth.jwt.secret, this.config.auth.jwt.options) } as any); - }catch (e) { + } catch (e) { return res.status(400).json({msg: e.message}); } } @@ -1037,7 +1046,7 @@ export default class RestAuthCtrl { } - Tele.emit('evt', {evt_type: 'project:invite', count:count?.count}) + Tele.emit('evt', {evt_type: 'project:invite', count: count?.count}) this.xcMeta.audit(req.body.project_id, null, 'nc_audit', { op_type: 'AUTHENTICATION', op_sub_type: 'INVITE', @@ -1265,9 +1274,9 @@ export default class RestAuthCtrl { }, aclRow.id); } } - this.xcMeta.commit(); + await this.xcMeta.commit(); } catch (e) { - this.xcMeta.rollback(e); + await this.xcMeta.rollback(e); } } } @@ -1293,9 +1302,9 @@ export default class RestAuthCtrl { }); } } - this.xcMeta.commit(); + await this.xcMeta.commit(); } catch (e) { - this.xcMeta.rollback(e); + await this.xcMeta.rollback(e); } } }