diff --git a/app/Events/Email/TooManyEmailsSent.php b/app/Events/Email/TooManyEmailsSent.php new file mode 100644 index 00000000000..262916b2b38 --- /dev/null +++ b/app/Events/Email/TooManyEmailsSent.php @@ -0,0 +1,15 @@ +user_id = $user_id; + } +} diff --git a/app/Listeners/Email/ReportTooManyEmailsSent.php b/app/Listeners/Email/ReportTooManyEmailsSent.php new file mode 100644 index 00000000000..6b1e2fed40e --- /dev/null +++ b/app/Listeners/Email/ReportTooManyEmailsSent.php @@ -0,0 +1,14 @@ +request = request(); + $this->middleware = 'too_many_emails_sent'; + $this->user_id = $event->user_id; + + $this->loadConfig(); + + if ($this->skip($event)) { + return; + } + + $log = $this->log(); + + event(new AttackDetected($log)); + } + + public function loadConfig(): void + { + $config = array_merge_recursive( + Config::get('firewall'), + [ + 'middleware' => [ + $this->middleware => [ + 'enabled' => env('FIREWALL_MIDDLEWARE_' . strtoupper($this->middleware) . '_ENABLED', env('FIREWALL_ENABLED', true)), + + 'methods' => ['post'], + + 'routes' => [ + 'only' => [], // i.e. 'contact' + 'except' => [], // i.e. 'admin/*' + ], + + 'auto_block' => [ + 'attempts' => env('FIREWALL_MIDDLEWARE_' . strtoupper($this->middleware) . '_AUTO_BLOCK_ATTEMPTS', 20), + 'frequency' => 1 * 60, // 1 minute + 'period' => 30 * 60, // 30 minutes + ], + ], + ], + ] + ); + + Config::set('firewall', $config); + } + + public function skip($event): bool + { + if ($this->isDisabled()) { + return true; + } + + if ($this->isWhitelist()) { + return true; + } + + return false; + } +} diff --git a/app/Providers/Event.php b/app/Providers/Event.php index 9593392f523..1f3a6b8087c 100644 --- a/app/Providers/Event.php +++ b/app/Providers/Event.php @@ -104,6 +104,10 @@ class Event extends Provider 'App\Events\Setting\CategoryDeleted' => [ 'App\Listeners\Setting\DeleteCategoryDeletedSubCategories', ], + 'App\Events\Email\TooManyEmailsSent' => [ + 'App\Listeners\Email\ReportTooManyEmailsSent', + 'App\Listeners\Email\TellFirewallTooManyEmailsSent', + ], ]; /** diff --git a/app/Traits/Emails.php b/app/Traits/Emails.php index 633d8ee2f53..fd30fe44e1b 100644 --- a/app/Traits/Emails.php +++ b/app/Traits/Emails.php @@ -3,7 +3,7 @@ namespace App\Traits; use App\Abstracts\Job; -use App\Exceptions\Common\TooManyEmailsSent; +use App\Events\Email\TooManyEmailsSent; use App\Traits\Jobs; use Illuminate\Support\Facades\RateLimiter; @@ -14,7 +14,7 @@ trait Emails public function sendEmail(Job $job): array { // Check if the user has reached the limit of emails per month - $key_per_month = 'email-month:' . user()->id; + $key_per_month = 'email-month:' . user_id(); $limit_per_month = config('app.throttles.email.month'); $decay_per_month = 60 * 60 * 24 * 30; @@ -22,7 +22,7 @@ public function sendEmail(Job $job): array if ($can_send) { // Check if the user has reached the limit of emails per minute - $key_per_minute = 'email-minute:' . user()->id; + $key_per_minute = 'email-minute:' . user_id(); $limit_per_minute = config('app.throttles.email.minute'); $can_send = RateLimiter::attempt($key_per_minute, $limit_per_minute, fn() => null); @@ -31,25 +31,21 @@ public function sendEmail(Job $job): array if ($can_send) { $this->dispatch($job); - $response = [ + return [ 'success' => true, 'error' => false, 'data' => '', 'message' => '', ]; - - return $response; } - $response = [ + event(new TooManyEmailsSent(user_id())); + + return [ 'success' => false, 'error' => true, 'data' => null, 'message' => 'Too many emails sent!', ]; - - report(new TooManyEmailsSent('Too many emails sent!')); - - return $response; } } diff --git a/composer.lock b/composer.lock index 87a641ab648..5478d5eaf8e 100644 --- a/composer.lock +++ b/composer.lock @@ -142,16 +142,16 @@ }, { "name": "akaunting/laravel-firewall", - "version": "2.1.0", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/akaunting/laravel-firewall.git", - "reference": "6a44c0bf31530f3ae94fbee849395ee91c7ffb54" + "reference": "ef48b2e63a7746e0513ce47d8e811ac58ad3bfc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/akaunting/laravel-firewall/zipball/6a44c0bf31530f3ae94fbee849395ee91c7ffb54", - "reference": "6a44c0bf31530f3ae94fbee849395ee91c7ffb54", + "url": "https://api.github.com/repos/akaunting/laravel-firewall/zipball/ef48b2e63a7746e0513ce47d8e811ac58ad3bfc7", + "reference": "ef48b2e63a7746e0513ce47d8e811ac58ad3bfc7", "shasum": "" }, "require": { @@ -203,9 +203,9 @@ ], "support": { "issues": "https://github.com/akaunting/laravel-firewall/issues", - "source": "https://github.com/akaunting/laravel-firewall/tree/2.1.0" + "source": "https://github.com/akaunting/laravel-firewall/tree/2.1.3" }, - "time": "2023-03-07T12:53:34+00:00" + "time": "2023-03-25T11:05:54+00:00" }, { "name": "akaunting/laravel-language", @@ -798,23 +798,27 @@ }, { "name": "aws/aws-crt-php", - "version": "v1.0.4", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "f5c64ee7c5fce196e2519b3d9b7138649efe032d" + "reference": "1926277fc71d253dfa820271ac5987bdb193ccf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/f5c64ee7c5fce196e2519b3d9b7138649efe032d", - "reference": "f5c64ee7c5fce196e2519b3d9b7138649efe032d", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/1926277fc71d253dfa820271ac5987bdb193ccf5", + "reference": "1926277fc71d253dfa820271ac5987bdb193ccf5", "shasum": "" }, "require": { "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "^4.8.35|^5.6.3" + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." }, "type": "library", "autoload": { @@ -833,7 +837,7 @@ } ], "description": "AWS Common Runtime for PHP", - "homepage": "http://aws.amazon.com/sdkforphp", + "homepage": "https://github.com/awslabs/aws-crt-php", "keywords": [ "amazon", "aws", @@ -842,22 +846,22 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.0.4" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.1" }, - "time": "2023-01-31T23:08:25+00:00" + "time": "2023-03-24T20:22:19+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.261.14", + "version": "3.262.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "121638bb7e62ee2f71838c52e79884f4301a9400" + "reference": "42ca7ade60a775fc5eb103d4631df3d366b48a29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/121638bb7e62ee2f71838c52e79884f4301a9400", - "reference": "121638bb7e62ee2f71838c52e79884f4301a9400", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/42ca7ade60a775fc5eb103d4631df3d366b48a29", + "reference": "42ca7ade60a775fc5eb103d4631df3d366b48a29", "shasum": "" }, "require": { @@ -936,9 +940,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.261.14" + "source": "https://github.com/aws/aws-sdk-php/tree/3.262.1" }, - "time": "2023-03-17T18:21:00+00:00" + "time": "2023-03-24T18:20:43+00:00" }, { "name": "balping/json-raw-encoder", @@ -2934,16 +2938,16 @@ }, { "name": "genealabs/laravel-model-caching", - "version": "0.13.2", + "version": "0.13.3", "source": { "type": "git", "url": "https://github.com/GeneaLabs/laravel-model-caching.git", - "reference": "1fe37744efa9d5ed3d8c245c68271022b0e452ab" + "reference": "5dd9c100f7dbad5134771140f4dfeee808c54783" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GeneaLabs/laravel-model-caching/zipball/1fe37744efa9d5ed3d8c245c68271022b0e452ab", - "reference": "1fe37744efa9d5ed3d8c245c68271022b0e452ab", + "url": "https://api.github.com/repos/GeneaLabs/laravel-model-caching/zipball/5dd9c100f7dbad5134771140f4dfeee808c54783", + "reference": "5dd9c100f7dbad5134771140f4dfeee808c54783", "shasum": "" }, "require": { @@ -2997,22 +3001,22 @@ "description": "Automatic caching for Eloquent models.", "support": { "issues": "https://github.com/GeneaLabs/laravel-model-caching/issues", - "source": "https://github.com/GeneaLabs/laravel-model-caching/tree/0.13.2" + "source": "https://github.com/GeneaLabs/laravel-model-caching/tree/0.13.3" }, - "time": "2023-03-09T14:37:04+00:00" + "time": "2023-03-20T14:38:15+00:00" }, { "name": "genealabs/laravel-pivot-events", - "version": "10.0.0", + "version": "10.0.1", "source": { "type": "git", "url": "https://github.com/GeneaLabs/laravel-pivot-events.git", - "reference": "48dc3cc7c26d6343741dd23f75763e79b7a2706b" + "reference": "862371f6f89be296cc026c9cf5b372dca4d7958b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GeneaLabs/laravel-pivot-events/zipball/48dc3cc7c26d6343741dd23f75763e79b7a2706b", - "reference": "48dc3cc7c26d6343741dd23f75763e79b7a2706b", + "url": "https://api.github.com/repos/GeneaLabs/laravel-pivot-events/zipball/862371f6f89be296cc026c9cf5b372dca4d7958b", + "reference": "862371f6f89be296cc026c9cf5b372dca4d7958b", "shasum": "" }, "require": { @@ -3054,7 +3058,7 @@ "issues": "https://github.com/GeneaLabs/laravel-pivot/issues", "source": "https://github.com/GeneaLabs/laravel-pivot" }, - "time": "2023-02-17T14:30:37+00:00" + "time": "2023-03-22T14:46:23+00:00" }, { "name": "graham-campbell/markdown", @@ -4655,16 +4659,16 @@ }, { "name": "jaybizzle/crawler-detect", - "version": "v1.2.113", + "version": "v1.2.114", "source": { "type": "git", "url": "https://github.com/JayBizzle/Crawler-Detect.git", - "reference": "6710b75871da2b718550c2bc33388315a3b20151" + "reference": "62d0e6b38f6715c673e156ffb0fc894791de3452" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/6710b75871da2b718550c2bc33388315a3b20151", - "reference": "6710b75871da2b718550c2bc33388315a3b20151", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/62d0e6b38f6715c673e156ffb0fc894791de3452", + "reference": "62d0e6b38f6715c673e156ffb0fc894791de3452", "shasum": "" }, "require": { @@ -4701,9 +4705,9 @@ ], "support": { "issues": "https://github.com/JayBizzle/Crawler-Detect/issues", - "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.113" + "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.114" }, - "time": "2023-02-02T21:01:40+00:00" + "time": "2023-03-21T21:54:27+00:00" }, { "name": "jean85/pretty-package-versions", @@ -5544,16 +5548,16 @@ }, { "name": "league/commonmark", - "version": "2.3.9", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "c1e114f74e518daca2729ea8c4bf1167038fa4b5" + "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c1e114f74e518daca2729ea8c4bf1167038fa4b5", - "reference": "c1e114f74e518daca2729ea8c4bf1167038fa4b5", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d44a24690f16b8c1808bf13b1bd54ae4c63ea048", + "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048", "shasum": "" }, "require": { @@ -5589,7 +5593,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" + "dev-main": "2.5-dev" } }, "autoload": { @@ -5646,7 +5650,7 @@ "type": "tidelift" } ], - "time": "2023-02-15T14:07:24+00:00" + "time": "2023-03-24T15:16:10+00:00" }, { "name": "league/config", @@ -9087,16 +9091,16 @@ }, { "name": "psy/psysh", - "version": "v0.11.12", + "version": "v0.11.13", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "52cb7c47d403c31c0adc9bf7710fc355f93c20f7" + "reference": "722317c9f5627e588788e340f29b923e58f92f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/52cb7c47d403c31c0adc9bf7710fc355f93c20f7", - "reference": "52cb7c47d403c31c0adc9bf7710fc355f93c20f7", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/722317c9f5627e588788e340f29b923e58f92f54", + "reference": "722317c9f5627e588788e340f29b923e58f92f54", "shasum": "" }, "require": { @@ -9157,9 +9161,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.12" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.13" }, - "time": "2023-01-29T21:24:40+00:00" + "time": "2023-03-21T14:22:44+00:00" }, { "name": "ralouphie/getallheaders", @@ -9807,16 +9811,16 @@ }, { "name": "sentry/sentry-laravel", - "version": "3.3.0", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-laravel.git", - "reference": "e9c87d6580fc56147f580e1d714d8eb4e06d2752" + "reference": "c502e8b9005990d03f5ec5cc852e98a27c26056d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/e9c87d6580fc56147f580e1d714d8eb4e06d2752", - "reference": "e9c87d6580fc56147f580e1d714d8eb4e06d2752", + "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/c502e8b9005990d03f5ec5cc852e98a27c26056d", + "reference": "c502e8b9005990d03f5ec5cc852e98a27c26056d", "shasum": "" }, "require": { @@ -9884,7 +9888,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-laravel/issues", - "source": "https://github.com/getsentry/sentry-laravel/tree/3.3.0" + "source": "https://github.com/getsentry/sentry-laravel/tree/3.3.2" }, "funding": [ { @@ -9896,7 +9900,7 @@ "type": "custom" } ], - "time": "2023-03-16T12:25:43+00:00" + "time": "2023-03-22T10:51:03+00:00" }, { "name": "simple-icons/simple-icons", @@ -13198,16 +13202,16 @@ }, { "name": "brianium/paratest", - "version": "v7.1.1", + "version": "v7.1.2", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "abc123183e90f33ce1312b5bfaa49d80d8c646b2" + "reference": "10e66ccdad397200f8129a034f0d3bf8cbe4c524" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/abc123183e90f33ce1312b5bfaa49d80d8c646b2", - "reference": "abc123183e90f33ce1312b5bfaa49d80d8c646b2", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/10e66ccdad397200f8129a034f0d3bf8cbe4c524", + "reference": "10e66ccdad397200f8129a034f0d3bf8cbe4c524", "shasum": "" }, "require": { @@ -13221,7 +13225,7 @@ "phpunit/php-code-coverage": "^10.0.2", "phpunit/php-file-iterator": "^4.0.1", "phpunit/php-timer": "^6.0", - "phpunit/phpunit": "^10.0.16", + "phpunit/phpunit": "^10.0.17", "sebastian/environment": "^6.0", "symfony/console": "^6.2.7", "symfony/process": "^6.2.7" @@ -13231,8 +13235,8 @@ "ext-pcov": "*", "ext-posix": "*", "infection/infection": "^0.26.19", - "phpstan/phpstan": "^1.10.6", - "phpstan/phpstan-deprecation-rules": "^1.1.2", + "phpstan/phpstan": "^1.10.7", + "phpstan/phpstan-deprecation-rules": "^1.1.3", "phpstan/phpstan-phpunit": "^1.3.10", "phpstan/phpstan-strict-rules": "^1.5", "squizlabs/php_codesniffer": "^3.7.2", @@ -13277,7 +13281,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.1.1" + "source": "https://github.com/paratestphp/paratest/tree/v7.1.2" }, "funding": [ { @@ -13289,7 +13293,7 @@ "type": "paypal" } ], - "time": "2023-03-13T10:11:07+00:00" + "time": "2023-03-20T15:15:41+00:00" }, { "name": "fakerphp/faker", @@ -13675,16 +13679,16 @@ }, { "name": "nunomaduro/collision", - "version": "v7.1.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "f502ff3b2051124c89b4dd3a8a497ca65f3ce26c" + "reference": "c680af93e414110b36056029f63120e6bc78f6e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f502ff3b2051124c89b4dd3a8a497ca65f3ce26c", - "reference": "f502ff3b2051124c89b4dd3a8a497ca65f3ce26c", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/c680af93e414110b36056029f63120e6bc78f6e3", + "reference": "c680af93e414110b36056029f63120e6bc78f6e3", "shasum": "" }, "require": { @@ -13694,19 +13698,19 @@ "symfony/console": "^6.2.7" }, "conflict": { - "phpunit/phpunit": "<10.0.16" + "phpunit/phpunit": "<10.0.17" }, "require-dev": { - "brianium/paratest": "^7.1.1", - "laravel/framework": "^10.3.3", - "laravel/pint": "^1.6.0", + "brianium/paratest": "^7.1.2", + "laravel/framework": "^10.4.1", + "laravel/pint": "^1.7.0", "laravel/sail": "^1.21.2", "laravel/sanctum": "^3.2.1", "laravel/tinker": "^2.8.1", "nunomaduro/larastan": "^2.5.1", - "orchestra/testbench-core": "^8.0.5", - "pestphp/pest": "^2.0.0", - "phpunit/phpunit": "^10.0.16", + "orchestra/testbench-core": "^8.1.1", + "pestphp/pest": "^2.0.2", + "phpunit/phpunit": "^10.0.17", "sebastian/environment": "^6.0.0", "spatie/laravel-ignition": "^2.0.0" }, @@ -13767,7 +13771,7 @@ "type": "patreon" } ], - "time": "2023-03-14T14:34:49+00:00" + "time": "2023-03-23T21:41:35+00:00" }, { "name": "phar-io/manifest", @@ -14200,16 +14204,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.0.16", + "version": "10.0.18", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "07d386a11ac7094032900f07cada1c8975d16607" + "reference": "582563ed2edc62d1455cdbe00ea49fe09428eef3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/07d386a11ac7094032900f07cada1c8975d16607", - "reference": "07d386a11ac7094032900f07cada1c8975d16607", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/582563ed2edc62d1455cdbe00ea49fe09428eef3", + "reference": "582563ed2edc62d1455cdbe00ea49fe09428eef3", "shasum": "" }, "require": { @@ -14280,7 +14284,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.0.16" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.0.18" }, "funding": [ { @@ -14296,7 +14301,7 @@ "type": "tidelift" } ], - "time": "2023-03-13T09:02:40+00:00" + "time": "2023-03-22T06:15:31+00:00" }, { "name": "sebastian/cli-parser", @@ -14600,16 +14605,16 @@ }, { "name": "sebastian/diff", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "70dd1b20bc198da394ad542e988381b44e64e39f" + "reference": "aae9a0a43bff37bd5d8d0311426c87bf36153f02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/70dd1b20bc198da394ad542e988381b44e64e39f", - "reference": "70dd1b20bc198da394ad542e988381b44e64e39f", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/aae9a0a43bff37bd5d8d0311426c87bf36153f02", + "reference": "aae9a0a43bff37bd5d8d0311426c87bf36153f02", "shasum": "" }, "require": { @@ -14654,7 +14659,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.0.1" }, "funding": [ { @@ -14662,7 +14668,7 @@ "type": "github" } ], - "time": "2023-02-03T07:00:31+00:00" + "time": "2023-03-23T05:12:41+00:00" }, { "name": "sebastian/environment",