From 23ba777e5aaf72a0352e1fbd336d0d2c3d09c4b8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 25 Aug 2022 14:16:29 +0200 Subject: [PATCH] Frontend validation --- dto/src/responses/auth.ts | 10 +++------- dto/src/responses/base.ts | 12 ++++++++++-- dto/src/responses/fs.ts | 20 +++++++------------- dto/tsconfig.json | 3 ++- frontend/src/api/auth.ts | 2 +- frontend/src/api/base.ts | 14 +++++++++++--- frontend/src/views/SetTokenView.vue | 2 +- frontend/tsconfig.json | 3 +++ tsconfig.json | 3 ++- 9 files changed, 40 insertions(+), 29 deletions(-) diff --git a/dto/src/responses/auth.ts b/dto/src/responses/auth.ts index 418223d..46e5257 100644 --- a/dto/src/responses/auth.ts +++ b/dto/src/responses/auth.ts @@ -1,4 +1,4 @@ -import { BaseResponse, SuccessResponse } from './base'; +import { SuccessResponse } from './base'; import { IsBase32, IsJWT, IsNotEmpty } from 'class-validator'; export type TfaRequiredResponse = SuccessResponse; @@ -8,17 +8,13 @@ export type TfaCompletedResponse = SuccessResponse; export type SignupResponse = SuccessResponse; export type RefreshResponse = LoginResponse; -export class LoginResponse extends BaseResponse { - statusCode: 200; - +export class LoginResponse extends SuccessResponse { @IsNotEmpty() @IsJWT() jwt: string; } -export class RequestTotpTfaResponse extends BaseResponse { - statusCode: 200; - +export class RequestTotpTfaResponse extends SuccessResponse { @IsNotEmpty() qrCode: string; diff --git a/dto/src/responses/base.ts b/dto/src/responses/base.ts index 583eed3..48ec026 100644 --- a/dto/src/responses/base.ts +++ b/dto/src/responses/base.ts @@ -1,12 +1,20 @@ export class BaseResponse { + constructor(statusCode: number) { + this.statusCode = statusCode; + } + statusCode: number; } export class SuccessResponse extends BaseResponse { - statusCode: 200; + constructor() { + super(200); + } + + declare statusCode: 200; } export class ErrorResponse extends BaseResponse { - statusCode: 400 | 401 | 403; + declare statusCode: 400 | 401 | 403; message?: string; } diff --git a/dto/src/responses/fs.ts b/dto/src/responses/fs.ts index e4cf40f..cfa7f70 100644 --- a/dto/src/responses/fs.ts +++ b/dto/src/responses/fs.ts @@ -1,21 +1,17 @@ -import { BaseResponse, SuccessResponse } from './base'; +import { SuccessResponse } from './base'; import { IsBoolean, IsInt, IsNotEmpty, Min } from 'class-validator'; export type UploadFileResponse = SuccessResponse; export type DeleteResponse = SuccessResponse; export type CreateFileResponse = CreateFolderResponse; -export class GetRootResponse extends BaseResponse { - statusCode: 200; - +export class GetRootResponse extends SuccessResponse { @IsInt() @Min(1) rootId: number; } -export class GetNodeResponse extends BaseResponse { - statusCode: 200; - +export class GetNodeResponse extends SuccessResponse { @IsInt() @Min(1) id: number; @@ -28,21 +24,19 @@ export class GetNodeResponse extends BaseResponse { parent: number | null; + @IsInt({ each: true }) + @Min(1, { each: true }) children?: number[]; size?: number; } -export class GetPathResponse extends BaseResponse { - statusCode: 200; - +export class GetPathResponse extends SuccessResponse { @IsNotEmpty() path: string; } -export class CreateFolderResponse extends BaseResponse { - statusCode: 200; - +export class CreateFolderResponse extends SuccessResponse { @IsInt() @Min(1) id: number; diff --git a/dto/tsconfig.json b/dto/tsconfig.json index 7fe4cb9..eedea79 100644 --- a/dto/tsconfig.json +++ b/dto/tsconfig.json @@ -11,7 +11,8 @@ "outDir": "./dist", "baseUrl": "./src", "incremental": true, - "skipLibCheck": true + "skipLibCheck": true, + "strictPropertyInitialization": false }, "exclude": ["node_modules", "dist"] } diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts index 8453e62..aed3adb 100644 --- a/frontend/src/api/auth.ts +++ b/frontend/src/api/auth.ts @@ -27,4 +27,4 @@ export const auth_signup = ( export const refresh_token = ( token: string ): Promise => - post_token('/api/auth/refresh', '', token); + post_token('/api/auth/refresh', {}, token); diff --git a/frontend/src/api/base.ts b/frontend/src/api/base.ts index 406d9bb..180a095 100644 --- a/frontend/src/api/base.ts +++ b/frontend/src/api/base.ts @@ -1,5 +1,7 @@ import axios from 'axios'; import { Requests, Responses } from 'dto'; +export { Requests, Responses }; +import { validateSync } from 'class-validator'; export const post = (url: string, data: T) => axios @@ -9,12 +11,17 @@ export const post = (url: string, data: T) => .then((res) => res.data) .catch((err) => err.response.data); -export const post_token = ( +export function post_token( url: string, data: T, token: string -) => - axios +) { + const errors = validateSync(data); + if (errors.length > 0) { + console.error('Validation failed, errors: ', errors); + throw new Error('Validation failed'); + } + return axios .post(url, data, { headers: { Authorization: 'Bearer ' + token, @@ -23,6 +30,7 @@ export const post_token = ( }) .then((res) => res.data) .catch((err) => err.response.data); +} export const post_token_form = ( url: string, diff --git a/frontend/src/views/SetTokenView.vue b/frontend/src/views/SetTokenView.vue index e737e33..d15660e 100644 --- a/frontend/src/views/SetTokenView.vue +++ b/frontend/src/views/SetTokenView.vue @@ -13,7 +13,7 @@ router.replace({ path: '/' }); diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 9772821..e47981e 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -11,6 +11,9 @@ "forceConsistentCasingInFileNames": true, "useDefineForClassFields": true, "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, "baseUrl": ".", "types": [ "webpack-env" diff --git a/tsconfig.json b/tsconfig.json index 71e4661..631555b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,8 @@ "baseUrl": "./", "incremental": true, "skipLibCheck": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "strictPropertyInitialization": false }, "exclude": ["node_modules", "dist", "test", "**/*spec.ts", "frontend"] }