added form login, user for frontend and backend
This commit is contained in:
parent
a5ef904c1e
commit
5488a80b91
11
app/Filament/Resources/Users/Pages/CreateUser.php
Normal file
11
app/Filament/Resources/Users/Pages/CreateUser.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\Users\Pages;
|
||||||
|
|
||||||
|
use App\Filament\Resources\Users\UserResource;
|
||||||
|
use Filament\Resources\Pages\CreateRecord;
|
||||||
|
|
||||||
|
class CreateUser extends CreateRecord
|
||||||
|
{
|
||||||
|
protected static string $resource = UserResource::class;
|
||||||
|
}
|
||||||
19
app/Filament/Resources/Users/Pages/EditUser.php
Normal file
19
app/Filament/Resources/Users/Pages/EditUser.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\Users\Pages;
|
||||||
|
|
||||||
|
use App\Filament\Resources\Users\UserResource;
|
||||||
|
use Filament\Actions\DeleteAction;
|
||||||
|
use Filament\Resources\Pages\EditRecord;
|
||||||
|
|
||||||
|
class EditUser extends EditRecord
|
||||||
|
{
|
||||||
|
protected static string $resource = UserResource::class;
|
||||||
|
|
||||||
|
protected function getHeaderActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
DeleteAction::make(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Filament/Resources/Users/Pages/ListUsers.php
Normal file
19
app/Filament/Resources/Users/Pages/ListUsers.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\Users\Pages;
|
||||||
|
|
||||||
|
use App\Filament\Resources\Users\UserResource;
|
||||||
|
use Filament\Actions\CreateAction;
|
||||||
|
use Filament\Resources\Pages\ListRecords;
|
||||||
|
|
||||||
|
class ListUsers extends ListRecords
|
||||||
|
{
|
||||||
|
protected static string $resource = UserResource::class;
|
||||||
|
|
||||||
|
protected function getHeaderActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
CreateAction::make(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
35
app/Filament/Resources/Users/Schemas/UserForm.php
Normal file
35
app/Filament/Resources/Users/Schemas/UserForm.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\Users\Schemas;
|
||||||
|
|
||||||
|
use Filament\Forms\Components\Checkbox;
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Schemas\Schema;
|
||||||
|
|
||||||
|
class UserForm
|
||||||
|
{
|
||||||
|
public static function configure(Schema $schema): Schema
|
||||||
|
{
|
||||||
|
return $schema
|
||||||
|
->components([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('Name')
|
||||||
|
->required(),
|
||||||
|
TextInput::make('email')
|
||||||
|
->label('E-Mail')
|
||||||
|
->email()
|
||||||
|
->required()
|
||||||
|
->unique(ignoreRecord: true),
|
||||||
|
TextInput::make('password')
|
||||||
|
->label('Passwort')
|
||||||
|
->password()
|
||||||
|
->revealable()
|
||||||
|
->required(fn (string $operation) => $operation === 'create')
|
||||||
|
->dehydrateStateUsing(fn ($state) => filled($state) ? bcrypt($state) : null)
|
||||||
|
->dehydrated(fn ($state) => filled($state))
|
||||||
|
->minLength(8),
|
||||||
|
Checkbox::make('is_admin')
|
||||||
|
->label('Administrator'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
app/Filament/Resources/Users/Tables/UsersTable.php
Normal file
44
app/Filament/Resources/Users/Tables/UsersTable.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\Users\Tables;
|
||||||
|
|
||||||
|
use Filament\Actions\BulkActionGroup;
|
||||||
|
use Filament\Actions\DeleteBulkAction;
|
||||||
|
use Filament\Actions\EditAction;
|
||||||
|
use Filament\Tables\Columns\IconColumn;
|
||||||
|
use Filament\Tables\Columns\TextColumn;
|
||||||
|
use Filament\Tables\Table;
|
||||||
|
|
||||||
|
class UsersTable
|
||||||
|
{
|
||||||
|
public static function configure(Table $table): Table
|
||||||
|
{
|
||||||
|
return $table
|
||||||
|
->columns([
|
||||||
|
TextColumn::make('name')
|
||||||
|
->label('Name')
|
||||||
|
->searchable()
|
||||||
|
->sortable(),
|
||||||
|
TextColumn::make('email')
|
||||||
|
->label('E-Mail')
|
||||||
|
->searchable()
|
||||||
|
->sortable(),
|
||||||
|
IconColumn::make('is_admin')
|
||||||
|
->label('Administrator'),
|
||||||
|
TextColumn::make('created_at')
|
||||||
|
->label('Erstellt')
|
||||||
|
->dateTime()
|
||||||
|
->sortable()
|
||||||
|
->toggleable(isToggledHiddenByDefault: true),
|
||||||
|
])
|
||||||
|
->filters([])
|
||||||
|
->recordActions([
|
||||||
|
EditAction::make(),
|
||||||
|
])
|
||||||
|
->toolbarActions([
|
||||||
|
BulkActionGroup::make([
|
||||||
|
DeleteBulkAction::make(),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
app/Filament/Resources/Users/UserResource.php
Normal file
54
app/Filament/Resources/Users/UserResource.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\Users;
|
||||||
|
|
||||||
|
use App\Filament\Resources\Users\Pages\CreateUser;
|
||||||
|
use App\Filament\Resources\Users\Pages\EditUser;
|
||||||
|
use App\Filament\Resources\Users\Pages\ListUsers;
|
||||||
|
use App\Filament\Resources\Users\Schemas\UserForm;
|
||||||
|
use App\Filament\Resources\Users\Tables\UsersTable;
|
||||||
|
use App\Models\User;
|
||||||
|
use BackedEnum;
|
||||||
|
use Filament\Resources\Resource;
|
||||||
|
use Filament\Schemas\Schema;
|
||||||
|
use Filament\Support\Icons\Heroicon;
|
||||||
|
use Filament\Tables\Table;
|
||||||
|
|
||||||
|
class UserResource extends Resource
|
||||||
|
{
|
||||||
|
protected static ?string $model = User::class;
|
||||||
|
|
||||||
|
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedUsers;
|
||||||
|
|
||||||
|
protected static ?string $recordTitleAttribute = 'name';
|
||||||
|
|
||||||
|
protected static ?string $navigationLabel = 'Benutzer';
|
||||||
|
|
||||||
|
protected static ?string $modelLabel = 'Benutzer';
|
||||||
|
|
||||||
|
protected static ?string $pluralModelLabel = 'Benutzer';
|
||||||
|
|
||||||
|
public static function form(Schema $schema): Schema
|
||||||
|
{
|
||||||
|
return UserForm::configure($schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function table(Table $table): Table
|
||||||
|
{
|
||||||
|
return UsersTable::configure($table);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getRelations(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getPages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'index' => ListUsers::route('/'),
|
||||||
|
'create' => CreateUser::route('/create'),
|
||||||
|
'edit' => EditUser::route('/{record}/edit'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
37
app/Http/Controllers/LoginController.php
Normal file
37
app/Http/Controllers/LoginController.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class LoginController extends Controller
|
||||||
|
{
|
||||||
|
public function show()
|
||||||
|
{
|
||||||
|
return view('auth.login');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
$credentials = $request->validate([
|
||||||
|
'email' => ['required', 'email'],
|
||||||
|
'password' => ['required'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (Auth::attempt($credentials, $request->boolean('remember'))) {
|
||||||
|
$request->session()->regenerate();
|
||||||
|
return redirect()->intended('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->withErrors(['email' => 'Die eingegebenen Daten stimmen nicht überein.'])->onlyInput('email');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout(Request $request)
|
||||||
|
{
|
||||||
|
Auth::logout();
|
||||||
|
$request->session()->invalidate();
|
||||||
|
$request->session()->regenerateToken();
|
||||||
|
return redirect('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,31 +2,33 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
|
||||||
use Database\Factories\UserFactory;
|
use Database\Factories\UserFactory;
|
||||||
|
use Filament\Models\Contracts\FilamentUser;
|
||||||
|
use Filament\Panel;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Hidden;
|
use Illuminate\Database\Eloquent\Attributes\Hidden;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
|
||||||
#[Fillable(['name', 'email', 'password'])]
|
#[Fillable(['name', 'email', 'password', 'is_admin'])]
|
||||||
#[Hidden(['password', 'remember_token'])]
|
#[Hidden(['password', 'remember_token'])]
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable implements FilamentUser
|
||||||
{
|
{
|
||||||
/** @use HasFactory<UserFactory> */
|
/** @use HasFactory<UserFactory> */
|
||||||
use HasFactory, Notifiable;
|
use HasFactory, Notifiable;
|
||||||
|
|
||||||
/**
|
public function canAccessPanel(Panel $panel): bool
|
||||||
* Get the attributes that should be cast.
|
{
|
||||||
*
|
return $this->is_admin;
|
||||||
* @return array<string, string>
|
}
|
||||||
*/
|
|
||||||
protected function casts(): array
|
protected function casts(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
'password' => 'hashed',
|
'password' => 'hashed',
|
||||||
|
'is_admin' => 'boolean',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,11 +25,12 @@ class UserFactory extends Factory
|
|||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => fake()->name(),
|
'name' => fake()->name(),
|
||||||
'email' => fake()->unique()->safeEmail(),
|
'email' => fake()->unique()->safeEmail(),
|
||||||
'email_verified_at' => now(),
|
'email_verified_at' => now(),
|
||||||
'password' => static::$password ??= Hash::make('password'),
|
'password' => static::$password ??= Hash::make('password'),
|
||||||
'remember_token' => Str::random(10),
|
'remember_token' => Str::random(10),
|
||||||
|
'is_admin' => false,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_admin')->default(false)->after('remember_token');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('is_admin');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -12,6 +12,7 @@ class DatabaseSeeder extends Seeder
|
|||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$this->call([
|
$this->call([
|
||||||
|
UserSeeder::class,
|
||||||
PhotoprofileSeeder::class,
|
PhotoprofileSeeder::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
31
database/seeders/UserSeeder.php
Normal file
31
database/seeders/UserSeeder.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class UserSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
User::firstOrCreate(
|
||||||
|
['email' => 'admin@fotobox.local'],
|
||||||
|
[
|
||||||
|
'name' => 'Admin',
|
||||||
|
'password' => Hash::make('admin'),
|
||||||
|
'is_admin' => true,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
User::firstOrCreate(
|
||||||
|
['email' => 'user@fotobox.local'],
|
||||||
|
[
|
||||||
|
'name' => 'User',
|
||||||
|
'password' => Hash::make('user'),
|
||||||
|
'is_admin' => false,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
resources/views/auth/login.blade.php
Normal file
45
resources/views/auth/login.blade.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Fotobox – Anmelden</title>
|
||||||
|
@if (file_exists(public_path('build/manifest.json')) || file_exists(public_path('hot')))
|
||||||
|
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||||
|
@endif
|
||||||
|
</head>
|
||||||
|
<body class="bg-gray-950 text-white min-h-screen flex flex-col items-center justify-center p-6">
|
||||||
|
|
||||||
|
<h1 class="text-3xl font-bold mb-8 tracking-wide">Fotobox</h1>
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('login') }}" class="w-full max-w-sm flex flex-col gap-4">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<label for="email" class="text-sm text-gray-400">E-Mail</label>
|
||||||
|
<input id="email" type="email" name="email" value="{{ old('email') }}" required autofocus
|
||||||
|
class="rounded-xl bg-white/10 border border-white/20 px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-white/40">
|
||||||
|
@error('email')
|
||||||
|
<span class="text-sm text-red-400">{{ $message }}</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<label for="password" class="text-sm text-gray-400">Passwort</label>
|
||||||
|
<input id="password" type="password" name="password" required
|
||||||
|
class="rounded-xl bg-white/10 border border-white/20 px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-white/40">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="flex items-center gap-2 text-sm text-gray-400 cursor-pointer">
|
||||||
|
<input type="checkbox" name="remember" class="rounded">
|
||||||
|
Angemeldet bleiben
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button type="submit"
|
||||||
|
class="mt-2 px-10 py-4 bg-white text-gray-950 font-semibold text-lg rounded-full shadow-lg hover:bg-gray-200 active:scale-95 transition-all duration-150">
|
||||||
|
Anmelden
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,8 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\LoginController;
|
||||||
use App\Http\Controllers\PhotoController;
|
use App\Http\Controllers\PhotoController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::middleware('auth.basic')->group(function () {
|
Route::middleware('guest')->group(function () {
|
||||||
|
Route::get('/login', [LoginController::class, 'show'])->name('login');
|
||||||
|
Route::post('/login', [LoginController::class, 'login']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::post('/logout', [LoginController::class, 'logout'])->name('logout')->middleware('auth');
|
||||||
|
|
||||||
|
Route::middleware('auth')->group(function () {
|
||||||
Route::get('/', [PhotoController::class, 'index'])->name('camera');
|
Route::get('/', [PhotoController::class, 'index'])->name('camera');
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user