mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
User registration and corresponding test
This commit is contained in:
+3
-2
@@ -15,12 +15,12 @@ return [
|
||||
*/
|
||||
|
||||
'features' => [
|
||||
Features::users(),
|
||||
Features::registration(),
|
||||
],
|
||||
|
||||
'models' => [
|
||||
|
||||
// 'model' => App\Models\Model::class,
|
||||
'user' => config('auth.providers.users.model'),
|
||||
|
||||
],
|
||||
|
||||
@@ -80,6 +80,7 @@ return [
|
||||
'login' => Filament\Http\Livewire\Auth\Login::class,
|
||||
'forgot-password' => Filament\Http\Livewire\Auth\ForgotPassword::class,
|
||||
'reset-password' => Filament\Http\Livewire\Auth\ResetPassword::class,
|
||||
'register' => Filament\Http\Livewire\Auth\Register::class,
|
||||
'dashboard' => Filament\Http\Livewire\Dashboard::class,
|
||||
],
|
||||
|
||||
|
||||
@@ -15,4 +15,6 @@ return [
|
||||
|
||||
'signin' => 'Sign in to your account',
|
||||
|
||||
'register' => 'Create a new account',
|
||||
|
||||
];
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<form wire:submit.prevent="login" class="space-y-4">
|
||||
<x-filament::input-group-stacked name="email" :label="__('E-Mail Address')" required>
|
||||
<x-filament::input type="email" name="email" wire:model.defer="email" id="email" required autocomplete="email" autofocus />
|
||||
@if (Route::has('filament.register'))
|
||||
<x-slot name="hint">
|
||||
<a href="{{ route('filament.register') }}" class="text-current hover:text-blue">
|
||||
{{ __('filament::auth.register') }}
|
||||
</a>
|
||||
</x-slot>
|
||||
@endif
|
||||
</x-filament::input-group-stacked>
|
||||
|
||||
<x-filament::input-group-stacked name="password" :label="__('Password')" required>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<form wire:submit.prevent="register" class="space-y-4">
|
||||
<x-filament::input-group-stacked name="name" :label="__('Name')" required>
|
||||
<x-filament::input name="name" wire:model.defer="name" id="name" required autofocus />
|
||||
<x-slot name="hint">
|
||||
<a href="{{ route('filament.login') }}" class="text-current hover:text-blue">
|
||||
← {{ __('Back to login') }}
|
||||
</a>
|
||||
</x-slot>
|
||||
</x-filament::input-group-stacked>
|
||||
|
||||
<x-filament::input-group-stacked name="email" :label="__('E-Mail Address')" required>
|
||||
<x-filament::input type="email" name="email" wire:model.lazy="email" id="email" required autocomplete="email" />
|
||||
</x-filament::input-group-stacked>
|
||||
|
||||
<x-filament::input-group-stacked name="password" :label="__('New Password')" required>
|
||||
<x-filament::input type="password" name="password" wire:model.defer="password" id="password" required autocomplete="new-password" />
|
||||
</x-filament::input-group-stacked>
|
||||
|
||||
<x-filament::input-group-stacked name="password_confirmation" :label="__('Confirm New Password')" required>
|
||||
<x-filament::input type="password" name="password_confirmation" wire:model.defer="password_confirmation" id="password_confirmation" required autocomplete="new-password" />
|
||||
</x-filament::input-group-stacked>
|
||||
|
||||
<x-filament::button type="submit" class="w-full" wire:loading.attr="disabled">
|
||||
<x-filament::loader class="w-6 h-6 absolute left-0 ml-2 pointer-events-none" wire:loading />
|
||||
{{ __('Register') }}
|
||||
</x-filament::button>
|
||||
</form>
|
||||
+5
-13
@@ -24,23 +24,15 @@ Route::group([
|
||||
Route::get('/forgot-password', config('filament.livewire.forgot-password'))->name('password.forgot');
|
||||
Route::get('/reset-password/{token}', config('filament.livewire.reset-password'))->name('password.reset');
|
||||
|
||||
// Registration
|
||||
if (Features::registersUsers()) {
|
||||
Route::get('/register', config('filament.livewire.register'))->name('register');
|
||||
}
|
||||
|
||||
// Authenticated routes
|
||||
Route::group(['middleware' => ['auth', 'verified']], function () {
|
||||
// Dashboard
|
||||
Route::get('/', config('filament.livewire.dashboard'))->name('dashboard');
|
||||
|
||||
/*
|
||||
// User profile
|
||||
Route::get('/profile', config('filament.livewire.profile'))->name('profile');
|
||||
|
||||
// Users
|
||||
if (Features::managesUsers()) {
|
||||
Route::name('users.')->group(function () {
|
||||
Route::get('/users', config('filament.livewire.users'))->name('index');
|
||||
Route::get('/user/{user}', config('filament.livewire.user'))->name('show');
|
||||
});
|
||||
}
|
||||
*/
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Contracts;
|
||||
|
||||
interface User
|
||||
{
|
||||
//
|
||||
}
|
||||
+6
-6
@@ -16,22 +16,22 @@ class Features
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the application manages users.
|
||||
* Determine if the application allows user registration.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function managesUsers()
|
||||
public static function registersUsers()
|
||||
{
|
||||
return static::enabled(static::users());
|
||||
return static::enabled(static::registration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the users feature.
|
||||
* Enable the user registration feature.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function users()
|
||||
public static function registration()
|
||||
{
|
||||
return 'users';
|
||||
return 'registration';
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use Illuminate\Support\Facades\{
|
||||
Blade,
|
||||
};
|
||||
use Livewire\Livewire;
|
||||
use Filament\Contracts\User as UserContract;
|
||||
use Filament\Commands\{
|
||||
MakeUser,
|
||||
};
|
||||
@@ -50,13 +51,13 @@ class FilamentServiceProvider extends ServiceProvider
|
||||
|
||||
protected function bootModelBindings(): void
|
||||
{
|
||||
$config = $this->app->config['filament.models'];
|
||||
$models = $this->app->config['filament.models'];
|
||||
|
||||
if (! $config) {
|
||||
if (! $models) {
|
||||
return;
|
||||
}
|
||||
|
||||
// $this->app->bind(ModelContract::class, $config['model']);
|
||||
$this->app->bind(UserContract::class, $models['user']);
|
||||
}
|
||||
|
||||
protected function bootPolicies(): void
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Http\Livewire\Auth;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
use Filament\Contracts\User as UserContract;
|
||||
|
||||
class Register extends Component
|
||||
{
|
||||
public $name;
|
||||
public $email;
|
||||
public $password;
|
||||
public $password_confirmation;
|
||||
|
||||
protected $rules = [
|
||||
'name' => 'required|min:2',
|
||||
'email' => 'required|email|unique:users',
|
||||
'password' => 'required|min:8|confirmed',
|
||||
'password_confirmation' => 'required|same:password',
|
||||
];
|
||||
|
||||
public function updatedEmail($value)
|
||||
{
|
||||
$this->validateOnly('email', ['email' => 'unique:users']);
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
$this->validate();
|
||||
$userClass = app(UserContract::class);
|
||||
$user = $userClass::create([
|
||||
'name' => $this->name,
|
||||
'email' => $this->email,
|
||||
'password' => Hash::make($this->password),
|
||||
]);
|
||||
Auth::login($user);
|
||||
return redirect()->route('filament.dashboard');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('filament::livewire.auth.register')
|
||||
->layout('filament::layouts.auth', ['title' => __('filament::auth.register')]);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ class ResetPassword extends Component
|
||||
protected $rules = [
|
||||
'email' => 'required|email',
|
||||
'password' => 'required|min:8|confirmed',
|
||||
'password_confirmation' => 'required',
|
||||
'password_confirmation' => 'required|same:password',
|
||||
];
|
||||
|
||||
public function mount(Request $request, $token)
|
||||
|
||||
@@ -14,10 +14,25 @@ class User extends Authenticatable
|
||||
use HasFactory, Notifiable, FilamentUser;
|
||||
|
||||
/**
|
||||
* Disable Laravel's mass assignment protection
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for arrays.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
namespace Filament\Tests\Feature;
|
||||
|
||||
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
@@ -9,8 +9,8 @@ use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Livewire\Livewire;
|
||||
use Filament\Tests\TestCase;
|
||||
use Filament\Http\Livewire\Auth\ForgotPassword;
|
||||
use Filament\Tests\Database\Models\User;
|
||||
use Filament\Http\Livewire\Auth\ForgotPassword;
|
||||
|
||||
class ForgotPasswordTest extends TestCase
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
namespace Filament\Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Livewire;
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Livewire;
|
||||
use Filament\Tests\TestCase;
|
||||
use Filament\Http\Livewire\Auth\Register;
|
||||
use Filament\Tests\Database\Models\User;
|
||||
|
||||
class RegisterTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_can_see_register_form()
|
||||
{
|
||||
$this->get(route('filament.register'))
|
||||
->assertSuccessful()
|
||||
->assertSee(__('filament::auth.register'));
|
||||
}
|
||||
|
||||
public function test_can_register()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->set('name', 'Me')
|
||||
->set('email', 'me@example.com')
|
||||
->set('password', 'password')
|
||||
->set('password_confirmation', 'password')
|
||||
->call('register')
|
||||
->assertHasNoErrors(['name', 'email', 'password', 'password_confirmation'])
|
||||
->assertRedirect(route('filament.dashboard'));
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'name' => 'Me',
|
||||
'email' => 'me@example.com',
|
||||
]);
|
||||
|
||||
$this->assertAuthenticated();
|
||||
}
|
||||
|
||||
public function test_name_is_required()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->call('register')
|
||||
->assertHasErrors(['name' => 'required']);
|
||||
}
|
||||
|
||||
public function test_name_is_minimum_two_characters()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->set('name', 'a')
|
||||
->call('register')
|
||||
->assertHasErrors(['name' => 'min']);
|
||||
}
|
||||
|
||||
public function test_email_is_required()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->call('register')
|
||||
->assertHasErrors(['email' => 'required']);
|
||||
}
|
||||
|
||||
public function test_email_is_valid_email()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->set('email', 'Something')
|
||||
->call('register')
|
||||
->assertHasErrors(['email' => 'email']);
|
||||
}
|
||||
|
||||
public function test_email_is_unique()
|
||||
{
|
||||
User::factory()->create(['email' => 'test@example.com']);
|
||||
|
||||
Livewire::test(Register::class)
|
||||
->set('email', 'test@example.com')
|
||||
->assertHasErrors(['email' => 'unique']);
|
||||
}
|
||||
|
||||
public function test_password_is_required()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->call('register')
|
||||
->assertHasErrors(['password' => 'required']);
|
||||
}
|
||||
|
||||
public function test_password_is_minimum_eight_characters()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->set('password', 'test')
|
||||
->call('register')
|
||||
->assertHasErrors(['password' => 'min']);
|
||||
}
|
||||
|
||||
public function test_password_must_be_confirmed()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->set('password', 'test')
|
||||
->call('register')
|
||||
->assertHasErrors(['password' => 'confirmed']);
|
||||
}
|
||||
|
||||
public function test_password_confirmation_is_required()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->call('register')
|
||||
->assertHasErrors(['password_confirmation' => 'required']);
|
||||
}
|
||||
|
||||
public function test_password_confirmation_matches_password()
|
||||
{
|
||||
Livewire::test(Register::class)
|
||||
->set('password', 'test')
|
||||
->set('password_confirmation', 'test2')
|
||||
->call('register')
|
||||
->assertHasErrors(['password_confirmation' => 'same']);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
namespace Filament\Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Livewire\Livewire;
|
||||
use Filament\Tests\TestCase;
|
||||
use Filament\Tests\Database\Models\User;
|
||||
use Filament\Http\Livewire\Auth\Login;
|
||||
use Filament\Http\Livewire\Auth\ResetPassword;
|
||||
use Filament\Tests\Database\Models\User;
|
||||
|
||||
class ResetPasswordTest extends TestCase
|
||||
{
|
||||
|
||||
@@ -78,5 +78,6 @@ abstract class TestCase extends OrchestraTestCase
|
||||
]);
|
||||
|
||||
$app['config']->set('auth.providers.users.model', User::class);
|
||||
$app['config']->set('filament.models.user', User::class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user