diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php
index afed2928261f..894c6046d764 100644
--- a/app/Jobs/Util/Import.php
+++ b/app/Jobs/Util/Import.php
@@ -1091,15 +1091,15 @@ class Import implements ShouldQueue
{
Invoice::unguard();
- $rules = [
- '*.client_id' => ['required'],
- ];
+ // $rules = [
+ // '*.client_id' => ['required'],
+ // ];
- $validator = Validator::make($data, $rules);
+ // // $validator = Validator::make($data, $rules);
- if ($validator->fails()) {
- throw new MigrationValidatorFailed(json_encode($validator->errors()));
- }
+ // if ($validator->fails()) {
+ // throw new MigrationValidatorFailed(json_encode($validator->errors()));
+ // }
$invoice_repository = new InvoiceMigrationRepository();
@@ -1145,6 +1145,8 @@ class Import implements ShouldQueue
$key = "invoices_{$resource['id']}";
+ nlog($invoice->id);
+
$this->ids['invoices'][$key] = [
'old' => $resource['id'],
'new' => $invoice->id,
@@ -2056,7 +2058,7 @@ class Import implements ShouldQueue
public function failed($exception = null)
{
- info('the job failed');
+ nlog('the job failed');
config(['queue.failed.driver' => null]);
@@ -2067,11 +2069,11 @@ class Import implements ShouldQueue
LightLogs::create($job_failure)
->queue();
- info(print_r($exception->getMessage(), 1));
+ nlog(print_r($exception->getMessage(), 1));
- if (Ninja::isHosted()) {
+ // if (Ninja::isHosted()) {
app('sentry')->captureException($exception);
- }
+ // }
}
diff --git a/app/Listeners/User/UpdateUserLastLogin.php b/app/Listeners/User/UpdateUserLastLogin.php
index bc0404e29f36..56b3a1ff6864 100644
--- a/app/Listeners/User/UpdateUserLastLogin.php
+++ b/app/Listeners/User/UpdateUserLastLogin.php
@@ -63,7 +63,6 @@ class UpdateUserLastLogin implements ShouldQueue
$ip = array_key_exists('ip', $event->event_vars) ? $event->event_vars['ip'] : 'IP address not resolved';
$key = "user_logged_in_{$user->id}{$event->company->db}";
-
if ($user->ip != $ip && is_null(Cache::get($key)) && $user->user_logged_in_notification) {
$nmo = new NinjaMailerObject();
$nmo->mailable = new UserLoggedIn($user, $user->account->companies->first(), $ip);
diff --git a/app/Mail/Admin/EntityCreatedObject.php b/app/Mail/Admin/EntityCreatedObject.php
index c58108013652..baab3068db25 100644
--- a/app/Mail/Admin/EntityCreatedObject.php
+++ b/app/Mail/Admin/EntityCreatedObject.php
@@ -73,7 +73,8 @@ class EntityCreatedObject
);
$mail_obj->markdown = 'email.admin.generic';
-
+ $mail_obj->text_view = 'email.template.text';
+
$content = ctrans(
$this->template_body,
[
@@ -92,7 +93,7 @@ class EntityCreatedObject
'logo' => $this->company->present()->logo(),
'settings' => $this->company->settings,
'whitelabel' => $this->company->account->isPaid() ? true : false,
- 'text_body' => $content,
+ 'text_body' => str_replace(['$view_button','$viewButton','$viewLink','$view_url'], '$view_url', $content),
];
} else {
$this->entity->load('client.country', 'client.company');
@@ -179,7 +180,7 @@ class EntityCreatedObject
'logo' => $this->company->present()->logo(),
'settings' => $settings,
'whitelabel' => $this->company->account->isPaid() ? true : false,
- 'text_body' => $content,
+ 'text_body' => str_replace(['$view_button','$viewButton','$view_link','$view_button'], '$view_url', $content),
];
}
}
diff --git a/app/Mail/Engine/BaseEmailEngine.php b/app/Mail/Engine/BaseEmailEngine.php
index ebb90796fbc1..a850dc804e21 100644
--- a/app/Mail/Engine/BaseEmailEngine.php
+++ b/app/Mail/Engine/BaseEmailEngine.php
@@ -123,6 +123,15 @@ class BaseEmailEngine implements EngineInterface
public function setTextBody($text)
{
+
+ if (! empty($this->variables)) {
+
+ $text = str_replace(['$paymentLink', '$viewButton', '$view_button', '$viewLink', '$view_link'], '$view_url', $text);
+ $text = str_replace(array_keys($this->variables), array_values($this->variables), $text);
+ $text = str_replace(array_keys($this->variables), array_values($this->variables), $text);
+
+ }
+
$this->text_body = $text;
return $this;
@@ -189,22 +198,4 @@ class BaseEmailEngine implements EngineInterface
return $this->text_body;
}
- private function replaceEntities($content)
- {
- $find = [
- '
',
- '
',
- '',
- '<\div>',
- ];
-
- $replace = [
- '',
- '\n\n',
- '',
- '\n\n',
- ];
-
- return str_replace($find, $replace, $content);
- }
}
diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php
index 0b89106304db..ade3c995603a 100644
--- a/app/Mail/Engine/PaymentEmailEngine.php
+++ b/app/Mail/Engine/PaymentEmailEngine.php
@@ -31,6 +31,7 @@ class PaymentEmailEngine extends BaseEmailEngine
public $client;
+ /** @var \App\Models\Payment $payment */
public $payment;
public $template_data;
@@ -91,6 +92,7 @@ class PaymentEmailEngine extends BaseEmailEngine
->setVariables($this->makeValues())
->setSubject($subject_template)
->setBody($body_template)
+ ->setTextBody($body_template)
->setFooter('')
->setViewLink('')
->setViewText('');
diff --git a/app/Mail/User/UserLoggedIn.php b/app/Mail/User/UserLoggedIn.php
index a7137166cacb..dd2a329f0080 100644
--- a/app/Mail/User/UserLoggedIn.php
+++ b/app/Mail/User/UserLoggedIn.php
@@ -12,31 +12,21 @@
namespace App\Mail\User;
-use Illuminate\Bus\Queueable;
+use App\Models\User;
+use App\Models\Company;
use Illuminate\Mail\Mailable;
-use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
class UserLoggedIn extends Mailable
{
- // use Queueable, SerializesModels;
-
- public $company;
-
- public $user;
-
- public $ip;
/**
* Create a new message instance.
*
* @return void
*/
- public function __construct($user, $company, $ip)
+ public function __construct(public User $user, public Company $company, public string $ip)
{
- $this->company = $company;
- $this->user = $user;
- $this->ip = $ip;
}
/**
@@ -48,11 +38,13 @@ class UserLoggedIn extends Mailable
{
App::setLocale($this->company->getLocale());
+ $text = ctrans('texts.new_login_description', ['email' => $this->user->email, 'ip' => $this->ip, 'time' => now()]);
+
return $this->from(config('mail.from.address'), config('mail.from.name'))
->subject(ctrans('texts.new_login_detected'))
->text('email.admin.generic_text', [
'title' => ctrans('texts.new_login_detected'),
- 'body' => strip_tags(ctrans('texts.new_login_description', ['email' => $this->user->email, 'ip' => $this->ip, 'time' => now()])),
+ 'body' => $text,
])
->view('email.admin.notification')
->with([
diff --git a/app/Repositories/ClientContactRepository.php b/app/Repositories/ClientContactRepository.php
index f00bd4d0cc20..4a508fc18964 100644
--- a/app/Repositories/ClientContactRepository.php
+++ b/app/Repositories/ClientContactRepository.php
@@ -85,13 +85,14 @@ class ClientContactRepository extends BaseRepository
if (array_key_exists('password', $contact) && strlen($contact['password']) > 1 && strlen($update_contact->email) > 3) { //updating on a blank contact email will cause large table scanning
$update_contact->password = Hash::make($contact['password']);
- $client->company
- ->client_contacts()
- ->where('email', $update_contact->email)->cursor()
- ->each(function ($saveable_contact) use ($update_contact){
- $saveable_contact->password = $update_contact->password;
- $saveable_contact->save();
- });
+ ClientContact::withTrashed()
+ ->where('company_id', $client->id)
+ ->where('client_id', $client->company_id)
+ ->where('email', $update_contact->email)->cursor()
+ ->each(function ($saveable_contact) use ($update_contact){
+ $saveable_contact->password = $update_contact->password;
+ $saveable_contact->save();
+ });
}
if (array_key_exists('email', $contact)) {
diff --git a/app/Utils/Traits/Inviteable.php b/app/Utils/Traits/Inviteable.php
index 735937d81fa8..fef8239788a3 100644
--- a/app/Utils/Traits/Inviteable.php
+++ b/app/Utils/Traits/Inviteable.php
@@ -49,7 +49,9 @@ trait Inviteable
public function getPaymentLink()
{
+
if (Ninja::isHosted()) {
+ /**@var \App\Models\Company $company */
$domain = $this->company->domain();
} else {
$domain = config('ninja.app_url');
@@ -105,7 +107,11 @@ trait Inviteable
switch ($this->company->portal_mode) {
case 'subdomain':
- return $domain.'/client/'.$entity_type.'/'.$this->key;
+
+ if(Ninja::isHosted())
+ return 'https://router.invoiceninja.com/route/'.encrypt($domain.'/client/'.$entity_type.'/'.$this->key);
+ else
+ return $domain.'/client/'.$entity_type.'/'.$this->key;
break;
case 'iframe':
return $domain.'/client/'.$entity_type.'/'.$this->key;
diff --git a/resources/views/email/admin/generic_text.blade.php b/resources/views/email/admin/generic_text.blade.php
index 1fdebc4f23ab..8b540769fb71 100644
--- a/resources/views/email/admin/generic_text.blade.php
+++ b/resources/views/email/admin/generic_text.blade.php
@@ -1,9 +1,15 @@
-{!! $title !!}
+{{ $title }}
@isset($body)
-{!! $body !!}
+{{ strip_tags(str_replace("
", "\r\n", $body)) }}
@endisset
@isset($content)
-{!! $content !!}
+{{ strip_tags(str_replace("
", "\r\n", $content)) }}
+@endisset
+
+@isset($whitelabel)
+@if(!$whitelabel)
+{{ ctrans('texts.ninja_email_footer', ['site' => 'https://invoiceninja.com']) }}
+@endif
@endisset
\ No newline at end of file
diff --git a/resources/views/email/template/client.blade.php b/resources/views/email/template/client.blade.php
index 2986b35345fb..1076ab9d32a9 100644
--- a/resources/views/email/template/client.blade.php
+++ b/resources/views/email/template/client.blade.php
@@ -233,7 +233,7 @@
- @isset($email_preferences)
+ @if(isset($email_preferences) && $email_preferences)
|
- @endisset
+ @endif
diff --git a/resources/views/email/template/text.blade.php b/resources/views/email/template/text.blade.php
index 5af56ef5ff4e..302642f32281 100644
--- a/resources/views/email/template/text.blade.php
+++ b/resources/views/email/template/text.blade.php
@@ -1,7 +1,7 @@
-{!! $text_body !!}
+{{ strip_tags(str_replace("
", "\r\n", $text_body)) }}
+
@isset($whitelabel)
@if(!$whitelabel)
-
{{ ctrans('texts.ninja_email_footer', ['site' => 'https://invoiceninja.com']) }}
@endif
@endisset
diff --git a/routes/client.php b/routes/client.php
index 1394734d5977..3bf5d6798365 100644
--- a/routes/client.php
+++ b/routes/client.php
@@ -141,6 +141,15 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie
Route::get('unsubscribe/{entity}/{invitation_key}', [App\Http\Controllers\ClientPortal\InvitationController::class, 'unsubscribe'])->name('unsubscribe');
});
+
+Route::get('route/{hash}', function ($hash) {
+
+ return redirect(decrypt($hash));
+
+});
+
+
+
Route::get('phantom/{entity}/{invitation_key}', [Phantom::class, 'displayInvitation'])->middleware(['invite_db', 'phantom_secret'])->name('phantom_view');
Route::get('blade/', [Phantom::class, 'blade'])->name('blade');