Skip to content

Commit

Permalink
feat(role): implement CRUD actions with permissions (#82)
Browse files Browse the repository at this point in the history
Add `RoleController` for listing, showing, creating, updating, and
deleting roles.
Assign the following permissions:

- `index()`: `show-roles`
- `store()`: `create-roles`
- `show()`: `show-roles`
- `update()`: `update-roles`
- `destroy()`: `delete-roles`

---

**Closes**:

- Close #15 
- Close #16 
- Close #17 
- Close #18 
- Close #19

---------

Signed-off-by: Valentin Sickert <[email protected]>
  • Loading branch information
Lapotor authored Dec 16, 2023
1 parent 33da7aa commit 9801067
Show file tree
Hide file tree
Showing 8 changed files with 918 additions and 0 deletions.
120 changes: 120 additions & 0 deletions app/Http/Controllers/RoleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace App\Http\Controllers;

use App\Http\Responses\ApiSuccessResponse;
use App\Permissions\RolesPermissions;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Models\Role;

class RoleController extends Controller
{
/**
* RoleController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
/**
* Permissions:
* - index: show-roles
* - store: create-roles
* - show: show-roles
* - update: update-roles
* - destroy: delete-roles
*/
$this->middleware('permission:'.RolesPermissions::CAN_SHOW_ROLES)->only(['index', 'show']);
$this->middleware('permission:'.RolesPermissions::CAN_CREATE_ROLES)->only(['store']);
$this->middleware('permission:'.RolesPermissions::CAN_UPDATE_ROLES)->only(['update']);
$this->middleware('permission:'.RolesPermissions::CAN_DELETE_ROLES)->only(['destroy']);
}

/**
* Retrieve all roles with their permissions.
*
* @return \App\Http\Responses\ApiSuccessResponse
*/
public function index()
{
$roles = Role::all();

// Combine the roles with their permissions with out pivot table.
foreach ($roles as &$role) {
$role['permissions'] = $role->permissions()->get(['id', 'name'])->makeHidden(['pivot'])->toArray();
}

return new ApiSuccessResponse($roles->toArray());
}

/**
* Store a newly created role in the database.
*
* @param \Illuminate\Http\Request $request
* @return \App\Http\Responses\ApiSuccessResponse
*/
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|unique:roles,name',
'permissions' => 'present|array',
'permissions.*' => 'sometimes|int|exists:permissions,id',
]);

$role = Role::create(['name' => $validated['name'], 'guard_name' => 'web']);
$role->syncPermissions($validated['permissions']);

$role['permissions'] = $role->permissions()->get(['id', 'name'])->makeHidden(['pivot'])->toArray();

return new ApiSuccessResponse($role->toArray(), Response::HTTP_CREATED);
}

/**
* Display the specified role.
*
* @param \Spatie\Permission\Models\Role $role
* @return \App\Http\Responses\ApiSuccessResponse
*/
public function show(Role $role)
{
$role['permissions'] = $role->permissions()->get(['id', 'name'])->makeHidden(['pivot'])->toArray();
return new ApiSuccessResponse($role);
}

/**
* Update a role.
*
* @param \Illuminate\Http\Request $request
* @param \Spatie\Permission\Models\Role $role
* @return \App\Http\Responses\ApiSuccessResponse
*/
public function update(Request $request, Role $role)
{
$validated = $request->validate([
'name' => 'required|string|unique:roles,name,'.$role->id,
'permissions' => 'present|array',
'permissions.*' => 'sometimes|int|exists:permissions,id',
]);

$role->update(['name' => $validated['name']]);
$role->syncPermissions($validated['permissions']);

$role['permissions'] = $role->permissions()->get(['id', 'name'])->makeHidden(['pivot'])->toArray();

return new ApiSuccessResponse($role);
}

/**
* Delete a role.
*
* @param \Spatie\Permission\Models\Role $role
* @return \App\Http\Responses\ApiSuccessResponse
*/
public function destroy(Role $role)
{
$role->delete();

return new ApiSuccessResponse("Role successfully deleted.");
}
}
11 changes: 11 additions & 0 deletions app/Models/Role.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Spatie\Permission\Models\Role as RoleModel;

class Role extends RoleModel
{
use HasFactory;
}
23 changes: 23 additions & 0 deletions app/Permissions/RolesPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Permissions;

/**
* Class UsersPermissions
*
* This class defines the permissions related to users.
*/
class RolesPermissions
{
/** Permission for showing roles. */
public const CAN_SHOW_ROLES = 'show-roles';

/** Permission for creating users. */
public const CAN_CREATE_ROLES = 'create-roles';

/** Permission for updating users. */
public const CAN_UPDATE_ROLES = 'update-roles';

/** Permission for deleting users. */
public const CAN_DELETE_ROLES = 'delete-roles';
}
27 changes: 27 additions & 0 deletions database/factories/RoleFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Database\Factories;

use App\Models\Role;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Role>
*/
class RoleFactory extends Factory
{
protected $model = Role::class;

/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => implode('-', $this->faker->unique()->words(3)),
'guard_name' => 'web',
];
}
}
54 changes: 54 additions & 0 deletions database/migrations/2023_12_14_193625_add_roles_permissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

use App\Permissions\RolesPermissions;
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' => RolesPermissions::CAN_SHOW_ROLES,
'guard_name' => 'web',
'created_at' => now(),
'updated_at' => now(),
],
[
'name' => RolesPermissions::CAN_CREATE_ROLES,
'guard_name' => 'web',
'created_at' => now(),
'updated_at' => now(),
],
[
'name' => RolesPermissions::CAN_UPDATE_ROLES,
'guard_name' => 'web',
'created_at' => now(),
'updated_at' => now(),
],
[
'name' => RolesPermissions::CAN_DELETE_ROLES,
'guard_name' => 'web',
'created_at' => now(),
'updated_at' => now(),
],
]);
}

/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('permissions')->whereIn('name', [
RolesPermissions::CAN_SHOW_ROLES,
RolesPermissions::CAN_CREATE_ROLES,
RolesPermissions::CAN_UPDATE_ROLES,
RolesPermissions::CAN_DELETE_ROLES,
])->delete();
}
};
1 change: 1 addition & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
Route::group(['prefix' => 'v1'], function () {
require __DIR__ . '/api/v1/auth.php';
require __DIR__ . '/api/v1/user.php';
require __DIR__ . '/api/v1/role.php';
});
12 changes: 12 additions & 0 deletions routes/api/v1/role.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

use App\Http\Controllers\RoleController;
use Illuminate\Support\Facades\Route;

Route::group(['middleware' => 'auth:sanctum'], function () {
Route::get('/roles', [RoleController::class, 'index'])->name('api.v1.roles.index');
Route::post('/roles', [RoleController::class, 'store'])->name('api.v1.roles.store');
Route::get('/roles/{role}', [RoleController::class, 'show'])->name('api.v1.roles.show');
Route::put('/roles/{role}', [RoleController::class, 'update'])->name('api.v1.roles.update');
Route::delete('/roles/{role}', [RoleController::class, 'destroy'])->name('api.v1.roles.destroy');
});
Loading

0 comments on commit 9801067

Please sign in to comment.