diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 6b6468945cf8..9edbdfaad489 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -16,12 +16,14 @@ use App\Factory\CreditFactory; use App\Factory\InvoiceFactory; use App\Factory\QuoteFactory; use App\Factory\RecurringInvoiceFactory; +use App\Http\Requests\Preview\DesignPreviewRequest; use App\Http\Requests\Preview\PreviewInvoiceRequest; use App\Jobs\Util\PreviewPdf; use App\Libraries\MultiDB; use App\Models\Client; use App\Models\ClientContact; use App\Models\Credit; +use App\Models\GroupSetting; use App\Models\Invoice; use App\Models\InvoiceInvitation; use App\Models\Quote; @@ -30,9 +32,9 @@ use App\Repositories\CreditRepository; use App\Repositories\InvoiceRepository; use App\Repositories\QuoteRepository; use App\Repositories\RecurringInvoiceRepository; -use App\Services\PdfMaker\Design; use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfMakerDesign; +use App\Services\PdfMaker\Design; use App\Services\PdfMaker\PdfMaker; use App\Utils\HostedPDF\NinjaPdf; use App\Utils\HtmlEngine; @@ -173,6 +175,170 @@ class PreviewController extends BaseController return $this->blankEntity(); } + public function design(DesignPreviewRequest $request) + { + $company = auth()->user()->company(); + + MultiDB::setDb($company->db); + + if ($request->input('entity') == 'quote') { + $repo = new QuoteRepository(); + $entity_obj = QuoteFactory::create($company->id, auth()->user()->id); + $class = Quote::class; + } elseif ($request->input('entity') == 'credit') { + $repo = new CreditRepository(); + $entity_obj = CreditFactory::create($company->id, auth()->user()->id); + $class = Credit::class; + } elseif ($request->input('entity') == 'recurring_invoice') { + $repo = new RecurringInvoiceRepository(); + $entity_obj = RecurringInvoiceFactory::create($company->id, auth()->user()->id); + $class = RecurringInvoice::class; + } else { //assume it is either an invoice or a null object + $repo = new InvoiceRepository(); + $entity_obj = InvoiceFactory::create($company->id, auth()->user()->id); + $class = Invoice::class; + } + + try { + DB::connection(config('database.default'))->beginTransaction(); + + if ($request->has('entity_id')) { + $entity_obj = $class::on(config('database.default')) + ->with('client.company') + ->where('id', $this->decodePrimaryKey($request->input('entity_id'))) + ->where('company_id', $company->id) + ->withTrashed() + ->first(); + } + + if($request->has('client_id')) { + $client = Client::withTrashed()->find($this->decodePrimaryKey($request->client_id)); + if($request->settings_type == 'client'){ + $client->settings = $request->settings; + $client->save(); + } + + } + + if($request->has('group_id')) { + $group = GroupSetting::withTrashed()->find($this->decodePrimaryKey($request->group_id)); + if($request->settings_type == 'group'){ + $group->settings = $request->settings; + $group->save(); + } + + } + + if($request->settings_type == 'company'){ + $company->settings = $request->settings; + $company->save(); + } + + if($request->has('footer') && !$request->filled('footer') && $request->input('entity') == 'recurring_invoice') + $request->merge(['footer' => $company->settings->invoice_footer]); + + if($request->has('terms') && !$request->filled('terms') && $request->input('entity') == 'recurring_invoice') + $request->merge(['terms' => $company->settings->invoice_terms]); + + $entity_obj = $repo->save($request->all(), $entity_obj); + + if (! $request->has('entity_id')) { + $entity_obj->service()->fillDefaults()->save(); + } + + App::forgetInstance('translator'); + $t = app('translator'); + App::setLocale($entity_obj->client->locale()); + $t->replace(Ninja::transformTranslations($entity_obj->client->getMergedSettings())); + + $html = new HtmlEngine($entity_obj->invitations()->first()); + + $design = \App\Models\Design::find($entity_obj->design_id); + + /* Catch all in case migration doesn't pass back a valid design */ + if (! $design) { + $design = \App\Models\Design::find(2); + } + + if ($design->is_custom) { + $options = [ + 'custom_partials' => json_decode(json_encode($design->design), true), + ]; + $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); + } else { + $template = new PdfMakerDesign(strtolower($design->name)); + } + + $variables = $html->generateLabelsAndValues(); + + $state = [ + 'template' => $template->elements([ + 'client' => $entity_obj->client, + 'entity' => $entity_obj, + 'pdf_variables' => (array) $entity_obj->company->settings->pdf_variables, + '$product' => $design->design->product, + 'variables' => $variables, + ]), + 'variables' => $variables, + 'options' => [ + 'all_pages_header' => $entity_obj->client->getSetting('all_pages_header'), + 'all_pages_footer' => $entity_obj->client->getSetting('all_pages_footer'), + ], + 'process_markdown' => $entity_obj->client->company->markdown_enabled, + ]; + + $maker = new PdfMaker($state); + + $maker + ->design($template) + ->build(); + + DB::connection(config('database.default'))->rollBack(); +nlog($maker->getCompiledHTML()); + if (request()->query('html') == 'true') { + nlog($maker->getCompiledHTML()); + return $maker->getCompiledHTML(); + } + + } + catch(\Exception $e){ + nlog($e->getMessage()); + DB::connection(config('database.default'))->rollBack(); + + return; + } + + //if phantom js...... inject here.. + if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { + return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); + } + + if(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){ + $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); + + $numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company()); + + + $numbered_pdf = $this->pageNumbering($pdf, auth()->user()->company()); + + if ($numbered_pdf) { + $pdf = $numbered_pdf; + } + + return $pdf; + } + + $file_path = (new PreviewPdf($maker->getCompiledHTML(true), $company))->handle(); + + $response = Response::make($file_path, 200); + $response->header('Content-Type', 'application/pdf'); + + return $response; + + + + } + public function live(PreviewInvoiceRequest $request) { $company = auth()->user()->company(); diff --git a/app/Http/Requests/Webhook/StoreWebhookRequest.php b/app/Http/Requests/Webhook/StoreWebhookRequest.php index 22978933693b..900cc14ed540 100644 --- a/app/Http/Requests/Webhook/StoreWebhookRequest.php +++ b/app/Http/Requests/Webhook/StoreWebhookRequest.php @@ -28,8 +28,10 @@ class StoreWebhookRequest extends Request public function rules() { return [ - 'target_url' => 'required|url', - 'event_id' => 'required', + 'target_url' => 'bail|required|url', + 'event_id' => 'bail|required', + 'headers' => 'bail|sometimes|json', + 'rest_method' => 'required|in:post,put' ]; } @@ -37,6 +39,9 @@ class StoreWebhookRequest extends Request { $input = $this->all(); + if(isset($input['headers']) && count($input['headers']) == 0) + $input['headers'] = null; + $this->replace($input); } } diff --git a/app/Http/Requests/Webhook/UpdateWebhookRequest.php b/app/Http/Requests/Webhook/UpdateWebhookRequest.php index bc255153f889..7d809acf1ba0 100644 --- a/app/Http/Requests/Webhook/UpdateWebhookRequest.php +++ b/app/Http/Requests/Webhook/UpdateWebhookRequest.php @@ -27,13 +27,16 @@ class UpdateWebhookRequest extends Request */ public function authorize() : bool { - return auth()->user()->isAdmin(); + return auth()->user()->can('edit', $this->webhook); } public function rules() { return [ - 'target_url' => 'url', + 'target_url' => 'bail|required|url', + 'event_id' => 'bail|required', + 'rest_method' => 'required|in:post,put', + 'headers' => 'bail|sometimes|json', ]; } @@ -41,6 +44,9 @@ class UpdateWebhookRequest extends Request { $input = $this->all(); + if(isset($input['headers']) && count($input['headers']) == 0) + $input['headers'] = null; + $this->replace($input); } } diff --git a/app/Policies/WebhookPolicy.php b/app/Policies/WebhookPolicy.php index b6c1f778eded..47d830362519 100644 --- a/app/Policies/WebhookPolicy.php +++ b/app/Policies/WebhookPolicy.php @@ -11,9 +11,22 @@ namespace App\Policies; +use App\Models\User; + /** * Class WebhookPolicy. */ class WebhookPolicy extends EntityPolicy { + /** + * Checks if the user has create permissions. + * + * @param User $user + * @return bool + */ + public function create(User $user) : bool + { + return $user->isAdmin(); + } + } diff --git a/routes/api.php b/routes/api.php index 886588d72223..6a5805f757ae 100644 --- a/routes/api.php +++ b/routes/api.php @@ -228,6 +228,7 @@ Route::group(['middleware' => ['throttle:300,1', 'api_db', 'token_auth', 'locale Route::post('preview', [PreviewController::class, 'show'])->name('preview.show'); Route::post('live_preview', [PreviewController::class, 'live'])->name('preview.live'); + Route::post('live_design', [PreviewController::class, 'design'])->name('preview.design'); Route::post('preview/purchase_order', [PreviewPurchaseOrderController::class, 'show'])->name('preview_purchase_order.show'); Route::post('live_preview/purchase_order', [PreviewPurchaseOrderController::class, 'live'])->name('preview_purchase_order.live');