Feat: Moving things, updating OTP, cleaning stuff up
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Auth\Events;
|
||||
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
|
||||
class UserCreated
|
||||
{
|
||||
public function __construct(
|
||||
public readonly Authenticatable $user,
|
||||
) {}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
||||
class CustomerOtpMail extends Mailable
|
||||
class UserOtpMail extends Mailable
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $name,
|
||||
@@ -20,6 +20,6 @@ class CustomerOtpMail extends Mailable
|
||||
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(view: 'core::auth.mail.customer-otp');
|
||||
return new Content(view: 'core::auth.mail.user-otp');
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Auth\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Lunar\Models\Contracts\Customer;
|
||||
use Lunar\Facades\ModelManifest;
|
||||
use Modules\Core\Auth\Mail\CustomerOtpMail;
|
||||
|
||||
class CustomerOtpService
|
||||
{
|
||||
private const EXPIRY_MINUTES = 10;
|
||||
private const CODE_LENGTH = 6;
|
||||
|
||||
public function generateAndSend(string $email): bool
|
||||
{
|
||||
$customer = $this->findByEmail($email);
|
||||
|
||||
if (! $customer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code = str_pad((string) random_int(0, 999999), self::CODE_LENGTH, '0', STR_PAD_LEFT);
|
||||
|
||||
$customer->otp_code = $code;
|
||||
$customer->otp_expires_at = now()->addMinutes(self::EXPIRY_MINUTES);
|
||||
$customer->save();
|
||||
|
||||
Mail::to($email)->send(new CustomerOtpMail($customer->full_name, $code));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate(string $email, string $code): ?Customer
|
||||
{
|
||||
$customer = $this->findByEmail($email);
|
||||
|
||||
if (! $customer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $customer->otp_expires_at || $customer->otp_code != $code || now()->isAfter($customer->otp_expires_at)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$customer->otp_code = null;
|
||||
$customer->otp_expires_at = null;
|
||||
$customer->save();
|
||||
|
||||
return $customer;
|
||||
}
|
||||
|
||||
private function findByEmail(string $email): ?Customer
|
||||
{
|
||||
$model = ModelManifest::get(Customer::class);
|
||||
|
||||
return $model::query()
|
||||
->whereHas('emails', fn ($query) => $query->where('email', $email))
|
||||
->first();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Auth\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Modules\Core\Auth\Mail\UserOtpMail;
|
||||
|
||||
class UserOtpService
|
||||
{
|
||||
private const EXPIRY_MINUTES = 10;
|
||||
private const CODE_LENGTH = 6;
|
||||
|
||||
public function generateAndSend(string $email): bool
|
||||
{
|
||||
$model = config('auth.providers.users.model');
|
||||
$user = $model::firstOrCreate(['email' => $email]);
|
||||
|
||||
$code = str_pad((string) random_int(0, 999999), self::CODE_LENGTH, '0', STR_PAD_LEFT);
|
||||
|
||||
$user->otp_code = $code;
|
||||
$user->otp_expires_at = now()->addMinutes(self::EXPIRY_MINUTES);
|
||||
$user->save();
|
||||
|
||||
Mail::to($user->email)->send(new UserOtpMail($user->name ?? $user->email, $code));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate(string $email, string $code)
|
||||
{
|
||||
$model = config('auth.providers.users.model');
|
||||
$user = $model::where('email', $email)->first();
|
||||
|
||||
if (! $user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $user->otp_expires_at || $user->otp_code != $code || now()->isAfter($user->otp_expires_at)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$user->otp_code = null;
|
||||
$user->otp_expires_at = null;
|
||||
$user->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,21 @@
|
||||
namespace Modules\Core\Customer\Extensions;
|
||||
|
||||
use Lunar\Admin\Filament\Resources\CustomerResource\RelationManagers\AddressRelationManager as BaseAddressRelationManager;
|
||||
use Lunar\Admin\Filament\Resources\CustomerResource\RelationManagers\UserRelationManager as BaseUserRelationManager;
|
||||
use Lunar\Admin\Support\Extending\BaseExtension;
|
||||
use Modules\Core\Customer\RelationManagers\AddressRelationManager;
|
||||
use Modules\Core\Customer\RelationManagers\UserRelationManager;
|
||||
|
||||
class CustomerResourceExtension extends BaseExtension
|
||||
{
|
||||
public function getRelations(array $relations): array
|
||||
{
|
||||
return array_map(
|
||||
fn ($relation) => $relation == BaseAddressRelationManager::class
|
||||
? AddressRelationManager::class
|
||||
: $relation,
|
||||
fn ($relation) => match ($relation) {
|
||||
BaseAddressRelationManager::class => AddressRelationManager::class,
|
||||
BaseUserRelationManager::class => UserRelationManager::class,
|
||||
default => $relation,
|
||||
},
|
||||
$relations
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Customer\Listeners;
|
||||
|
||||
use Lunar\Facades\ModelManifest;
|
||||
use Lunar\Models\Contracts\Customer as CustomerContract;
|
||||
use Modules\Core\Auth\Events\UserCreated;
|
||||
|
||||
class CreateCustomerForUser
|
||||
{
|
||||
public function handle(UserCreated $event): void
|
||||
{
|
||||
if (! config('core.auto_create_customer_for_user')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$model = ModelManifest::get(CustomerContract::class);
|
||||
|
||||
$customer = $model::create([]);
|
||||
|
||||
$customer->users()->attach($event->user);
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,8 @@
|
||||
|
||||
namespace Modules\Core\Customer\Models;
|
||||
|
||||
use Illuminate\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
||||
use Illuminate\Foundation\Auth\Access\Authorizable;
|
||||
|
||||
class Customer extends \Lunar\Models\Customer implements AuthenticatableContract
|
||||
class Customer extends \Lunar\Models\Customer
|
||||
{
|
||||
use Authenticatable;
|
||||
use Authorizable;
|
||||
|
||||
protected $casts = [
|
||||
'otp_expires_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function getTitleAttribute(): ?string
|
||||
{
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Customer\RelationManagers;
|
||||
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Lunar\Admin\Events\CustomerUserEdited;
|
||||
use Lunar\Admin\Filament\Resources\CustomerResource\RelationManagers\UserRelationManager as BaseUserRelationManager;
|
||||
|
||||
class UserRelationManager extends BaseUserRelationManager
|
||||
{
|
||||
public function getDefaultTable(Table $table): Table
|
||||
{
|
||||
return $table->columns([
|
||||
Tables\Columns\TextColumn::make('name')
|
||||
->label(__('lunarpanel::user.table.name.label')),
|
||||
Tables\Columns\TextColumn::make('email')
|
||||
->label(__('lunarpanel::user.table.email.label')),
|
||||
])->actions([
|
||||
Tables\Actions\EditAction::make('edit')
|
||||
->after(
|
||||
fn (Model $record) => CustomerUserEdited::dispatch($record)
|
||||
)
|
||||
->form([
|
||||
TextInput::make('email')
|
||||
->label(__('lunarpanel::user.form.email.label'))
|
||||
->required()
|
||||
->email(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -2,44 +2,13 @@
|
||||
|
||||
namespace Modules\Core\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Lunar\Admin\Filament\Resources\StaffResource;
|
||||
use Lunar\Admin\Models\Staff as LunarStaff;
|
||||
use Lunar\Admin\Support\Facades\LunarPanel;
|
||||
use Lunar\Models\Customer as LunarCustomer;
|
||||
use Modules\Core\Auth\Extensions\StaffResourceExtension;
|
||||
use Modules\Core\Auth\Mail\InviteMail;
|
||||
use Modules\Core\Command\CreateAdminCommand;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot(): void
|
||||
{
|
||||
LunarPanel::extensions([
|
||||
StaffResource::class => StaffResourceExtension::class,
|
||||
]);
|
||||
|
||||
LunarStaff::addActivitylogExcept([
|
||||
'otp_code',
|
||||
'otp_expires_at',
|
||||
'password',
|
||||
'remember_token',
|
||||
'email_verified_at',
|
||||
'two_factor_secret',
|
||||
'two_factor_recovery_codes',
|
||||
'two_factor_confirmed_at',
|
||||
]);
|
||||
|
||||
LunarCustomer::addActivitylogExcept([
|
||||
'otp_code',
|
||||
'otp_expires_at',
|
||||
]);
|
||||
|
||||
LunarStaff::created(function (LunarStaff $staff) {
|
||||
Mail::to($staff->email)->send(new InviteMail($staff->first_name));
|
||||
});
|
||||
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->app->booted(fn () => $this->commands([CreateAdminCommand::class]));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Modules\Core\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Modules\Core\Command\AnonymizeCommand;
|
||||
use Modules\Core\Command\ExportCleanupCommand;
|
||||
@@ -10,13 +11,21 @@ use Modules\Core\Command\ImportCommand;
|
||||
|
||||
class CoreServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void {}
|
||||
public function register(): void
|
||||
{
|
||||
$this->mergeConfigFrom(__DIR__ . '/../../config/core.php', 'core');
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadViewsFrom(__DIR__ . '/../../resources/views', 'core');
|
||||
Blade::anonymousComponentPath(__DIR__ . '/../../resources/views', 'core');
|
||||
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../../config/core.php' => config_path('core.php'),
|
||||
], 'core-config');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../../resources/logos' => public_path('static/logos/core'),
|
||||
__DIR__ . '/../../resources/js/stoic_embed.js' => public_path('js/stoic_embed.js'),
|
||||
|
||||
@@ -2,22 +2,20 @@
|
||||
|
||||
namespace Modules\Core\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Lunar\Admin\Filament\Resources\CustomerResource;
|
||||
use Lunar\Admin\Support\Facades\LunarPanel;
|
||||
use Lunar\Facades\ModelManifest;
|
||||
use Lunar\Models\Contracts\Customer as LunarCustomer;
|
||||
use Modules\Core\Customer\Extensions\CustomerResourceExtension;
|
||||
use Modules\Core\Auth\Events\UserCreated;
|
||||
use Modules\Core\Customer\Listeners\CreateCustomerForUser;
|
||||
use Modules\Core\Customer\Models\Customer;
|
||||
|
||||
class CustomerServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot(): void
|
||||
{
|
||||
LunarPanel::extensions([
|
||||
CustomerResource::class => CustomerResourceExtension::class,
|
||||
]);
|
||||
|
||||
ModelManifest::replace(LunarCustomer::class, Customer::class);
|
||||
|
||||
Event::listen(UserCreated::class, CreateCustomerForUser::class);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user