From 0587c712c96a98595371234ec96a9ff7ce7c739a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Duli=C3=A7i?= Date: Tue, 13 Sep 2022 16:13:31 +0300 Subject: [PATCH 1/6] styling --- resources/views/components/layouts/admin/menu.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/components/layouts/admin/menu.blade.php b/resources/views/components/layouts/admin/menu.blade.php index e63cb67e6..208aaf334 100644 --- a/resources/views/components/layouts/admin/menu.blade.php +++ b/resources/views/components/layouts/admin/menu.blade.php @@ -19,7 +19,7 @@ - {{ trans('general.title.new', ['type' => trans_choice('general.expenses', 1)]) }} + {{ trans('general.title.new', ['type' => trans_choice('general.expenses', 1)]) }} @endcan @@ -36,7 +36,7 @@ data-menu="profile-menu" > @if (setting('default.use_gravatar', '0') == '1') From bf2f83981cb16f9ee62f18aa3871a8525fab78e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Duli=C3=A7i?= Date: Wed, 14 Sep 2022 01:15:05 +0300 Subject: [PATCH 2/6] added throttle for email --- app/Http/Kernel.php | 4 ++++ app/Providers/Route.php | 4 ++++ config/app.php | 1 + routes/admin.php | 12 ++++++++---- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index f7cc49ecc..8d320b7a7 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -134,6 +134,10 @@ class Kernel extends HttpKernel 'import' => [ 'throttle:import', ], + + 'email' => [ + 'throttle:email', + ], ]; /** diff --git a/app/Providers/Route.php b/app/Providers/Route.php index 952966034..ada05b003 100644 --- a/app/Providers/Route.php +++ b/app/Providers/Route.php @@ -289,5 +289,9 @@ class Route extends Provider RateLimiter::for('import', function (Request $request) { return Limit::perMinute(config('app.throttles.import')); }); + + RateLimiter::for('email', function (Request $request) { + return Limit::perMinute(config('app.throttles.email')); + }); } } diff --git a/config/app.php b/config/app.php index dbf827b95..7bb8c325a 100644 --- a/config/app.php +++ b/config/app.php @@ -25,6 +25,7 @@ return [ 'throttles' => [ 'api' => env('APP_THROTTLES_API', '60'), 'import' => env('APP_THROTTLES_IMPORT', '1'), + 'email' => env('APP_THROTTLES_EMAIL', '1'), ], /* diff --git a/routes/admin.php b/routes/admin.php index 2ad6b90bf..0b95b1a03 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -259,9 +259,13 @@ Route::group(['as' => 'modals.', 'prefix' => 'modals'], function () { 'middleware' => ['date.format', 'money', 'dropzone'] ]); - Route::resource('transactions/{transaction}/emails', 'Modals\TransactionEmails', ['names' => 'transactions.emails']); - Route::resource('transactions/{transaction}/share', 'Modals\TransactionShare', ['names' => 'transactions.share']); - Route::resource('invoices/{invoice}/emails', 'Modals\InvoiceEmails', ['names' => 'invoices.emails']); - Route::resource('invoices/{invoice}/share', 'Modals\InvoiceShare', ['names' => 'invoices.share']); + Route::get('invoices/{invoice}/emails/create', 'Modals\InvoiceEmails@create')->name('invoices.emails.create'); + Route::post('invoices/{invoice}/emails', 'Modals\InvoiceEmails@store')->middleware('email')->name('invoices.emails.store'); + Route::get('invoices/{invoice}/share/create', 'Modals\InvoiceShare@create')->name('invoices.share.create'); + + Route::get('transactions/{transaction}/emails/create', 'Modals\TransactionEmails@create')->name('transactions.emails.create'); + Route::post('transactions/{transaction}/emails', 'Modals\TransactionEmails@store')->middleware('email')->name('transactions.emails.store'); + Route::get('transactions/{transaction}/share/create', 'Modals\TransactionShare@create')->name('transactions.share.create'); + Route::resource('taxes', 'Modals\Taxes'); }); From eb3b080ee895f4c0be9c63a124d513ecaed0b981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Duli=C3=A7i?= Date: Wed, 14 Sep 2022 11:53:22 +0300 Subject: [PATCH 3/6] improved email throttle --- app/Exceptions/Common/TooManyEmailsSent.php | 10 ++++ app/Http/Controllers/Modals/InvoiceEmails.php | 24 +++----- .../Controllers/Modals/TransactionEmails.php | 30 ++++------ app/Providers/Route.php | 5 +- app/Traits/Emails.php | 55 +++++++++++++++++++ config/app.php | 5 +- routes/admin.php | 4 +- 7 files changed, 92 insertions(+), 41 deletions(-) create mode 100644 app/Exceptions/Common/TooManyEmailsSent.php create mode 100644 app/Traits/Emails.php diff --git a/app/Exceptions/Common/TooManyEmailsSent.php b/app/Exceptions/Common/TooManyEmailsSent.php new file mode 100644 index 000000000..2831835f5 --- /dev/null +++ b/app/Exceptions/Common/TooManyEmailsSent.php @@ -0,0 +1,10 @@ +middleware('permission:delete-sales-invoices')->only('destroy'); } - /** - * Show the form for creating a new resource. - * - * @param Document $invoice - * - * @return Response - */ - public function create(Document $invoice) + public function create(Document $invoice): JsonResponse { $notification = new Notification($invoice, 'invoice_new_customer', true); @@ -58,16 +55,9 @@ class InvoiceEmails extends Controller ]); } - /** - * Store a newly created resource in storage. - * - * @param Request $request - * - * @return Response - */ - public function store(Request $request) + public function store(Request $request): JsonResponse { - $response = $this->ajaxDispatch(new SendDocumentAsCustomMail($request, 'invoice_new_customer')); + $response = $this->sendEmail(new SendDocumentAsCustomMail($request, 'invoice_new_customer')); if ($response['success']) { $invoice = Document::find($request->get('document_id')); diff --git a/app/Http/Controllers/Modals/TransactionEmails.php b/app/Http/Controllers/Modals/TransactionEmails.php index b40eb6e3c..e4672906b 100644 --- a/app/Http/Controllers/Modals/TransactionEmails.php +++ b/app/Http/Controllers/Modals/TransactionEmails.php @@ -8,9 +8,13 @@ use App\Notifications\Portal\PaymentReceived as PaymentReceivedNotification; use App\Notifications\Banking\Transaction as TransactionNotification; use App\Jobs\Banking\SendTransactionAsCustomMail; use App\Http\Requests\Common\CustomMail as Request; +use Illuminate\Http\JsonResponse; +use App\Traits\Emails; class TransactionEmails extends Controller { + use Emails; + /** * Instantiate a new controller instance. */ @@ -23,17 +27,10 @@ class TransactionEmails extends Controller $this->middleware('permission:delete-banking-transactions')->only('destroy'); } - /** - * Show the form for creating a new resource. - * - * @param Transaction $transaction - * - * @return Response - */ - public function create(Transaction $transaction) - { + public function create(Transaction $transaction): JsonResponse + { $email_template = config('type.transaction.' . $transaction->type . '.email_template'); - + if (request()->get('email_template')) { $email_template = request()->get('email_template'); } @@ -42,7 +39,7 @@ class TransactionEmails extends Controller case 'invoice_payment_customer': $notification = new PaymentReceivedNotification($transaction->document, $transaction, $email_template, true); break; - + default: $notification = new TransactionNotification($transaction, $email_template, true); break; @@ -73,20 +70,13 @@ class TransactionEmails extends Controller ]); } - /** - * Store a newly created resource in storage. - * - * @param Request $request - * - * @return Response - */ - public function store(Request $request) + public function store(Request $request): JsonResponse { $transaction = Transaction::find($request->get('transaction_id')); $email_template = config('type.transaction.' . $transaction->type . '.email_template'); - $response = $this->ajaxDispatch(new SendTransactionAsCustomMail($request, $email_template)); + $response = $this->sendEmail(new SendTransactionAsCustomMail($request, $email_template)); if ($response['success']) { $route = config('type.transaction.' . $transaction->type . '.route.prefix'); diff --git a/app/Providers/Route.php b/app/Providers/Route.php index ada05b003..69034ef4c 100644 --- a/app/Providers/Route.php +++ b/app/Providers/Route.php @@ -291,7 +291,10 @@ class Route extends Provider }); RateLimiter::for('email', function (Request $request) { - return Limit::perMinute(config('app.throttles.email')); + return [ + Limit::perDay(config('app.throttles.email.month'), 30), + Limit::perMinute(config('app.throttles.email.minute')), + ]; }); } } diff --git a/app/Traits/Emails.php b/app/Traits/Emails.php new file mode 100644 index 000000000..ce8388a80 --- /dev/null +++ b/app/Traits/Emails.php @@ -0,0 +1,55 @@ +id; + $limit_per_month = config('app.throttles.email.month'); + $decay_per_month = 60 * 60 * 24 * 30; + + $can_send = RateLimiter::attempt($key_per_month, $limit_per_month, fn() => '', $decay_per_month); + + if ($can_send) { + // Check if the user has reached the limit of emails per minute + $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() => ''); + } + + if ($can_send) { + $this->dispatch($job); + + $response = [ + 'success' => true, + 'error' => false, + 'data' => '', + 'message' => '', + ]; + + return $response; + } + + $response = [ + 'success' => false, + 'error' => true, + 'data' => null, + 'message' => 'Too many emails sent!', + ]; + + report(new TooManyEmailsSent('Too many emails sent!')); + + return $response; + } +} diff --git a/config/app.php b/config/app.php index 7bb8c325a..a01930e41 100644 --- a/config/app.php +++ b/config/app.php @@ -25,7 +25,10 @@ return [ 'throttles' => [ 'api' => env('APP_THROTTLES_API', '60'), 'import' => env('APP_THROTTLES_IMPORT', '1'), - 'email' => env('APP_THROTTLES_EMAIL', '1'), + 'email' => [ + 'minute' => env('APP_THROTTLES_EMAIL_MINUTE', '3'), + 'month' => env('APP_THROTTLES_EMAIL_MONTH', '500'), + ], ], /* diff --git a/routes/admin.php b/routes/admin.php index 0b95b1a03..f81e103e1 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -260,11 +260,11 @@ Route::group(['as' => 'modals.', 'prefix' => 'modals'], function () { ]); Route::get('invoices/{invoice}/emails/create', 'Modals\InvoiceEmails@create')->name('invoices.emails.create'); - Route::post('invoices/{invoice}/emails', 'Modals\InvoiceEmails@store')->middleware('email')->name('invoices.emails.store'); + Route::post('invoices/{invoice}/emails', 'Modals\InvoiceEmails@store')->name('invoices.emails.store'); Route::get('invoices/{invoice}/share/create', 'Modals\InvoiceShare@create')->name('invoices.share.create'); Route::get('transactions/{transaction}/emails/create', 'Modals\TransactionEmails@create')->name('transactions.emails.create'); - Route::post('transactions/{transaction}/emails', 'Modals\TransactionEmails@store')->middleware('email')->name('transactions.emails.store'); + Route::post('transactions/{transaction}/emails', 'Modals\TransactionEmails@store')->name('transactions.emails.store'); Route::get('transactions/{transaction}/share/create', 'Modals\TransactionShare@create')->name('transactions.share.create'); Route::resource('taxes', 'Modals\Taxes'); From c692a25da9bb7dfa0439eddca4319700cd9f6218 Mon Sep 17 00:00:00 2001 From: Burak Civan Date: Wed, 14 Sep 2022 12:02:04 +0300 Subject: [PATCH 4/6] added cancel prefix --- resources/views/components/layouts/admin/scripts.blade.php | 7 +++++++ .../views/components/layouts/portal/scripts.blade.php | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/resources/views/components/layouts/admin/scripts.blade.php b/resources/views/components/layouts/admin/scripts.blade.php index b75deebbf..263af8674 100644 --- a/resources/views/components/layouts/admin/scripts.blade.php +++ b/resources/views/components/layouts/admin/scripts.blade.php @@ -139,6 +139,8 @@ if (button.getAttribute("data-menu") !== menuRef && iconButton.children[0].textContent != "cancel") { button.children[0].textContent = button.children[0].getAttribute("name"); button.children[0].classList.remove("active"); // inactive icon + let split_id = iconButton.children[0].id.split("-cancel"); + button.children[0].id = split_id[0]; } } }); @@ -148,6 +150,7 @@ if (menu.classList.contains(menuRef) && iconButton.children[0].textContent != "cancel") { iconButton.children[0].textContent = "cancel"; iconButton.children[0].classList.add("active"); + iconButton.children[0].id += "-cancel"; menu.classList.remove("ltr:-left-80", "rtl:-right-80"); menu.classList.add("ltr:left-14", "rtl:right-14"); @@ -177,6 +180,9 @@ iconButton.children[0].textContent = icon; iconButton.children[0].classList.remove("active"); + let split_id = iconButton.children[0].id.split("-cancel"); + iconButton.children[0].id = split_id[0]; + menu.classList.add("ltr:-left-80", "rtl:-right-80"); menu.classList.remove("ltr:left-14", "rtl:right-14"); @@ -242,6 +248,7 @@ settings_icon_html.children[0].textContent = "cancel"; settings_icon_html.children[0].classList.add("active"); + settings_icon_html.children[0].id += "-cancel"; toggleButton.classList.add("invisible"); } diff --git a/resources/views/components/layouts/portal/scripts.blade.php b/resources/views/components/layouts/portal/scripts.blade.php index 4a82d6b95..37f0ef28a 100644 --- a/resources/views/components/layouts/portal/scripts.blade.php +++ b/resources/views/components/layouts/portal/scripts.blade.php @@ -122,6 +122,8 @@ if (button.getAttribute("data-menu") !== menuRef && iconButton.children[0].textContent != "cancel") { button.children[0].textContent = button.children[0].getAttribute("name"); button.children[0].classList.remove("active"); // inactive icon + let split_id = iconButton.children[0].id.split("-cancel"); + button.children[0].id = split_id[0]; } } }); @@ -131,6 +133,7 @@ if (menu.classList.contains(menuRef) && iconButton.children[0].textContent != "cancel") { iconButton.children[0].textContent = "cancel"; iconButton.children[0].classList.add("active"); + iconButton.children[0].id += "-cancel"; menu.classList.remove("ltr:-left-80", "rtl:-right-80"); menu.classList.add("ltr:left-14", "rtl:right-14"); @@ -155,6 +158,9 @@ iconButton.children[0].textContent = icon; iconButton.children[0].classList.remove("active"); + let split_id = iconButton.children[0].id.split("-cancel"); + iconButton.children[0].id = split_id[0]; + menu.classList.add("ltr:-left-80", "rtl:-right-80"); menu.classList.remove("ltr:left-14", "rtl:right-14"); mainContent.classList.remove("hidden"); From 792892f5d9496c8e4691ad3ec351b94a3d84e456 Mon Sep 17 00:00:00 2001 From: Burak Civan Date: Wed, 14 Sep 2022 14:04:46 +0300 Subject: [PATCH 5/6] code refactoring --- resources/views/components/layouts/admin/scripts.blade.php | 3 ++- resources/views/components/layouts/portal/scripts.blade.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/views/components/layouts/admin/scripts.blade.php b/resources/views/components/layouts/admin/scripts.blade.php index 263af8674..b846eceab 100644 --- a/resources/views/components/layouts/admin/scripts.blade.php +++ b/resources/views/components/layouts/admin/scripts.blade.php @@ -139,7 +139,8 @@ if (button.getAttribute("data-menu") !== menuRef && iconButton.children[0].textContent != "cancel") { button.children[0].textContent = button.children[0].getAttribute("name"); button.children[0].classList.remove("active"); // inactive icon - let split_id = iconButton.children[0].id.split("-cancel"); + + let split_id = button.children[0].id.split("-cancel"); button.children[0].id = split_id[0]; } } diff --git a/resources/views/components/layouts/portal/scripts.blade.php b/resources/views/components/layouts/portal/scripts.blade.php index 37f0ef28a..e5c4b94f8 100644 --- a/resources/views/components/layouts/portal/scripts.blade.php +++ b/resources/views/components/layouts/portal/scripts.blade.php @@ -122,7 +122,8 @@ if (button.getAttribute("data-menu") !== menuRef && iconButton.children[0].textContent != "cancel") { button.children[0].textContent = button.children[0].getAttribute("name"); button.children[0].classList.remove("active"); // inactive icon - let split_id = iconButton.children[0].id.split("-cancel"); + + let split_id = button.children[0].id.split("-cancel"); button.children[0].id = split_id[0]; } } From 011533e97bd909917c08dda023ea2ae2994de531 Mon Sep 17 00:00:00 2001 From: Burak Civan Date: Wed, 14 Sep 2022 14:31:53 +0300 Subject: [PATCH 6/6] payment method slider fixed --- resources/views/components/layouts/portal/head.blade.php | 1 + resources/views/components/layouts/signed/head.blade.php | 1 + resources/views/portal/invoices/show.blade.php | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/views/components/layouts/portal/head.blade.php b/resources/views/components/layouts/portal/head.blade.php index de4c696cd..52bae9384 100644 --- a/resources/views/components/layouts/portal/head.blade.php +++ b/resources/views/components/layouts/portal/head.blade.php @@ -26,6 +26,7 @@ + diff --git a/resources/views/components/layouts/signed/head.blade.php b/resources/views/components/layouts/signed/head.blade.php index de4c696cd..52bae9384 100644 --- a/resources/views/components/layouts/signed/head.blade.php +++ b/resources/views/components/layouts/signed/head.blade.php @@ -26,6 +26,7 @@ + diff --git a/resources/views/portal/invoices/show.blade.php b/resources/views/portal/invoices/show.blade.php index 239a04d13..67844fe81 100644 --- a/resources/views/portal/invoices/show.blade.php +++ b/resources/views/portal/invoices/show.blade.php @@ -33,7 +33,7 @@
{{ $name }}