From 373da6d83dd308ad03eb81fb96d06577f9f44232 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Sun, 26 Feb 2023 02:31:03 +0530 Subject: [PATCH] feat: add validations and schema for all apis Signed-off-by: Pranav C --- packages/nocodb-sdk/src/lib/Api.ts | 116 ++++++----- packages/nocodb/src/lib/meta/api/auditApis.ts | 3 + .../nocodb/src/lib/meta/api/formViewApis.ts | 1 + .../nocodb/src/lib/meta/api/mapViewApis.ts | 1 + .../nocodb/src/lib/meta/api/orgTokenApis.ts | 2 + .../nocodb/src/lib/meta/api/orgUserApis.ts | 3 + .../nocodb/src/lib/meta/api/pluginApis.ts | 4 + .../src/lib/meta/api/projectUserApis.ts | 3 + .../nocodb/src/lib/meta/api/sharedBaseApis.ts | 3 + .../src/lib/meta/api/userApi/userApis.ts | 1 + scripts/sdk/swagger.json | 197 ++++++++++++------ 11 files changed, 215 insertions(+), 119 deletions(-) diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index 918aa4fe2d..814c90e2c9 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -672,7 +672,7 @@ export interface SignInReqType { password: string; } -export interface ForgotPasswordReqType { +export interface PasswordForgotReqType { email: string; } @@ -686,7 +686,7 @@ export interface PasswordChangeReqType { } export interface ApiTokenReqType { - description?: string; + description?: string | null; } export interface PluginType { @@ -881,6 +881,45 @@ export type VisibilityRuleReqType = { export type NcBoolType = boolean | number | null; +export interface CommentReqType { + row_id: string; + fk_model_id: string; + description?: string; +} + +export interface AuditRowUpdateReqType { + fk_model_id?: string; + column_name?: string; + row_id?: string; + value?: any; + prev_value?: any; +} + +export interface OrgUserReqType { + email?: string; + roles?: string; +} + +export interface ProjectUserReqType { + email?: string; + roles?: string; +} + +export interface SharedBaseReqType { + uuid?: string | null; + roles?: string | null; +} + +export interface PluginTestReqType { + title?: string; + input?: any; +} + +export interface PluginReqType { + active?: NcBoolType; + input?: any; +} + import axios, { AxiosInstance, AxiosRequestConfig, ResponseType } from 'axios'; export type QueryParamsType = Record; @@ -1149,7 +1188,7 @@ export class Api< * @response `200` `void` OK * @response `401` `void` Unauthorized */ - passwordForgot: (data: ForgotPasswordReqType, params: RequestParams = {}) => + passwordForgot: (data: PasswordForgotReqType, params: RequestParams = {}) => this.request({ path: `/api/v1/auth/password/forgot`, method: 'POST', @@ -1304,7 +1343,7 @@ export class Api< */ projectUserAdd: ( projectId: string, - data: any, + data: ProjectUserReqType, params: RequestParams = {} ) => this.request({ @@ -1328,7 +1367,7 @@ export class Api< projectUserUpdate: ( projectId: string, userId: string, - data: any, + data: ProjectUserReqType, params: RequestParams = {} ) => this.request({ @@ -1427,7 +1466,7 @@ export class Api< * @request POST:/api/v1/tokens * @response `200` `void` OK */ - create: (data: ApiTokenType, params: RequestParams = {}) => + create: (data: ApiTokenReqType, params: RequestParams = {}) => this.request({ path: `/api/v1/tokens`, method: 'POST', @@ -1605,7 +1644,11 @@ export class Api< * @request PATCH:/api/v1/users/{userId} * @response `200` `void` OK */ - update: (userId: string, data: UserType, params: RequestParams = {}) => + update: ( + userId: string, + data: OrgUserReqType, + params: RequestParams = {} + ) => this.request({ path: `/api/v1/users/${userId}`, method: 'PATCH', @@ -1903,18 +1946,13 @@ export class Api< }), /** - * No description - * - * @tags Project - * @name SharedBaseCreate - * @request POST:/api/v1/db/meta/projects/{projectId}/shared - * @response `200` `{ - uuid?: string, - url?: string, - roles?: string, - -}` OK - */ + * No description + * + * @tags Project + * @name SharedBaseCreate + * @request POST:/api/v1/db/meta/projects/{projectId}/shared + * @response `200` `SharedBaseReqType` OK + */ sharedBaseCreate: ( projectId: string, data: { @@ -1923,14 +1961,7 @@ export class Api< }, params: RequestParams = {} ) => - this.request< - { - uuid?: string; - url?: string; - roles?: string; - }, - any - >({ + this.request({ path: `/api/v1/db/meta/projects/${projectId}/shared`, method: 'POST', body: data, @@ -4353,14 +4384,7 @@ export class Api< * @request POST:/api/v1/db/meta/audits/comments * @response `200` `void` OK */ - commentRow: ( - data: { - row_id: string; - fk_model_id: string; - description?: string; - }, - params: RequestParams = {} - ) => + commentRow: (data: CommentReqType, params: RequestParams = {}) => this.request({ path: `/api/v1/db/meta/audits/comments`, method: 'POST', @@ -4402,13 +4426,7 @@ export class Api< */ auditRowUpdate: ( rowId: string, - data: { - fk_model_id?: string; - column_name?: string; - row_id?: string; - value?: string; - prev_value?: string; - }, + data: AuditRowUpdateReqType, params: RequestParams = {} ) => this.request({ @@ -4833,15 +4851,7 @@ export class Api< * @response `400` `void` Bad Request * @response `401` `void` Unauthorized */ - test: ( - data: { - id?: string; - title?: string; - input?: any; - category?: string; - }, - params: RequestParams = {} - ) => + test: (data: PluginTestReqType, params: RequestParams = {}) => this.request({ path: `/api/v1/db/meta/plugins/test`, method: 'POST', @@ -4857,10 +4867,10 @@ export class Api< * @tags Plugin * @name Update * @request PATCH:/api/v1/db/meta/plugins/{pluginId} - * @response `200` `PluginType` OK + * @response `200` `PluginReqType` OK */ update: (pluginId: string, data: PluginType, params: RequestParams = {}) => - this.request({ + this.request({ path: `/api/v1/db/meta/plugins/${pluginId}`, method: 'PATCH', body: data, diff --git a/packages/nocodb/src/lib/meta/api/auditApis.ts b/packages/nocodb/src/lib/meta/api/auditApis.ts index a9c6b89dcd..fdf9f70daf 100644 --- a/packages/nocodb/src/lib/meta/api/auditApis.ts +++ b/packages/nocodb/src/lib/meta/api/auditApis.ts @@ -6,6 +6,7 @@ import { PagedResponseImpl } from '../helpers/PagedResponse'; import ncMetaAclMw from '../helpers/ncMetaAclMw'; import DOMPurify from 'isomorphic-dompurify'; +import { getAjvValidatorMw } from './helpers'; export async function commentRow(req: Request, res) { res.json( @@ -69,10 +70,12 @@ router.get( ); router.post( '/api/v1/db/meta/audits/comments', + getAjvValidatorMw('swagger.json#/components/schemas/CommentReq'), ncMetaAclMw(commentRow, 'commentRow') ); router.post( '/api/v1/db/meta/audits/rows/:rowId/update', + getAjvValidatorMw('swagger.json#/components/schemas/AuditRowUpdateReq'), ncMetaAclMw(auditRowUpdate, 'auditRowUpdate') ); router.get( diff --git a/packages/nocodb/src/lib/meta/api/formViewApis.ts b/packages/nocodb/src/lib/meta/api/formViewApis.ts index 98955f9076..fda614c803 100644 --- a/packages/nocodb/src/lib/meta/api/formViewApis.ts +++ b/packages/nocodb/src/lib/meta/api/formViewApis.ts @@ -55,6 +55,7 @@ router.get( router.patch( '/api/v1/db/meta/forms/:formViewId', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/FormReq'), ncMetaAclMw(formViewUpdate, 'formViewUpdate') ); router.delete( diff --git a/packages/nocodb/src/lib/meta/api/mapViewApis.ts b/packages/nocodb/src/lib/meta/api/mapViewApis.ts index ca0dcca4ed..5771284da4 100644 --- a/packages/nocodb/src/lib/meta/api/mapViewApis.ts +++ b/packages/nocodb/src/lib/meta/api/mapViewApis.ts @@ -28,6 +28,7 @@ export async function mapViewUpdate(req, res) { const router = Router({ mergeParams: true }); +// todo: add schema in swagger and use getAjvValidatorMw router.post( '/api/v1/db/meta/tables/:tableId/maps', metaApiMetrics, diff --git a/packages/nocodb/src/lib/meta/api/orgTokenApis.ts b/packages/nocodb/src/lib/meta/api/orgTokenApis.ts index a9f1f9fc14..300a804c4e 100644 --- a/packages/nocodb/src/lib/meta/api/orgTokenApis.ts +++ b/packages/nocodb/src/lib/meta/api/orgTokenApis.ts @@ -8,6 +8,7 @@ import getHandler from '../helpers/getHandler'; import ncMetaAclMw from '../helpers/ncMetaAclMw'; import { PagedResponseImpl } from '../helpers/PagedResponse'; import { apiTokenListEE } from './ee/orgTokenApis'; +import { getAjvValidatorMw } from './helpers'; async function apiTokenList(req, res) { const fk_user_id = req.user.id; @@ -65,6 +66,7 @@ router.get( router.post( '/api/v1/tokens', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/ApiTokenReq'), ncMetaAclMw(apiTokenCreate, 'apiTokenCreate', { // allowedRoles: [OrgUserRoles.SUPER], blockApiTokenAccess: true, diff --git a/packages/nocodb/src/lib/meta/api/orgUserApis.ts b/packages/nocodb/src/lib/meta/api/orgUserApis.ts index f9d5e077f7..62c3cdf2aa 100644 --- a/packages/nocodb/src/lib/meta/api/orgUserApis.ts +++ b/packages/nocodb/src/lib/meta/api/orgUserApis.ts @@ -22,6 +22,7 @@ import { extractProps } from '../helpers/extractProps'; import ncMetaAclMw from '../helpers/ncMetaAclMw'; import { PagedResponseImpl } from '../helpers/PagedResponse'; import { randomTokenString } from '../helpers/stringHelpers'; +import { getAjvValidatorMw } from './helpers'; import { sendInviteEmail } from './projectUserApis'; async function userList(req, res) { @@ -266,6 +267,7 @@ router.get( router.patch( '/api/v1/users/:userId', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/OrgUserReq'), ncMetaAclMw(userUpdate, 'userUpdate', { allowedRoles: [OrgUserRoles.SUPER_ADMIN], blockApiTokenAccess: true, @@ -282,6 +284,7 @@ router.delete( router.post( '/api/v1/users', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/OrgUserReq'), ncMetaAclMw(userAdd, 'userAdd', { allowedRoles: [OrgUserRoles.SUPER_ADMIN], blockApiTokenAccess: true, diff --git a/packages/nocodb/src/lib/meta/api/pluginApis.ts b/packages/nocodb/src/lib/meta/api/pluginApis.ts index e0a39646af..6934e17b41 100644 --- a/packages/nocodb/src/lib/meta/api/pluginApis.ts +++ b/packages/nocodb/src/lib/meta/api/pluginApis.ts @@ -6,6 +6,7 @@ import { PluginType } from 'nocodb-sdk'; import NcPluginMgrv2 from '../helpers/NcPluginMgrv2'; import ncMetaAclMw from '../helpers/ncMetaAclMw'; import { metaApiMetrics } from '../helpers/apiMetrics'; +import { getAjvValidatorMw } from './helpers'; export async function pluginList(_req: Request, res: Response) { res.json(new PagedResponseImpl(await Plugin.list())); @@ -43,6 +44,8 @@ router.get( router.post( '/api/v1/db/meta/plugins/test', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/PluginTestReq'), + ncMetaAclMw(pluginTest, 'pluginTest') ); router.get( @@ -53,6 +56,7 @@ router.get( router.patch( '/api/v1/db/meta/plugins/:pluginId', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/PluginReq'), ncMetaAclMw(pluginUpdate, 'pluginUpdate') ); router.get( diff --git a/packages/nocodb/src/lib/meta/api/projectUserApis.ts b/packages/nocodb/src/lib/meta/api/projectUserApis.ts index e0165452ac..3f0610fee6 100644 --- a/packages/nocodb/src/lib/meta/api/projectUserApis.ts +++ b/packages/nocodb/src/lib/meta/api/projectUserApis.ts @@ -17,6 +17,7 @@ import Noco from '../../Noco'; import { PluginCategory } from 'nocodb-sdk'; import { metaApiMetrics } from '../helpers/apiMetrics'; import { randomTokenString } from '../helpers/stringHelpers'; +import { getAjvValidatorMw } from './helpers'; async function userList(req, res) { res.json({ @@ -310,11 +311,13 @@ router.get( router.post( '/api/v1/db/meta/projects/:projectId/users', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/ProjectUserReq'), ncMetaAclMw(userInvite, 'userInvite') ); router.patch( '/api/v1/db/meta/projects/:projectId/users/:userId', metaApiMetrics, + getAjvValidatorMw('swagger.json#/components/schemas/ProjectUserReq'), ncMetaAclMw(projectUserUpdate, 'projectUserUpdate') ); router.delete( diff --git a/packages/nocodb/src/lib/meta/api/sharedBaseApis.ts b/packages/nocodb/src/lib/meta/api/sharedBaseApis.ts index e1ce599a8f..c232327aa8 100644 --- a/packages/nocodb/src/lib/meta/api/sharedBaseApis.ts +++ b/packages/nocodb/src/lib/meta/api/sharedBaseApis.ts @@ -4,6 +4,7 @@ import ncMetaAclMw from '../helpers/ncMetaAclMw'; import { v4 as uuidv4 } from 'uuid'; import Project from '../../models/Project'; import { NcError } from '../helpers/catchError'; +import { getAjvValidatorMw } from './helpers'; // todo: load from config const config = { dashboardPath: '/nc', @@ -96,10 +97,12 @@ router.get( ); router.post( '/api/v1/db/meta/projects/:projectId/shared', + getAjvValidatorMw('swagger.json#/components/schemas/SharedBaseReq'), ncMetaAclMw(createSharedBaseLink, 'createSharedBaseLink') ); router.patch( '/api/v1/db/meta/projects/:projectId/shared', + getAjvValidatorMw('swagger.json#/components/schemas/SharedBaseReq'), ncMetaAclMw(updateSharedBaseLink, 'updateSharedBaseLink') ); router.delete( diff --git a/packages/nocodb/src/lib/meta/api/userApi/userApis.ts b/packages/nocodb/src/lib/meta/api/userApi/userApis.ts index 7c4b90b5cb..4d5b5ce7c5 100644 --- a/packages/nocodb/src/lib/meta/api/userApi/userApis.ts +++ b/packages/nocodb/src/lib/meta/api/userApi/userApis.ts @@ -593,6 +593,7 @@ const mapRoutes = (router) => { ); router.post( '/api/v1/db/auth/password/reset/:tokenId', + getAjvValidatorMw('swagger.json#/components/schemas/PasswordResetReq'), catchError(passwordReset) ); router.post( diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json index 521a9d6c61..3571cb5a98 100644 --- a/scripts/sdk/swagger.json +++ b/scripts/sdk/swagger.json @@ -478,7 +478,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ApiToken" + "$ref": "#/components/schemas/ApiTokenReq" } } } @@ -713,7 +713,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/User" + "$ref": "#/components/schemas/OrgUserReq" } } }, @@ -858,7 +858,8 @@ "description": "OK", "content": { "application/json": { - "schema": {} + "schema": { + } } } } @@ -866,7 +867,9 @@ "requestBody": { "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/ProjectUserReq" + } } } }, @@ -977,7 +980,9 @@ "requestBody": { "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/ProjectUserReq" + } } } }, @@ -1472,18 +1477,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "uuid": { - "type": "string" - }, - "url": { - "type": "string" - }, - "roles": { - "type": "string" - } - } + "$ref": "#/components/schemas/SharedBaseReq" } } } @@ -5793,23 +5787,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "row_id": { - "type": "string" - }, - "fk_model_id": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "row_id", - "fk_model_id", - "comment" - ] + "$ref": "#/components/schemas/CommentReq" } } } @@ -5946,24 +5924,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "fk_model_id": { - "type": "string" - }, - "column_name": { - "type": "string" - }, - "row_id": { - "type": "string" - }, - "value": { - "type": "string" - }, - "prev_value": { - "type": "string" - } - } + "$ref": "#/components/schemas/AuditRowUpdateReq" } } } @@ -6307,19 +6268,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "input": {}, - "category": { - "type": "string" - } - } + "$ref": "#/components/schemas/PluginTestReq" } } } @@ -6346,7 +6295,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Plugin" + "$ref": "#/components/schemas/PluginReq" } } } @@ -10028,6 +9977,22 @@ "updated_at": {} } }, + "ApiTokenReq": { + "title": "ApiToken", + "type": "object", + "properties": { + "description": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + } + }, "HookLog": { "title": "ApiToken", "type": "object", @@ -10468,6 +10433,106 @@ "type": "null" } ] + }, + "CommentReq": { + "type": "object", + "properties": { + "row_id": { + "type": "string" + }, + "fk_model_id": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "row_id", + "fk_model_id", + "comment" + ] + }, + "AuditRowUpdateReq": { + "type": "object", + "properties": { + "fk_model_id": { + "type": "string" + }, + "column_name": { + "type": "string" + }, + "row_id": { + "type": "string" + }, + "value": { }, + "prev_value": { } + } + }, + "OrgUserReq": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "roles": { + "type": "string" + } + } + }, + "ProjectUserReq": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "roles": { + "type": "string" + } + } + }, + "SharedBaseReq": { + "type": "object", + "properties": { + "uuid": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "roles": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + } + }, + "PluginTestReq": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "input": {} + } + }, + "PluginReq": { + "type": "object", + "properties": { + "active": { + "$ref": "#/components/schemas/NcBool" + }, + "input": {} + } } }, "requestBodies": {