From 1b099d09cc35b9706e8a5d1ec09ab21c37d9c7fb Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 16 Nov 2015 20:02:04 +0200 Subject: [PATCH 1/8] Check for large logo image files --- app/Http/Controllers/AccountController.php | 20 ++++++++++---- app/Http/routes.php | 1 + resources/lang/en/texts.php | 1 + resources/views/accounts/details.blade.php | 31 +++++++++++++--------- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 71e326a070..840e8f5540 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -1,7 +1,6 @@ account; + if ($account->hasLogo()) { + $filename = $account->getLogoPath(); + $bytes = File::size($filename); + if ($bytes > MAX_LOGO_FILE_SIZE * 1000) { + $bytes /= 1000; + Session::flash('warning', trans('texts.logo_too_large', ['size' => round($bytes) . 'KB'])); + } + } + $data = [ 'account' => Account::with('users')->findOrFail(Auth::user()->account_id), 'countries' => Cache::get('countries'), @@ -842,7 +852,7 @@ class AccountController extends BaseController { $rules = array( 'name' => 'required', - 'logo' => 'sometimes|max:200|mimes:jpeg,gif,png', + 'logo' => 'sometimes|max:' . MAX_LOGO_FILE_SIZE . '|mimes:jpeg,gif,png', ); $validator = Validator::make(Input::all(), $rules); @@ -905,7 +915,7 @@ class AccountController extends BaseController } } - Event::fire(new UserSettingsChanged()); + event(new UserSettingsChanged()); Session::flash('message', trans('texts.updated_settings')); return Redirect::to('settings/' . ACCOUNT_COMPANY_DETAILS); @@ -940,7 +950,7 @@ class AccountController extends BaseController $user->save(); - Event::fire(new UserSettingsChanged()); + event(new UserSettingsChanged()); Session::flash('message', trans('texts.updated_settings')); return Redirect::to('settings/' . ACCOUNT_USER_DETAILS); } @@ -957,7 +967,7 @@ class AccountController extends BaseController $account->military_time = Input::get('military_time') ? true : false; $account->save(); - Event::fire(new UserSettingsChanged()); + event(new UserSettingsChanged()); Session::flash('message', trans('texts.updated_settings')); return Redirect::to('settings/' . ACCOUNT_LOCALIZATION); diff --git a/app/Http/routes.php b/app/Http/routes.php index 9d587db5b9..d882bfc9e7 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -334,6 +334,7 @@ if (!defined('CONTACT_EMAIL')) { define('MAX_NUM_USERS', 20); define('MAX_SUBDOMAIN_LENGTH', 30); define('MAX_IFRAME_URL_LENGTH', 250); + define('MAX_LOGO_FILE_SIZE', 200); // KB define('DEFAULT_FONT_SIZE', 9); define('DEFAULT_SEND_RECURRING_HOUR', 8); diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 0cd003ad4d..eab4e221a4 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -918,4 +918,5 @@ return array( 'country' => 'Country', 'include' => 'Include', + 'logo_too_large' => 'Your logo is :size, for better performance we suggest uploading an image file less than 200KB', ); diff --git a/resources/views/accounts/details.blade.php b/resources/views/accounts/details.blade.php index 3d8a0d3f42..5023c132ed 100644 --- a/resources/views/accounts/details.blade.php +++ b/resources/views/accounts/details.blade.php @@ -22,7 +22,7 @@ ->addClass('warn-on-exit') ->autocomplete('on') ->rules([ - 'name' => 'required' + 'name' => 'required' ]) !!} {{ Former::populate($account) }} @@ -37,24 +37,29 @@

{!! trans('texts.details') !!}

- - {!! Former::text('name') !!} + + {!! Former::text('name') !!} {!! Former::text('id_number') !!} {!! Former::text('vat_number') !!} - {!! Former::text('work_email') !!} - {!! Former::text('work_phone') !!} + {!! Former::text('work_email') !!} + {!! Former::text('work_phone') !!} {!! Former::file('logo')->max(2, 'MB')->accept('image')->inlineHelp(trans('texts.logo_help')) !!} - @if ($account->hasLogo()) -
- {!! HTML::image($account->getLogoPath().'?no_cache='.time(), 'Logo', ['width' => 200]) !!}   - {{ trans('texts.remove_logo') }} -

- @endif + @if ($account->hasLogo()) + + @endif - {!! Former::select('size_id')->addOption('','')->fromQuery($sizes, 'name', 'id') !!} - {!! Former::select('industry_id')->addOption('','')->fromQuery($industries, 'name', 'id') !!} + {!! Former::select('size_id')->addOption('','')->fromQuery($sizes, 'name', 'id') !!} + {!! Former::select('industry_id')->addOption('','')->fromQuery($industries, 'name', 'id') !!}
From ce4524ba1a86db814be208b19b042a88d6d6527c Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 16 Nov 2015 21:07:23 +0200 Subject: [PATCH 2/8] Bug fixes --- app/Http/Controllers/InvoiceController.php | 10 +++++++--- app/Libraries/Utils.php | 2 +- resources/lang/en/texts.php | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 14676624c2..b81fb92e35 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -203,7 +203,10 @@ class InvoiceController extends BaseController public function edit($publicId, $clone = false) { $account = Auth::user()->account; - $invoice = Invoice::scope($publicId)->withTrashed()->with('invitations', 'account.country', 'client.contacts', 'client.country', 'invoice_items')->firstOrFail(); + $invoice = Invoice::scope($publicId) + ->with('invitations', 'account.country', 'client.contacts', 'client.country', 'invoice_items') + ->withTrashed() + ->firstOrFail(); $entityType = $invoice->getEntityType(); $contactIds = DB::table('invitations') @@ -270,6 +273,7 @@ class InvoiceController extends BaseController $lastSent = ($invoice->is_recurring && $invoice->last_sent_date) ? $invoice->recurring_invoices->last() : null; $data = array( + 'clients' => Client::scope()->withTrashed()->with('contacts', 'country')->whereId($invoice->id)->get(), 'entityType' => $entityType, 'showBreadcrumbs' => $clone, 'invoice' => $invoice, @@ -282,7 +286,7 @@ class InvoiceController extends BaseController 'actions' => $actions, 'lastSent' => $lastSent); $data = array_merge($data, self::getViewModel()); - + if ($clone) { $data['formIsChanged'] = true; } @@ -327,6 +331,7 @@ class InvoiceController extends BaseController $invoice->public_id = 0; $data = [ + 'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(), 'entityType' => $invoice->getEntityType(), 'invoice' => $invoice, 'method' => 'POST', @@ -361,7 +366,6 @@ class InvoiceController extends BaseController 'account' => Auth::user()->account->load('country'), 'products' => Product::scope()->with('default_tax_rate')->orderBy('id')->get(), 'countries' => Cache::get('countries'), - 'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->orderBy('name')->get(), 'currencies' => Cache::get('currencies'), 'languages' => Cache::get('languages'), diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index 121bc5914b..08e74055c3 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -207,12 +207,12 @@ class Utils $data = [ 'context' => $context, 'user_id' => Auth::check() ? Auth::user()->id : 0, + 'account_id' => Auth::check() ? Auth::user()->account_id : 0, 'user_name' => Auth::check() ? Auth::user()->getDisplayName() : '', 'url' => Input::get('url', Request::url()), 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '', 'ip' => Request::getClientIp(), 'count' => Session::get('error_count', 0), - //'input' => Input::all() ]; Log::error($error."\n", $data); diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index eab4e221a4..7922889f53 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -919,4 +919,7 @@ return array( 'include' => 'Include', 'logo_too_large' => 'Your logo is :size, for better performance we suggest uploading an image file less than 200KB', + 'can_not_email_inactive_client' => 'Emails can not be sent to inactive clients', + 'can_not_email_inactive_invoice' => 'Emails can not be sent to inactive invoices', + ); From eaf73077b15e2e466b99697be6ea0dec4b753600 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 16 Nov 2015 21:21:48 +0200 Subject: [PATCH 3/8] Bug fixes --- app/Models/Invoice.php | 1 + app/Models/OwnedByClientTrait.php | 13 +++++++++++++ resources/views/invoices/edit.blade.php | 22 +++++++++++----------- 3 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 app/Models/OwnedByClientTrait.php diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 2655611b8f..a49f2636fc 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -15,6 +15,7 @@ use App\Events\QuoteInvitationWasEmailed; class Invoice extends EntityModel implements BalanceAffecting { use PresentableTrait; + use OwnedByClientTrait; use SoftDeletes { SoftDeletes::trashed as parentTrashed; } diff --git a/app/Models/OwnedByClientTrait.php b/app/Models/OwnedByClientTrait.php new file mode 100644 index 0000000000..7f11448324 --- /dev/null +++ b/app/Models/OwnedByClientTrait.php @@ -0,0 +1,13 @@ +client) { + return false; + } + + return $this->client->trashed(); + } +} \ No newline at end of file diff --git a/resources/views/invoices/edit.blade.php b/resources/views/invoices/edit.blade.php index e48c42c11b..7666952780 100644 --- a/resources/views/invoices/edit.blade.php +++ b/resources/views/invoices/edit.blade.php @@ -392,19 +392,18 @@ {!! Button::primary(trans('texts.download_pdf'))->withAttributes(array('onclick' => 'onDownloadClick()'))->appendIcon(Icon::create('download-alt')) !!} - @if (!$invoice->trashed()) - + @if ($invoice->isClientTrashed()) + + @elseif ($invoice->trashed()) + {!! Button::success(trans('texts.restore'))->withAttributes(['onclick' => 'submitBulkAction("restore")'])->appendIcon(Icon::create('cloud-download')) !!} + @elseif (!$invoice->trashed()) {!! Button::success(trans("texts.save_{$entityType}"))->withAttributes(array('id' => 'saveButton', 'onclick' => 'onSaveClick()'))->appendIcon(Icon::create('floppy-disk')) !!} {!! Button::info(trans("texts.email_{$entityType}"))->withAttributes(array('id' => 'emailButton', 'onclick' => 'onEmailClick()'))->appendIcon(Icon::create('send')) !!} - @if ($invoice->id) {!! DropdownButton::normal(trans('texts.more_actions')) ->withContents($actions) ->dropup() !!} @endif - - @elseif ($invoice->trashed()) - {!! Button::success(trans('texts.restore'))->withAttributes(['onclick' => 'submitBulkAction("restore")'])->appendIcon(Icon::create('cloud-download')) !!} @endif @@ -1007,16 +1006,17 @@ } function isEmailValid() { - var isValid = false; + var isValid = true; var sendTo = false; var client = model.invoice().client(); for (var i=0; i Date: Mon, 16 Nov 2015 21:29:22 +0200 Subject: [PATCH 4/8] Bug fixes --- app/Http/Controllers/InvoiceController.php | 2 +- app/Ninja/Mailers/ContactMailer.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index b81fb92e35..1987d754e6 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -273,7 +273,7 @@ class InvoiceController extends BaseController $lastSent = ($invoice->is_recurring && $invoice->last_sent_date) ? $invoice->recurring_invoices->last() : null; $data = array( - 'clients' => Client::scope()->withTrashed()->with('contacts', 'country')->whereId($invoice->id)->get(), + 'clients' => Client::scope()->withTrashed()->with('contacts', 'country')->whereId($invoice->client_id)->get(), 'entityType' => $entityType, 'showBreadcrumbs' => $clone, 'invoice' => $invoice, diff --git a/app/Ninja/Mailers/ContactMailer.php b/app/Ninja/Mailers/ContactMailer.php index 1f485138fe..966ea96fc7 100644 --- a/app/Ninja/Mailers/ContactMailer.php +++ b/app/Ninja/Mailers/ContactMailer.php @@ -23,8 +23,10 @@ class ContactMailer extends Mailer $client = $invoice->client; $account = $invoice->account; - if ($invoice->trashed() || $client->trashed()) { - return false; + if ($client->trashed()) { + return trans('texts.can_not_email_inactive_client'); + } elseif ($invoice->trashed()) { + return trans('texts.can_not_email_inactive_invoice'); } $account->loadLocalizationSettings($client); From cd3aecdf5bf1654d6e81c1be20bc7d8a41c3db1c Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 16 Nov 2015 21:51:34 +0200 Subject: [PATCH 5/8] Clarifying email errors --- app/Http/routes.php | 3 +-- app/Ninja/Mailers/ContactMailer.php | 25 ++++++++++++++----------- resources/lang/en/texts.php | 12 +++++++++--- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/app/Http/routes.php b/app/Http/routes.php index d882bfc9e7..71cfbc8984 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,6 +1,5 @@ id === 1) { Auth::loginUsingId(1); } -*/ \ No newline at end of file +*/ diff --git a/app/Ninja/Mailers/ContactMailer.php b/app/Ninja/Mailers/ContactMailer.php index 966ea96fc7..67ba09a17d 100644 --- a/app/Ninja/Mailers/ContactMailer.php +++ b/app/Ninja/Mailers/ContactMailer.php @@ -24,9 +24,9 @@ class ContactMailer extends Mailer $account = $invoice->account; if ($client->trashed()) { - return trans('texts.can_not_email_inactive_client'); + return trans('texts.email_errors.inactive_client'); } elseif ($invoice->trashed()) { - return trans('texts.can_not_email_inactive_invoice'); + return trans('texts.email_errors.inactive_invoice'); } $account->loadLocalizationSettings($client); @@ -40,7 +40,8 @@ class ContactMailer extends Mailer } foreach ($invoice->invitations as $invitation) { - if ($this->sendInvitation($invitation, $invoice, $emailTemplate, $emailSubject, $pdfString)) { + $response = $this->sendInvitation($invitation, $invoice, $emailTemplate, $emailSubject, $pdfString); + if ($response === true) { $sent = true; } } @@ -55,7 +56,7 @@ class ContactMailer extends Mailer } } - return $sent ?: trans('texts.email_error'); + return $response; } private function sendInvitation($invitation, $invoice, $body, $subject, $pdfString) @@ -72,12 +73,14 @@ class ContactMailer extends Mailer } } - if (!$user->email || !$user->confirmed) { - return false; - } - - if (!$invitation->contact->email || $invitation->contact->trashed()) { - return false; + if (!$user->email || !$user->registered) { + return trans('texts.email_errors.user_unregistered'); + } elseif (!$user->confirmed) { + return trans('texts.email_errors.user_unconfirmed'); + } elseif (!$invitation->contact->email) { + return trans('texts.email_errors.invalid_contact_email'); + } elseif ($invitation->contact->trashed()) { + return trans('texts.email_errors.inactive_contact'); } $variables = [ @@ -110,7 +113,7 @@ class ContactMailer extends Mailer if ($response === true) { return true; } else { - return false; + return $response; } } diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 7922889f53..9b61b69413 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -919,7 +919,13 @@ return array( 'include' => 'Include', 'logo_too_large' => 'Your logo is :size, for better performance we suggest uploading an image file less than 200KB', - 'can_not_email_inactive_client' => 'Emails can not be sent to inactive clients', - 'can_not_email_inactive_invoice' => 'Emails can not be sent to inactive invoices', - + 'email_errors' => [ + 'inactive_client' => 'Emails can not be sent to inactive clients', + 'inactive_contact' => 'Emails can not be sent to inactive contacts', + 'inactive_invoice' => 'Emails can not be sent to inactive invoices', + 'user_unregistered' => 'Please register your account to send emails', + 'user_unconfirmed' => 'Please confirm your account to send emails', + 'invalid_contact_email' => 'Invalid contact email', + ] + ); From b4e5690103749796fd6dccf20f43535b31286d4f Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 17 Nov 2015 10:46:14 +0200 Subject: [PATCH 6/8] Fixed problem creating client with invoice in the API --- app/Http/Controllers/InvoiceApiController.php | 19 ++++++++++++------- app/Ninja/Repositories/ClientRepository.php | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php index 2be9b2d70f..ada578daf0 100644 --- a/app/Http/Controllers/InvoiceApiController.php +++ b/app/Http/Controllers/InvoiceApiController.php @@ -4,6 +4,7 @@ use Auth; use Utils; use Response; use Input; +use Validator; use App\Models\Invoice; use App\Models\Client; use App\Models\Contact; @@ -102,12 +103,18 @@ class InvoiceApiController extends Controller } if (isset($data['email'])) { - $client = Client::scope()->whereHas('contacts', function($query) use ($data) { - $query->where('email', '=', $data['email']); + $email = $data['email']; + $client = Client::scope()->whereHas('contacts', function($query) use ($email) { + $query->where('email', '=', $email); })->first(); if (!$client) { - $clientData = ['contact' => ['email' => $data['email']]]; + $validator = Validator::make(['email'=>$email], ['email' => 'email']); + if ($validator->fails()) { + return $validator->message(); + } + + $clientData = ['contact' => ['email' => $email]]; foreach (['name', 'private_notes'] as $field) { if (isset($data[$field])) { $clientData[$field] = $data[$field]; @@ -118,10 +125,8 @@ class InvoiceApiController extends Controller $clientData[$field] = $data[$field]; } } - $error = $this->clientRepo->getErrors($clientData); - if (!$error) { - $client = $this->clientRepo->save($clientData); - } + + $client = $this->clientRepo->save($clientData); } } else if (isset($data['client_id'])) { $client = Client::scope($data['client_id'])->first(); diff --git a/app/Ninja/Repositories/ClientRepository.php b/app/Ninja/Repositories/ClientRepository.php index 728b0bccae..0cea09c554 100644 --- a/app/Ninja/Repositories/ClientRepository.php +++ b/app/Ninja/Repositories/ClientRepository.php @@ -54,7 +54,7 @@ class ClientRepository extends BaseRepository $contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts']; $contactIds = []; - foreach ($data['contacts'] as $contact) { + foreach ($contacts as $contact) { $contact = $client->addContact($contact, $first); $contactIds[] = $contact->public_id; $first = false; From 1d82881814e08839628257891b64a45a4ca51f1e Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 17 Nov 2015 10:55:33 +0200 Subject: [PATCH 7/8] Removing payments of archived/deleted invoices from the dashboard --- app/Http/Controllers/DashboardController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 6dbc8ef610..d15c6d0da7 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -110,6 +110,7 @@ class DashboardController extends BaseController ->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id') ->where('payments.account_id', '=', Auth::user()->account_id) ->where('payments.deleted_at', '=', null) + ->where('invoices.deleted_at', '=', null) ->where('clients.deleted_at', '=', null) ->where('contacts.deleted_at', '=', null) ->where('contacts.is_primary', '=', true) From 9f4cd6283221b566ac19848684eb5cd9023c783f Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 17 Nov 2015 15:42:54 +0200 Subject: [PATCH 8/8] Add space --- app/Console/Commands/SendReminders.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Commands/SendReminders.php b/app/Console/Commands/SendReminders.php index a2bfdc29da..a7e6cc4d01 100644 --- a/app/Console/Commands/SendReminders.php +++ b/app/Console/Commands/SendReminders.php @@ -45,7 +45,7 @@ class SendReminders extends Command foreach ($invoices as $invoice) { if ($reminder = $invoice->getReminder()) { - $this->info('Send to' . $invoice->id); + $this->info('Send to ' . $invoice->id); $this->mailer->sendInvoice($invoice, $reminder); } }