From 53f79440c061408b5360e522d5151ca638937acc Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 22 Feb 2021 08:27:00 +1100 Subject: [PATCH 1/4] Connected accounts --- app/Exceptions/Handler.php | 16 +- .../ConnectedAccountController.php | 139 ++++++++++++++++++ routes/api.php | 2 + 3 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 app/Http/Controllers/ConnectedAccountController.php diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 850c67dfaeb1..159fadedfe0e 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -99,21 +99,21 @@ class Handler extends ExceptionHandler private function validException($exception) { - if (strpos($exception->getMessage(), 'file_put_contents') !== false) { + if (strpos($exception->getMessage(), 'file_put_contents') !== false) return false; - } - if (strpos($exception->getMessage(), 'Permission denied') !== false) { + if (strpos($exception->getMessage(), 'Permission denied') !== false) return false; - } - if (strpos($exception->getMessage(), 'flock()') !== false) { + if (strpos($exception->getMessage(), 'flock()') !== false) return false; - } - if (strpos($exception->getMessage(), 'expects parameter 1 to be resource') !== false) { + if (strpos($exception->getMessage(), 'expects parameter 1 to be resource') !== false) return false; - } + + if (strpos($exception->getMessage(), 'fwrite()') !== false) + return false + return true; } diff --git a/app/Http/Controllers/ConnectedAccountController.php b/app/Http/Controllers/ConnectedAccountController.php new file mode 100644 index 000000000000..f212396af2f2 --- /dev/null +++ b/app/Http/Controllers/ConnectedAccountController.php @@ -0,0 +1,139 @@ +input('provider') == 'google') { + return $this->handleGoogleOauth(); + } + + return response() + ->json(['message' => 'Provider not supported'], 400) + ->header('X-App-Version', config('ninja.app_version')) + ->header('X-Api-Version', config('ninja.minimum_client_version')); + } + + private function handleGoogleOauth() + { + $user = false; + + $google = new Google(); + + $user = $google->getTokenResponse(request()->input('id_token')); + + if (is_array($user)) { + + $query = [ + 'oauth_user_id' => $google->harvestSubField($user), + 'oauth_provider_id'=> 'google', + ]; + + /* Cannot allow duplicates! */ + if ($existing_user = MultiDB::hasUser($query)) { + return response() + ->json(['message' => 'User already exists in system.'], 401) + ->header('X-App-Version', config('ninja.app_version')) + ->header('X-Api-Version', config('ninja.minimum_client_version')); + } + } + + 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')); + + $refresh_token = ''; + + if (array_key_exists('refresh_token', $token)) { + $refresh_token = $token['refresh_token']; + } + + + $connected_account = [ + 'password' => '', + 'email' => $google->harvestEmail($user), + 'oauth_user_id' => $google->harvestSubField($user), + 'oauth_user_token' => $token, + 'oauth_user_refresh_token' => $refresh_token, + 'oauth_provider_id' => 'google', + 'email_verified_at' =>now() + ]; + + auth()->user()->update($connected_account); + auth()->user()->email_verified_at = now(); + auth()->user()->save(); + + //$ct = CompanyUser::whereUserId(auth()->user()->id); + + return $this->listResponse(auth()->user()); + } + + 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')); + } +} diff --git a/routes/api.php b/routes/api.php index 53e6e8fc87dd..bc148ded9fc6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -36,6 +36,8 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a Route::put('clients/{client}/upload', 'ClientController@upload')->name('clients.upload'); Route::post('clients/bulk', 'ClientController@bulk')->name('clients.bulk'); + Route::post('connected_account', 'ConnectedAccountController@index'); + Route::resource('client_statement', 'ClientStatementController@statement'); // name = (client_statement. index / create / show / update / destroy / edit Route::post('companies/purge/{company}', 'MigrationController@purgeCompany')->middleware('password_protected'); From e8d40d2fde33941225970c328af81ce538e99ba4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 22 Feb 2021 08:29:39 +1100 Subject: [PATCH 2/4] Fixes for tests --- app/Exceptions/Handler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 159fadedfe0e..3351dc65a4e1 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -112,7 +112,7 @@ class Handler extends ExceptionHandler return false; if (strpos($exception->getMessage(), 'fwrite()') !== false) - return false + return false; return true; From c72fcfed64f1ceb94125a57b540b28978bc8acc3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 22 Feb 2021 11:18:52 +1100 Subject: [PATCH 3/4] Mail listeners to harvest message ids --- .../ConnectedAccountController.php | 4 +- app/Jobs/Entity/EmailEntity.php | 2 +- app/Listeners/Mail/MailSentListener.php | 47 +++++++++++++++++++ app/Mail/Engine/BaseEmailEngine.php | 13 +++++ app/Mail/Engine/CreditEmailEngine.php | 3 +- app/Mail/Engine/InvoiceEmailEngine.php | 3 +- app/Mail/Engine/QuoteEmailEngine.php | 4 +- app/Mail/TemplateEmail.php | 7 ++- app/Providers/EventServiceProvider.php | 8 ++++ 9 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 app/Listeners/Mail/MailSentListener.php diff --git a/app/Http/Controllers/ConnectedAccountController.php b/app/Http/Controllers/ConnectedAccountController.php index f212396af2f2..456f519c2634 100644 --- a/app/Http/Controllers/ConnectedAccountController.php +++ b/app/Http/Controllers/ConnectedAccountController.php @@ -23,8 +23,8 @@ class ConnectedAccountController extends BaseController parent::__construct(); } -/** - * Refreshes the data feed with the current Company User. + /** + * Connect an OAuth account to a regular email/password combination account * * @param Request $request * @return User Refresh Feed. diff --git a/app/Jobs/Entity/EmailEntity.php b/app/Jobs/Entity/EmailEntity.php index 95c16acbf030..63b859906cd8 100644 --- a/app/Jobs/Entity/EmailEntity.php +++ b/app/Jobs/Entity/EmailEntity.php @@ -105,7 +105,7 @@ class EmailEntity implements ShouldQueue MultiDB::setDB($this->company->db); $nmo = new NinjaMailerObject; - $nmo->mailable = new TemplateEmail($this->email_entity_builder,$this->invitation->contact); + $nmo->mailable = new TemplateEmail($this->email_entity_builder,$this->invitation->contact, $this->invitation); $nmo->company = $this->company; $nmo->settings = $this->settings; $nmo->to_user = $this->invitation->contact; diff --git a/app/Listeners/Mail/MailSentListener.php b/app/Listeners/Mail/MailSentListener.php new file mode 100644 index 000000000000..603c8f2b94f5 --- /dev/null +++ b/app/Listeners/Mail/MailSentListener.php @@ -0,0 +1,47 @@ +company->db); + //$postmark_id = $message->getHeaders()->get('x-pm-message-id')->getValue(); + + if(property_exists($event->message, 'invitation')){ + nlog($event->message->invitation); + } + + } +} diff --git a/app/Mail/Engine/BaseEmailEngine.php b/app/Mail/Engine/BaseEmailEngine.php index 982487ff448b..01727dfd8aef 100644 --- a/app/Mail/Engine/BaseEmailEngine.php +++ b/app/Mail/Engine/BaseEmailEngine.php @@ -31,6 +31,8 @@ class BaseEmailEngine implements EngineInterface public $text; + public $invitation; + public function setFooter($footer) { $this->footer = $footer; @@ -141,4 +143,15 @@ class BaseEmailEngine implements EngineInterface public function build() { } + + public function setInvitation($invitation) + { + $this->invitation = $invitation; + } + + public function getInvitation() + { + return $this->invitation; + } } + diff --git a/app/Mail/Engine/CreditEmailEngine.php b/app/Mail/Engine/CreditEmailEngine.php index 57b0ffb45c4c..c97827b0fdb5 100644 --- a/app/Mail/Engine/CreditEmailEngine.php +++ b/app/Mail/Engine/CreditEmailEngine.php @@ -85,7 +85,8 @@ class CreditEmailEngine extends BaseEmailEngine ->setBody($body_template) ->setFooter("".ctrans('texts.view_credit').'') ->setViewLink($this->invitation->getLink()) - ->setViewText(ctrans('texts.view_credit')); + ->setViewText(ctrans('texts.view_credit')) + ->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())]); diff --git a/app/Mail/Engine/InvoiceEmailEngine.php b/app/Mail/Engine/InvoiceEmailEngine.php index 07f857aaafcb..40cd3eee7211 100644 --- a/app/Mail/Engine/InvoiceEmailEngine.php +++ b/app/Mail/Engine/InvoiceEmailEngine.php @@ -94,7 +94,8 @@ class InvoiceEmailEngine extends BaseEmailEngine ->setBody($body_template) ->setFooter("".ctrans('texts.view_invoice').'') ->setViewLink($this->invitation->getLink()) - ->setViewText(ctrans('texts.view_invoice')); + ->setViewText(ctrans('texts.view_invoice')) + ->setInvitation($this->invitation); if ($this->client->getSetting('pdf_email_attachment') !== false) { $this->setAttachments([$this->invoice->pdf_file_path()]); diff --git a/app/Mail/Engine/QuoteEmailEngine.php b/app/Mail/Engine/QuoteEmailEngine.php index 574ade2ea57a..a79a1fa0779b 100644 --- a/app/Mail/Engine/QuoteEmailEngine.php +++ b/app/Mail/Engine/QuoteEmailEngine.php @@ -85,7 +85,9 @@ class QuoteEmailEngine extends BaseEmailEngine ->setBody($body_template) ->setFooter("".ctrans('texts.view_quote').'') ->setViewLink($this->invitation->getLink()) - ->setViewText(ctrans('texts.view_quote')); + ->setViewText(ctrans('texts.view_quote')) + ->setInvitation($this->invitation); + if ($this->client->getSetting('pdf_email_attachment') !== false) { // $this->setAttachments([$this->quote->pdf_file_path()]); diff --git a/app/Mail/TemplateEmail.php b/app/Mail/TemplateEmail.php index f6382ffafad4..62c7ed921763 100644 --- a/app/Mail/TemplateEmail.php +++ b/app/Mail/TemplateEmail.php @@ -29,7 +29,9 @@ class TemplateEmail extends Mailable private $company; - public function __construct($build_email, ClientContact $contact) + private $invitation; + + public function __construct($build_email, ClientContact $contact, $invitation = null) { $this->build_email = $build_email; @@ -38,6 +40,8 @@ class TemplateEmail extends Mailable $this->client = $contact->client; $this->company = $contact->company; + + $this->invitation = $invitation; } public function build() @@ -77,6 +81,7 @@ class TemplateEmail extends Mailable ]) ->withSwiftMessage(function ($message) use($company){ $message->getHeaders()->addTextHeader('Tag', $company->company_key); + $message->invitation = $this->invitation; }); //conditionally attach files diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 8a5209f6ff49..8728ecb8d81c 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -136,6 +136,7 @@ use App\Listeners\Invoice\InvoiceRestoredActivity; use App\Listeners\Invoice\InvoiceReversedActivity; use App\Listeners\Invoice\InvoiceViewedActivity; use App\Listeners\Invoice\UpdateInvoiceActivity; +use App\Listeners\Mail\MailSentListener; use App\Listeners\Misc\InvitationViewedListener; use App\Listeners\Payment\PaymentEmailFailureActivity; use App\Listeners\Payment\PaymentEmailedActivity; @@ -157,6 +158,8 @@ use App\Listeners\User\RestoredUserActivity; use App\Listeners\User\UpdateUserLastLogin; use App\Listeners\User\UpdatedUserActivity; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use Illuminate\Mail\Events\MessageSending; +use Illuminate\Mail\Events\MessageSent; class EventServiceProvider extends ServiceProvider { @@ -166,6 +169,11 @@ class EventServiceProvider extends ServiceProvider * @var array */ protected $listen = [ + MessageSending::class =>[ + ], + MessageSent::class => [ + MailSentListener::class, + ], UserWasCreated::class => [ CreatedUserActivity::class, SendVerificationNotification::class, From 0317bae985d5fc1f43d18299759fd016c8f9f07c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 22 Feb 2021 11:57:54 +1100 Subject: [PATCH 4/4] Harvest message ID from postmark --- app/Listeners/Mail/MailSentListener.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/app/Listeners/Mail/MailSentListener.php b/app/Listeners/Mail/MailSentListener.php index 603c8f2b94f5..0774daa68c65 100644 --- a/app/Listeners/Mail/MailSentListener.php +++ b/app/Listeners/Mail/MailSentListener.php @@ -36,11 +36,22 @@ class MailSentListener implements ShouldQueue */ public function handle(MessageSent $event) { - //MultiDB::setDb($event->company->db); - //$postmark_id = $message->getHeaders()->get('x-pm-message-id')->getValue(); - + if(property_exists($event->message, 'invitation')){ - nlog($event->message->invitation); + + MultiDB::setDb($event->message->invitation->company->db); + + if($event->message->getHeaders()->get('x-pm-message-id')){ + + $postmark_id = $event->message->getHeaders()->get('x-pm-message-id')->getValue(); + + nlog($postmark_id); + $invitation = $event->message->invitation; + $invitation->message_id = $postmark_id; + $invitation->save(); + + } + } }