diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index d8522173..c0d4503c 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -2,13 +2,36 @@
 
 namespace App\Http\Controllers;
 
+use App\Http\Responses\ApiErrorResponse;
 use App\Http\Responses\ApiSuccessResponse;
 use App\Models\User;
+use App\Permissions\UsersPermissions;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 
 class UserController extends Controller
 {
+
+    /**
+     * UserController constructor.
+     */
+    public function __construct()
+    {
+        /**
+         * Permissions:
+         * - index: list-users
+         * - store: create-users
+         * - show: show-users || list-users
+         * - update-users || update-users-self
+         * - destroy: delete-users
+         */
+        $this->middleware('permission:'.UsersPermissions::CAN_LIST_USERS)->only('index');
+        $this->middleware('permission:'.UsersPermissions::CAN_LIST_USERS.'|'.UsersPermissions::CAN_SHOW_USERS)->only('show');
+        $this->middleware('permission:'.UsersPermissions::CAN_CREATE_USERS)->only('store');
+        $this->middleware('permission:'.UsersPermissions::CAN_UPDATE_USERS.'|'.UsersPermissions::CAN_UPDATE_USERS_SELF)->only('update');
+        $this->middleware('permission:'.UsersPermissions::CAN_DELETE_USERS)->only('destroy');
+    }
+
     /**
      * Display a listing of the resource.
      */
@@ -42,6 +65,12 @@ public function store(Request $request)
      */
     public function show(User $user)
     {
+        /** @var User $authUser */
+        $authUser = auth()->user();
+
+        if(!$authUser->checkPermissionTo(UsersPermissions::CAN_LIST_USERS) && !$authUser->is($user)) {
+            return new ApiErrorResponse("You can only view your own user.", status: Response::HTTP_FORBIDDEN);
+        }
         return new ApiSuccessResponse($user);
     }
 
@@ -56,6 +85,13 @@ public function update(Request $request, User $user)
             'password'  => 'sometimes|required|min:8|confirmed',
         ]);
 
+        /** @var User $authUser */
+        $authUser = auth()->user();
+
+        if($authUser->checkPermissionTo(UsersPermissions::CAN_UPDATE_USERS_SELF) && !$authUser->is($user)) {
+            return new ApiErrorResponse("You can only update your own user.", status: Response::HTTP_FORBIDDEN);
+        }
+
         $user->update($validated);
 
         return new ApiSuccessResponse($user);
diff --git a/app/Permissions/UsersPermissions.php b/app/Permissions/UsersPermissions.php
new file mode 100644
index 00000000..7291619e
--- /dev/null
+++ b/app/Permissions/UsersPermissions.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Permissions;
+
+/**
+ * Class UsersPermissions
+ *
+ * This class defines the permissions related to users.
+ */
+class UsersPermissions
+{
+    /** Permission for listing and view all users. */
+    public const CAN_LIST_USERS = 'list-users';
+
+    /** Permission for showing users itself. */
+    public const CAN_SHOW_USERS = 'show-users';
+
+    /** Permission for creating users. */
+    public const CAN_CREATE_USERS = 'create-users';
+
+    /** Permission for updating users. */
+    public const CAN_UPDATE_USERS = 'update-users';
+
+    /** Permission for updating users itself. */
+    public const CAN_UPDATE_USERS_SELF = 'update-users-self';
+
+    /** Permission for deleting users. */
+    public const CAN_DELETE_USERS = 'delete-users';
+}
diff --git a/database/migrations/2023_12_13_214743_add_user_permissions.php b/database/migrations/2023_12_13_214743_add_user_permissions.php
new file mode 100644
index 00000000..fb6336fd
--- /dev/null
+++ b/database/migrations/2023_12_13_214743_add_user_permissions.php
@@ -0,0 +1,71 @@
+<?php
+
+use App\Permissions\UsersPermissions;
+use Carbon\Carbon;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Support\Facades\DB;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        DB::table('permissions')->insert(
+            [
+                [
+                    'name' => UsersPermissions::CAN_LIST_USERS,
+                    'guard_name' => 'web',
+                    'created_at' => Carbon::now(),
+                    'updated_at' => Carbon::now(),
+                ],
+                [
+                    'name' => UsersPermissions::CAN_SHOW_USERS,
+                    'guard_name' => 'web',
+                    'created_at' => Carbon::now(),
+                    'updated_at' => Carbon::now(),
+                ],
+                [
+                    'name' => UsersPermissions::CAN_CREATE_USERS,
+                    'guard_name' => 'web',
+                    'created_at' => Carbon::now(),
+                    'updated_at' => Carbon::now(),
+                ],
+                [
+                    'name' => UsersPermissions::CAN_UPDATE_USERS,
+                    'guard_name' => 'web',
+                    'created_at' => Carbon::now(),
+                    'updated_at' => Carbon::now(),
+                ],
+                [
+                    'name' => UsersPermissions::CAN_UPDATE_USERS_SELF,
+                    'guard_name' => 'web',
+                    'created_at' => Carbon::now(),
+                    'updated_at' => Carbon::now(),
+                ],
+                [
+                    'name' => UsersPermissions::CAN_DELETE_USERS,
+                    'guard_name' => 'web',
+                    'created_at' => Carbon::now(),
+                    'updated_at' => Carbon::now(),
+                ]
+            ]
+        );
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        DB::table('permissions')->whereIn('name', [
+            UsersPermissions::CAN_LIST_USERS,
+            UsersPermissions::CAN_SHOW_USERS,
+            UsersPermissions::CAN_CREATE_USERS,
+            UsersPermissions::CAN_UPDATE_USERS,
+            UsersPermissions::CAN_UPDATE_USERS_SELF,
+            UsersPermissions::CAN_DELETE_USERS,
+        ])->delete();
+    }
+};
diff --git a/tests/Feature/Http/Controllers/UserControllerTest.php b/tests/Feature/Http/Controllers/UserControllerTest.php
index a706a7b4..5a35ec81 100644
--- a/tests/Feature/Http/Controllers/UserControllerTest.php
+++ b/tests/Feature/Http/Controllers/UserControllerTest.php
@@ -3,28 +3,37 @@
 namespace Tests\Feature\Http\Controllers;
 
 use App\Models\User;
+use App\Permissions\UsersPermissions;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Laravel\Sanctum\Sanctum;
 use Tests\TestCase;
 
+/**
+ * @coversDefaultClass \App\Http\Controllers\UserController
+ */
 class UserControllerTest extends TestCase
 {
     use RefreshDatabase;
 
     /**
-     * Test the index method.
+     * Test that the index method list users with minimal permission.
+     *
+     * @group UserController.Index
+     * @covers ::index
      */
-    public function test_users_index(): void
+    public function test_index_users_with_minimal_permission(): void
     {
         // Create some dummy users
         User::factory()->count(10)->create();
 
         Sanctum::actingAs(
-            User::factory()->create()
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_LIST_USERS
+            ])
         );
 
         // Send a GET request to the index endpoint
-        $response = $this->get('/api/v1/users');
+        $response = $this->getJson('/api/v1/users');
 
         // Assert that the response has a successful status code
         $response->assertStatus(200);
@@ -34,14 +43,70 @@ public function test_users_index(): void
     }
 
     /**
-     * Test the store method.
+     * Test that the index method don't list users with unauthorized user permissions.
+     *
+     * @group UserController.Index
+     * @covers ::index
+     */
+    public function test_not_index_users_with_unauthorized_user_permissions(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_SHOW_USERS,
+                UsersPermissions::CAN_CREATE_USERS,
+                UsersPermissions::CAN_UPDATE_USERS,
+                UsersPermissions::CAN_UPDATE_USERS_SELF,
+                UsersPermissions::CAN_DELETE_USERS,
+            ])
+        );
+
+        // Send a GET request to the index endpoint
+        $response = $this->getJson('/api/v1/users');
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+    /**
+     * Test the index method without permission.
+     *
+     * @group UserController.Index
+     * @covers ::index
      */
-    public function test_create_user(): void
+    public function test_not_index_users_without_any_permission(): void
     {
         Sanctum::actingAs(
             User::factory()->create()
         );
 
+        // Send a GET request to the index endpoint
+        $response = $this->getJson('/api/v1/users');
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+    /**
+     * Test that the store method creates users with minimal permission.
+     *
+     * @group UserController.Store
+     * @covers ::store
+     */
+    public function test_store_user_with_minimal_permission(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_CREATE_USERS,
+            ])
+        );
+
+        // Array of user data to create
         $userData = [
             'name' => 'John Doe',
             'email' => 'john.doe@example.com',
@@ -50,9 +115,9 @@ public function test_create_user(): void
         ];
 
         // Send a POST request to the store endpoint
-        $response = $this->post('/api/v1/users', $userData);
+        $response = $this->postJson('/api/v1/users', $userData);
 
-        // Assert that the response has a successful status code
+        // Assert that the response has a created status code
         $response->assertStatus(201);
 
         // Assert that the database has the user
@@ -69,14 +134,96 @@ public function test_create_user(): void
     }
 
     /**
-     * Test the show method.
+     * Test the store method with unauthorized permission.
+     *
+     * @group UserController.Store
+     * @covers ::store
+     */
+
+    public function test_not_store_user_with_unauthorized_user_permissions(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_LIST_USERS,
+                UsersPermissions::CAN_SHOW_USERS,
+                UsersPermissions::CAN_UPDATE_USERS,
+                UsersPermissions::CAN_UPDATE_USERS_SELF,
+                UsersPermissions::CAN_DELETE_USERS,
+            ])
+        );
+
+        $userData = [
+            'name' => 'John Doe',
+            'email' => 'john.doe@example.com',
+            'password' => 'password',
+            'password_confirmation' => 'password',
+        ];
+
+        // Send a POST request to the store endpoint
+        $response = $this->postJson('/api/v1/users', $userData);
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the database did not create the user
+        $this->assertDatabaseMissing('users', [
+            'name' => $userData['name'],
+            'email' => $userData['email'],
+        ]);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+    /**
+     * Test the store method without permission.
+     *
+     * @group UserController.Store
+     * @covers ::store
      */
-    public function test_users_show(): void
+    public function test_not_store_user_without_any_permission(): void
     {
         Sanctum::actingAs(
             User::factory()->create()
         );
 
+        $userData = [
+            'name' => 'John Doe',
+            'email' => 'john.doe@example.com',
+            'password' => 'password',
+            'password_confirmation' => 'password',
+        ];
+
+        // Send a POST request to the store endpoint
+        $response = $this->postJson('/api/v1/users', $userData);
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the database did not create the user
+        $this->assertDatabaseMissing('users', [
+            'name' => $userData['name'],
+            'email' => $userData['email'],
+        ]);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+    /**
+     * Test the show method for other users
+     *
+     * @group UserController.Show
+     * @covers ::show
+     */
+    public function test_show_other_users_with_list_permission(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_LIST_USERS,
+            ])
+        );
+
         $user = User::factory()->create();
 
         // Send a GET request to the show endpoint
@@ -90,9 +237,100 @@ public function test_users_show(): void
     }
 
     /**
-     * Test the update method.
+     * Test the show method for self.
+     *
+     * @group UserController.Show
+     * @covers ::show
      */
-    public function test_users_update(): void
+    public function test_show_users_self_with_show_permission(): void
+    {
+        $user = User::factory()->create();
+
+        Sanctum::actingAs($user->givePermissionTo([
+                UsersPermissions::CAN_SHOW_USERS,
+        ]));
+
+        $user = User::find($user->id);
+
+        // Send a GET request to the show endpoint
+        $response = $this->getJson('/api/v1/users/' . $user->id);
+
+        // Assert that the response has a successful status code
+        $response->assertStatus(200);
+
+        // Assert that the response contains the user data
+        $response->assertJsonFragment($user->toArray());
+    }
+
+
+    /**
+     * Test the show method for other users with self permission.
+     *
+     * @group UserController.Show
+     * @covers ::show
+     */
+    public function test_not_show_other_users_with_self_permission(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_SHOW_USERS,
+            ])
+        );
+
+        $user = User::factory()->create();
+
+        // Send a GET request to the show endpoint
+        $response = $this->get('/api/v1/users/' . $user->id);
+
+        // Assert that the response has a successful status code
+        $response->assertStatus(403);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'You can only view your own user.']);
+    }
+
+    /**
+     * Test the show method with unauthorized user permissions.
+     *
+     * @group UserController.Show
+     * @covers ::show
+     */
+    public function test_not_show_other_users_with_unauthorized_user_permissions(): void
+    {
+        $unauthorizedPerms = [
+            UsersPermissions::CAN_CREATE_USERS,
+            UsersPermissions::CAN_UPDATE_USERS,
+            UsersPermissions::CAN_UPDATE_USERS_SELF,
+            UsersPermissions::CAN_DELETE_USERS,
+        ];
+
+        foreach ($unauthorizedPerms as $perm) {
+            Sanctum::actingAs(
+                User::factory()->create()->givePermissionTo([
+                    $perm,
+                ])
+            );
+
+            $user = User::factory()->create();
+
+            // Send a GET request to the show endpoint
+            $response = $this->getJson('/api/v1/users/' . $user->id);
+
+            // Assert that the response has a unauthorized status code
+            $response->assertStatus(403);
+
+            // Assert that the response contains the error message
+            $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+        }
+    }
+
+    /**
+     * Test the show method without permission.
+     *
+     * @group UserController.Show
+     * @covers ::show
+     */
+    public function test_not_show_users_without_any_permission(): void
     {
         Sanctum::actingAs(
             User::factory()->create()
@@ -100,18 +338,43 @@ public function test_users_update(): void
 
         $user = User::factory()->create();
 
+        // Send a GET request to the show endpoint
+        $response = $this->getJson('/api/v1/users/' . $user->id);
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+    /**
+     * Test the update method for self.
+     *
+     * @group UserController.Update
+     * @covers ::update
+     */
+    public function test_update_users_self_with_self_permission(): void
+    {
+        $user = User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_UPDATE_USERS_SELF,
+        ]);
+
+        Sanctum::actingAs($user);
+
         $userData = [
             'name' => 'Updated Name',
             'email' => 'updated.email@example.com',
         ];
 
-        // Send a PATCH request to the update endpoint
-        $response = $this->put('/api/v1/users/' . $user->id, $userData);
+        // Send a PUT request to the update endpoint
+        $response = $this->putJson('/api/v1/users/' . $user->id, $userData);
 
         // Assert that the response has a successful status code
         $response->assertStatus(200);
 
         $this->assertDatabaseHas('users', [
+            'id' => $user->id,
             'name' => $userData['name'],
             'email' => $userData['email'],
         ]);
@@ -121,9 +384,126 @@ public function test_users_update(): void
     }
 
     /**
-     * Test the destroy method.
+     * Test the update method for other users with self permission.
+     *
+     * @group UserController.Update
+     * @covers ::update
+     */
+    public function test_update_other_users_with_update_permission(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_UPDATE_USERS,
+            ])
+        );
+
+        $user = User::factory()->create();
+
+        $userData = [
+            'name' => 'Updated Name',
+            'email' => 'updated.email@example.com',
+        ];
+
+        // Send a PATCH request to the update endpoint
+        $response = $this->putJson('/api/v1/users/' . $user->id, $userData);
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(200);
+
+        // Assert that the database did not update the user
+        $this->assertDatabaseHas('users', [
+            'id' => $user->id,
+            'name' => $userData['name'],
+            'email' => $userData['email'],
+        ]);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment($userData);
+    }
+
+    /**
+     * Test the update method for other users with self permission.
+     *
+     * @group UserController.Update
+     * @covers ::update
+     */
+    public function test_not_update_other_users_with_self_permission(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_UPDATE_USERS_SELF
+            ])
+        );
+
+        $user = User::factory()->create();
+
+        $userData = [
+            'name' => 'Updated Name',
+            'email' => 'updated.email@example.com',
+        ];
+
+        // Send a PATCH request to the update endpoint
+        $response = $this->putJson('/api/v1/users/' . $user->id, $userData);
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the database did not update the user
+        $this->assertDatabaseMissing('users', [
+            'id' => $user->id,
+            'name' => $userData['name'],
+            'email' => $userData['email'],
+        ]);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'You can only update your own user.']);
+    }
+
+    /**
+     * Test the update method for other users with unauthorized user permissions.
+     */
+    public function test_not_update_other_users_with_unauthorized_user_permissions(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_LIST_USERS,
+                UsersPermissions::CAN_SHOW_USERS,
+                UsersPermissions::CAN_CREATE_USERS,
+                UsersPermissions::CAN_DELETE_USERS,
+            ])
+        );
+
+        $user = User::factory()->create();
+
+        $userData = [
+            'name' => 'Updated Name',
+            'email' => 'updated.email@example.com',
+        ];
+
+        // Send a PATCH request to the update endpoint
+        $response = $this->putJson('/api/v1/users/' . $user->id, $userData);
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the database did not update the user
+        $this->assertDatabaseMissing('users', [
+            'id' => $user->id,
+            'name' => $userData['name'],
+            'email' => $userData['email'],
+        ]);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+    /**
+     * Test the update method without any permission.
+     *
+     * @group UserController.Update
+     * @covers ::update
      */
-    public function test_users_destroy(): void
+    public function test_not_update_users_without_any_permission(): void
     {
         Sanctum::actingAs(
             User::factory()->create()
@@ -131,6 +511,44 @@ public function test_users_destroy(): void
 
         $user = User::factory()->create();
 
+        $userData = [
+            'name' => 'Updated Name',
+            'email' => 'updated.email@example.com',
+        ];
+
+        // Send a PATCH request to the update endpoint
+        $response = $this->putJson('/api/v1/users/' . $user->id, $userData);
+
+        // Assert that the response has a unauthorized status code
+        $response->assertStatus(403);
+
+        // Assert that the database did not update the user
+        $this->assertDatabaseMissing('users', [
+            'id' => $user->id,
+            'name' => $userData['name'],
+            'email' => $userData['email'],
+        ]);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+    /**
+     * Test the destroy method with minimal permission.
+     *
+     * @group UserController.Destroy
+     * @covers ::destroy
+     */
+    public function test_destroy_users_with_minimal_permission(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_DELETE_USERS,
+            ])
+        );
+
+        $user = User::factory()->create();
+
         // Send a DELETE request to the destroy endpoint
         $response = $this->delete('/api/v1/users/' . $user->id);
 
@@ -140,4 +558,59 @@ public function test_users_destroy(): void
         // Assert that the response contains the success message
         $response->assertJsonFragment(['data' => 'User deleted successfully.']);
     }
+
+    /**
+     * Test the destroy method with unauthorized user permissions.
+     *
+     * @group UserController.Destroy
+     * @covers ::destroy
+     */
+    public function test_not_destroy_users_with_unauthorized_user_permissions(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()->givePermissionTo([
+                UsersPermissions::CAN_LIST_USERS,
+                UsersPermissions::CAN_SHOW_USERS,
+                UsersPermissions::CAN_CREATE_USERS,
+                UsersPermissions::CAN_UPDATE_USERS,
+                UsersPermissions::CAN_UPDATE_USERS_SELF,
+            ])
+        );
+
+        $user = User::factory()->create();
+
+        // Send a DELETE request to the destroy endpoint
+        $response = $this->deleteJson('/api/v1/users/' . $user->id);
+
+        // Assert that the response has a successful status code
+        $response->assertStatus(403);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
+
+
+    /**
+     * Test the destroy method without permission.
+     *
+     * @group UserController.Destroy
+     * @covers ::destroy
+     */
+    public function test_users_destroy_without_any_permission(): void
+    {
+        Sanctum::actingAs(
+            User::factory()->create()
+        );
+
+        $user = User::factory()->create();
+
+        // Send a DELETE request to the destroy endpoint
+        $response = $this->deleteJson('/api/v1/users/' . $user->id);
+
+        // Assert that the response has a successful status code
+        $response->assertStatus(403);
+
+        // Assert that the response contains the error message
+        $response->assertJsonFragment(['message' => 'User does not have the right permissions.']);
+    }
 }