diff --git a/.env.example b/.env.example
index 4978f6a78..f07f28c5f 100644
--- a/.env.example
+++ b/.env.example
@@ -47,3 +47,6 @@ AGENDASH_AUTH_PASSWORD=123123
SIGNUP_DISABLED=false
SIGNUP_ALLOWED_DOMAINS=
SIGNUP_ALLOWED_EMAILS=
+
+# API rate limit (points,duration,block duration).
+API_RATE_LIMIT=120,60,600
\ No newline at end of file
diff --git a/packages/server/src/config/index.ts b/packages/server/src/config/index.ts
index ff1fedb6a..bc6833130 100644
--- a/packages/server/src/config/index.ts
+++ b/packages/server/src/config/index.ts
@@ -1,9 +1,12 @@
import dotenv from 'dotenv';
import path from 'path';
+import { toInteger } from 'lodash';
import { castCommaListEnvVarToArray, parseBoolean } from '@/utils';
dotenv.config();
+const API_RATE_LIMIT = process.env.API_RATE_LIMIT?.split(',') || [];
+
module.exports = {
/**
* Your favorite port
@@ -97,7 +100,7 @@ module.exports = {
jwtSecret: process.env.JWT_SECRET,
/**
- *
+ *
*/
resetPasswordSeconds: 600,
@@ -130,9 +133,9 @@ module.exports = {
blockDuration: 60 * 15,
},
requests: {
- points: 60,
- duration: 60,
- blockDuration: 60 * 10,
+ points: API_RATE_LIMIT[0] ? toInteger(API_RATE_LIMIT[0]) : 120,
+ duration: API_RATE_LIMIT[1] ? toInteger(API_RATE_LIMIT[1]) : 60,
+ blockDuration: API_RATE_LIMIT[2] ? toInteger(API_RATE_LIMIT[2]) : 60 * 10,
},
},
diff --git a/packages/webapp/src/containers/GlobalErrors/GlobalErrors.tsx b/packages/webapp/src/containers/GlobalErrors/GlobalErrors.tsx
index 211402c0f..e972733d8 100644
--- a/packages/webapp/src/containers/GlobalErrors/GlobalErrors.tsx
+++ b/packages/webapp/src/containers/GlobalErrors/GlobalErrors.tsx
@@ -9,6 +9,7 @@ import { compose } from '@/utils';
let toastKeySessionExpired;
let toastKeySomethingWrong;
+let toastTooManyRequests;
function GlobalErrors({
// #withGlobalErrors
@@ -41,6 +42,18 @@ function GlobalErrors({
toastKeySomethingWrong,
);
}
+ if (globalErrors.too_many_requests) {
+ toastTooManyRequests = AppToaster.show(
+ {
+ message: intl.get('global_error.too_many_requests'),
+ intent: Intent.DANGER,
+ onDismiss: () => {
+ globalErrorsSet({ too_many_requests: false });
+ },
+ },
+ toastTooManyRequests,
+ );
+ }
if (globalErrors.access_denied) {
toastKeySomethingWrong = AppToaster.show(
{
diff --git a/packages/webapp/src/hooks/useRequest.tsx b/packages/webapp/src/hooks/useRequest.tsx
index c092f1faf..12635ad0a 100644
--- a/packages/webapp/src/hooks/useRequest.tsx
+++ b/packages/webapp/src/hooks/useRequest.tsx
@@ -60,6 +60,9 @@ export default function useApiRequest() {
if (status === 403) {
setGlobalErrors({ access_denied: true });
}
+ if (status === 429) {
+ setGlobalErrors({ too_many_requests: true });
+ }
if (status === 400) {
const lockedError = data.errors.find(
(error) => error.type === 'TRANSACTIONS_DATE_LOCKED',
diff --git a/packages/webapp/src/lang/en/index.json b/packages/webapp/src/lang/en/index.json
index 2010d32b1..6fb394354 100644
--- a/packages/webapp/src/lang/en/index.json
+++ b/packages/webapp/src/lang/en/index.json
@@ -2292,5 +2292,6 @@
"sidebar.projects": "Projects",
"sidebar.new_project": "New Project",
"sidebar.new_time_entry": "New Time Entry",
- "sidebar.project_profitability_summary": "Project Profitability Summary"
+ "sidebar.project_profitability_summary": "Project Profitability Summary",
+ "global_error.too_many_requests": "Too many requests"
}
\ No newline at end of file
diff --git a/packages/webapp/src/style/components/BigcapitalLoading.scss b/packages/webapp/src/style/components/BigcapitalLoading.scss
index 2375d2a1f..c387b5b13 100644
--- a/packages/webapp/src/style/components/BigcapitalLoading.scss
+++ b/packages/webapp/src/style/components/BigcapitalLoading.scss
@@ -1,10 +1,12 @@
+@import '@/style/variables.scss';
+
.bigcapital-loading {
height: 100%;
width: 100%;
position: fixed;
display: flex;
background: #fff;
- z-index: 999999;
+ z-index: $zindex-dashboard-splash-screen;
.center {
width: auto;
@@ -18,4 +20,4 @@
opacity: 0.85;
display: none;
}
-}
+}
\ No newline at end of file
diff --git a/packages/webapp/src/style/variables.scss b/packages/webapp/src/style/variables.scss
index bea903aa4..21fe0ded6 100644
--- a/packages/webapp/src/style/variables.scss
+++ b/packages/webapp/src/style/variables.scss
@@ -45,3 +45,7 @@ $form-check-input-checked-color: #fff;
$form-check-input-checked-bg-color: $blue1;
$form-check-input-checked-bg-image: url("data:image/svg+xml,") !default;
$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,") !default;
+
+// z-indexs
+$zindex-dashboard-splash-screen: 39;
+$zindex-toast: 40;
\ No newline at end of file