diff --git a/app/Http/Controllers/ClientPortal/DocumentController.php b/app/Http/Controllers/ClientPortal/DocumentController.php index 88024a39a3be..92c17bc32071 100644 --- a/app/Http/Controllers/ClientPortal/DocumentController.php +++ b/app/Http/Controllers/ClientPortal/DocumentController.php @@ -12,16 +12,17 @@ namespace App\Http\Controllers\ClientPortal; -use App\Http\Controllers\Controller; -use App\Http\Requests\ClientPortal\Documents\ShowDocumentRequest; -use App\Http\Requests\Document\DownloadMultipleDocumentsRequest; -use App\Libraries\MultiDB; -use App\Models\Document; use App\Utils\TempFile; +use App\Models\Document; +use Illuminate\View\View; +use App\Libraries\MultiDB; use App\Utils\Traits\MakesHash; +use App\Http\Controllers\Controller; +use Illuminate\Support\Facades\Cache; use Illuminate\Contracts\View\Factory; use Illuminate\Support\Facades\Storage; -use Illuminate\View\View; +use App\Http\Requests\Document\DownloadMultipleDocumentsRequest; +use App\Http\Requests\ClientPortal\Documents\ShowDocumentRequest; class DocumentController extends Controller { @@ -68,6 +69,29 @@ class DocumentController extends Controller return Storage::disk($document->disk)->download($document->url, $document->name, $headers); } + public function hashDownload(string $hash) + { + + $hash = Cache::pull($hash); + + if(!$hash) + abort(404); + + MultiDB::setDb($hash['db']); + + /** @var \App\Models\Document $document **/ + $document = Document::where('hash', $hash['doc_hash'])->firstOrFail(); + + $headers = ['Cache-Control:' => 'no-cache']; + + if (request()->input('inline') == 'true') { + $headers = array_merge($headers, ['Content-Disposition' => 'inline']); + } + + return Storage::disk($document->disk)->download($document->url, $document->name, $headers); + } + + public function downloadMultiple(DownloadMultipleDocumentsRequest $request) { /** @var \Illuminate\Database\Eloquent\Collection $documents **/ diff --git a/app/Mail/Engine/CreditEmailEngine.php b/app/Mail/Engine/CreditEmailEngine.php index e927fe287ecf..feffbcf0181a 100644 --- a/app/Mail/Engine/CreditEmailEngine.php +++ b/app/Mail/Engine/CreditEmailEngine.php @@ -11,13 +11,15 @@ namespace App\Mail\Engine; -use App\Jobs\Entity\CreateRawPdf; -use App\Models\Account; -use App\Utils\HtmlEngine; use App\Utils\Ninja; use App\Utils\Number; +use App\Models\Account; +use App\Utils\HtmlEngine; +use Illuminate\Support\Str; +use App\Jobs\Entity\CreateRawPdf; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\URL; +use Illuminate\Support\Facades\Cache; class CreditEmailEngine extends BaseEmailEngine { @@ -125,7 +127,11 @@ class CreditEmailEngine extends BaseEmailEngine // Storage::url $this->credit->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->credit->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null, 'file' => base64_encode($document->getFile())]]); } @@ -133,7 +139,11 @@ class CreditEmailEngine extends BaseEmailEngine $this->credit->company->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->credit->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null, 'file' => base64_encode($document->getFile())]]); } diff --git a/app/Mail/Engine/InvoiceEmailEngine.php b/app/Mail/Engine/InvoiceEmailEngine.php index eff0d34a9210..8c0593f43636 100644 --- a/app/Mail/Engine/InvoiceEmailEngine.php +++ b/app/Mail/Engine/InvoiceEmailEngine.php @@ -11,17 +11,19 @@ namespace App\Mail\Engine; -use App\DataMapper\EmailTemplateDefaults; -use App\Jobs\Entity\CreateRawPdf; -use App\Models\Account; -use App\Models\Expense; use App\Models\Task; -use App\Utils\HtmlEngine; use App\Utils\Ninja; use App\Utils\Number; +use App\Models\Account; +use App\Models\Expense; +use App\Utils\HtmlEngine; +use Illuminate\Support\Str; use App\Utils\Traits\MakesHash; +use App\Jobs\Entity\CreateRawPdf; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\URL; +use Illuminate\Support\Facades\Cache; +use App\DataMapper\EmailTemplateDefaults; class InvoiceEmailEngine extends BaseEmailEngine { @@ -132,12 +134,18 @@ class InvoiceEmailEngine extends BaseEmailEngine $this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->invoice->numberFormatter().'.pdf']]); } +// $hash = Str::uuid(); +// $url = \Illuminate\Support\Facades\URL::temporarySignedRoute('protected_download', now()->addHour(), ['hash' => $hash]); +// Cache::put($hash, $url, now()->addHour()); + //attach third party documents if ($this->client->getSetting('document_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) { if ($this->invoice->recurring_invoice()->exists()) { $this->invoice->recurring_invoice->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->invoice->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } @@ -147,7 +155,11 @@ class InvoiceEmailEngine extends BaseEmailEngine // Storage::url $this->invoice->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->invoice->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } @@ -155,7 +167,11 @@ class InvoiceEmailEngine extends BaseEmailEngine $this->invoice->company->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->invoice->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } @@ -177,7 +193,11 @@ class InvoiceEmailEngine extends BaseEmailEngine ->each(function ($expense) { $expense->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->invoice->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } @@ -197,7 +217,11 @@ class InvoiceEmailEngine extends BaseEmailEngine ->each(function ($task) { $task->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->invoice->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index f1929d11b52d..0b89106304db 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -11,17 +11,19 @@ namespace App\Mail\Engine; -use App\DataMapper\EmailTemplateDefaults; -use App\Jobs\Entity\CreateRawPdf; -use App\Models\Account; -use App\Models\Payment; -use App\Services\Template\TemplateAction; -use App\Utils\Helpers; use App\Utils\Ninja; use App\Utils\Number; +use App\Utils\Helpers; +use App\Models\Account; +use App\Models\Payment; +use Illuminate\Support\Str; use App\Utils\Traits\MakesDates; +use App\Jobs\Entity\CreateRawPdf; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\URL; +use Illuminate\Support\Facades\Cache; +use App\DataMapper\EmailTemplateDefaults; +use App\Services\Template\TemplateAction; class PaymentEmailEngine extends BaseEmailEngine { @@ -145,23 +147,17 @@ class PaymentEmailEngine extends BaseEmailEngine if ($this->client->getSetting('document_email_attachment') !== false) { $invoice->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->payment->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } }); } - // if($this->client->getSetting('enable_e_invoice')) - // { - - // $e_invoice_filepath = $invoice->service()->getEInvoice($this->contact); - - // if($e_invoice_filepath && strlen($e_invoice_filepath) > 1) - // $this->setAttachments([['file' => base64_encode($e_invoice_filepath), 'name' => $invoice->getFileName("xml")]]); - - // } - }); } diff --git a/app/Mail/Engine/PurchaseOrderEmailEngine.php b/app/Mail/Engine/PurchaseOrderEmailEngine.php index 3a90cf1313af..bf97de9284c1 100644 --- a/app/Mail/Engine/PurchaseOrderEmailEngine.php +++ b/app/Mail/Engine/PurchaseOrderEmailEngine.php @@ -11,17 +11,19 @@ namespace App\Mail\Engine; -use App\DataMapper\EmailTemplateDefaults; -use App\Jobs\Entity\CreateRawPdf; -use App\Models\Account; -use App\Models\PurchaseOrder; -use App\Models\Vendor; use App\Utils\Ninja; use App\Utils\Number; +use App\Models\Vendor; +use App\Models\Account; +use Illuminate\Support\Str; +use App\Models\PurchaseOrder; use App\Utils\Traits\MakesHash; use App\Utils\VendorHtmlEngine; +use App\Jobs\Entity\CreateRawPdf; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\URL; +use Illuminate\Support\Facades\Cache; +use App\DataMapper\EmailTemplateDefaults; class PurchaseOrderEmailEngine extends BaseEmailEngine { @@ -129,7 +131,12 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine // Storage::url $this->purchase_order->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->purchase_order->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]); } @@ -137,7 +144,11 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine $this->purchase_order->company->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->purchase_order->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]); } diff --git a/app/Mail/Engine/QuoteEmailEngine.php b/app/Mail/Engine/QuoteEmailEngine.php index a4b3df35db97..ace3f40512a4 100644 --- a/app/Mail/Engine/QuoteEmailEngine.php +++ b/app/Mail/Engine/QuoteEmailEngine.php @@ -11,13 +11,15 @@ namespace App\Mail\Engine; -use App\Jobs\Entity\CreateRawPdf; -use App\Models\Account; -use App\Utils\HtmlEngine; use App\Utils\Ninja; use App\Utils\Number; +use App\Models\Account; +use App\Utils\HtmlEngine; +use Illuminate\Support\Str; +use App\Jobs\Entity\CreateRawPdf; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\URL; +use Illuminate\Support\Facades\Cache; class QuoteEmailEngine extends BaseEmailEngine { @@ -123,7 +125,11 @@ class QuoteEmailEngine extends BaseEmailEngine // Storage::url $this->quote->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->quote->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } @@ -131,7 +137,11 @@ class QuoteEmailEngine extends BaseEmailEngine $this->quote->company->documents()->where('is_public', true)->cursor()->each(function ($document) { if ($document->size > $this->max_attachment_size) { - $this->setAttachmentLinks([" $document->hash]) ."'>". $document->name .""]); + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->quote->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + $this->setAttachmentLinks([" $hash]) ."'>". $document->name .""]); } else { $this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => null, ]]); } diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php index fd9a5c1cf2f7..e24e6a2d470d 100644 --- a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -271,6 +271,28 @@ class PayPalPPCPPaymentDriver extends BaseDriver //capture $orderID = $response['orderID']; + + if($this->company_gateway->require_shipping_address) + { + + $shipping_data = + [[ + "op" => "replace", + "path" => "/purchase_units/@reference_id=='default'/shipping/address", + "value" => [ + "address_line_1" => strlen($this->client->shipping_address1) > 1 ? $this->client->shipping_address1 : $this->client->address1, + "address_line_2" => $this->client->shipping_address2, + "admin_area_2" => strlen($this->client->shipping_city) > 1 ? $this->client->shipping_city : $this->client->city, + "admin_area_1" => strlen($this->client->shipping_state) > 1 ? $this->client->shipping_state : $this->client->state, + "postal_code" => strlen($this->client->shipping_postal_code) > 1 ? $this->client->shipping_postal_code : $this->client->postal_code, + "country_code" => $this->client->present()->shipping_country_code(), + ], + ]]; + + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $shipping_data); + + } + $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); $response = $r; @@ -467,11 +489,11 @@ class PayPalPPCPPaymentDriver extends BaseDriver [ "address" => [ - "address_line_1" => $this->client->shipping_address1, + "address_line_1" => strlen($this->client->shipping_address1) > 1 ? $this->client->shipping_address1 : $this->client->address1, "address_line_2" => $this->client->shipping_address2, - "admin_area_2" => $this->client->shipping_city, - "admin_area_1" => $this->client->shipping_state, - "postal_code" => $this->client->shipping_postal_code, + "admin_area_2" => strlen($this->client->shipping_city) > 1 ? $this->client->shipping_city : $this->client->city, + "admin_area_1" => strlen($this->client->shipping_state) > 1 ? $this->client->shipping_state : $this->client->state, + "postal_code" => strlen($this->client->shipping_postal_code) > 1 ? $this->client->shipping_postal_code : $this->client->postal_code, "country_code" => $this->client->present()->shipping_country_code(), ], ] diff --git a/app/Services/Email/EmailMailable.php b/app/Services/Email/EmailMailable.php index fd2831cb443b..fae76d738759 100644 --- a/app/Services/Email/EmailMailable.php +++ b/app/Services/Email/EmailMailable.php @@ -13,9 +13,11 @@ namespace App\Services\Email; use App\Utils\Ninja; use App\Models\Document; +use Illuminate\Support\Str; use Illuminate\Mail\Mailable; use Illuminate\Mail\Attachment; use Illuminate\Support\Facades\URL; +use Illuminate\Support\Facades\Cache; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Headers; use Illuminate\Mail\Mailables\Envelope; @@ -62,7 +64,11 @@ class EmailMailable extends Mailable ->where('size', '>', $this->max_attachment_size) ->cursor() ->map(function ($document) { - return " $document->hash]) ."'>". $document->name .""; + + $hash = Str::random(64); + Cache::put($hash, ['db' => $this->email_object->company->db, 'doc_hash' => $document->hash], now()->addDays(7)); + + return " $hash]) ."'>". $document->name .""; }); return new Content( diff --git a/routes/client.php b/routes/client.php index 192f9f20424c..1394734d5977 100644 --- a/routes/client.php +++ b/routes/client.php @@ -37,7 +37,9 @@ Route::get('tmp_pdf/{hash}', [App\Http\Controllers\ClientPortal\TempRouteControl Route::get('client/key_login/{contact_key}', [App\Http\Controllers\ClientPortal\ContactHashLoginController::class, 'login'])->name('client.contact_login')->middleware(['domain_db','contact_key_login']); Route::get('client/magic_link/{magic_link}', [App\Http\Controllers\ClientPortal\ContactHashLoginController::class, 'magicLink'])->name('client.contact_magic_link')->middleware(['domain_db','contact_key_login']); + Route::get('documents/{document_hash}', [App\Http\Controllers\ClientPortal\DocumentController::class, 'publicDownload'])->name('documents.public_download')->middleware(['api_db','token_auth']); +Route::get('documents/{hash}/hashed', [App\Http\Controllers\ClientPortal\DocumentController::class, 'hashDownload'])->name('documents.hashed_download'); Route::get('error', [App\Http\Controllers\ClientPortal\ContactHashLoginController::class, 'errorPage'])->name('client.error'); Route::get('client/payment/{contact_key}/{payment_id}', [App\Http\Controllers\ClientPortal\InvitationController::class, 'paymentRouter'])->middleware(['domain_db','contact_key_login']); Route::get('client/ninja/{contact_key}/{company_key}', [App\Http\Controllers\ClientPortal\NinjaPlanController::class, 'index'])->name('client.ninja_contact_login')->middleware(['domain_db']); diff --git a/tests/Unit/CompanyDocumentsTest.php b/tests/Unit/CompanyDocumentsTest.php index a4e6e490bdfe..aae613c72261 100644 --- a/tests/Unit/CompanyDocumentsTest.php +++ b/tests/Unit/CompanyDocumentsTest.php @@ -63,50 +63,6 @@ class CompanyDocumentsTest extends TestCase $this->assertEquals(0, Document::whereCompanyId($this->company->id)->count()); - // $this->assertFalse(Storage::exists($document->url)); } - // public function testSignedRoutes() - // { - - // $company_key = $this->company->company_key; - - // $original_count = Document::whereCompanyId($this->company->id)->count(); - - // $image = UploadedFile::fake()->image('avatar.jpg'); - - - // $document = (new UploadFile( - // $image, - // UploadFile::IMAGE, - // $this->user, - // $this->company, - // $this->invoice))->handle(); - - // $this->assertNotNull($document); - - // // $url = \Illuminate\Support\Facades\URL::signedRoute('api.documents.show', ['document' => $document->hashed_id]); - // $url = \Illuminate\Support\Facades\URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]); - - // nlog($url); - - // $response = $this->withHeaders([ - // 'X-API-SECRET' => config('ninja.api_secret'), - // 'X-API-TOKEN' => $this->token, - // ])->get($url); - - - // $content = $response->streamedContent(); - // nlog($content); - - - // $response->assertStatus(200); - - // $arr = $response->json(); - - - - // $this->assertFalse($arr); - - // } -} +} \ No newline at end of file