Browse Source

Merge pull request #7070 from nocodb/fix/5492-validate-select-options

fix: Validate select options before insert
nc-oss/44517c26
Raju Udava 1 year ago committed by GitHub
parent
commit
42be112f5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 59
      packages/nocodb/src/db/BaseModelSqlv2.ts
  2. 15
      packages/nocodb/src/services/columns.service.ts

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

@ -2977,6 +2977,8 @@ class BaseModelSqlv2 {
}
}
await this.validateOptions(col, insertObj);
// validate data
if (col?.meta?.validate && col?.validate) {
const validate = col.getValidators();
@ -3208,7 +3210,12 @@ class BaseModelSqlv2 {
}
async bulkUpdateAll(
args: { where?: string; filterArr?: Filter[]; viewId?: string } = {},
args: {
where?: string;
filterArr?: Filter[];
viewId?: string;
skipValidationAndHooks?: boolean;
} = {},
data,
{ cookie }: { cookie?: any } = {},
) {
@ -3219,7 +3226,7 @@ class BaseModelSqlv2 {
this.clientMeta,
this.dbDriver,
);
await this.validate(updateData);
if (!args.skipValidationAndHooks) await this.validate(updateData);
const pkValues = await this._extractPksValues(updateData);
if (pkValues) {
// pk is specified - by pass
@ -3253,7 +3260,7 @@ class BaseModelSqlv2 {
);
}
await conditionV2(this, conditionObj, qb);
await conditionV2(this, conditionObj, qb, undefined, true);
count = (
await this.execAndParse(
@ -3271,6 +3278,7 @@ class BaseModelSqlv2 {
await this.execAndParse(qb, null, { raw: true });
}
if (!args.skipValidationAndHooks)
await this.afterBulkUpdate(null, count, this.dbDriver, cookie, true);
return count;
@ -3763,6 +3771,8 @@ class BaseModelSqlv2 {
// let cols = Object.keys(this.columns);
for (let i = 0; i < this.model.columns.length; ++i) {
const column = this.model.columns[i];
await this.validateOptions(column, columns);
// skip validation if `validate` is undefined or false
if (!column?.meta?.validate || !column?.validate) continue;
@ -3797,6 +3807,49 @@ class BaseModelSqlv2 {
return true;
}
// method for validating otpions if column is single/multi select
private async validateOptions(
column: Column<any>,
insertOrUpdateObject: Record<string, any>,
) {
// if SingleSelect or MultiSelect, then validate the options
if (
!(
column.uidt === UITypes.SingleSelect ||
column.uidt === UITypes.MultiSelect
)
) {
return;
}
const options = await column
.getColOptions<{ options: SelectOption[] }>()
.then(({ options }) => options.map((opt) => opt.title));
const columnTitle = column.title;
const columnName = column.column_name;
const columnValue =
insertOrUpdateObject?.[columnTitle] ?? insertOrUpdateObject?.[columnName];
if (!columnValue) {
return;
}
// if multi select, then split the values
const columnValueArr =
column.uidt === UITypes.MultiSelect
? columnValue.split(',')
: [columnValue];
for (let j = 0; j < columnValueArr.length; ++j) {
const val = columnValueArr[j];
if (!options.includes(val)) {
NcError.badRequest(
`Invalid option "${val}" provided for column "${columnTitle}". Valid options are "${options.join(
', ',
)}"`,
);
}
}
}
async addChild({
colId,
rowId,

15
packages/nocodb/src/services/columns.service.ts

@ -546,7 +546,10 @@ export class ColumnsService {
]);
} else {
await baseModel.bulkUpdateAll(
{ where: `(${column.title},eq,${option.title})` },
{
where: `(${column.title},eq,${option.title})`,
skipValidationAndHooks: true,
},
{ [column.column_name]: null },
{ cookie },
);
@ -728,7 +731,10 @@ export class ColumnsService {
]);
} else {
await baseModel.bulkUpdateAll(
{ where: `(${column.title},eq,${option.title})` },
{
where: `(${column.title},eq,${option.title})`,
skipValidationAndHooks: true,
},
{ [column.column_name]: newOp.title },
{ cookie },
);
@ -814,7 +820,10 @@ export class ColumnsService {
]);
} else {
await baseModel.bulkUpdateAll(
{ where: `(${column.title},eq,${ch.temp_title})` },
{
where: `(${column.title},eq,${ch.temp_title})`,
skipValidationAndHooks: true,
},
{ [column.column_name]: newOp.title },
{ cookie },
);

Loading…
Cancel
Save