|
|
@ -38,6 +38,7 @@ import { packageVersion } from 'nc-help'; |
|
|
|
import NcMetaIO, { META_TABLES } from './NcMetaIO'; |
|
|
|
import NcMetaIO, { META_TABLES } from './NcMetaIO'; |
|
|
|
import { promisify } from 'util'; |
|
|
|
import { promisify } from 'util'; |
|
|
|
import NcTemplateParser from '../../templateParser/NcTemplateParser'; |
|
|
|
import NcTemplateParser from '../../templateParser/NcTemplateParser'; |
|
|
|
|
|
|
|
import UITypes from '../../sqlUi/UITypes'; |
|
|
|
|
|
|
|
|
|
|
|
const XC_PLUGIN_DET = 'XC_PLUGIN_DET'; |
|
|
|
const XC_PLUGIN_DET = 'XC_PLUGIN_DET'; |
|
|
|
|
|
|
|
|
|
|
@ -128,19 +129,24 @@ export default class NcMetaMgr { |
|
|
|
}) |
|
|
|
}) |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// todo: add multer middleware only for certain api calls
|
|
|
|
if (!process.env.NC_SERVERLESS_TYPE && !this.config.try) { |
|
|
|
if (!process.env.NC_SERVERLESS_TYPE && !this.config.try) { |
|
|
|
const upload = multer({ |
|
|
|
const upload = multer({ |
|
|
|
dest: path.join(this.config.toolDir, 'uploads') |
|
|
|
storage: multer.diskStorage({ |
|
|
|
|
|
|
|
// dest: path.join(this.config.toolDir, 'uploads')
|
|
|
|
|
|
|
|
}) |
|
|
|
}); |
|
|
|
}); |
|
|
|
router.post(this.config.dashboardPath, upload.single('file')); |
|
|
|
// router.post(this.config.dashboardPath, upload.single('file'));
|
|
|
|
|
|
|
|
router.post(this.config.dashboardPath, upload.any()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
router.post(this.config.dashboardPath, (req, res, next) => |
|
|
|
router.post(this.config.dashboardPath, (req, res, next) => |
|
|
|
this.handlePublicRequest(req, res, next) |
|
|
|
this.handlePublicRequest(req, res, next) |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
|
router.post(this.config.dashboardPath, async (req: any, res, next) => { |
|
|
|
router.post(this.config.dashboardPath, async (req: any, res, next) => { |
|
|
|
if (req.file && req.body.json) { |
|
|
|
if (req.files && req.body.json) { |
|
|
|
req.body = JSON.parse(req.body.json); |
|
|
|
req.body = JSON.parse(req.body.json); |
|
|
|
} |
|
|
|
} |
|
|
|
if (req?.session?.passport?.user?.isAuthorized) { |
|
|
|
if (req?.session?.passport?.user?.isAuthorized) { |
|
|
@ -209,7 +215,7 @@ export default class NcMetaMgr { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (req.file) { |
|
|
|
if (req.files) { |
|
|
|
await this.handleRequestWithFile(req, res, next); |
|
|
|
await this.handleRequestWithFile(req, res, next); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
await this.handleRequest(req, res, next); |
|
|
|
await this.handleRequest(req, res, next); |
|
|
@ -219,11 +225,11 @@ export default class NcMetaMgr { |
|
|
|
async (req: any, res) => { |
|
|
|
async (req: any, res) => { |
|
|
|
try { |
|
|
|
try { |
|
|
|
let output; |
|
|
|
let output; |
|
|
|
if (req.file) { |
|
|
|
if (req.files && req.body.json) { |
|
|
|
req.body = JSON.parse(req.body.json); |
|
|
|
req.body = JSON.parse(req.body.json); |
|
|
|
output = await this.projectMgr |
|
|
|
output = await this.projectMgr |
|
|
|
.getSqlMgr({ id: req.body.project_id }) |
|
|
|
.getSqlMgr({ id: req.body.project_id }) |
|
|
|
.handleRequestWithFile(req.body.api, req.body, req.file); |
|
|
|
.handleRequestWithFile(req.body.api, req.body, req.files); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
output = await this.projectMgr |
|
|
|
output = await this.projectMgr |
|
|
|
.getSqlMgr({ id: req.body.project_id }) |
|
|
|
.getSqlMgr({ id: req.body.project_id }) |
|
|
@ -336,7 +342,7 @@ export default class NcMetaMgr { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async handleRequestWithFile(req, res, next) { |
|
|
|
public async handleRequestWithFile(req, res, next) { |
|
|
|
const [operation, args, file] = [req.body.api, req.body, req.file]; |
|
|
|
const [operation, args, file] = [req.body.api, req.body, req.files?.[0]]; |
|
|
|
let result; |
|
|
|
let result; |
|
|
|
try { |
|
|
|
try { |
|
|
|
switch (operation) { |
|
|
|
switch (operation) { |
|
|
@ -1230,43 +1236,15 @@ export default class NcMetaMgr { |
|
|
|
const prependName = args.args.prependName?.length |
|
|
|
const prependName = args.args.prependName?.length |
|
|
|
? args.args.prependName.join('_') + '_' |
|
|
|
? args.args.prependName.join('_') + '_' |
|
|
|
: ''; |
|
|
|
: ''; |
|
|
|
const fileName = `${prependName}${nanoid(6)}_${file.originalname}`; |
|
|
|
return await this._uploadFile({ |
|
|
|
let destPath; |
|
|
|
prependName, |
|
|
|
if (args?.args?.public) { |
|
|
|
file, |
|
|
|
destPath = path.join('nc', 'public', 'files', 'uploads', ...appendPath); |
|
|
|
storeInPublicFolder: args?.args?.public, |
|
|
|
} else { |
|
|
|
appendPath, |
|
|
|
destPath = path.join( |
|
|
|
req, |
|
|
|
'nc', |
|
|
|
dbAlias: this.getDbAlias(args), |
|
|
|
this.getProjectId(args), |
|
|
|
projectId: this.getProjectId(args) |
|
|
|
this.getDbAlias(args), |
|
|
|
}); |
|
|
|
'uploads', |
|
|
|
|
|
|
|
...appendPath |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
let url = await this.storageAdapter.fileCreate( |
|
|
|
|
|
|
|
slash(path.join(destPath, fileName)), |
|
|
|
|
|
|
|
file |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
if (!url) { |
|
|
|
|
|
|
|
if (args?.args?.public) { |
|
|
|
|
|
|
|
url = `${req.ncSiteUrl}/dl/public/files/${ |
|
|
|
|
|
|
|
appendPath?.length ? appendPath.join('/') + '/' : '' |
|
|
|
|
|
|
|
}${fileName}`;
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
url = `${req.ncSiteUrl}/dl/${this.getProjectId( |
|
|
|
|
|
|
|
args |
|
|
|
|
|
|
|
)}/${this.getDbAlias(args)}/${ |
|
|
|
|
|
|
|
appendPath?.length ? appendPath.join('/') + '/' : '' |
|
|
|
|
|
|
|
}${fileName}`;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
url, |
|
|
|
|
|
|
|
title: file.originalname, |
|
|
|
|
|
|
|
mimetype: file.mimetype, |
|
|
|
|
|
|
|
size: file.size, |
|
|
|
|
|
|
|
icon: mimeIcons[path.extname(file.originalname).slice(1)] || undefined |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
} catch (e) { |
|
|
|
throw e; |
|
|
|
throw e; |
|
|
|
} finally { |
|
|
|
} finally { |
|
|
@ -1274,6 +1252,54 @@ export default class NcMetaMgr { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private async _uploadFile({ |
|
|
|
|
|
|
|
prependName = '', |
|
|
|
|
|
|
|
file, |
|
|
|
|
|
|
|
storeInPublicFolder = false, |
|
|
|
|
|
|
|
appendPath = [], |
|
|
|
|
|
|
|
req, |
|
|
|
|
|
|
|
projectId, |
|
|
|
|
|
|
|
dbAlias |
|
|
|
|
|
|
|
}: { |
|
|
|
|
|
|
|
prependName?: string; |
|
|
|
|
|
|
|
file: any; |
|
|
|
|
|
|
|
storeInPublicFolder: boolean; |
|
|
|
|
|
|
|
appendPath?: string[]; |
|
|
|
|
|
|
|
req: express.Request & any; |
|
|
|
|
|
|
|
projectId?: string; |
|
|
|
|
|
|
|
dbAlias?: string; |
|
|
|
|
|
|
|
}) { |
|
|
|
|
|
|
|
const fileName = `${prependName}${nanoid(6)}_${file.originalname}`; |
|
|
|
|
|
|
|
let destPath; |
|
|
|
|
|
|
|
if (storeInPublicFolder) { |
|
|
|
|
|
|
|
destPath = path.join('nc', 'public', 'files', 'uploads', ...appendPath); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
destPath = path.join('nc', projectId, dbAlias, 'uploads', ...appendPath); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
let url = await this.storageAdapter.fileCreate( |
|
|
|
|
|
|
|
slash(path.join(destPath, fileName)), |
|
|
|
|
|
|
|
file |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
if (!url) { |
|
|
|
|
|
|
|
if (storeInPublicFolder) { |
|
|
|
|
|
|
|
url = `${req.ncSiteUrl}/dl/public/files/${ |
|
|
|
|
|
|
|
appendPath?.length ? appendPath.join('/') + '/' : '' |
|
|
|
|
|
|
|
}${fileName}`;
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
url = `${req.ncSiteUrl}/dl/${projectId}/${dbAlias}/${ |
|
|
|
|
|
|
|
appendPath?.length ? appendPath.join('/') + '/' : '' |
|
|
|
|
|
|
|
}${fileName}`;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
url, |
|
|
|
|
|
|
|
title: file.originalname, |
|
|
|
|
|
|
|
mimetype: file.mimetype, |
|
|
|
|
|
|
|
size: file.size, |
|
|
|
|
|
|
|
icon: mimeIcons[path.extname(file.originalname).slice(1)] || undefined |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected async initTwilio(overwrite = false): Promise<void> { |
|
|
|
protected async initTwilio(overwrite = false): Promise<void> { |
|
|
|
const activeStorage = await this.xcMeta.metaGet(null, null, 'nc_plugins', { |
|
|
|
const activeStorage = await this.xcMeta.metaGet(null, null, 'nc_plugins', { |
|
|
|
active: true, |
|
|
|
active: true, |
|
|
@ -1294,7 +1320,11 @@ export default class NcMetaMgr { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected async handlePublicRequest(req, res, next) { |
|
|
|
protected async handlePublicRequest(req, res, next) { |
|
|
|
const args = req.body; |
|
|
|
let args = req.body; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
if (req.body.json) args = JSON.parse(req.body.json); |
|
|
|
|
|
|
|
} catch {} |
|
|
|
let result; |
|
|
|
let result; |
|
|
|
try { |
|
|
|
try { |
|
|
|
switch (args.api) { |
|
|
|
switch (args.api) { |
|
|
@ -1304,7 +1334,6 @@ export default class NcMetaMgr { |
|
|
|
case 'getSharedViewData': |
|
|
|
case 'getSharedViewData': |
|
|
|
result = await this.getSharedViewData(req, args); |
|
|
|
result = await this.getSharedViewData(req, args); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 'sharedViewGet': |
|
|
|
case 'sharedViewGet': |
|
|
|
result = await this.sharedViewGet(req, args); |
|
|
|
result = await this.sharedViewGet(req, args); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -3723,12 +3752,18 @@ export default class NcMetaMgr { |
|
|
|
const queryParams = JSON.parse(viewMeta.query_params); |
|
|
|
const queryParams = JSON.parse(viewMeta.query_params); |
|
|
|
// const meta = JSON.parse(viewMeta.meta);
|
|
|
|
// const meta = JSON.parse(viewMeta.meta);
|
|
|
|
|
|
|
|
|
|
|
|
const fields: string[] = Object.keys(queryParams.showFields); |
|
|
|
const fields: string[] = Object.keys(queryParams.showFields).filter( |
|
|
|
|
|
|
|
k => queryParams.showFields[k] |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const apiBuilder = this.app?.projectBuilders |
|
|
|
const apiBuilder = this.app?.projectBuilders |
|
|
|
?.find(pb => pb.id === sharedViewMeta.project_id) |
|
|
|
?.find(pb => pb.id === sharedViewMeta.project_id) |
|
|
|
?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias); |
|
|
|
?.apiBuilders?.find(ab => ab.dbAlias === sharedViewMeta.db_alias); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const tableMeta = (viewMeta.meta = apiBuilder?.getMeta( |
|
|
|
|
|
|
|
sharedViewMeta.model_name |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
|
|
|
|
const insertObject = Object.entries(args.args.data).reduce( |
|
|
|
const insertObject = Object.entries(args.args.data).reduce( |
|
|
|
(obj, [key, val]) => { |
|
|
|
(obj, [key, val]) => { |
|
|
|
if (fields.includes(key)) { |
|
|
|
if (fields.includes(key)) { |
|
|
@ -3745,7 +3780,31 @@ export default class NcMetaMgr { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const attachments = {}; |
|
|
|
|
|
|
|
for (const file of req.files || []) { |
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
|
|
fields.includes(file?.fieldname) && |
|
|
|
|
|
|
|
tableMeta.columns.find( |
|
|
|
|
|
|
|
c => c._cn === file?.fieldname && c.uidt === UITypes.Attachment |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
attachments[file.fieldname] = attachments[file.fieldname] || []; |
|
|
|
|
|
|
|
attachments[file.fieldname].push( |
|
|
|
|
|
|
|
await this._uploadFile({ |
|
|
|
|
|
|
|
file, |
|
|
|
|
|
|
|
storeInPublicFolder: true, |
|
|
|
|
|
|
|
req |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const [column, data] of Object.entries(attachments)) { |
|
|
|
|
|
|
|
insertObject[column] = JSON.stringify(data); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const model = apiBuilder?.xcModels?.[sharedViewMeta.model_name]; |
|
|
|
const model = apiBuilder?.xcModels?.[sharedViewMeta.model_name]; |
|
|
|
|
|
|
|
|
|
|
|
if (model) { |
|
|
|
if (model) { |
|
|
|
req.query.form = viewMeta.view_name; |
|
|
|
req.query.form = viewMeta.view_name; |
|
|
|
await model.nestedInsert(insertObject, null, req); |
|
|
|
await model.nestedInsert(insertObject, null, req); |
|
|
|