diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php
new file mode 100644
index 0000000..4f48f06
--- /dev/null
+++ b/app/Http/Controllers/ProfileController.php
@@ -0,0 +1,42 @@
+with('user', $user);
+ }
+
+ /**
+ * Show the form for editing a user's profile data.
+ */
+ public function edit(User $user): View
+ {
+ return view('profiles.edit')->with('user', $user);
+ }
+
+ /**
+ * Update the user profile data.
+ */
+ public function update(UpdateUserRequest $request, User $user): RedirectResponse
+ {
+ $this->updateUser($request, $user);
+ $user->refresh();
+ session()->flash('message', "Profile updated!");
+ return redirect()->route('profiles.show', $user);
+ }
+
+}
diff --git a/app/Http/Controllers/Traits/UpdatesUser.php b/app/Http/Controllers/Traits/UpdatesUser.php
new file mode 100644
index 0000000..e257893
--- /dev/null
+++ b/app/Http/Controllers/Traits/UpdatesUser.php
@@ -0,0 +1,45 @@
+validated();
+ $input['remember_token'] = Str::random(10);
+ if (!empty($input['password'])) {
+ $input['password'] = Hash::make($input['password']);
+ }
+ else {
+ unset($input['password']);
+ }
+ $input['admin'] = $input['admin'] ?? false;
+
+ $user->fill($input)->save();
+
+ // Handle image.
+ if (!empty($input['image'])) {
+ /** @var \Illuminate\Http\UploadedFile $file */
+ $file = $input['image'];
+ $user->clearMediaCollection();
+ $user
+ ->addMediaFromRequest('image')
+ ->usingName($user->username)
+ ->usingFileName("{$user->slug}.{$file->extension()}")
+ ->toMediaCollection();
+ }
+ elseif (isset($input['remove_image']) && $input['remove_image']) {
+ $user->clearMediaCollection();
+ }
+ }
+
+}
diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index 0bc7c0e..adaa87f 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -2,15 +2,16 @@
namespace App\Http\Controllers;
+use App\Http\Controllers\Traits\UpdatesUser;
use App\Http\Requests\UpdateUserRequest;
use App\Models\User;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
-use Illuminate\Support\Facades\Hash;
-use Illuminate\Support\Str;
class UserController extends Controller
{
+ use UpdatesUser;
+
/**
* Display a listing of the resource.
*/
@@ -50,33 +51,7 @@ class UserController extends Controller
*/
public function update(UpdateUserRequest $request, User $user): RedirectResponse
{
- $input = $request->validated();
- $input['remember_token'] = Str::random(10);
- if (!empty($input['password'])) {
- $input['password'] = Hash::make($input['password']);
- }
- else {
- unset($input['password']);
- }
- $input['admin'] = $input['admin'] ?? false;
-
- $user->fill($input)->save();
-
- // Handle image.
- if (!empty($input['image'])) {
- /** @var \Illuminate\Http\UploadedFile $file */
- $file = $input['image'];
- $user->clearMediaCollection();
- $user
- ->addMediaFromRequest('image')
- ->usingName($user->username)
- ->usingFileName("{$user->slug}.{$file->extension()}")
- ->toMediaCollection();
- }
- elseif (isset($input['remove_image']) && $input['remove_image']) {
- $user->clearMediaCollection();
- }
-
+ $this->updateUser($request, $user);
session()->flash('message', "User {$user->name} updated!");
return redirect()->route('users.index');
}
diff --git a/app/Models/User.php b/app/Models/User.php
index 0633864..e84dcc6 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -83,6 +83,14 @@ final class User extends Authenticatable implements HasMedia
'admin' => 'bool',
];
+ /**
+ * @inheritdoc
+ */
+ public function sluggable(): array
+ {
+ return ['slug' => ['source' => 'username']];
+ }
+
/**
* Get the User's goals.
*/
diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php
index a77e091..f0e0d88 100644
--- a/app/Policies/UserPolicy.php
+++ b/app/Policies/UserPolicy.php
@@ -16,6 +16,13 @@ class UserPolicy
return $user->admin;
}
+ /**
+ * Determine whether the user can edit a user via the "profile".
+ */
+ public function editProfile(User $user, User $model): bool {
+ return $user->id === $model->id;
+ }
+
/**
* Determine whether the user can delete the model.
*/
diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php
index d68f311..75e4c49 100644
--- a/app/Providers/AuthServiceProvider.php
+++ b/app/Providers/AuthServiceProvider.php
@@ -8,10 +8,9 @@ use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvid
class AuthServiceProvider extends ServiceProvider
{
+
/**
- * The policy mappings for the application.
- *
- * @var array
+ * @inheritdoc
*/
protected $policies = [
User::class => UserPolicy::class,
diff --git a/resources/views/profiles/edit.blade.php b/resources/views/profiles/edit.blade.php
new file mode 100644
index 0000000..b90240b
--- /dev/null
+++ b/resources/views/profiles/edit.blade.php
@@ -0,0 +1,70 @@
+
+ Edit Profile
+
+ Edit Profile
+
+
+
diff --git a/resources/views/profiles/show.blade.php b/resources/views/profiles/show.blade.php
new file mode 100644
index 0000000..35c2a7e
--- /dev/null
+++ b/resources/views/profiles/show.blade.php
@@ -0,0 +1,9 @@
+
+ Profile
+
+
+
Profile
+
+
+ {{ $user->name }}
+
diff --git a/routes/auth.php b/routes/auth.php
index 3813b29..7628fdc 100644
--- a/routes/auth.php
+++ b/routes/auth.php
@@ -4,6 +4,7 @@ use App\Http\Controllers\FoodController;
use App\Http\Controllers\GoalController;
use App\Http\Controllers\IngredientPickerController;
use App\Http\Controllers\JournalEntryController;
+use App\Http\Controllers\ProfileController;
use App\Http\Controllers\RecipeController;
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use Illuminate\Support\Facades\Route;
@@ -15,7 +16,9 @@ use Illuminate\Support\Facades\Route;
*/
Route::middleware(['auth'])->group(function () {
+ // Auth.
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])->name('logout');
+
// Foods.
Route::resource('foods', FoodController::class);
Route::get('/foods/{food}/delete', [FoodController::class, 'delete'])->name('foods.delete');
@@ -36,4 +39,13 @@ Route::middleware(['auth'])->group(function () {
// Recipes.
Route::resource('recipes', RecipeController::class);
Route::get('/recipes/{recipe}/delete', [RecipeController::class, 'delete'])->name('recipes.delete');
+
+ // Users.
+ Route::get('/profile/{user}', [ProfileController::class, 'show'])->name('profiles.show');
+});
+
+Route::middleware(['auth', 'can:editProfile,user'])->group(function () {
+ // Profiles (non-admin Users variant).
+ Route::get('/profile/{user}/edit', [ProfileController::class, 'edit'])->name('profiles.edit');
+ Route::put('/profile/{user}', [ProfileController::class, 'update'])->name('profiles.update');
});