Browse Source

fix: validate pk value before query execution (#8640)

pull/8645/head
Pranav C 6 months ago committed by GitHub
parent
commit
2759f1982a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      packages/nocodb-sdk/src/lib/globals.ts
  2. 23
      packages/nocodb/src/db/BaseModelSqlv2.ts
  3. 12
      packages/nocodb/src/helpers/catchError.ts

1
packages/nocodb-sdk/src/lib/globals.ts

@ -146,6 +146,7 @@ export enum NcErrorType {
DATABASE_ERROR = 'DATABASE_ERROR', DATABASE_ERROR = 'DATABASE_ERROR',
UNKNOWN_ERROR = 'UNKNOWN_ERROR', UNKNOWN_ERROR = 'UNKNOWN_ERROR',
BAD_JSON = 'BAD_JSON', BAD_JSON = 'BAD_JSON',
INVALID_PK_VALUE = 'INVALID_PK_VALUE',
} }
type Roles = OrgUserRoles | ProjectRoles | WorkspaceUserRoles; type Roles = OrgUserRoles | ProjectRoles | WorkspaceUserRoles;

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

@ -3007,9 +3007,9 @@ class BaseModelSqlv2 {
} }
} }
async _wherePk(id, skipGetColumns = false) { async _wherePk(id, skipGetColumns = false, skipPkValidation = false) {
if (!skipGetColumns) await this.model.getColumns(); if (!skipGetColumns) await this.model.getColumns();
return _wherePk(this.model.primaryKeys, id); return _wherePk(this.model.primaryKeys, id, skipPkValidation);
} }
comparePks(pk1, pk2) { comparePks(pk1, pk2) {
@ -6894,24 +6894,35 @@ function applyPaginate(
return query; return query;
} }
export function _wherePk(primaryKeys: Column[], id: unknown | unknown[]) { export function _wherePk(
primaryKeys: Column[],
id: unknown | unknown[],
skipPkValidation = false,
) {
const where = {}; const where = {};
// if id object is provided use as it is // if id object is provided use as it is
if (id && typeof id === 'object' && !Array.isArray(id)) { if (id && typeof id === 'object' && !Array.isArray(id)) {
// verify all pk columns are present in id object // verify all pk columns are present in id object
for (const pk of primaryKeys) { for (const pk of primaryKeys) {
let key: string;
if (pk.id in id) { if (pk.id in id) {
where[pk.column_name] = id[pk.id]; key = pk.id;
} else if (pk.title in id) { } else if (pk.title in id) {
where[pk.column_name] = id[pk.title]; key = pk.title;
} else if (pk.column_name in id) { } else if (pk.column_name in id) {
where[pk.column_name] = id[pk.column_name]; key = pk.column_name;
} else { } else {
NcError.badRequest( NcError.badRequest(
`Primary key column ${pk.title} not found in id object`, `Primary key column ${pk.title} not found in id object`,
); );
} }
where[pk.column_name] = id[key];
// validate value if auto-increment column
// todo: add more validation based on column constraints
if (!skipPkValidation && pk.ai && !/^\d+$/.test(id[key])) {
NcError.invalidPrimaryKey(id[key], pk.title);
}
} }
return where; return where;

12
packages/nocodb/src/helpers/catchError.ts

@ -520,6 +520,11 @@ const errorHelpers: {
message: (offset: string) => `Offset value '${offset}' is invalid`, message: (offset: string) => `Offset value '${offset}' is invalid`,
code: 422, code: 422,
}, },
[NcErrorType.INVALID_PK_VALUE]: {
message: (value: any, pkColumn: string) =>
`Primary key value '${value}' is invalid for column '${pkColumn}'`,
code: 422,
},
[NcErrorType.INVALID_LIMIT_VALUE]: { [NcErrorType.INVALID_LIMIT_VALUE]: {
message: `Limit value should be between ${defaultLimitConfig.limitMin} and ${defaultLimitConfig.limitMax}`, message: `Limit value should be between ${defaultLimitConfig.limitMin} and ${defaultLimitConfig.limitMax}`,
code: 422, code: 422,
@ -681,6 +686,13 @@ export class NcError {
}); });
} }
static invalidPrimaryKey(value: any, pkColumn: string, args?: NcErrorArgs) {
throw new NcBaseErrorv2(NcErrorType.INVALID_PK_VALUE, {
params: [value, pkColumn],
...args,
});
}
static invalidLimitValue(args?: NcErrorArgs) { static invalidLimitValue(args?: NcErrorArgs) {
throw new NcBaseErrorv2(NcErrorType.INVALID_LIMIT_VALUE, { throw new NcBaseErrorv2(NcErrorType.INVALID_LIMIT_VALUE, {
...args, ...args,

Loading…
Cancel
Save