From dd77eba16ac674cd076236c5f922ec272ffb35b1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 17 Dec 2023 08:38:30 +1100 Subject: [PATCH 1/5] PayPal --- .../ninja2020/gateways/paypal/pay.blade.php | 15 ++++++++------- .../ninja2020/gateways/paypal/ppcp/pay.blade.php | 5 ----- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php b/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php index 0828d552a248..a315da556015 100644 --- a/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php @@ -1,11 +1,6 @@ -@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal']) +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => '']) @section('gateway_head') - @endsection @@ -20,7 +15,7 @@ -
+
@endsection @@ -46,6 +41,9 @@ createOrder: function(data, actions) { return "{!! $order_id !!}" }, + onCancel: function() { + window.location.href = "/client/invoices/"; + }, onApprove: function(data, actions) { return actions.order.capture().then(function(details) { @@ -58,6 +56,9 @@ }, onError: function(err) { console.log(err); + }, + onClick: function (){ + document.getElementById('paypal-button-container').hidden = true; } }).render('#paypal-button-container').catch(function(err) { diff --git a/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php index dd7c487d0fe1..8986491be90e 100644 --- a/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php @@ -1,11 +1,6 @@ @extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal']) @section('gateway_head') - @endsection From bbb60eea3a6d4d6ff47415635e8b158223baa66b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 17 Dec 2023 09:50:35 +1100 Subject: [PATCH 2/5] Updates for spam notifications --- app/Jobs/PostMark/ProcessPostmarkWebhook.php | 40 ++++++++----------- .../Ninja/EmailSpamNotification.php | 10 ++--- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/app/Jobs/PostMark/ProcessPostmarkWebhook.php b/app/Jobs/PostMark/ProcessPostmarkWebhook.php index a1b54aff4b81..b2152c8eb017 100644 --- a/app/Jobs/PostMark/ProcessPostmarkWebhook.php +++ b/app/Jobs/PostMark/ProcessPostmarkWebhook.php @@ -11,24 +11,25 @@ namespace App\Jobs\PostMark; -use App\DataMapper\Analytics\Mail\EmailBounce; -use App\DataMapper\Analytics\Mail\EmailSpam; -use App\Jobs\Util\SystemLogger; +use App\Models\Company; +use App\Models\SystemLog; use App\Libraries\MultiDB; +use Postmark\PostmarkClient; +use Illuminate\Bus\Queueable; +use App\Jobs\Util\SystemLogger; +use App\Models\QuoteInvitation; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; +use Illuminate\Queue\SerializesModels; +use Turbo124\Beacon\Facades\LightLogs; use App\Models\PurchaseOrderInvitation; -use App\Models\QuoteInvitation; +use Illuminate\Queue\InteractsWithQueue; use App\Models\RecurringInvoiceInvitation; -use App\Models\SystemLog; -use App\Notifications\Ninja\EmailSpamNotification; -use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Postmark\PostmarkClient; -use Turbo124\Beacon\Facades\LightLogs; +use App\DataMapper\Analytics\Mail\EmailSpam; +use App\DataMapper\Analytics\Mail\EmailBounce; +use App\Notifications\Ninja\EmailSpamNotification; class ProcessPostmarkWebhook implements ShouldQueue { @@ -82,9 +83,14 @@ class ProcessPostmarkWebhook implements ShouldQueue public function handle() { MultiDB::findAndSetDbByCompanyKey($this->request['Tag']); + $company = Company::where('company_key', $this->request['Tag'])->first(); $this->invitation = $this->discoverInvitation($this->request['MessageID']); + if ($company && $this->request['RecordType'] == 'SpamComplaint' && config('ninja.notification.slack')) { + $company->notification(new EmailSpamNotification($company))->ninja(); + } + if (!$this->invitation) { return; } @@ -305,20 +311,8 @@ class ProcessPostmarkWebhook implements ShouldQueue if($sl) { $this->updateSystemLog($sl, $data); - - if (config('ninja.notification.slack')) { - $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); - } - - return; } - (new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); - -if (config('ninja.notification.slack')) { - $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); -} - } private function discoverInvitation($message_id) diff --git a/app/Notifications/Ninja/EmailSpamNotification.php b/app/Notifications/Ninja/EmailSpamNotification.php index e4cd98b6c5b4..8abdc6e8f1a2 100644 --- a/app/Notifications/Ninja/EmailSpamNotification.php +++ b/app/Notifications/Ninja/EmailSpamNotification.php @@ -11,6 +11,7 @@ namespace App\Notifications\Ninja; +use App\Models\Company; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; @@ -21,11 +22,8 @@ class EmailSpamNotification extends Notification * * @return void */ - protected $account; - - public function __construct($account) + public function __construct(protected Company $company) { - $this->account = $account; } /** @@ -63,9 +61,9 @@ class EmailSpamNotification extends Notification public function toSlack($notifiable) { - $content = "Email SPAM notification for Account {$this->account->key} \n"; + $content = "Email SPAM notification for Company {$this->company->company_key} \n"; - $owner = $this->account->companies()->first()->owner(); + $owner = $this->company->owner(); $content .= "Owner {$owner->present()->name() } | {$owner->email}"; From 4bf7e075141f14d7af5d7732c12cf07b3c6d7c1e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 17 Dec 2023 10:05:33 +1100 Subject: [PATCH 3/5] Improve email validation --- .../BulkBankIntegrationRequest.php | 5 ++++- app/Http/Requests/Email/SendEmailRequest.php | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/Http/Requests/BankIntegration/BulkBankIntegrationRequest.php b/app/Http/Requests/BankIntegration/BulkBankIntegrationRequest.php index 965b245608f0..1604b3532e91 100644 --- a/app/Http/Requests/BankIntegration/BulkBankIntegrationRequest.php +++ b/app/Http/Requests/BankIntegration/BulkBankIntegrationRequest.php @@ -22,7 +22,10 @@ class BulkBankIntegrationRequest extends Request */ public function authorize() : bool { - return auth()->user()->isAdmin(); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->isAdmin(); } public function rules() diff --git a/app/Http/Requests/Email/SendEmailRequest.php b/app/Http/Requests/Email/SendEmailRequest.php index 69eb19f90167..9c004ebfb964 100644 --- a/app/Http/Requests/Email/SendEmailRequest.php +++ b/app/Http/Requests/Email/SendEmailRequest.php @@ -11,16 +11,18 @@ namespace App\Http\Requests\Email; -use App\Http\Requests\Request; use App\Utils\Ninja; -use App\Utils\Traits\MakesHash; -use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Support\Str; +use App\Http\Requests\Request; +use App\Utils\Traits\MakesHash; +use Illuminate\Validation\Rule; +use Illuminate\Auth\Access\AuthorizationException; class SendEmailRequest extends Request { use MakesHash; + private string $entity_plural = ''; private string $error_message = ''; /** * Determine if the user is authorized to make this request. @@ -39,10 +41,13 @@ class SendEmailRequest extends Request */ public function rules() { + /** @var \App\Models\User $user */ + $user = auth()->user(); + return [ 'template' => 'bail|required', - 'entity' => 'bail|required', - 'entity_id' => 'bail|required', + 'entity' => 'bail|required|in:App\Models\Invoice,App\Models\Quote,App\Models\Credit,App\Models\RecurringInvoice,App\Models\PurchaseOrder,App\Models\Payment', + 'entity_id' => ['bail', 'required', Rule::exists($this->entity_plural, 'id')->where('company_id', $user->company()->id)], 'cc_email.*' => 'bail|sometimes|email', ]; @@ -70,6 +75,8 @@ class SendEmailRequest extends Request $input['entity_id'] = $this->decodePrimaryKey($input['entity_id']); } + $this->entity_plural = Str::plural($input['entity']) ?? ''; + if (isset($input['entity'])) { $input['entity'] = "App\Models\\".ucfirst(Str::camel($input['entity'])); } From dfcf8e0a3990ea6eccc2b906ea289a11d2f24905 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 17 Dec 2023 10:16:02 +1100 Subject: [PATCH 4/5] Updates for send email validation --- app/DataMapper/EmailTemplateDefaults.php | 17 ++++++++++++++++ app/Http/Requests/Email/SendEmailRequest.php | 21 ++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/app/DataMapper/EmailTemplateDefaults.php b/app/DataMapper/EmailTemplateDefaults.php index 93be2e4e9805..0111277d8080 100644 --- a/app/DataMapper/EmailTemplateDefaults.php +++ b/app/DataMapper/EmailTemplateDefaults.php @@ -15,6 +15,23 @@ use Illuminate\Support\Facades\App; class EmailTemplateDefaults { + public array $templates = [ + 'email_template_invoice', + 'email_template_quote', + 'email_template_credit', + 'email_template_payment', + 'email_template_payment_partial', + 'email_template_statement', + 'email_template_reminder1', + 'email_template_reminder2', + 'email_template_reminder3', + 'email_template_reminder_endless', + 'email_template_custom1', + 'email_template_custom2', + 'email_template_custom3', + 'email_template_purchase_order', + ]; + public static function getDefaultTemplate($template, $locale) { App::setLocale($locale); diff --git a/app/Http/Requests/Email/SendEmailRequest.php b/app/Http/Requests/Email/SendEmailRequest.php index 9c004ebfb964..944296394336 100644 --- a/app/Http/Requests/Email/SendEmailRequest.php +++ b/app/Http/Requests/Email/SendEmailRequest.php @@ -24,6 +24,24 @@ class SendEmailRequest extends Request private string $entity_plural = ''; private string $error_message = ''; + + public array $templates = [ + 'email_template_invoice', + 'email_template_quote', + 'email_template_credit', + 'email_template_payment', + 'email_template_payment_partial', + 'email_template_statement', + 'email_template_reminder1', + 'email_template_reminder2', + 'email_template_reminder3', + 'email_template_reminder_endless', + 'email_template_custom1', + 'email_template_custom2', + 'email_template_custom3', + 'email_template_purchase_order', + ]; + /** * Determine if the user is authorized to make this request. * @@ -45,13 +63,12 @@ class SendEmailRequest extends Request $user = auth()->user(); return [ - 'template' => 'bail|required', + 'template' => 'bail|required|in:'.implode(',', $this->templates), 'entity' => 'bail|required|in:App\Models\Invoice,App\Models\Quote,App\Models\Credit,App\Models\RecurringInvoice,App\Models\PurchaseOrder,App\Models\Payment', 'entity_id' => ['bail', 'required', Rule::exists($this->entity_plural, 'id')->where('company_id', $user->company()->id)], 'cc_email.*' => 'bail|sometimes|email', ]; - } public function prepareForValidation() From a8ab24630d1d2e35bf99e9f0d156b17875deca2d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 17 Dec 2023 12:04:46 +1100 Subject: [PATCH 5/5] Update readme with Linux apps --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 144a617e861c..ff27c5f6695e 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ We offer a $30 per year white-label license to remove the Invoice Ninja branding ### Desktop Apps * [macOS](https://apps.apple.com/app/id1503970375?platform=mac) * [Windows](https://microsoft.com/en-us/p/invoice-ninja/9n3f2bbcfdr6) -* [Linux](https://snapcraft.io/invoiceninja) +* [Linux - Snap](https://snapcraft.io/invoiceninja) +* [Linux - Flatpak](https://flathub.org/apps/com.invoiceninja.InvoiceNinja) ### Installation Options * [Docker File](https://hub.docker.com/r/invoiceninja/invoiceninja/)