Skip to content

Commit

Permalink
Merge pull request #3 from 404NotFoundIndonesia/feature/1-role-and-pe…
Browse files Browse the repository at this point in the history
…rmission-management

#1 Role and Permission Management
  • Loading branch information
iqbaleff214 authored Feb 18, 2025
2 parents 4a71670 + 84b9a9a commit 698bdb3
Show file tree
Hide file tree
Showing 39 changed files with 1,516 additions and 59 deletions.
13 changes: 13 additions & 0 deletions app/Enum/PermissionAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Enum;

enum PermissionAction: string
{
case VIEW = 'view';
case CREATE = 'create';
case EDIT = 'edit';
case DELETE = 'delete';
case EXPORT = 'export';
case IMPORT = 'import';
}
9 changes: 9 additions & 0 deletions app/Enum/PermissionResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace App\Enum;

enum PermissionResource: string
{
case USER = 'user';
case ROLE = 'role';
}
65 changes: 65 additions & 0 deletions app/Http/Controllers/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,73 @@

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\View;

abstract class Controller
{
public function __construct()
{
$user = auth()->user();
if (! $user) {
return;
}

View::share('menus', [
[
'url' => route('dashboard'),
'name' => __('menu.dashboard'),
'icon' => 'bx-home-circle',
'active' => Route::is('dashboard'),
'available' => true,
],
[
'name' => __('menu.user_management'),
'icon' => 'bx-briefcase-alt-2',
'active' => Route::is('role.*') || Route::is('user.*'),
'available' => $user->can('view_user') || $user->can('view_role'),
'submenu' => [
[
'url' => route('user.index'),
'name' => __('menu.user'),
'active' => Route::is('user.*'),
'available' => $user->can('view_user'),
],
[
'url' => route('role.index'),
'name' => __('menu.role'),
'active' => Route::is('role.*'),
'available' => $user->can('view_role'),
],
],
],
[
'header' => __('menu.my_setting'),
'available' => true,
],
[
'name' => __('menu.account'),
'icon' => 'bx-user',
'active' => Route::is('account.*'),
'available' => true,
'submenu' => [
[
'url' => route('account.profile.edit'),
'name' => __('menu.profile'),
'active' => Route::is('account.profile.edit'),
'available' => true,
],
[
'url' => route('account.password.edit'),
'name' => __('menu.change_password'),
'active' => Route::is('account.password.edit'),
'available' => true,
],
],
],
]);
}

protected function successNotification(string $key, string $menu): array
{
return ['icon' => 'success', 'title' => __($menu), 'message' => __($key, ['menu' => __($menu)])];
Expand Down
145 changes: 145 additions & 0 deletions app/Http/Controllers/RoleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

namespace App\Http\Controllers;

use App\Enum\PermissionAction;
use App\Enum\PermissionResource;
use App\Http\Requests\StoreRoleRequest;
use App\Http\Requests\UpdateRoleRequest;
use App\Models\Role;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class RoleController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): View
{
return view('pages.role.index', [
'items' => Role::query()
->search($request->query('q'))
->render($request->query('size')),
]);
}

/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('pages.role.create', [
'actions' => PermissionAction::cases(),
'resources' => PermissionResource::cases(),
]);
}

/**
* Store a newly created resource in storage.
*/
public function store(StoreRoleRequest $request): RedirectResponse
{
try {
$input = $request->validated();

$role = Role::create(['name' => $input['role']]);
if (isset($input['permission'])) {
$role->syncPermissions($input['permission']);
}

return redirect()
->route('role.index')
->with('notification', $this->successNotification('notification.success_create', 'menu.role'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return redirect()
->route('role.index')
->with('notification', $this->failNotification('notification.fail_create', 'menu.role'));
}
}

/**
* Display the specified resource.
*/
public function show(Role $role): View
{
$permissions = [];
foreach ($role->permissions as $permission) {
$permissions[$permission->name] = true;
}

return view('pages.role.show', [
'actions' => PermissionAction::cases(),
'resources' => PermissionResource::cases(),
'item' => $role,
'permissions' => $permissions,
]);
}

/**
* Show the form for editing the specified resource.
*/
public function edit(Role $role): View
{
$permissions = [];
foreach ($role->permissions as $permission) {
$permissions[$permission->name] = true;
}

return view('pages.role.edit', [
'actions' => PermissionAction::cases(),
'resources' => PermissionResource::cases(),
'item' => $role,
'permissions' => $permissions,
]);
}

/**
* Update the specified resource in storage.
*/
public function update(UpdateRoleRequest $request, Role $role): RedirectResponse
{
try {
$input = $request->validated();

$role->update([
'name' => $input['role'],
]);
if (isset($input['permission'])) {
$role->syncPermissions($input['permission']);
}

return back()
->with('notification', $this->successNotification('notification.success_update', 'menu.role'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return back()
->with('notification', $this->failNotification('notification.fail_update', 'menu.role'));
}
}

/**
* Remove the specified resource from storage.
*/
public function destroy(Role $role): RedirectResponse
{
try {
$role->delete();

return redirect()
->route('role.index')
->with('notification', $this->successNotification('notification.success_delete', 'menu.role'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return redirect()
->route('role.index')
->with('notification', $this->failNotification('notification.fail_delete', 'menu.role'));
}
}
}
137 changes: 137 additions & 0 deletions app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Models\Role;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class UserController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): View
{
return view('pages.user.index', [
'items' => User::with('roles')
->search($request->query('q'))
->render($request->query('size')),
]);
}

/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('pages.user.create', [
'roles' => Role::all()->map(fn ($r) => [$r->name, $r->name]),
]);
}

/**
* Store a newly created resource in storage.
*/
public function store(StoreUserRequest $request): RedirectResponse
{
try {
$input = $request->validated();
$role = $input['role'];
unset($input['role']);

$user = User::query()->create([
...$input,
'password' => Hash::make('password'),
]);

$user->assignRole($role);

return redirect()
->route('user.index')
->with('notification', $this->successNotification('notification.success_create', 'menu.user'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return redirect()
->route('user.index')
->with('notification', $this->failNotification('notification.fail_create', 'menu.user'));
}
}

/**
* Display the specified resource.
*/
public function show(User $user): View
{
$user->load(['roles']);

return view('pages.user.show', [
'item' => $user,
]);
}

/**
* Show the form for editing the specified resource.
*/
public function edit(User $user): View
{
$user->load(['roles']);

return view('pages.user.edit', [
'roles' => Role::all()->map(fn ($r) => [$r->name, $r->name]),
'item' => $user,
]);
}

/**
* Update the specified resource in storage.
*/
public function update(UpdateUserRequest $request, User $user): RedirectResponse
{
try {
$input = $request->validated();
$role = $input['role'];
unset($input['role']);

$user->update($input);

$user->syncRoles([$role]);
$user->assignRole($role);

return back()
->with('notification', $this->successNotification('notification.success_update', 'menu.user'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return back()
->with('notification', $this->failNotification('notification.fail_update', 'menu.user'));
}
}

/**
* Remove the specified resource from storage.
*/
public function destroy(User $user): RedirectResponse
{
try {
$user->delete();

return redirect()
->route('user.index')
->with('notification', $this->successNotification('notification.success_delete', 'menu.user'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return redirect()
->route('user.index')
->with('notification', $this->failNotification('notification.fail_delete', 'menu.user'));
}
}
}
Loading

0 comments on commit 698bdb3

Please sign in to comment.