diff --git a/packages/nc-gui-v2/windi.config.ts b/packages/nc-gui-v2/windi.config.ts
index 037d3bbd39..306b909724 100644
--- a/packages/nc-gui-v2/windi.config.ts
+++ b/packages/nc-gui-v2/windi.config.ts
@@ -57,6 +57,18 @@ export default defineConfig({
primary: 'rgba(var(--color-primary), var(--tw-text-opacity))',
accent: 'rgba(var(--color-accent), var(--tw-text-opacity))',
},
+ borderColor: {
+ primary: 'rgba(var(--color-primary), var(--tw-border-opacity))',
+ accent: 'rgba(var(--color-accent), var(--tw-border-opacity))',
+ },
+ backgroundColor: {
+ primary: 'rgba(var(--color-primary), var(--tw-bg-opacity))',
+ accent: 'rgba(var(--color-accent), var(--tw-bg-opacity))',
+ },
+ ringColor: {
+ primary: 'rgba(var(--color-primary), var(--tw-ring-opacity))',
+ accent: 'rgba(var(--color-accent), var(--tw-ring-opacity))',
+ },
colors: {
...windiColors,
...themeColors,
diff --git a/packages/nc-gui/components/ProjectTreeView.vue b/packages/nc-gui/components/ProjectTreeView.vue
index 94218ed6d3..e94e966000 100644
--- a/packages/nc-gui/components/ProjectTreeView.vue
+++ b/packages/nc-gui/components/ProjectTreeView.vue
@@ -1431,7 +1431,8 @@ export default {
let item = cookie;
try {
await this.$api.dbTable.update(item.id, {
- title,
+ project_id: this.projectId,
+ table_name: title,
});
} catch (e) {
this.$toast.error(await this._extractSdkResponseErrorMsg(e)).goAway(3000);
diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts
index 748b959145..08c38fdef7 100644
--- a/packages/nocodb-sdk/src/lib/Api.ts
+++ b/packages/nocodb-sdk/src/lib/Api.ts
@@ -121,6 +121,7 @@ export interface TableType {
columns?: ColumnType[];
columnsById?: object;
slug?: string;
+ project_id?: string;
}
export interface ViewType {
@@ -169,7 +170,7 @@ export interface TableReqType {
deleted?: boolean;
order?: number;
mm?: boolean;
- columns?: ColumnType[];
+ columns: ColumnType[];
}
export interface TableListType {
@@ -1487,7 +1488,7 @@ export class Api<
*/
update: (
tableId: string,
- data: { title?: string },
+ data: { table_name?: string; project_id?: string },
params: RequestParams = {}
) =>
this.request
({
diff --git a/packages/nocodb/src/lib/meta/api/tableApis.ts b/packages/nocodb/src/lib/meta/api/tableApis.ts
index 45ea1968c8..50fae6beb5 100644
--- a/packages/nocodb/src/lib/meta/api/tableApis.ts
+++ b/packages/nocodb/src/lib/meta/api/tableApis.ts
@@ -2,6 +2,7 @@ import { Request, Response, Router } from 'express';
import Model from '../../models/Model';
import { PagedResponseImpl } from '../helpers/PagedResponse';
import { Tele } from 'nc-help';
+import DOMPurify from 'isomorphic-dompurify';
import {
AuditOperationSubTypes,
AuditOperationTypes,
@@ -102,6 +103,8 @@ export async function tableCreate(req: Request, res) {
}
}
+ req.body.table_name = DOMPurify.sanitize(req.body.table_name);
+
// validate table name
if (/^\s+|\s+$/.test(req.body.table_name)) {
NcError.badRequest(
@@ -217,18 +220,86 @@ export async function tableCreate(req: Request, res) {
export async function tableUpdate(req: Request, res) {
const model = await Model.get(req.params.tableId);
+ const project = await Project.getWithInfo(req.body.project_id);
+ const base = project.bases[0];
+
+ if (!req.body.table_name) {
+ NcError.badRequest(
+ 'Missing table name `table_name` property in request body'
+ );
+ }
+
+ if (project.prefix) {
+ if (!req.body.table_name.startsWith(project.prefix)) {
+ req.body.table_name = `${project.prefix}${req.body.table_name}`;
+ }
+ }
+
+ req.body.table_name = DOMPurify.sanitize(req.body.table_name);
+
+ // validate table name
+ if (/^\s+|\s+$/.test(req.body.table_name)) {
+ NcError.badRequest(
+ 'Leading or trailing whitespace not allowed in table names'
+ );
+ }
+
+ if (
+ !(await Model.checkTitleAvailable({
+ table_name: req.body.table_name,
+ project_id: project.id,
+ base_id: base.id,
+ }))
+ ) {
+ NcError.badRequest('Duplicate table name');
+ }
+
+ if (!req.body.title) {
+ req.body.title = getTableNameAlias(
+ req.body.table_name,
+ project.prefix,
+ base
+ );
+ }
+
if (
!(await Model.checkAliasAvailable({
title: req.body.title,
- project_id: model.project_id,
- base_id: model.base_id,
- exclude_id: req.params.tableId,
+ project_id: project.id,
+ base_id: base.id,
}))
) {
- NcError.badRequest('Duplicate table name');
+ NcError.badRequest('Duplicate table alias');
}
- await Model.updateAlias(req.params.tableId, req.body.title);
+ const sqlMgr = await ProjectMgrv2.getSqlMgr(project);
+ const sqlClient = NcConnectionMgrv2.getSqlClient(base);
+
+ let tableNameLengthLimit = 255;
+ const sqlClientType = sqlClient.clientType;
+ if (sqlClientType === 'mysql2' || sqlClientType === 'mysql') {
+ tableNameLengthLimit = 64;
+ } else if (sqlClientType === 'pg') {
+ tableNameLengthLimit = 63;
+ } else if (sqlClientType === 'mssql') {
+ tableNameLengthLimit = 128;
+ }
+
+ if (req.body.table_name.length > tableNameLengthLimit) {
+ NcError.badRequest(`Table name exceeds ${tableNameLengthLimit} characters`);
+ }
+
+ await Model.updateAliasAndTableName(
+ req.params.tableId,
+ req.body.title,
+ req.body.table_name
+ );
+
+ await sqlMgr.sqlOpPlus(base, 'tableRename', {
+ ...req.body,
+ tn: req.body.table_name,
+ tn_old: model.table_name,
+ });
Tele.emit('evt', { evt_type: 'table:updated' });
diff --git a/packages/nocodb/src/lib/models/Model.ts b/packages/nocodb/src/lib/models/Model.ts
index ef0bbc439b..7104a44c38 100644
--- a/packages/nocodb/src/lib/models/Model.ts
+++ b/packages/nocodb/src/lib/models/Model.ts
@@ -412,14 +412,25 @@ export default class Model implements TableType {
return insertObj;
}
- static async updateAlias(tableId, title: string, ncMeta = Noco.ncMeta) {
- if (!title) NcError.badRequest("Missing 'title' property in body");
+ static async updateAliasAndTableName(
+ tableId,
+ title: string,
+ table_name: string,
+ ncMeta = Noco.ncMeta
+ ) {
+ if (!title) {
+ NcError.badRequest("Missing 'title' property in body");
+ }
+ if (!table_name) {
+ NcError.badRequest("Missing 'table_name' property in body");
+ }
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
// update alias
if (o) {
o.title = title;
+ o.table_name = table_name;
// set cache
await NocoCache.set(key, o);
}
@@ -430,6 +441,7 @@ export default class Model implements TableType {
MetaTable.MODELS,
{
title,
+ table_name,
},
tableId
);
diff --git a/packages/nocodb/src/lib/plugins/smtp/SMTP.ts b/packages/nocodb/src/lib/plugins/smtp/SMTP.ts
index 3e7695eeca..9ceb06e703 100644
--- a/packages/nocodb/src/lib/plugins/smtp/SMTP.ts
+++ b/packages/nocodb/src/lib/plugins/smtp/SMTP.ts
@@ -14,11 +14,12 @@ export default class SMTP implements IEmailAdapter {
public async init(): Promise {
const config = {
- // from: this.input.from,
- // options: {
host: this.input?.host,
port: parseInt(this.input?.port, 10),
- secure: this.input?.secure === 'true',
+ secure:
+ typeof this.input?.secure === 'boolean'
+ ? this.input?.secure
+ : this.input?.secure === 'true',
ignoreTLS:
typeof this.input?.ignoreTLS === 'boolean'
? this.input?.ignoreTLS
@@ -27,8 +28,11 @@ export default class SMTP implements IEmailAdapter {
user: this.input?.username,
pass: this.input?.password,
},
- // }
+ tls: {
+ rejectUnauthorized: this.input?.rejectUnauthorized,
+ },
};
+
this.transporter = nodemailer.createTransport(config);
}
diff --git a/packages/nocodb/src/lib/plugins/smtp/index.ts b/packages/nocodb/src/lib/plugins/smtp/index.ts
index f239bfd009..2f17f0ade6 100644
--- a/packages/nocodb/src/lib/plugins/smtp/index.ts
+++ b/packages/nocodb/src/lib/plugins/smtp/index.ts
@@ -8,7 +8,7 @@ import SMTPPlugin from './SMTPPlugin';
const config: XcPluginConfig = {
builder: SMTPPlugin,
title: 'SMTP',
- version: '0.0.1',
+ version: '0.0.2',
// icon: 'mdi-email-outline',
description: 'SMTP email client',
price: 'Free',
@@ -42,8 +42,8 @@ const config: XcPluginConfig = {
key: 'secure',
label: 'Secure',
placeholder: 'Secure',
- type: XcType.SingleLineText,
- required: true,
+ type: XcType.Checkbox,
+ required: false,
},
{
key: 'ignoreTLS',
@@ -52,6 +52,13 @@ const config: XcPluginConfig = {
type: XcType.Checkbox,
required: false,
},
+ {
+ key: 'rejectUnauthorized',
+ label: 'Reject Unauthorized',
+ placeholder: 'Reject Unauthorized',
+ type: XcType.Checkbox,
+ required: false,
+ },
{
key: 'username',
label: 'Username',
diff --git a/packages/nocodb/tests/pg-cy-quick/01-cy-quick.sql b/packages/nocodb/tests/pg-cy-quick/01-cy-quick.sql
index d71eaf7f3b..39a4970fb6 100644
--- a/packages/nocodb/tests/pg-cy-quick/01-cy-quick.sql
+++ b/packages/nocodb/tests/pg-cy-quick/01-cy-quick.sql
@@ -3308,7 +3308,7 @@ nc_iyhlectialukbv Vultr Object Storage Using Vultr Object Storage can give flexi
nc_lr8pcvg64g5bho OvhCloud Object Storage Upload your files to a space that you can access via HTTPS using the OpenStack Swift API, or the S3 API. f \N 0.0.1 \N install \N plugins/ovhCloud.png \N Storage Storage {"title":"Configure OvhCloud Object Storage","items":[{"key":"bucket","label":"Bucket Name","placeholder":"Bucket Name","type":"SingleLineText","required":true},{"key":"region","label":"Region","placeholder":"Region","type":"SingleLineText","required":true},{"key":"access_key","label":"Access Key","placeholder":"Access Key","type":"SingleLineText","required":true},{"key":"access_secret","label":"Access Secret","placeholder":"Access Secret","type":"Password","required":true}],"actions":[{"label":"Test","placeholder":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","placeholder":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed and attachment will be stored in OvhCloud Object Storage","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.60416+00 2022-06-13 07:00:02.60416+00
nc_3f19m6v5iyudty Linode Object Storage S3-compatible Linode Object Storage makes it easy and more affordable to manage unstructured data such as content assets, as well as sophisticated and data-intensive storage challenges around artificial intelligence and machine learning. f \N 0.0.1 \N install \N plugins/linode.svg \N Storage Storage {"title":"Configure Linode Object Storage","items":[{"key":"bucket","label":"Bucket Name","placeholder":"Bucket Name","type":"SingleLineText","required":true},{"key":"region","label":"Region","placeholder":"Region","type":"SingleLineText","required":true},{"key":"access_key","label":"Access Key","placeholder":"Access Key","type":"SingleLineText","required":true},{"key":"access_secret","label":"Access Secret","placeholder":"Access Secret","type":"Password","required":true}],"actions":[{"label":"Test","placeholder":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","placeholder":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed and attachment will be stored in Linode Object Storage","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.606391+00 2022-06-13 07:00:02.606391+00
nc_ikemr7ajwzfcr3 UpCloud Object Storage The perfect home for your data. Thanks to the S3-compatible programmable interface,\nyou have a host of options for existing tools and code implementations.\n f \N 0.0.1 \N install \N plugins/upcloud.png \N Storage Storage {"title":"Configure UpCloud Object Storage","items":[{"key":"bucket","label":"Bucket Name","placeholder":"Bucket Name","type":"SingleLineText","required":true},{"key":"endpoint","label":"Endpoint","placeholder":"Endpoint","type":"SingleLineText","required":true},{"key":"access_key","label":"Access Key","placeholder":"Access Key","type":"SingleLineText","required":true},{"key":"access_secret","label":"Access Secret","placeholder":"Access Secret","type":"Password","required":true}],"actions":[{"label":"Test","placeholder":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","placeholder":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed and attachment will be stored in UpCloud Object Storage","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.6085+00 2022-06-13 07:00:02.6085+00
-nc_tv5fgn17fgvcwh SMTP SMTP email client f \N 0.0.1 \N install \N \N \N Email Email {"title":"Configure Email SMTP","items":[{"key":"from","label":"From","placeholder":"eg: admin@run.com","type":"SingleLineText","required":true},{"key":"host","label":"Host","placeholder":"eg: smtp.run.com","type":"SingleLineText","required":true},{"key":"port","label":"Port","placeholder":"Port","type":"SingleLineText","required":true},{"key":"secure","label":"Secure","placeholder":"Secure","type":"SingleLineText","required":true},{"key":"ignoreTLS","label":"Ignore TLS","placeholder":"Ignore TLS","type":"Checkbox","required":false},{"key":"username","label":"Username","placeholder":"Username","type":"SingleLineText","required":false},{"key":"password","label":"Password","placeholder":"Password","type":"Password","required":false}],"actions":[{"label":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed and email notification will use SMTP configuration","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.61079+00 2022-06-13 07:00:02.61079+00
+nc_tv5fgn17fgvcwh SMTP SMTP email client f \N 0.0.1 \N install \N \N \N Email Email {"title":"Configure Email SMTP","items":[{"key":"from","label":"From","placeholder":"eg: admin@run.com","type":"SingleLineText","required":true},{"key":"host","label":"Host","placeholder":"eg: smtp.run.com","type":"SingleLineText","required":true},{"key":"port","label":"Port","placeholder":"Port","type":"SingleLineText","required":true},{"key":"secure","label":"Secure","placeholder":"Secure","type":"Checkbox","required":false},{"key":"ignoreTLS","label":"Ignore TLS","placeholder":"Ignore TLS","type":"Checkbox","required":false},{"key":"username","label":"Username","placeholder":"Username","type":"SingleLineText","required":false},{"key":"password","label":"Password","placeholder":"Password","type":"Password","required":false}],"actions":[{"label":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed and email notification will use SMTP configuration","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.61079+00 2022-06-13 07:00:02.61079+00
nc_hcnsq71s0tr8um MailerSend MailerSend email client f \N 0.0.1 \N install \N plugins/mailersend.svg \N Email Email {"title":"Configure MailerSend","items":[{"key":"api_key","label":"API KEy","placeholder":"eg: ***************","type":"Password","required":true},{"key":"from","label":"From","placeholder":"eg: admin@run.com","type":"SingleLineText","required":true},{"key":"from_name","label":"From Name","placeholder":"eg: Adam","type":"SingleLineText","required":true}],"actions":[{"label":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed and email notification will use MailerSend configuration","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.612874+00 2022-06-13 07:00:02.612874+00
nc_z2zas0qdy0cz7e Scaleway Object Storage Scaleway Object Storage is an S3-compatible object store from Scaleway Cloud Platform. f \N 0.0.1 \N install \N plugins/scaleway.png \N Storage Storage {"title":"Setup Scaleway","items":[{"key":"bucket","label":"Bucket name","placeholder":"Bucket name","type":"SingleLineText","required":true},{"key":"region","label":"Region of bucket","placeholder":"Region of bucket","type":"SingleLineText","required":true},{"key":"access_key","label":"Access Key","placeholder":"Access Key","type":"SingleLineText","required":true},{"key":"access_secret","label":"Access Secret","placeholder":"Access Secret","type":"Password","required":true}],"actions":[{"label":"Test","placeholder":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","placeholder":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed Scaleway Object Storage","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.61482+00 2022-06-13 07:00:02.61482+00
nc_96vkc0jdyw7los SES Amazon Simple Email Service (SES) is a cost-effective, flexible, and scalable email service that enables developers to send mail from within any application. f \N 0.0.1 \N install \N plugins/aws.png \N Email Email {"title":"Configure Amazon Simple Email Service (SES)","items":[{"key":"from","label":"From","placeholder":"From","type":"SingleLineText","required":true},{"key":"region","label":"Region","placeholder":"Region","type":"SingleLineText","required":true},{"key":"access_key","label":"Access Key","placeholder":"Access Key","type":"SingleLineText","required":true},{"key":"access_secret","label":"Access Secret","placeholder":"Access Secret","type":"Password","required":true}],"actions":[{"label":"Test","placeholder":"Test","key":"test","actionType":"TEST","type":"Button"},{"label":"Save","placeholder":"Save","key":"save","actionType":"SUBMIT","type":"Button"}],"msgOnInstall":"Successfully installed and email notification will use Amazon SES","msgOnUninstall":""} \N \N \N \N 2022-06-13 07:00:02.617114+00 2022-06-13 07:00:02.617114+00
diff --git a/scripts/cypress/integration/common/1a_table_operations.js b/scripts/cypress/integration/common/1a_table_operations.js
index 3e5b2793bc..f13449ddf3 100644
--- a/scripts/cypress/integration/common/1a_table_operations.js
+++ b/scripts/cypress/integration/common/1a_table_operations.js
@@ -76,6 +76,9 @@ export const genTest = (apiType, dbType) => {
cy.closeTableTab("CityX");
+ // revert re-name operation to not impact rest of test suite
+ cy.renameTable("CityX", "City");
+
// 4. verify linked contents in other table
// 4a. Address table, has many field
cy.openTableTab("Address", 25);
@@ -97,9 +100,6 @@ export const genTest = (apiType, dbType) => {
.contains("Kabul")
.should("exist");
cy.closeTableTab("Country");
-
- // revert re-name operation to not impact rest of test suite
- cy.renameTable("CityX", "City");
});
});
};
diff --git a/scripts/cypress/support/page_objects/mainPage.js b/scripts/cypress/support/page_objects/mainPage.js
index b388264871..3d6b4f8a45 100644
--- a/scripts/cypress/support/page_objects/mainPage.js
+++ b/scripts/cypress/support/page_objects/mainPage.js
@@ -222,7 +222,8 @@ export class _mainPage {
.click()
.type(host);
cy.getActiveModal().find('[placeholder="Port"]').click().type(port);
- cy.getActiveModal().find('[placeholder="Secure"]').click().type(secure);
+ // TODO: in v2, it would be a button
+ // if (secure) cy.getActiveModal().find('[placeholder="Secure"]').click();
cy.getActiveModal().find("button").contains("Save").click();
cy.toastWait(
"Successfully installed and email notification will use SMTP configuration"
diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json
index 25796f98d0..85c16c1795 100644
--- a/scripts/sdk/swagger.json
+++ b/scripts/sdk/swagger.json
@@ -1309,7 +1309,10 @@
"schema": {
"type": "object",
"properties": {
- "title": {
+ "table_name": {
+ "type": "string"
+ },
+ "project_id": {
"type": "string"
}
}
@@ -6050,6 +6053,9 @@
},
"slug": {
"type": "string"
+ },
+ "project_id": {
+ "type": "string"
}
},
"required": [