Explorar el Código

feat: permissões e middleware

Denis hace 1 año
padre
commit
a9a1c430d6

+ 0 - 6
app/Http/Controllers/UserController.php

@@ -49,12 +49,6 @@ public function show(int $id): JsonResponse
         return $this->successResponse(payload: new UserResource($user));
     }
 
-    public function findByEmail(string $email): JsonResponse
-    {
-        $user = $this->userService->findByEmail($email);
-        return $this->successResponse(payload: new UserResource($user));
-    }
-
     public function updateLanguage(UserLanguageRequest $request, int $id): JsonResponse
     {
         $user = $this->userService->updateLanguage(UserLanguageDto::fromRequest($request), $id);

+ 4 - 4
app/Http/Controllers/UserTypePermissionController.php

@@ -2,7 +2,7 @@
 
 namespace App\Http\Controllers;
 
-use App\Http\Resources\UserTypePermissionResource;
+use App\Http\Resources\UserTypePermissionCollection;
 use App\Services\UserTypePermissionService;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Support\Facades\Auth;
@@ -17,13 +17,13 @@ public function __construct(
     public function allGuestPermissions(): JsonResponse
     {
         $userTypePermission = $this->userTypePermissionService->allGuestPermissions();
-        return $this->successResponse(payload: new UserTypePermissionResource($userTypePermission));
+        return $this->successResponse(payload: new UserTypePermissionCollection($userTypePermission));
     }
 
     public function allPermissionsByUserType(): JsonResponse
     {
         $user = Auth::user();
-        $userTypePermission = $this->userTypePermissionService->allPermissionsByUserType($user->user_type);
-        return $this->successResponse(payload: new UserTypePermissionResource($userTypePermission));
+        $userTypePermission = $this->userTypePermissionService->allPermissionsByUserType($user->type);
+        return $this->successResponse(payload: new UserTypePermissionCollection($userTypePermission));
     }
 }

+ 68 - 0
app/Http/Middleware/CheckPermission.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Http\Resources\UserTypePermissionCollection;
+use Closure;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use App\Services\UserTypePermissionService;
+
+class CheckPermission
+{
+    public function __construct(
+        protected UserTypePermissionService $userTypePermissionService,
+    ) {
+    }
+
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
+     * @param  string  $scope
+     * @param  string  $permissionType
+     * @return \Symfony\Component\HttpFoundation\Response
+     */
+    public function handle(Request $request, Closure $next, string $scope, string $permissionType)
+    {
+        $user = Auth::user();
+
+        if (!$user) {
+            $userPermissions = new UserTypePermissionCollection($this->userTypePermissionService->allGuestPermissions());
+        } else {
+            $userPermissions = new UserTypePermissionCollection($this->userTypePermissionService->allPermissionsByUserType($user->type));
+        }
+
+        if (!$this->hasPermission($userPermissions, $scope, $permissionType)) {
+            return response()->json(['message' => 'Forbidden'], 403);
+        }
+
+        return $next($request);
+    }
+
+    private function hasPermission(UserTypePermissionCollection $userPermissions, string $scope, string $permissionType): bool
+    {
+        $bitwisePermissionTable = [
+            'view' => 1,
+            'add' => 2,
+            'edit' => 4,
+            'delete' => 8,
+            'print' => 16,
+            'export' => 32,
+            'import' => 64,
+            'limit' => 128,
+            'menu' => 256,
+        ];
+
+        $requiredPermission = $bitwisePermissionTable[$permissionType] ?? 0;
+
+        foreach ($userPermissions as $permission) {
+            if ($permission['scope'] === $scope && ($permission['bits'] & $requiredPermission)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}

+ 1 - 1
app/Http/Resources/PermissionResource.php

@@ -16,7 +16,7 @@ public function toArray(Request $request): array
     {
         return [
             'id' => $this->id,
-            'name' => $this->name,
+            'scope' => $this->scope,
             'description' => $this->description,
             'bits' => $this->bits,
             'parent_id' => $this->parent_id,

+ 21 - 0
app/Http/Resources/UserTypePermissionCollection.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\ResourceCollection;
+
+class UserTypePermissionCollection extends ResourceCollection
+{
+    /**
+     * Transform the resource collection into an array.
+     *
+     * @return array<int|string, mixed>
+     */
+    public function toArray(Request $request): array
+    {
+        return $this->collection->transform(function ($user_type_permission) {
+            return new UserTypePermissionResource($user_type_permission);
+        })->toArray();
+    }
+}

+ 5 - 3
app/Http/Resources/UserTypePermissionResource.php

@@ -3,7 +3,6 @@
 namespace App\Http\Resources;
 
 use Illuminate\Http\Request;
-use App\Http\Resources\PermissionCollection;
 use Illuminate\Http\Resources\Json\JsonResource;
 
 class UserTypePermissionResource extends JsonResource
@@ -17,8 +16,11 @@ public function toArray(Request $request): array
     {
         return [
             'id' => $this->id,
-            'name' => $this->name,
-            'permissions' => new PermissionCollection($this->permissions),
+            'scope' => $this->permission->scope,
+            'permission_id' => $this->permission_id,
+            'description' => $this->permission->description,
+            'parent_id' => $this->permission->parent_id,
+            'bits' => $this->bits,
             'created_at' => $this->created_at,
             'updated_at' => $this->updated_at,
         ];

+ 6 - 5
app/Repositories/UserTypePermissionRepository.php

@@ -3,17 +3,18 @@
 namespace App\Repositories;
 
 use App\Models\UserTypePermission;
-use App\DataTransferObjects\UserTypeDto;
+use App\Enums\UserTypeSource;
+use Illuminate\Database\Eloquent\Collection;
 
 class UserTypePermissionRepository implements UserTypePermissionRepositoryInterface
 {
-    public function allGuestPermissions(): ?UserTypePermission
+    public function allGuestPermissions(): ?Collection
     {
-        return UserTypePermission::where('user_type', 'guest')->with('permission')->get();
+        return UserTypePermission::where('user_type', 'guest')->join('permissions', 'user_type_permissions.permission_id', '=', 'permissions.id')->get();
     }
 
-    public function allPermissionsByUserType(string $userType): ?UserTypePermission
+    public function allPermissionsByUserType(UserTypeSource $userType): ?Collection
     {
-        return UserTypePermission::where('user_type', $userType)->with('permission')->get();
+        return UserTypePermission::where('user_type', $userType)->join('permissions', 'user_type_permissions.permission_id', '=', 'permissions.id')->get();
     }
 }

+ 5 - 4
app/Repositories/UserTypePermissionRepositoryInterface.php

@@ -2,12 +2,13 @@
 
 namespace App\Repositories;
 
-use App\DataTransferObjects\UserTypeDto;
-use App\Models\UserTypePermission;
+use App\Enums\UserTypeSource;
+use Illuminate\Database\Eloquent\Collection;
 
 interface UserTypePermissionRepositoryInterface
 {
-    public function allGuestPermissions(): ?UserTypePermission;
+    public function allGuestPermissions(): ?Collection;
 
-    public function allPermissionsByUserType(string $userType): ?UserTypePermission;
+    public function allPermissionsByUserType(UserTypeSource $userType): ?Collection
+;
 }

+ 4 - 4
app/Services/UserTypePermissionService.php

@@ -2,9 +2,9 @@
 
 namespace App\Services;
 
-use App\Models\UserTypePermission;
 use App\Repositories\UserTypePermissionRepositoryInterface;
-use App\DataTransferObjects\UserTypeDto;
+use App\Enums\UserTypeSource;
+use Illuminate\Database\Eloquent\Collection;
 
 class UserTypePermissionService
 {
@@ -13,12 +13,12 @@ public function __construct(
     ) {
     }
 
-    public function allGuestPermissions(): ?UserTypePermission
+    public function allGuestPermissions(): ?Collection
     {
         return $this->userTypePermissionRepository->allGuestPermissions();
     }
 
-    public function allPermissionsByUserType(string $userType): ?UserTypePermission
+    public function allPermissionsByUserType(UserTypeSource $userType): ?Collection
     {
         return $this->userTypePermissionRepository->allPermissionsByUserType($userType);
     }

+ 4 - 0
bootstrap/app.php

@@ -5,6 +5,7 @@
 use Illuminate\Foundation\Configuration\Middleware;
 use Illuminate\Console\Scheduling\Schedule;
 use App\Http\Middleware\SetUserLanguage;
+use App\Http\Middleware\CheckPermission;
 use App\Tasks\DeleteExpiredTokens;
 
 
@@ -18,6 +19,9 @@
     ->withMiddleware(function (Middleware $middleware) {
         $middleware->statefulApi();
         $middleware->append(SetUserLanguage::class);
+        $middleware->alias([
+            'permission' => CheckPermission::class,
+        ]);
     })
     ->withSchedule(function (Schedule $schedule) {
         $schedule->call(new DeleteExpiredTokens)->everyMinute();

+ 27 - 13
database/seeders/PermissionSeeder.php

@@ -5,6 +5,7 @@
 use App\DataTransferObjects\PermissionDto;
 use Illuminate\Database\Seeder;
 use App\Services\PermissionService;
+
 class PermissionSeeder extends Seeder
 {
     public function __construct(
@@ -16,14 +17,14 @@ public function run(): void
     {
         // Criação de Permissões
         /*
-        visualizar = 1
-        adicionar = 2
-        editar = 4
-        deletar = 8
-        imprimir = 16
-        exportar = 32
-        importar = 64
-        limitar = 128
+        view = 1
+        add = 2
+        edit = 4
+        delete = 8
+        print = 16
+        export = 32
+        import = 64
+        limit = 128
         menu = 256
 
         para cada cada bit selecionado se faz a soma dos valores.
@@ -36,10 +37,23 @@ public function run(): void
                 'children' => []
             ],
             [
-                'scope' => 'usuarios',
-                'description' => 'Usuários',
+                'scope' => 'config',
+                'description' => 'Configurações',
                 'bits' => 271,
-                'children' => []
+                'children' => [
+                    [
+                        'scope' => 'config.user',
+                        'description' => 'Configurações de Usuários',
+                        'bits' => 271,
+                        'children' => []
+                    ],
+                    [
+                        'scope' => 'config.permission',
+                        'description' => 'Configurações de Permissões',
+                        'bits' => 271,
+                        'children' => []
+                    ]
+                ],
             ],
         ];
 
@@ -49,9 +63,9 @@ public function run(): void
     private function createPermissionsAndChildren(array $permissions)
     {
         foreach ($permissions as $permission) {
-            $this->permissionService->store(PermissionDto::fromArray($permission));
+            $this->permissionService->store(PermissionDto::fromArray((array) $permission));
 
-            if (isset($permission['children'])) {
+            if (!empty($permission['children'])) {
                 $this->createPermissionsAndChildren($permission['children']);
             }
         }

+ 5 - 7
routes/authRoutes/permission.php

@@ -3,14 +3,12 @@
 use App\Http\Controllers\PermissionController;
 use Illuminate\Support\Facades\Route;
 
-Route::get('/permission', [PermissionController::class, 'index']);
+Route::get('/permission', [PermissionController::class, 'index'])->middleware('permission:config.permission,view');
 
-Route::get('/permission-no-tree', [PermissionController::class, 'allNoTree']);
+Route::get('/permission-no-tree', [PermissionController::class, 'allNoTree'])->middleware('permission:config.permission,view');
 
-Route::get('/permission/{id}', [PermissionController::class, 'show']);
+Route::get('/permission/{id}', [PermissionController::class, 'show'])->middleware('permission:config.permission,view');
 
-Route::post('/permission/{id}', [PermissionController::class, 'update']);
+Route::post('/permission/{id}', [PermissionController::class, 'update'])->middleware('permission:config.permission,edit');
 
-Route::post('/permission', [PermissionController::class, 'store']);
-
-Route::get('/user/permissions', [PermissionController::class, 'userPermissions']);
+Route::post('/permission', [PermissionController::class, 'store'])->middleware('permission:config.permission,add');

+ 4 - 6
routes/authRoutes/user.php

@@ -3,16 +3,14 @@
 use Illuminate\Support\Facades\Route;
 use App\Http\Controllers\UserController;
 
-Route::get('/user', [UserController::class, 'index']);
+Route::get('/user', [UserController::class, 'index'])->middleware('permission:config.user,view');
 
-Route::post('/user', [UserController::class, 'store']);
+Route::post('/user', [UserController::class, 'store'])->middleware('permission:config.user,add');
 
 Route::get('/user/{id}', [UserController::class, 'show']);
 
-Route::put('/user/{id}', [UserController::class, 'update']);
+Route::put('/user/{id}', [UserController::class, 'update'])->middleware('permission:config.user,edit');
 
-Route::delete('/user/{id}', [UserController::class, 'destroy']);
-
-Route::get('/user/email/{email}', [UserController::class, 'findByEmail']);
+Route::delete('/user/{id}', [UserController::class, 'destroy'])->middleware('permission:config.user,delete');
 
 Route::put('/user/language/{id}', [UserController::class, 'updateLanguage']);

+ 1 - 1
routes/authRoutes/user_type_permission.php

@@ -3,4 +3,4 @@
 use Illuminate\Support\Facades\Route;
 use App\Http\Controllers\UserTypePermissionController;
 
-Route::get('/user/permissions/{user_type}', [UserTypePermissionController::class, 'allPermissionsByUserType']);
+Route::get('/permissions-by-type', [UserTypePermissionController::class, 'allPermissionsByUserType']);

+ 1 - 1
routes/noAuthRoutes/user_type_permission.php

@@ -3,4 +3,4 @@
 use Illuminate\Support\Facades\Route;
 use App\Http\Controllers\UserTypePermissionController;
 
-Route::get('/user/permissions/guest', [UserTypePermissionController::class, 'allGuestPermissions']);
+Route::get('/permissions-by-type/guest', [UserTypePermissionController::class, 'allGuestPermissions']);