diff --git a/Common/Types/API/HTTPErrorResponse.ts b/Common/Types/API/HTTPErrorResponse.ts index 4462742bff..6df1dca277 100644 --- a/Common/Types/API/HTTPErrorResponse.ts +++ b/Common/Types/API/HTTPErrorResponse.ts @@ -1,4 +1,5 @@ import { JSONObject } from '../JSON'; +import Typeof from '../Typeof'; import HTTPResponse from './HTTPResponse'; export default class HTTPErrorResponse extends HTTPResponse { @@ -10,6 +11,11 @@ export default class HTTPErrorResponse extends HTTPResponse { if (!this.data['error']) { return ''; } + + if (this.data['data'] && Typeof.String === this.data['data']) { + return this.data['data'] as string; + } + return this.data['error'] as string; } } diff --git a/Common/Types/API/HTTPResponse.ts b/Common/Types/API/HTTPResponse.ts index 6b9cbec571..2c2c6930ef 100644 --- a/Common/Types/API/HTTPResponse.ts +++ b/Common/Types/API/HTTPResponse.ts @@ -5,6 +5,7 @@ import { JSONObject, JSONObjectOrArray, } from '../JSON'; +import Typeof from '../Typeof'; export default class HTTPResponse< T extends JSONObjectOrArray | BaseModel | Array @@ -78,6 +79,10 @@ export default class HTTPResponse< ); } else if (Array.isArray(data)) { this.jsonData = JSONFunctions.deserializeArray(data as JSONArray); + } else if (Typeof.String === typeof data) { + this.jsonData = { + data, + }; } else { this.jsonData = JSONFunctions.deserialize(data as JSONObject); } diff --git a/Common/Types/JSON.ts b/Common/Types/JSON.ts index 7cb8c52fbf..456758239b 100644 --- a/Common/Types/JSON.ts +++ b/Common/Types/JSON.ts @@ -40,6 +40,7 @@ enum ObjectType { Hostname = 'Hostname', HashedString = 'HashedString', DateTime = 'DateTime', + Buffer = 'Buffer', InBetween = 'InBetween', } @@ -51,6 +52,7 @@ export type JSONValue = | Array | boolean | JSONObject + | Uint8Array | JSONArray | Date | Array @@ -148,7 +150,10 @@ export class JSONFunctions { } else if (typeof val === Typeof.Number) { return val; } else if (ArrayBuffer.isView(val)) { - return val; + return { + _type: ObjectType.Buffer, + value: val as Uint8Array, + }; } else if (val && val instanceof Name) { return { _type: ObjectType.Name, @@ -240,6 +245,14 @@ export class JSONFunctions { _type: ObjectType.DateTime, value: OneUptimeDate.toString(val as Date).toString(), }; + } else if ( + typeof val === Typeof.Object && + (val as JSONObject)['_type'] && + Object.keys(ObjectType).includes( + (val as JSONObject)['_type'] as string + ) + ) { + return val; } else if (typeof val === Typeof.Object) { return this.serialize(val as JSONObject); } @@ -255,8 +268,17 @@ export class JSONFunctions { val.toString().trim() === '' ) { return val; - } else if (ArrayBuffer.isView(val)) { - return val; + } else if ( + val && + typeof val === Typeof.Object && + (val as JSONObject)['_type'] && + (val as JSONObject)['value'] && + ((val as JSONObject)['value'] as JSONObject)['type'] && + ((val as JSONObject)['value'] as JSONObject)['type'] === + ObjectType.Buffer && + ((val as JSONObject)['_type'] as string) === ObjectType.Buffer + ) { + return Buffer.from((val as JSONObject)['value'] as Uint8Array); } else if (typeof val === Typeof.Number) { return val; } else if (val instanceof DatabaseProperty) { diff --git a/CommonUI/src/Components/CounterModelAlert/CounterModelAlert.tsx b/CommonUI/src/Components/CounterModelAlert/CounterModelAlert.tsx index 022ddc68ae..6d515de5c9 100644 --- a/CommonUI/src/Components/CounterModelAlert/CounterModelAlert.tsx +++ b/CommonUI/src/Components/CounterModelAlert/CounterModelAlert.tsx @@ -4,7 +4,6 @@ import BaseModel from 'Common/Models/BaseModel'; import Query from '../../Utils/ModelAPI/Query'; import ModelAPI, { RequestOptions } from '../../Utils/ModelAPI/ModelAPI'; import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; -import { JSONObject } from 'Common/Types/JSON'; export interface ComponentProps { alertType: AlertType; @@ -43,9 +42,8 @@ const CounterModelAlert: Function = ( } catch (err) { try { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } catch (e) { setError('Server Error. Please try again'); diff --git a/CommonUI/src/Components/FilePicker/FilePicker.tsx b/CommonUI/src/Components/FilePicker/FilePicker.tsx index e9cfb2646f..fece3334d5 100644 --- a/CommonUI/src/Components/FilePicker/FilePicker.tsx +++ b/CommonUI/src/Components/FilePicker/FilePicker.tsx @@ -14,6 +14,7 @@ import ComponentLoader from '../ComponentLoader/ComponentLoader'; import Icon, { IconProp, SizeProp, ThickProp } from '../Icon/Icon'; import { White } from 'Common/Types/BrandColors'; import HTTPResponse from 'Common/Types/API/HTTPResponse'; +import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; export interface ComponentProps { initialValue?: undefined | Array; @@ -34,7 +35,7 @@ const FilePicker: FunctionComponent = ( props: ComponentProps ): ReactElement => { const [isLoading, setIsLoading] = useState(false); - + const [error, setError] = useState(''); const [filesModel, setFilesModel] = useState>([]); useEffect(() => { @@ -51,39 +52,50 @@ const FilePicker: FunctionComponent = ( accept: { 'image/*': [], }, - onDrop: (async (acceptedFiles: Array) => { + onDrop: async (acceptedFiles: Array) => { setIsLoading(true); + try { + if (props.readOnly) { + return; + } - if (props.readOnly) { - return; + // Upload these files. + const filesResult: Array = []; + for (const acceptedFile of acceptedFiles) { + const fileModel: FileModel = new FileModel(); + fileModel.name = acceptedFile.name; + const fileBuffer = Buffer.from( + await getBase64(acceptedFile), + 'base64' + ); + fileModel.file = fileBuffer; + fileModel.isPublic = false; + fileModel.type = acceptedFile.type as MimeType; + + const result: HTTPResponse = + (await ModelAPI.create( + fileModel, + CommonURL.fromURL(FILE_URL).addRoute('/file') + )) as HTTPResponse; + filesResult.push(result.data as FileModel); + } + + setFilesModel(filesResult); + + props.onBlur && props.onBlur(); + props.onChange && props.onChange(filesModel); + } catch (err) { + try { + setError( + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' + ); + } catch (e) { + setError('Server Error. Please try again'); + } } - - // Upload these files. - const filesResult: Array = []; - for (const acceptedFile of acceptedFiles) { - const fileModel: FileModel = new FileModel(); - fileModel.name = acceptedFile.name; - const fileBuffer = Buffer.from( - await getBase64(acceptedFile), - 'base64' - ); - fileModel.file = fileBuffer; - fileModel.isPublic = false; - fileModel.type = acceptedFile.type as MimeType; - - const result: HTTPResponse = await ModelAPI.create( - fileModel, - CommonURL.fromURL(FILE_URL).addRoute('/file') - ) as HTTPResponse; - filesResult.push(result.data as FileModel); - } - - setFilesModel(filesResult); - - props.onBlur && props.onBlur(); - props.onChange && props.onChange(filesModel); setIsLoading(false); - }) + }, }); const getBase64 = (file: File): Promise => { @@ -105,10 +117,9 @@ const FilePicker: FunctionComponent = ( return <>; } - const blob = new Blob( - [new Uint8Array((file.file as any).data).buffer], - { type: file.type as string } - ); + const blob = new Blob([file.file as Uint8Array], { + type: file.type as string, + }); const url: string = URL.createObjectURL(blob); return (
@@ -158,13 +169,18 @@ const FilePicker: FunctionComponent = ( })} > - {!props.placeholder && ( + {!props.placeholder && !error && (

Drag and drop some files here, or click to select files.

)} - {props.placeholder && ( + {error && ( +

+ {error} +

+ )} + {props.placeholder && !error && (

{props.placeholder}

diff --git a/CommonUI/src/Components/Forms/ModelForm.tsx b/CommonUI/src/Components/Forms/ModelForm.tsx index bfe9e69b04..158992eab3 100644 --- a/CommonUI/src/Components/Forms/ModelForm.tsx +++ b/CommonUI/src/Components/Forms/ModelForm.tsx @@ -282,9 +282,8 @@ const ModelForm: Function = ( } catch (err) { try { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } catch (e) { setError('Server Error. Please try again'); @@ -305,9 +304,9 @@ const ModelForm: Function = ( } catch (err) { let error: string = ''; try { - error = ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string; + error = + (err as HTTPErrorResponse).message || + 'Server Error. Please try again'; } catch (e) { error = 'Server Error. Please try again'; } @@ -386,9 +385,8 @@ const ModelForm: Function = ( } } catch (err) { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } diff --git a/CommonUI/src/Components/ModelDelete/ModelDelete.tsx b/CommonUI/src/Components/ModelDelete/ModelDelete.tsx index fbe45e2970..65fea045e3 100644 --- a/CommonUI/src/Components/ModelDelete/ModelDelete.tsx +++ b/CommonUI/src/Components/ModelDelete/ModelDelete.tsx @@ -1,6 +1,5 @@ import BaseModel from 'Common/Models/BaseModel'; import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; -import { JSONObject } from 'Common/Types/JSON'; import ObjectID from 'Common/Types/ObjectID'; import React, { ReactElement, useState } from 'react'; import ModelAPI from '../../Utils/ModelAPI/ModelAPI'; @@ -35,9 +34,8 @@ const ModelDelete: Function = ( } catch (err) { try { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } catch (e) { setError('Server Error. Please try again'); diff --git a/CommonUI/src/Components/ModelDetail/ModelDetail.tsx b/CommonUI/src/Components/ModelDetail/ModelDetail.tsx index 7270548d6b..b3febd71d6 100644 --- a/CommonUI/src/Components/ModelDetail/ModelDetail.tsx +++ b/CommonUI/src/Components/ModelDetail/ModelDetail.tsx @@ -201,9 +201,9 @@ const ModelDetail: Function = ( } catch (err) { let error: string = ''; try { - error = ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string; + error = + (err as HTTPErrorResponse).message || + 'Server Error. Please try again'; } catch (e) { error = 'Server Error. Please try again'; } diff --git a/CommonUI/src/Components/ModelTable/ModelTable.tsx b/CommonUI/src/Components/ModelTable/ModelTable.tsx index 75003a7606..4ad6ed0361 100644 --- a/CommonUI/src/Components/ModelTable/ModelTable.tsx +++ b/CommonUI/src/Components/ModelTable/ModelTable.tsx @@ -207,9 +207,8 @@ const ModelTable: Function = ( } catch (err) { try { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } catch (e) { setError('Server Error. Please try again'); @@ -309,9 +308,8 @@ const ModelTable: Function = ( } catch (err) { try { setTableFilterError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } catch (e) { setTableFilterError('Server Error. Please try again'); @@ -359,9 +357,8 @@ const ModelTable: Function = ( } catch (err) { try { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } catch (e) { setError('Server Error. Please try again'); diff --git a/CommonUI/src/Components/MonitorGraphs/Uptime.tsx b/CommonUI/src/Components/MonitorGraphs/Uptime.tsx index 183961161c..d410fda8e3 100644 --- a/CommonUI/src/Components/MonitorGraphs/Uptime.tsx +++ b/CommonUI/src/Components/MonitorGraphs/Uptime.tsx @@ -16,7 +16,6 @@ import DayUptimeGraph, { Event } from '../Graphs/DayUptimeGraph'; import { Green } from 'Common/Types/BrandColors'; import ErrorMessage from '../ErrorMessage/ErrorMessage'; import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; -import { JSONObject } from 'Common/Types/JSON'; import useAsyncEffect from 'use-async-effect'; export interface ComponentProps { @@ -96,9 +95,8 @@ const MonitorUptimeGraph: FunctionComponent = ( } catch (err) { try { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } catch (e) { setError('Server Error. Please try again'); diff --git a/Dashboard/src/App.tsx b/Dashboard/src/App.tsx index 5190846f7c..b9c99f9629 100644 --- a/Dashboard/src/App.tsx +++ b/Dashboard/src/App.tsx @@ -66,7 +66,6 @@ import Logout from './Pages/Logout/Logout'; import ModelAPI, { ListResult } from 'CommonUI/src/Utils/ModelAPI/ModelAPI'; import Project from 'Model/Models/Project'; import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; -import { JSONObject } from 'Common/Types/JSON'; const App: FunctionComponent = () => { Navigation.setNavigateHook(useNavigate()); @@ -120,9 +119,8 @@ const App: FunctionComponent = () => { setProjects(result.data); } catch (err) { setError( - ((err as HTTPErrorResponse).data as JSONObject)[ - 'error' - ] as string + (err as HTTPErrorResponse).message || + 'Server Error. Please try again' ); } diff --git a/Nginx/default.conf b/Nginx/default.conf index bd3f660fe4..5baa5e94c5 100644 --- a/Nginx/default.conf +++ b/Nginx/default.conf @@ -131,6 +131,8 @@ server { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://file/; + + client_max_body_size 50M; } location /api {