diff --git a/src/app/Console/Commands/SetUserAdmin.php b/src/app/Console/Commands/SetUserAdmin.php new file mode 100644 index 0000000..26b04f4 --- /dev/null +++ b/src/app/Console/Commands/SetUserAdmin.php @@ -0,0 +1,50 @@ +argument('email'); + $user = User::where('email', $email)->first(); + + if (!$user) { + $this->error("User with email '{$email}' not found."); + return Command::FAILURE; + } + + $isAdmin = !$this->option('remove'); + $user->is_admin = $isAdmin; + $user->save(); + + if ($isAdmin) { + $this->info("User '{$user->name}' ({$email}) is now an admin."); + } else { + $this->info("Admin status removed from user '{$user->name}' ({$email})."); + } + + return Command::SUCCESS; + } +} + diff --git a/src/app/Http/Controllers/Admin/UserController.php b/src/app/Http/Controllers/Admin/UserController.php new file mode 100644 index 0000000..fdc4b8e --- /dev/null +++ b/src/app/Http/Controllers/Admin/UserController.php @@ -0,0 +1,104 @@ +paginate(20); + + return view('admin.users.index', compact('users')); + } + + /** + * Show the form for creating a new user. + */ + public function create() + { + return view('admin.users.create'); + } + + /** + * Store a newly created user in storage. + */ + public function store(Request $request) + { + $validated = $request->validate([ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:users'], + 'password' => ['required', 'confirmed', Rules\Password::defaults()], + 'is_admin' => ['boolean'], + ]); + + $user = User::create([ + 'name' => $validated['name'], + 'email' => $validated['email'], + 'password' => Hash::make($validated['password']), + 'is_admin' => $request->boolean('is_admin'), + ]); + + return redirect()->route('admin.users.index') + ->with('success', 'ユーザーを作成しました。'); + } + + /** + * Show the form for editing the specified user. + */ + public function edit(User $user) + { + return view('admin.users.edit', compact('user')); + } + + /** + * Update the specified user in storage. + */ + public function update(Request $request, User $user) + { + $validated = $request->validate([ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:users,email,' . $user->id], + 'password' => ['nullable', 'confirmed', Rules\Password::defaults()], + 'is_admin' => ['boolean'], + ]); + + $user->name = $validated['name']; + $user->email = $validated['email']; + $user->is_admin = $request->boolean('is_admin'); + + if (!empty($validated['password'])) { + $user->password = Hash::make($validated['password']); + } + + $user->save(); + + return redirect()->route('admin.users.index') + ->with('success', 'ユーザー情報を更新しました。'); + } + + /** + * Remove the specified user from storage. + */ + public function destroy(User $user) + { + // 自分自身は削除できない + if ($user->id === auth()->id()) { + return back()->with('error', '自分自身を削除することはできません。'); + } + + $user->delete(); + + return redirect()->route('admin.users.index') + ->with('success', 'ユーザーを削除しました。'); + } +} + diff --git a/src/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/src/app/Http/Controllers/Auth/AuthenticatedSessionController.php index 613bcd9..25f2954 100644 --- a/src/app/Http/Controllers/Auth/AuthenticatedSessionController.php +++ b/src/app/Http/Controllers/Auth/AuthenticatedSessionController.php @@ -28,7 +28,12 @@ public function store(LoginRequest $request): RedirectResponse $request->session()->regenerate(); - return redirect()->intended(route('dashboard', absolute: false)); + // 管理者はダッシュボードへ、一般ユーザーはフロントページへリダイレクト + if (Auth::user()->isAdmin()) { + return redirect()->intended(route('dashboard', absolute: false)); + } + + return redirect()->intended('/'); } /** diff --git a/src/app/Http/Middleware/AdminMiddleware.php b/src/app/Http/Middleware/AdminMiddleware.php new file mode 100644 index 0000000..1992d95 --- /dev/null +++ b/src/app/Http/Middleware/AdminMiddleware.php @@ -0,0 +1,25 @@ +user() || !$request->user()->isAdmin()) { + abort(403, 'Unauthorized. Admin access required.'); + } + + return $next($request); + } +} + diff --git a/src/app/Models/User.php b/src/app/Models/User.php index 749c7b7..da98d0a 100644 --- a/src/app/Models/User.php +++ b/src/app/Models/User.php @@ -21,8 +21,19 @@ class User extends Authenticatable 'name', 'email', 'password', + 'is_admin', ]; + /** + * Check if user is an administrator. + * + * @return bool + */ + public function isAdmin(): bool + { + return (bool) $this->is_admin; + } + /** * The attributes that should be hidden for serialization. * diff --git a/src/bootstrap/app.php b/src/bootstrap/app.php index c183276..9e13148 100644 --- a/src/bootstrap/app.php +++ b/src/bootstrap/app.php @@ -11,7 +11,9 @@ health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { - // + $middleware->alias([ + 'admin' => \App\Http\Middleware\AdminMiddleware::class, + ]); }) ->withExceptions(function (Exceptions $exceptions): void { // diff --git a/src/database/migrations/2025_11_29_012857_add_is_admin_to_users_table.php b/src/database/migrations/2025_11_29_012857_add_is_admin_to_users_table.php new file mode 100644 index 0000000..b15a101 --- /dev/null +++ b/src/database/migrations/2025_11_29_012857_add_is_admin_to_users_table.php @@ -0,0 +1,28 @@ +boolean('is_admin')->default(false)->after('email'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('is_admin'); + }); + } +}; diff --git a/src/resources/views/admin/users/create.blade.php b/src/resources/views/admin/users/create.blade.php new file mode 100644 index 0000000..694d00c --- /dev/null +++ b/src/resources/views/admin/users/create.blade.php @@ -0,0 +1,72 @@ + + +
+ + + + + +

+ 新規ユーザー作成 +

+
+
+ +
+
+
+
+
+ @csrf + + +
+ + + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ +
+ +
+ + キャンセル + + + 作成 + +
+
+
+
+
+
+
+ diff --git a/src/resources/views/admin/users/edit.blade.php b/src/resources/views/admin/users/edit.blade.php new file mode 100644 index 0000000..d9d6ed3 --- /dev/null +++ b/src/resources/views/admin/users/edit.blade.php @@ -0,0 +1,77 @@ + + +
+ + + + + +

+ ユーザー編集: {{ $user->name }} +

+
+
+ +
+
+
+
+
+ @csrf + @method('PUT') + + +
+ + + +
+ + +
+ + + +
+ + +
+ + + +

変更しない場合は空欄のままにしてください。

+
+ + +
+ + + +
+ + +
+ + @if($user->id === auth()->id()) +

※自分自身の管理者権限を外すと、管理画面にアクセスできなくなります。

+ @endif +
+ +
+ + キャンセル + + + 更新 + +
+
+
+
+
+
+
+ diff --git a/src/resources/views/admin/users/index.blade.php b/src/resources/views/admin/users/index.blade.php new file mode 100644 index 0000000..5903e62 --- /dev/null +++ b/src/resources/views/admin/users/index.blade.php @@ -0,0 +1,121 @@ + + +
+

+ ユーザー管理 +

+ + + + + 新規ユーザー + +
+
+ +
+
+ @if(session('success')) + + @endif + + @if(session('error')) + + @endif + +
+
+ + + + + + + + + + + + + @forelse($users as $user) + + + + + + + + + @empty + + + + @endforelse + +
+ ID + + 名前 + + メールアドレス + + 権限 + + 登録日 + + 操作 +
+ {{ $user->id }} + +
+
+ + {{ strtoupper(substr($user->name, 0, 1)) }} + +
+
+
+ {{ $user->name }} +
+
+
+
+ {{ $user->email }} + + @if($user->is_admin) + + 管理者 + + @else + + 一般ユーザー + + @endif + + {{ $user->created_at->format('Y/m/d H:i') }} + + 編集 + @if($user->id !== auth()->id()) +
+ @csrf + @method('DELETE') + +
+ @endif +
+ ユーザーが登録されていません。 +
+ +
+ {{ $users->links() }} +
+
+
+
+
+
+ diff --git a/src/resources/views/components/application-logo.blade.php b/src/resources/views/components/application-logo.blade.php index 46579cf..65497e1 100644 --- a/src/resources/views/components/application-logo.blade.php +++ b/src/resources/views/components/application-logo.blade.php @@ -1,3 +1,4 @@ - - + + + diff --git a/src/resources/views/layouts/knowledge-base.blade.php b/src/resources/views/layouts/knowledge-base.blade.php index 22fbd40..49d76d2 100644 --- a/src/resources/views/layouts/knowledge-base.blade.php +++ b/src/resources/views/layouts/knowledge-base.blade.php @@ -44,7 +44,8 @@ + + + + ユーザー管理 + + + @endif
@csrf