diff --git a/app/Http/Controllers/Auth/ContactForgotPasswordController.php b/app/Http/Controllers/Auth/ContactForgotPasswordController.php index 14441e8e987b..b6338633c775 100644 --- a/app/Http/Controllers/Auth/ContactForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ContactForgotPasswordController.php @@ -15,12 +15,15 @@ use App\Http\Controllers\Controller; use App\Http\Requests\ClientPortal\Contact\ContactPasswordResetRequest; use App\Libraries\MultiDB; use App\Models\Account; +use App\Models\ClientContact; +use App\Models\Company; use App\Utils\Ninja; use Illuminate\Contracts\View\Factory; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Password; +use Illuminate\Support\Str; use Illuminate\View\View; class ContactForgotPasswordController extends Controller @@ -80,19 +83,35 @@ class ContactForgotPasswordController extends Controller public function sendResetLinkEmail(ContactPasswordResetRequest $request) { - if(Ninja::isHosted() && $request->has('db')) - MultiDB::setDb($request->input('db')); + if(Ninja::isHosted() && $request->has('company_key')) + MultiDB::findAndSetDbByCompanyKey($request->input('company_key')); + + $this->validateEmail($request); // $user = MultiDB::hasContact($request->input('email')); + $company = Company::where('company_key', $request->input('company_key'))->first(); + $contact = MultiDB::findContact(['company_id' => $company->id, 'email' => $request->input('email')]); - $this->validateEmail($request); + $response = false; + + if($contact){ + + /* Update all instances of the client */ + $token = Str::random(60); + ClientContact::where('email', $contact->email)->update(['token' => $token]); + + $contact->sendPasswordResetNotification($token); + $response = Password::RESET_LINK_SENT; + } + else + return $this->sendResetLinkFailedResponse($request, Password::INVALID_USER); // We will send the password reset link to this user. Once we have attempted // to send the link, we will examine the response then see the message we // need to show to the user. Finally, we'll send out a proper response. - $response = $this->broker()->sendResetLink( - $this->credentials($request) - ); + // $response = $this->broker()->sendResetLink( + // $this->credentials($request) + // ); if ($request->ajax()) { diff --git a/app/Http/Controllers/Auth/ContactResetPasswordController.php b/app/Http/Controllers/Auth/ContactResetPasswordController.php index 2eaad8e23a18..7c32d664a1f0 100644 --- a/app/Http/Controllers/Auth/ContactResetPasswordController.php +++ b/app/Http/Controllers/Auth/ContactResetPasswordController.php @@ -14,11 +14,15 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Libraries\MultiDB; use App\Models\Account; +use App\Models\ClientContact; +use Illuminate\Auth\Events\PasswordReset; use Illuminate\Contracts\View\Factory; use Illuminate\Foundation\Auth\ResetsPasswords; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Password; +use Illuminate\Support\Str; use Illuminate\View\View; class ContactResetPasswordController extends Controller @@ -76,19 +80,28 @@ class ContactResetPasswordController extends Controller public function reset(Request $request) { - if($request->has('db')) - MultiDB::setDb($request->input('db')); + if($request->has('company_key')) + MultiDB::findAndSetDbByCompanyKey($request->input('company_key')); $request->validate($this->rules(), $this->validationErrorMessages()); - // Here we will attempt to reset the user's password. If it is successful we - // will update the password on an actual user model and persist it to the - // database. Otherwise we will parse the error and return the response. - $response = $this->broker()->reset( - $this->credentials($request), function ($user, $password) { - $this->resetPassword($user, $password); - } - ); + $user = ClientContact::where($request->only(['email','token']))->first(); + + if(!$user) + return $this->sendResetFailedResponse($request, PASSWORD::INVALID_USER); + + $hashed_password = Hash::make($request->input('password')); + + ClientContact::where('email', $user->email)->update([ + 'password' => $hashed_password, + 'remember_token' => Str::random(60) + ]); + + event(new PasswordReset($user)); + + auth()->login($user, true); + + $response = Password::PASSWORD_RESET; // Added this because it collides the session between // client & main portal giving unlimited redirects. diff --git a/app/Http/Controllers/ClientPortal/CreditController.php b/app/Http/Controllers/ClientPortal/CreditController.php index 926af864202b..2d5cafaa012d 100644 --- a/app/Http/Controllers/ClientPortal/CreditController.php +++ b/app/Http/Controllers/ClientPortal/CreditController.php @@ -2,10 +2,13 @@ namespace App\Http\Controllers\ClientPortal; +use App\Events\Credit\CreditWasViewed; +use App\Events\Misc\InvitationWasViewed; use App\Http\Controllers\Controller; use App\Http\Requests\ClientPortal\Credits\ShowCreditRequest; use App\Http\Requests\ClientPortal\Credits\ShowCreditsRequest; use App\Models\Credit; +use App\Utils\Ninja; class CreditController extends Controller { @@ -20,6 +23,16 @@ class CreditController extends Controller $data = ['credit' => $credit]; + $invitation = $credit->invitations()->where('client_contact_id', auth()->user()->id)->first(); + + if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) { + + $invitation->markViewed(); + + event(new InvitationWasViewed($credit, $invitation, $credit->company, Ninja::eventVars())); + event(new CreditWasViewed($invitation, $invitation->company, Ninja::eventVars())); + + } if ($request->query('mode') === 'fullscreen') { return render('credits.show-fullscreen', $data); diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index 6094b85fc6cc..6d25eda2f12b 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -11,11 +11,14 @@ namespace App\Http\Controllers\ClientPortal; +use App\Events\Invoice\InvoiceWasViewed; +use App\Events\Misc\InvitationWasViewed; use App\Http\Controllers\Controller; -use App\Http\Requests\ClientPortal\Invoices\ShowInvoicesRequest; use App\Http\Requests\ClientPortal\Invoices\ProcessInvoicesInBulkRequest; use App\Http\Requests\ClientPortal\Invoices\ShowInvoiceRequest; +use App\Http\Requests\ClientPortal\Invoices\ShowInvoicesRequest; use App\Models\Invoice; +use App\Utils\Ninja; use App\Utils\Number; use App\Utils\TempFile; use App\Utils\Traits\MakesDates; @@ -23,10 +26,10 @@ use App\Utils\Traits\MakesHash; use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; +use Illuminate\Support\Facades\Storage; use Illuminate\View\View; use ZipStream\Option\Archive; use ZipStream\ZipStream; -use Illuminate\Support\Facades\Storage; class InvoiceController extends Controller { @@ -56,6 +59,18 @@ class InvoiceController extends Controller $invoice->service()->removeUnpaidGatewayFees()->save(); + + $invitation = $invoice->invitations()->where('client_contact_id', auth()->user()->id)->first(); + + if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) { + + $invitation->markViewed(); + + event(new InvitationWasViewed($invoice, $invitation, $invoice->company, Ninja::eventVars())); + event(new InvoiceWasViewed($invitation, $invitation->company, Ninja::eventVars())); + + } + $data = [ 'invoice' => $invoice, ]; diff --git a/app/Http/Controllers/ClientPortal/QuoteController.php b/app/Http/Controllers/ClientPortal/QuoteController.php index 7ee8affbc028..2e39adf518fc 100644 --- a/app/Http/Controllers/ClientPortal/QuoteController.php +++ b/app/Http/Controllers/ClientPortal/QuoteController.php @@ -12,22 +12,24 @@ namespace App\Http\Controllers\ClientPortal; +use App\Events\Misc\InvitationWasViewed; use App\Events\Quote\QuoteWasApproved; +use App\Events\Quote\QuoteWasViewed; use App\Http\Controllers\Controller; use App\Http\Requests\ClientPortal\Quotes\ProcessQuotesInBulkRequest; -use App\Http\Requests\ClientPortal\Quotes\ShowQuotesRequest; use App\Http\Requests\ClientPortal\Quotes\ShowQuoteRequest; +use App\Http\Requests\ClientPortal\Quotes\ShowQuotesRequest; use App\Jobs\Invoice\InjectSignature; use App\Models\Quote; use App\Utils\Ninja; use App\Utils\TempFile; use App\Utils\Traits\MakesHash; use Illuminate\Contracts\View\Factory; +use Illuminate\Support\Facades\Storage; use Illuminate\View\View; use Symfony\Component\HttpFoundation\BinaryFileResponse; use ZipStream\Option\Archive; use ZipStream\ZipStream; -use Illuminate\Support\Facades\Storage; class QuoteController extends Controller { @@ -56,6 +58,18 @@ class QuoteController extends Controller 'quote' => $quote, ]; + + $invitation = $quote->invitations()->where('client_contact_id', auth()->user()->id)->first(); + + if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) { + + $invitation->markViewed(); + + event(new InvitationWasViewed($quote, $invitation, $quote->company, Ninja::eventVars())); + event(new QuoteWasViewed($invitation, $invitation->company, Ninja::eventVars())); + + } + if ($request->query('mode') === 'fullscreen') { return render('quotes.show-fullscreen', $data); } diff --git a/app/Libraries/MultiDB.php b/app/Libraries/MultiDB.php index 07d0cd0f7868..00a988d78b7f 100644 --- a/app/Libraries/MultiDB.php +++ b/app/Libraries/MultiDB.php @@ -174,6 +174,32 @@ class MultiDB return null; } + /** + * @param array $data + * @return User|null + */ + public static function findContact(array $search) : ?ClientContact + { + if (! config('ninja.db.multi_db_enabled')) + return ClientContact::where($search)->first(); + + $current_db = config('database.default'); + + foreach (self::$dbs as $db) { + + $user = ClientContact::on($db)->where($search)->first(); + + if ($user) { + self::setDb($db); + return $user; + } + } + + self::setDB($current_db); + return null; + } + + public static function contactFindAndSetDb($token) :bool { $current_db = config('database.default'); diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php index 9b103ca28eb9..3b164f4a64b8 100644 --- a/app/PaymentDrivers/PaytracePaymentDriver.php +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -191,6 +191,9 @@ class PaytracePaymentDriver extends BaseDriver $auth_data = json_decode($response); + if(!property_exists($auth_data, 'access_token')) + throw new \Exception('Error authenticating with PayTrace'); + $headers = []; $headers[] = 'Content-type: application/json'; $headers[] = 'Authorization: Bearer '.$auth_data->access_token; diff --git a/resources/views/portal/ninja2020/auth/login.blade.php b/resources/views/portal/ninja2020/auth/login.blade.php index 4dbeae512db3..7adb0f1fa6c9 100644 --- a/resources/views/portal/ninja2020/auth/login.blade.php +++ b/resources/views/portal/ninja2020/auth/login.blade.php @@ -53,7 +53,7 @@ href="{{ route('client.password.request') }}">{{ trans('texts.forgot_password') }} @if(isset($company) && !is_null($company)) - + @endif @if($company && !is_null($company)) - + @endif @csrf - @if($db) - + @if($company) + @endif