diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 4ab5402e6883..e770508853dc 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -312,7 +312,7 @@ class LoginController extends BaseController if(array_key_exists('refresh_token', $token)) $refresh_token = $token['refresh_token']; - $access_token = $token['access_token']; + $access_token = $token['access_token']; $name = OAuth::splitName($google->harvestName($user)); diff --git a/app/Jobs/Mail/BaseMailerJob.php b/app/Jobs/Mail/BaseMailerJob.php new file mode 100644 index 000000000000..dea597c57345 --- /dev/null +++ b/app/Jobs/Mail/BaseMailerJob.php @@ -0,0 +1,60 @@ +setGmailMailer(); + break; + default: + break; + } + + } + + private function setGmailMailer() + { + $sending_user = $this->entity->client->getSetting('gmail_sending_user_id'); + + $user = User::find($sending_user); + + $google = (new Google())->init(); + $google->getClient->setAccessToken($user->oauth_user_token); + + if ($google->getClient->isAccessTokenExpired()) { + $google->refreshToken($user); + } + + /* + * Now that our token is refresh and valid we can boot the + * mail driver at runtime and also set the token which will persist + * just for this request. + */ + + Config::set('mail.driver', 'gmail'); + Config::set('services.gmail.token', $user->oauth_user_token); + (new MailServiceProvider(app()))->register(); + + } + +} \ No newline at end of file diff --git a/app/Jobs/Mail/EntitySentEmail.php b/app/Jobs/Mail/EntitySentEmail.php index bbd48d59c7da..e2d1bcc8abc0 100644 --- a/app/Jobs/Mail/EntitySentEmail.php +++ b/app/Jobs/Mail/EntitySentEmail.php @@ -2,14 +2,23 @@ namespace App\Jobs\Mail; +use App\Jobs\Util\SystemLogger; +use App\Libraries\Google\Google; use App\Libraries\MultiDB; +use App\Mail\Admin\EntitySent; +use App\Mail\Admin\EntitySentObject; +use App\Models\SystemLog; +use App\Models\User; +use App\Providers\MailServiceProvider; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Config; +use Illuminate\Support\Facades\Mail; -class EntitySentEmail implements ShouldQueue +class EntitySentEmail extends BaseMailerJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -45,32 +54,37 @@ class EntitySentEmail implements ShouldQueue */ public function handle() { + //set DB MultiDB::setDb($this->company->db); //if we need to set an email driver do it now $this->setMailDriver($this->entity->client->getSetting('email_sending_method')); - } + $mail_obj = (new EntitySentObject($this->invitation, $this->entity_type))->build(); + $mail_obj->from = $this->entity->user->present()->name(); - private function setMailDriver(string $driver) - { - switch ($driver) { - case 'default': - break; - case 'gmail': - $this->setGmailMailer(); - break; - default: - - break; + //send email + // Mail::to($this->user->email) + Mail::to('turbo124@gmail.com') //@todo + ->send(new EntitySent($mail_obj)); + + //catch errors + if (count(Mail::failures()) > 0) { + $this->logMailError(Mail::failures()); } - if($driver == 'default') - return; + } - private function setGmailMailer() + private function logMailError($errors) { - $sending_user = $this->entity->client->getSetting('gmail_sending_user_id'); - + SystemLogger::dispatch( + $errors, + SystemLog::CATEGORY_MAIL, + SystemLog::EVENT_MAIL_SEND, + SystemLog::TYPE_FAILURE, + $this->invoice->client + ); } + + } diff --git a/app/Libraries/Google/Google.php b/app/Libraries/Google/Google.php new file mode 100644 index 000000000000..d5c29f5f6369 --- /dev/null +++ b/app/Libraries/Google/Google.php @@ -0,0 +1,65 @@ +client = new \Google_Client(); + } + + public function init() + { + $this->client->setClientId(config('ninja.auth.google.client_id')); + $this->client->setClientSecret(config('ninja.auth.google.client_secret')); + + return $this; + } + + public function getClient() + { + return $this->client; + } + + public function checkAccessToken() + { + + } + + public function refreshToken($user) + { + if($this->client->isAccessTokenExpired()) { + $this->client->fetchAccessTokenWithRefreshToken($user->oauth_user_refresh_token); + + $access_token = $this->client->getAccessToken(); + + if(is_string($access_token)) + $user->oauth_user_token = $access_token; + elseif(isset($access_token['access_token'])) + $user->oauth_user_token = $access_token['access_token']); + + $user->save(); + + $this->client->setAccessToken($access_token); + + } + + return $this; + } +} diff --git a/app/Mail/Admin/EntitySent.php b/app/Mail/Admin/EntitySent.php new file mode 100644 index 000000000000..c852fcfe219a --- /dev/null +++ b/app/Mail/Admin/EntitySent.php @@ -0,0 +1,45 @@ +mail_obj = $mail_obj; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this->from($this->mail_obj->from) //todo + ->subject($this->mail_obj->subject) + ->markdown($this->mail_obj->markdown, ['data' => $this->mail_obj->data]) + ->withSwiftMessage(function ($message) { + $message->getHeaders()->addTextHeader('Tag', $this->mail_obj->tag); + }); + } +} diff --git a/app/Mail/Admin/EntitySentObject.php b/app/Mail/Admin/EntitySentObject.php new file mode 100644 index 000000000000..da221682dada --- /dev/null +++ b/app/Mail/Admin/EntitySentObject.php @@ -0,0 +1,90 @@ +invitation = $invitation; + $this->entity_type = $entity_type; + $this->entity = $invitation->{$entity_type}; + $this->contact = $invitation->contact; + $this->company = $invitation->company; + $this->settings = $this->entity->client->getMergedSettings(); + } + + public function build() + { + $mail_obj = new \stdClass; + $mail_obj->amount = $this->getAmount(); + $mail_obj->subject = $this->getSubject(); + $mail_obj->data = $this->getData(); + $mail_obj->markdown = 'email.admin.generic'; + $mail_obj->tag = $this->company->company_key; + + return $mail_obj; + } + + private function getAmount() + { + return Number::formatMoney($this->entity->amount, $this->entity->client); + } + + private function getSubject() + { + return + ctrans( + "texts.notification_{$this->entity_type}_sent_subject", + [ + 'client' => $this->contact->present()->name(), + 'invoice' => $this->entity->number, + ] + ); + } + + private function getData() + { + $data = [ + 'title' => $this->getSubject, + 'message' => ctrans( + "texts.notification_{$this->entity_type}_sent", + [ + 'amount' => $amount, + 'client' => $this->contact->present()->name(), + 'invoice' => $this->entity->number, + ] + ), + 'url' => $this->invitation->getAdminLink(), + 'button' => ctrans("texts.view_{$this->entity_type}"), + 'signature' => $this->settings->email_signature, + 'logo' => $this->company->present()->logo(), + ]; + + return $data; + } +} \ No newline at end of file diff --git a/tests/Feature/CreditTest.php b/tests/Feature/CreditTest.php index adaeb097db71..75987b666139 100644 --- a/tests/Feature/CreditTest.php +++ b/tests/Feature/CreditTest.php @@ -34,7 +34,7 @@ class CreditTest extends TestCase public function testCreditsList() { - factory(Client::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) { + factory(Client::class, 1)->create(['user_id' => $this->user->id, 'company_id' => $this->company->id])->each(function ($c) { factory(\App\Models\ClientContact::class, 1)->create([ 'user_id' => $this->user->id, 'client_id' => $c->id, diff --git a/tests/Feature/InvoiceTest.php b/tests/Feature/InvoiceTest.php index 1b0246084ffd..e2c55a461dd0 100644 --- a/tests/Feature/InvoiceTest.php +++ b/tests/Feature/InvoiceTest.php @@ -44,64 +44,30 @@ class InvoiceTest extends TestCase public function testInvoiceList() { - Account::all()->each(function($account) { - $account->delete(); - }); - $data = [ - 'first_name' => $this->faker->firstName, - 'last_name' => $this->faker->lastName, - 'name' => $this->faker->company, - 'email' => $this->faker->unique()->safeEmail, - 'password' => 'ALongAndBrilliantPassword123', - '_token' => csrf_token(), - 'privacy_policy' => 1, - 'terms_of_service' => 1 - ]; - - - $response = $this->withHeaders([ - 'X-API-SECRET' => config('ninja.api_secret'), - ])->post('/api/v1/signup?include=account', $data); - - $acc = $response->json(); - - $account = Account::find($this->decodePrimaryKey($acc['data'][0]['account']['id'])); - - $company_token = $account->default_company->tokens()->first(); - $token = $company_token->token; - $company = $company_token->company; - - $user = $company_token->user; - - $this->assertNotNull($company_token); - $this->assertNotNull($token); - $this->assertNotNull($user); - $this->assertNotNull($company); - //$this->assertNotNull($user->token->company); - - factory(\App\Models\Client::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company) { + factory(\App\Models\Client::class, 1)->create(['user_id' => $this->user->id, 'company_id' => $this->company->id])->each(function ($c){ factory(\App\Models\ClientContact::class, 1)->create([ - 'user_id' => $user->id, + 'user_id' => $this->user->id, 'client_id' => $c->id, - 'company_id' => $company->id, + 'company_id' => $this->company->id, 'is_primary' => 1 ]); factory(\App\Models\ClientContact::class, 1)->create([ - 'user_id' => $user->id, + 'user_id' => $this->user->id, 'client_id' => $c->id, - 'company_id' => $company->id + 'company_id' => $this->company->id ]); }); + $client = Client::all()->first(); - factory(\App\Models\Invoice::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id, 'client_id' => $client->id]); + factory(\App\Models\Invoice::class, 1)->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id]); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $token, + 'X-API-TOKEN' => $this->token, ])->get('/api/v1/invoices'); $response->assertStatus(200);