diff --git a/app/Livewire/BillingPortal/Authentication/Register.php b/app/Livewire/BillingPortal/Authentication/Register.php new file mode 100644 index 000000000000..65fb21f598df --- /dev/null +++ b/app/Livewire/BillingPortal/Authentication/Register.php @@ -0,0 +1,152 @@ + true, // Use as preference. E-mail/password or OTP. + 'login_form' => false, + 'otp_form' => false, + 'initial_completed' => false, + ]; + + public function initial() + { + $this->validateOnly('email', ['email' => 'required|bail|email:rfc']); + + $contact = ClientContact::where('email', $this->email) + ->where('company_id', $this->subscription->company_id) + ->first(); + + if ($contact) { + $this->addError('email', ctrans('texts.email_already_exists')); + + return; + } + + $this->state['initial_completed'] = true; + + return $this->withOtp(); + } + + public function withOtp() + { + $code = rand(100000, 999999); + $email_hash = "subscriptions:otp:{$this->email}"; + + Cache::put($email_hash, $code, 600); + + $cc = new ClientContact(); + $cc->email = $this->email; + + $nmo = new NinjaMailerObject(); + $nmo->mailable = new OtpCode($this->subscription->company, $this->context['contact'] ?? null, $code); + $nmo->company = $this->subscription->company; + $nmo->settings = $this->subscription->company->settings; + $nmo->to_user = $cc; + + NinjaMailerJob::dispatch($nmo); + + if (app()->environment('local')) { + session()->flash('message', "[dev]: Your OTP is: {$code}"); + } + + $this->state['otp_form'] = true; + } + + public function handleOtp() + { + $this->validate([ + 'otp' => 'required|numeric|digits:6', + ]); + + $code = Cache::get("subscriptions:otp:{$this->email}"); + + if ($this->otp != $code) { //loose comparison prevents edge cases + $errors = $this->getErrorBag(); + $errors->add('otp', ctrans('texts.invalid_code')); + + return; + } + + $contact = $this->createClientContact(); + + auth()->guard('contact')->loginUsingId($contact->id, true); + + $this->dispatch('purchase.context', property: 'contact', value: $contact); + $this->dispatch('purchase.next'); + + return; + } + + private function createClientContact() + { + $company = $this->subscription->company; + $user = $this->subscription->user; + $user->setCompany($company); + + $client_repo = new ClientRepository(new ClientContactRepository()); + $data = [ + 'name' => '', + 'group_settings_id' => $this->subscription->group_id, + 'contacts' => [ + ['email' => $this->email], + ], + 'client_hash' => Str::random(40), + 'settings' => ClientSettings::defaults(), + ]; + + $client = $client_repo->save($data, ClientFactory::create($company->id, $user->id)); + + $contact = $client->fresh()->contacts()->first(); + + return $contact; + } + + public function mount() + { + if (auth()->guard('contact')->check()) { + $this->dispatch('purchase.context', property: 'contact', value: auth()->guard('contact')->user()); + $this->dispatch('purchase.next'); + } + } + + public function render() + { + return view('billing-portal.v3.authentication.register'); + } +} diff --git a/resources/views/billing-portal/v3/authentication/register.blade.php b/resources/views/billing-portal/v3/authentication/register.blade.php new file mode 100644 index 000000000000..714fe83f63f3 --- /dev/null +++ b/resources/views/billing-portal/v3/authentication/register.blade.php @@ -0,0 +1,57 @@ +
+ @if (session()->has('message')) + @component('portal.ninja2020.components.message') + {{ session('message') }} + @endcomponent + @endif + +
+

{{ ctrans('texts.contact') }}

+
+ + @if($state['initial_completed'] === false) +
+ @csrf + + + + +
+ @endif + + @if($state['otp_form']) +
+ @csrf + +
+ {{ ctrans('texts.code') }} + + + @error('otp') + + @enderror +
+ + +
+ @endif +