diff --git a/.all-contributorsrc b/.all-contributorsrc
index e37bacbf9..d69d4da6f 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -42,6 +42,15 @@
"contributions": [
"bug"
]
+ },
+ {
+ "login": "suhaibaffan",
+ "name": "Suhaib Affan",
+ "avatar_url": "https://avatars.githubusercontent.com/u/18115937?v=4",
+ "profile": "https://github.com/suhaibaffan",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
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/README.md b/README.md
index 3c5186476..208d39aab 100644
--- a/README.md
+++ b/README.md
@@ -69,9 +69,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 Ahmed Bouhuolia 💻 |
-  ElforJani13 💻 |
 Ameir Abdeldayem 🐛 |
+  ElforJani13 💻 |
 Lars Scheibling 🐛 |
+  Suhaib Affan 💻 |
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index 04c580729..b7e2e1040 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -21,10 +21,16 @@ services:
depends_on:
- server
- webapp
+ deploy:
+ restart_policy:
+ condition: unless-stopped
webapp:
container_name: bigcapital-webapp
image: ghcr.io/bigcapitalhq/webapp:latest
+ deploy:
+ restart_policy:
+ condition: unless-stopped
server:
container_name: bigcapital-server
@@ -37,6 +43,9 @@ services:
- mysql
- mongo
- redis
+ deploy:
+ restart_policy:
+ condition: unless-stopped
environment:
# Mail
- MAIL_HOST=${MAIL_HOST}
@@ -93,6 +102,9 @@ services:
mysql:
container_name: bigcapital-mysql
+ deploy:
+ restart_policy:
+ condition: unless-stopped
build:
context: ./docker/mariadb
environment:
@@ -106,7 +118,10 @@ services:
- '3306'
mongo:
- container_name: bigcapital-mongo
+ container_name: bigcapital-mongo
+ deploy:
+ restart_policy:
+ condition: unless-stopped
build: ./docker/mongo
expose:
- '27017'
@@ -115,6 +130,9 @@ services:
redis:
container_name: bigcapital-redis
+ deploy:
+ restart_policy:
+ condition: unless-stopped
build:
context: ./docker/redis
expose:
diff --git a/docker-compose.yml b/docker-compose.yml
index 11143c063..9563ae91e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -20,6 +20,9 @@ services:
- '3306'
ports:
- '3306:3306'
+ deploy:
+ restart_policy:
+ condition: unless-stopped
mongo:
build: ./docker/mongo
@@ -29,6 +32,9 @@ services:
- mongo:/var/lib/mongodb
ports:
- '27017:27017'
+ deploy:
+ restart_policy:
+ condition: unless-stopped
redis:
build:
@@ -37,6 +43,9 @@ services:
- "6379"
volumes:
- redis:/data
+ deploy:
+ restart_policy:
+ condition: unless-stopped
# Volumes
volumes:
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