From 5f14cc0c5d56aa053902b8c688461c2c9a4fa024 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 27 Feb 2021 21:08:39 +1100 Subject: [PATCH 1/7] Working on task range overlap --- app/Models/Company.php | 1 + ...1713_add_invoice_task_datelog_property.php | 31 +++++++++++ tests/Unit/RangeDetectionTest.php | 55 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 database/migrations/2021_02_27_091713_add_invoice_task_datelog_property.php create mode 100644 tests/Unit/RangeDetectionTest.php diff --git a/app/Models/Company.php b/app/Models/Company.php index 97f376d23170..8706ff03f8ca 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -85,6 +85,7 @@ class Company extends BaseModel 'expense_inclusive_taxes', 'session_timeout', 'oauth_password_required', + 'invoice_task_datelog', ]; protected $hidden = [ diff --git a/database/migrations/2021_02_27_091713_add_invoice_task_datelog_property.php b/database/migrations/2021_02_27_091713_add_invoice_task_datelog_property.php new file mode 100644 index 000000000000..3267ab777846 --- /dev/null +++ b/database/migrations/2021_02_27_091713_add_invoice_task_datelog_property.php @@ -0,0 +1,31 @@ +boolean('invoice_task_datelog')->default(0); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/tests/Unit/RangeDetectionTest.php b/tests/Unit/RangeDetectionTest.php new file mode 100644 index 000000000000..18ff33c08a72 --- /dev/null +++ b/tests/Unit/RangeDetectionTest.php @@ -0,0 +1,55 @@ +makeRanges($range); + } + + foreach($ranges as $range) + { + + } + + } + + private function makeRanges(array $ranges) + { + + return range($range[0], $range[1]); + + } + +} From e668e7fd5a6604f0e1a791adb0db48b1407d5d4e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 28 Feb 2021 13:12:55 +1100 Subject: [PATCH 2/7] Fixes for Quotes not attaching to emails --- app/Http/Middleware/UserVerified.php | 6 +++++- app/Mail/Engine/CreditEmailEngine.php | 4 +++- app/Mail/Engine/QuoteEmailEngine.php | 4 ++-- app/Models/Presenters/CompanyPresenter.php | 4 ++-- app/Models/Quote.php | 16 +++++++++------- app/Observers/CreditObserver.php | 2 +- app/Observers/QuoteObserver.php | 2 -- tests/Unit/RangeDetectionTest.php | 2 +- 8 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/Http/Middleware/UserVerified.php b/app/Http/Middleware/UserVerified.php index 35a0acdeea81..ce8a899764aa 100644 --- a/app/Http/Middleware/UserVerified.php +++ b/app/Http/Middleware/UserVerified.php @@ -26,7 +26,7 @@ class UserVerified public function __construct(?User $user) { - $this->user = $user ?: auth()->user(); + $this->user = property_exists($user, 'id') ? $user : auth()->user(); } /** @@ -44,6 +44,10 @@ class UserVerified 'errors' => new \stdClass, ]; + // nlog(auth()->user()->toArray()); + // nlog($this->user->toArray()); + // nlog((bool)$this->user->isVerified()); + if ($this->user && !$this->user->isVerified()) return response()->json($error, 403); diff --git a/app/Mail/Engine/CreditEmailEngine.php b/app/Mail/Engine/CreditEmailEngine.php index c97827b0fdb5..835c9d47aefa 100644 --- a/app/Mail/Engine/CreditEmailEngine.php +++ b/app/Mail/Engine/CreditEmailEngine.php @@ -89,7 +89,9 @@ class CreditEmailEngine extends BaseEmailEngine ->setInvitation($this->invitation); if ($this->client->getSetting('pdf_email_attachment') !== false) { - $this->setAttachments(['path' => $this->credit->pdf_file_path(), 'name' => basename($this->credit->pdf_file_path())]); + $this->setAttachments([$this->credit->pdf_file_path()]); + + // $this->setAttachments(['path' => $this->credit->pdf_file_path(), 'name' => basename($this->credit->pdf_file_path())]); } //attach third party documents diff --git a/app/Mail/Engine/QuoteEmailEngine.php b/app/Mail/Engine/QuoteEmailEngine.php index a79a1fa0779b..5751cdf5acae 100644 --- a/app/Mail/Engine/QuoteEmailEngine.php +++ b/app/Mail/Engine/QuoteEmailEngine.php @@ -90,8 +90,8 @@ class QuoteEmailEngine extends BaseEmailEngine if ($this->client->getSetting('pdf_email_attachment') !== false) { - // $this->setAttachments([$this->quote->pdf_file_path()]); - $this->setAttachments(['path' => $this->quote->pdf_file_path(), 'name' => basename($this->quote->pdf_file_path())]); + $this->setAttachments([$this->quote->pdf_file_path()]); + //$this->setAttachments(['path' => $this->quote->pdf_file_path(), 'name' => basename($this->quote->pdf_file_path())]); } diff --git a/app/Models/Presenters/CompanyPresenter.php b/app/Models/Presenters/CompanyPresenter.php index fec12b9eac87..10410d9a8a0b 100644 --- a/app/Models/Presenters/CompanyPresenter.php +++ b/app/Models/Presenters/CompanyPresenter.php @@ -91,13 +91,13 @@ class CompanyPresenter extends EntityPresenter } } - public function getSpcQrCode($client_currency, $invoice_number, $balance) + public function getSpcQrCode($client_currency, $invoice_number, $balance_due_raw) { $settings = $this->entity->settings; return - "SPC\n0200\n1\nCH860021421411198240K\nK\n{$this->name}\n{$settings->address1}\n{$settings->postal_code} {$settings->city}\n\n\nCH\n\n\n\n\n\n\n\n{$balance}\n{$client_currency}\n\n\n\n\n\n\n\nNON\n\n{$invoice_number}\nEPD\n"; + "SPC\n0200\n1\nCH860021421411198240K\nK\n{$this->name}\n{$settings->address1}\n{$settings->postal_code} {$settings->city}\n\n\nCH\n\n\n\n\n\n\n\n{$balance_due_raw}\n{$client_currency}\n\n\n\n\n\n\n\nNON\n\n{$invoice_number}\nEPD\n"; } } diff --git a/app/Models/Quote.php b/app/Models/Quote.php index 9038c6ef3b62..1f2b740ea81b 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -200,25 +200,27 @@ class Quote extends BaseModel return new QuoteService($this); } + public function pdf_file_path($invitation = null, string $type = 'url') { if (! $invitation) { - $invitation = $this->invitations->where('client_contact_id', $this->client->primary_contact()->first()->id)->first(); + $invitation = $this->invitations->first(); } $storage_path = Storage::$type($this->client->quote_filepath().$this->number.'.pdf'); - if (Storage::exists($this->client->quote_filepath().$this->number.'.pdf')) { - return $storage_path; + nlog($storage_path); + + if (! Storage::exists($this->client->quote_filepath().$this->number.'.pdf')) { + event(new QuoteWasUpdated($this, $this->company, Ninja::eventVars())); + CreateEntityPdf::dispatchNow($invitation); } - event(new QuoteWasUpdated($this, $this->company, Ninja::eventVars())); - - CreateEntityPdf::dispatchNow($invitation); - return $storage_path; } + + /** * @param int $status * @return string diff --git a/app/Observers/CreditObserver.php b/app/Observers/CreditObserver.php index 9969f7f02c60..fd7f3d2d25bd 100644 --- a/app/Observers/CreditObserver.php +++ b/app/Observers/CreditObserver.php @@ -37,7 +37,7 @@ class CreditObserver */ public function updated(Credit $credit) { - UnlinkFile::dispatchNow(config('filesystems.default'), $credit->client->credit_filepath() . $credit->number.'.pdf'); + } /** diff --git a/app/Observers/QuoteObserver.php b/app/Observers/QuoteObserver.php index f2a9471111af..1530b99a38c9 100644 --- a/app/Observers/QuoteObserver.php +++ b/app/Observers/QuoteObserver.php @@ -51,8 +51,6 @@ class QuoteObserver WebhookHandler::dispatch(Webhook::EVENT_UPDATE_QUOTE, $quote, $quote->company); } - UnlinkFile::dispatchNow(config('filesystems.default'), $quote->client->quote_filepath() . $quote->number.'.pdf'); - } /** diff --git a/tests/Unit/RangeDetectionTest.php b/tests/Unit/RangeDetectionTest.php index 18ff33c08a72..d00d7b20361d 100644 --- a/tests/Unit/RangeDetectionTest.php +++ b/tests/Unit/RangeDetectionTest.php @@ -45,7 +45,7 @@ class RangeDetectionTest extends TestCase } - private function makeRanges(array $ranges) + private function makeRanges(array $range) { return range($range[0], $range[1]); From fa5830f37b5edbc5168bd14a509dd52597c5cb9c Mon Sep 17 00:00:00 2001 From: = Date: Sun, 28 Feb 2021 15:32:08 +1100 Subject: [PATCH 3/7] Test for date ranges --- tests/Unit/RangeDetectionTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Unit/RangeDetectionTest.php b/tests/Unit/RangeDetectionTest.php index d00d7b20361d..1d8540502fc7 100644 --- a/tests/Unit/RangeDetectionTest.php +++ b/tests/Unit/RangeDetectionTest.php @@ -35,19 +35,19 @@ class RangeDetectionTest extends TestCase foreach($ranges as $range) { - $expanded_ranges[] = $this->makeRanges($range); + $expanded_ranges = array_merge(array_values($expanded_ranges),array_values($this->makeRanges($range))); } - foreach($ranges as $range) - { - - } + $value_count_array = array_count_values($expanded_ranges); + $value_count_array = array_diff($value_count_array, [1]); + + $this->assertEquals(count($value_count_array), 1); } + private function makeRanges(array $range) { - return range($range[0], $range[1]); } From 92f729c10d904ff2b97959f3ae972e6533bfbf9e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 28 Feb 2021 19:54:14 +1100 Subject: [PATCH 4/7] Catch if an OAuth user doesn't exist and attempts to login --- app/Http/Controllers/Auth/LoginController.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index fe3b7144a1f3..8cb1362841e6 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -286,11 +286,25 @@ class LoginController extends BaseController } if ($user) { + $client = new Google_Client(); $client->setClientId(config('ninja.auth.google.client_id')); $client->setClientSecret(config('ninja.auth.google.client_secret')); $client->setRedirectUri(config('ninja.app_url')); - $token = $client->authenticate(request()->input('server_auth_code')); + + $token = false; + + try{ + $token = $client->authenticate(request()->input('server_auth_code')); + } + catch(\Exception $e) { + + return response() + ->json(['message' => ctrans('texts.invalid_credentials')], 401) + ->header('X-App-Version', config('ninja.app_version')) + ->header('X-Api-Version', config('ninja.minimum_client_version')); + + } $refresh_token = ''; From d238d53b26a1f90bb9cb7234dcac6b78573dc2b6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 1 Mar 2021 10:40:18 +1100 Subject: [PATCH 5/7] Delete PDF helper --- app/Http/Middleware/SetEmailDb.php | 8 +++++--- app/Jobs/Entity/CreateEntityPdf.php | 2 ++ app/Jobs/Util/UnlinkFile.php | 2 ++ app/Libraries/MultiDB.php | 5 +++-- app/Services/Credit/CreditService.php | 10 +++++++++- app/Services/Quote/QuoteService.php | 8 ++++++++ app/Services/Recurring/RecurringService.php | 8 ++++++++ 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/Http/Middleware/SetEmailDb.php b/app/Http/Middleware/SetEmailDb.php index 2ae4e7d4890b..8a977d0f30a8 100644 --- a/app/Http/Middleware/SetEmailDb.php +++ b/app/Http/Middleware/SetEmailDb.php @@ -33,10 +33,12 @@ class SetEmailDb ]; if ($request->input('email') && config('ninja.db.multi_db_enabled')) { - nlog("trying to find db"); - if (! MultiDB::userFindAndSetDb($request->input('email'))) { + + + if (! MultiDB::userFindAndSetDb($request->input('email'))) return response()->json($error, 400); - } + + } // else { // return response()->json($error, 403); diff --git a/app/Jobs/Entity/CreateEntityPdf.php b/app/Jobs/Entity/CreateEntityPdf.php index e2467e254397..5f368e5d64fa 100644 --- a/app/Jobs/Entity/CreateEntityPdf.php +++ b/app/Jobs/Entity/CreateEntityPdf.php @@ -92,6 +92,8 @@ class CreateEntityPdf implements ShouldQueue App::forgetInstance('translator'); Lang::replace(Ninja::transformTranslations($this->entity->client->getMergedSettings())); + $this->entity->service()->deletePdf(); + if (config('ninja.phantomjs_pdf_generation')) { return (new Phantom)->generate($this->invitation); } diff --git a/app/Jobs/Util/UnlinkFile.php b/app/Jobs/Util/UnlinkFile.php index a7f5f02cb4de..70461add3b70 100644 --- a/app/Jobs/Util/UnlinkFile.php +++ b/app/Jobs/Util/UnlinkFile.php @@ -39,6 +39,8 @@ class UnlinkFile implements ShouldQueue */ public function handle() { + // nlog("deleting"); + // nlog($this->file_path); Storage::disk($this->disk)->delete($this->file_path); } } diff --git a/app/Libraries/MultiDB.php b/app/Libraries/MultiDB.php index 3240283af898..dd5237f35ec9 100644 --- a/app/Libraries/MultiDB.php +++ b/app/Libraries/MultiDB.php @@ -187,9 +187,10 @@ class MultiDB //multi-db active foreach (self::$dbs as $db) { - if (User::on($db)->where(['email' => $email])->get()->count() >= 1) { // if user already exists, validation will fail + + if (User::on($db)->where(['email' => $email])->count() >= 1) return true; - } + } return false; diff --git a/app/Services/Credit/CreditService.php b/app/Services/Credit/CreditService.php index 85ab8fddc64c..8912c41e3561 100644 --- a/app/Services/Credit/CreditService.php +++ b/app/Services/Credit/CreditService.php @@ -11,6 +11,7 @@ namespace App\Services\Credit; +use App\Jobs\Util\UnlinkFile; use App\Models\Credit; use App\Utils\Traits\MakesHash; @@ -134,7 +135,14 @@ class CreditService return $this; } - + + public function deletePdf() + { + UnlinkFile::dispatchNow(config('filesystems.default'), $this->credit->client->credit_filepath() . $this->credit->number.'.pdf'); + + return $this; + } + /** * Saves the credit. * @return Credit object diff --git a/app/Services/Quote/QuoteService.php b/app/Services/Quote/QuoteService.php index fbf53e623a37..01488348d12c 100644 --- a/app/Services/Quote/QuoteService.php +++ b/app/Services/Quote/QuoteService.php @@ -12,6 +12,7 @@ namespace App\Services\Quote; use App\Events\Quote\QuoteWasApproved; +use App\Jobs\Util\UnlinkFile; use App\Models\Invoice; use App\Models\Quote; use App\Repositories\QuoteRepository; @@ -189,6 +190,13 @@ class QuoteService return $this; } + public function deletePdf() + { + UnlinkFile::dispatchNow(config('filesystems.default'), $this->quote->client->quote_filepath() . $this->quote->number.'.pdf'); + + return $this; + } + /** * Saves the quote. * @return Quote|null diff --git a/app/Services/Recurring/RecurringService.php b/app/Services/Recurring/RecurringService.php index 9942efcc69e5..00811fa404ff 100644 --- a/app/Services/Recurring/RecurringService.php +++ b/app/Services/Recurring/RecurringService.php @@ -11,6 +11,7 @@ namespace App\Services\Recurring; +use App\Jobs\Util\UnlinkFile; use App\Models\RecurringInvoice; use App\Services\Recurring\GetInvoicePdf; use Illuminate\Support\Carbon; @@ -84,6 +85,13 @@ class RecurringService return (new GetInvoicePdf($this->recurring_entity, $contact))->run(); } + public function deletePdf() + { + UnlinkFile::dispatchNow(config('filesystems.default'), $this->recurring_entity->client->recurring_invoice_filepath() . $this->recurring_entity->number.'.pdf'); + + return $this; + } + public function save() { $this->recurring_entity->save(); From 9a2160c325a8ed35b499f34ded535c3a0bdf74a5 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 1 Mar 2021 13:51:00 +1100 Subject: [PATCH 6/7] Verified users only for hosted platform --- app/Http/Middleware/UserVerified.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/Http/Middleware/UserVerified.php b/app/Http/Middleware/UserVerified.php index ce8a899764aa..06b45d9c4926 100644 --- a/app/Http/Middleware/UserVerified.php +++ b/app/Http/Middleware/UserVerified.php @@ -13,6 +13,7 @@ namespace App\Http\Middleware; use App\Libraries\MultiDB; use App\Models\User; +use App\Utils\Ninja; use Closure; use Hashids\Hashids; use Illuminate\Http\Request; @@ -38,16 +39,14 @@ class UserVerified */ public function handle($request, Closure $next) { + if(Ninja::isSelfHost()) + return $next($request); $error = [ 'message' => 'Email confirmation required.', 'errors' => new \stdClass, ]; - // nlog(auth()->user()->toArray()); - // nlog($this->user->toArray()); - // nlog((bool)$this->user->isVerified()); - if ($this->user && !$this->user->isVerified()) return response()->json($error, 403); From 2ab76e909886a95ffacd18ca17feccc2b82dd029 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 1 Mar 2021 22:00:07 +1100 Subject: [PATCH 7/7] v5.1.12 --- VERSION.txt | 2 +- app/Models/Presenters/CompanyPresenter.php | 6 +++++- config/ninja.php | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 831c6cd60031..b3fc69690c5a 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.1.11 \ No newline at end of file +5.1.12 \ No newline at end of file diff --git a/app/Models/Presenters/CompanyPresenter.php b/app/Models/Presenters/CompanyPresenter.php index 10410d9a8a0b..dde59b55649e 100644 --- a/app/Models/Presenters/CompanyPresenter.php +++ b/app/Models/Presenters/CompanyPresenter.php @@ -36,7 +36,11 @@ class CompanyPresenter extends EntityPresenter $settings = $this->entity->settings; } - return (strlen($settings->company_logo) > 0) ? url('') . $settings->company_logo : 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'; + if(strlen($settings->company_logo)) + return asset($settings->company_logo); + else + return 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'; + } public function address($settings = null) diff --git a/config/ninja.php b/config/ninja.php index 39402be58760..0662c2573a02 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -13,7 +13,7 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', ''), - 'app_version' => '5.1.11', + 'app_version' => '5.1.12', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false),