mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 23:27:31 -05:00 
			
		
		
		
	passwordless login
This commit is contained in:
		
							parent
							
								
									b8696bb6d3
								
							
						
					
					
						commit
						c300ffc4d9
					
				@ -12,6 +12,9 @@
 | 
				
			|||||||
namespace App\Http\Livewire;
 | 
					namespace App\Http\Livewire;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Factory\ClientFactory;
 | 
					use App\Factory\ClientFactory;
 | 
				
			||||||
 | 
					use App\Jobs\Mail\NinjaMailerJob;
 | 
				
			||||||
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
 | 
					use App\Mail\ContactPasswordlessLogin;
 | 
				
			||||||
use App\Models\Subscription;
 | 
					use App\Models\Subscription;
 | 
				
			||||||
use App\Models\ClientContact;
 | 
					use App\Models\ClientContact;
 | 
				
			||||||
use App\Models\Invoice;
 | 
					use App\Models\Invoice;
 | 
				
			||||||
@ -102,6 +105,7 @@ class BillingPortalPurchase extends Component
 | 
				
			|||||||
        'fetched_payment_methods' => false,
 | 
					        'fetched_payment_methods' => false,
 | 
				
			||||||
        'fetched_client' => false,
 | 
					        'fetched_client' => false,
 | 
				
			||||||
        'show_start_trial' => false,
 | 
					        'show_start_trial' => false,
 | 
				
			||||||
 | 
					        'passwordless_login_sent' => false,
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -144,6 +148,13 @@ class BillingPortalPurchase extends Component
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public $price;
 | 
					    public $price;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Disabled state of passwordless login button.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @var bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public $passwordless_login_btn = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function mount()
 | 
					    public function mount()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->price = $this->subscription->service()->price();
 | 
					        $this->price = $this->subscription->service()->price();
 | 
				
			||||||
@ -290,11 +301,11 @@ class BillingPortalPurchase extends Component
 | 
				
			|||||||
            ->save();
 | 
					            ->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Cache::put($this->hash, [
 | 
					        Cache::put($this->hash, [
 | 
				
			||||||
            'subscription_id' => $this->subscription->id,
 | 
					                'subscription_id' => $this->subscription->id,
 | 
				
			||||||
            'email' => $this->email ?? $this->contact->email,
 | 
					                'email' => $this->email ?? $this->contact->email,
 | 
				
			||||||
            'client_id' => $this->contact->client->id,
 | 
					                'client_id' => $this->contact->client->id,
 | 
				
			||||||
            'invoice_id' => $this->invoice->id,
 | 
					                'invoice_id' => $this->invoice->id,
 | 
				
			||||||
            now()->addMinutes(60)]
 | 
					                now()->addMinutes(60)]
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->emit('beforePaymentEventsCompleted');
 | 
					        $this->emit('beforePaymentEventsCompleted');
 | 
				
			||||||
@ -348,6 +359,26 @@ class BillingPortalPurchase extends Component
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function passwordlessLogin()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->passwordless_login_btn = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $contact = ClientContact::query()
 | 
				
			||||||
 | 
					            ->where('email', $this->email)
 | 
				
			||||||
 | 
					            ->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $mailer = new NinjaMailerObject();
 | 
				
			||||||
 | 
					        $mailer->mailable = new ContactPasswordlessLogin($this->email, (string)route('client.subscription.purchase', $this->subscription->hashed_id));
 | 
				
			||||||
 | 
					        $mailer->company = $this->subscription->company;
 | 
				
			||||||
 | 
					        $mailer->settings = $this->subscription->company->settings;
 | 
				
			||||||
 | 
					        $mailer->to_user = $contact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        NinjaMailerJob::dispatchNow($mailer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->steps['passwordless_login_sent'] = true;
 | 
				
			||||||
 | 
					        $this->passwordless_login_btn = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function render()
 | 
					    public function render()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->contact instanceof ClientContact) {
 | 
					        if ($this->contact instanceof ClientContact) {
 | 
				
			||||||
 | 
				
			|||||||
@ -74,6 +74,11 @@ nlog($request->all());
 | 
				
			|||||||
nlog("double merp");
 | 
					nlog("double merp");
 | 
				
			||||||
            if($client_contact = ClientContact::where('email', $contact_email)->first()){
 | 
					            if($client_contact = ClientContact::where('email', $contact_email)->first()){
 | 
				
			||||||
                Auth::guard('contact')->login($client_contact, true);
 | 
					                Auth::guard('contact')->login($client_contact, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ($request->query('redirect') && !empty($request->query('redirect'))) {
 | 
				
			||||||
 | 
					                    return redirect()->to($request->query('redirect'));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return redirect()->to('client/dashboard');
 | 
					                return redirect()->to('client/dashboard');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										54
									
								
								app/Mail/ContactPasswordlessLogin.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								app/Mail/ContactPasswordlessLogin.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Mail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Utils\ClientPortal\MagicLink;
 | 
				
			||||||
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
 | 
					use Illuminate\Mail\Mailable;
 | 
				
			||||||
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ContactPasswordlessLogin extends Mailable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use Queueable, SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public $email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $url = 'https://google.com';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a new message instance.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param string $email
 | 
				
			||||||
 | 
					     * @param string $redirect
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function __construct(string $email, string $redirect = '')
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->email = $email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->url = MagicLink::create($email, $redirect);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Build the message.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return $this
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function build()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->view('email.billing.passwordless-login');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -18,13 +18,13 @@ class MagicLink
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //return a magic login link URL
 | 
					    //return a magic login link URL
 | 
				
			||||||
    public static function create($email) :string
 | 
					    public static function create($email, $url = null) :string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $magic_key = Str::random(64);
 | 
					        $magic_key = Str::random(64);
 | 
				
			||||||
        $timeout = 600; //seconds
 | 
					        $timeout = 600; //seconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Cache::add($magic_key, $email, $timeout);
 | 
					        Cache::add($magic_key, $email, $timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return route('client.contact_magic_link', ['magic_link' => $magic_key]);
 | 
					        return route('client.contact_magic_link', ['magic_link' => $magic_key, 'redirect' => $url]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								resources/views/email/billing/passwordless-login.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								resources/views/email/billing/passwordless-login.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					@component('email.template.master', ['design' => 'light'])
 | 
				
			||||||
 | 
					    @slot('header')
 | 
				
			||||||
 | 
					        @include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
 | 
				
			||||||
 | 
					    @endslot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h2>Passwordless login link requested</h2>
 | 
				
			||||||
 | 
					    <p>Hey, there was a request to log in using passwordless link.</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <a href="{{ $url }}" target="_blank" class="button">Sign in to Invoice Ninja</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <span style="margin-top: 35px; display: block;">Link above is only for you. Don't share it anyone.</span>
 | 
				
			||||||
 | 
					    <span>If you didn't request this, just ignore it.</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <span style="margin-top: 25px; display: block;">If you can't click on the button, copy following link:</span>
 | 
				
			||||||
 | 
					    <a href="{{ $url }}">{{ $url }}</a>
 | 
				
			||||||
 | 
					@endcomponent
 | 
				
			||||||
@ -166,6 +166,14 @@
 | 
				
			|||||||
                                </p>
 | 
					                                </p>
 | 
				
			||||||
                                @enderror
 | 
					                                @enderror
 | 
				
			||||||
                            </label>
 | 
					                            </label>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            <button wire:loading.attr="disabled" type="button" wire:click="passwordlessLogin" class="mt-4 text-sm active:outline-none focus:outline-none">
 | 
				
			||||||
 | 
					                                Log in without password
 | 
				
			||||||
 | 
					                            </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            @if($steps['passwordless_login_sent'])
 | 
				
			||||||
 | 
					                                <span class="block mt-2 text-sm text-green-600">E-mail sent. Please check your inbox!</span>
 | 
				
			||||||
 | 
					                            @endif
 | 
				
			||||||
                        @endif
 | 
					                        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <button type="submit"
 | 
					                        <button type="submit"
 | 
				
			||||||
@ -184,7 +192,7 @@
 | 
				
			|||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <form  wire:submit.prevent="handleCoupon" class="flex items-center mt-4">
 | 
					                    <form wire:submit.prevent="handleCoupon" class="flex items-center mt-4">
 | 
				
			||||||
                        @csrf
 | 
					                        @csrf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <label class="w-full mr-2">
 | 
					                        <label class="w-full mr-2">
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user