From 53a2c3a38eadfd154895372c31b01286190ca0f3 Mon Sep 17 00:00:00 2001 From: Daeng Deni Mardaeni Date: Sun, 22 Jun 2025 19:16:11 +0700 Subject: [PATCH] feat(auth): tambah validasi peran pengguna untuk modul lokasi - **Autentikasi dan Otorisasi**: - Menambah validasi akses berdasarkan peran pengguna menggunakan `Auth::guard('web')->user()`. - Menentukan izin seperti `location.read`, `location.create`, `location.update`, `location.delete`, dan `location.export` untuk setiap metode di controller. - Menambahkan pesan error khusus untuk user yang tidak memiliki izin akses tertentu. - **Peningkatan Controller**: - Mengubah properti `user` dari publik menjadi `protected`. - Menambahkan validasi peran pengguna pada metode di controller berikut: - `ProvincesController`: Pembatasan akses untuk operasi CRUD dan export. - `CitiesController`: Restriksi yang sama seperti pada `ProvincesController`. - `DistrictsController`: Menambahkan pengecekan otorisasi berdasarkan peran. - `VillagesController`: Validasi akses CRUD, export, dan data villager. - **Seeder**: - Menambahkan `PermissionSeeder` untuk menghasilkan izin CRUD dengan grup `location`. - Memastikan setiap action CRUD (`read`, `create`, `update`, dll.) terdaftar dalam basis data. - **Perbaikan API Response**: - Mengganti penggunaan `echo json_encode` dengan metode `response()->json()`. - Penanganan response untuk berbagai metode seperti `destroy`, dan validasi akses lainnya. Signed-off-by: Daeng Deni Mardaeni --- app/Http/Controllers/CitiesController.php | 53 ++++++++++++++---- app/Http/Controllers/DistrictsController.php | 55 ++++++++++++++++--- app/Http/Controllers/ProvincesController.php | 50 ++++++++++++++--- app/Http/Controllers/VillagesController.php | 57 +++++++++++++++++--- database/seeders/LocationDatabaseSeeder.php | 1 + database/seeders/PermissionSeeder.php | 50 +++++++++++++++++ 6 files changed, 235 insertions(+), 31 deletions(-) create mode 100644 database/seeders/PermissionSeeder.php diff --git a/app/Http/Controllers/CitiesController.php b/app/Http/Controllers/CitiesController.php index 1d7e464..eeb62b4 100644 --- a/app/Http/Controllers/CitiesController.php +++ b/app/Http/Controllers/CitiesController.php @@ -3,30 +3,46 @@ namespace Modules\Location\Http\Controllers; use App\Http\Controllers\Controller; -use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; -use Illuminate\Http\Response; +use Illuminate\Support\Facades\Auth; use Maatwebsite\Excel\Facades\Excel; use Modules\Location\Exports\CitiesExport; use Modules\Location\Http\Requests\CityRequest; use Modules\Location\Models\City; use Modules\Location\Models\Province; + class CitiesController extends Controller { - public $user; + protected $user; + + public function __construct() + { + $this->user = Auth::guard('web')->user(); + } public function index(){ - $provinces = Province::all(); - return view('location::cities.index', compact('provinces')); + if (is_null($this->user) || !$this->user->can('location.read')) { + abort(403, 'Sorry! You are not allowed to view cities.'); + } + + return view('location::cities.index'); } public function create(){ + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create cities.'); + } + $provinces = Province::all(); return view('location::cities.create',compact('provinces')); } public function store(CityRequest $request){ + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create cities.'); + } + $validate = $request->validated(); if($validate){ @@ -40,12 +56,20 @@ class CitiesController extends Controller } public function edit($id){ + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to update cities.'); + } + $city = City::find($id); $provinces = Province::all(); return view('location::cities.create', compact('city', 'provinces')); } public function update(CityRequest $request, $id){ + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to update cities.'); + } + $validate = $request->validated(); if($validate){ @@ -60,17 +84,21 @@ class CitiesController extends Controller } public function destroy($id){ + if (is_null($this->user) || !$this->user->can('provinces.delete')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to delete cities.']); + } + try { City::destroy($id); - echo json_encode(['message' => 'City deleted successfully', 'success' => true]); + return response()->json(['message' => 'City deleted successfully', 'success' => true]); } catch (\Exception $e) { - echo json_encode(['message' => 'Failed to delete city', 'success' => false]); + return response()->json(['message' => 'Failed to delete city', 'success' => false]); } } public function dataForDatatables(Request $request){ - if (is_null($this->user) || !$this->user->can('provinces.view')) { - //abort(403, 'Sorry! You are not allowed to view users.'); + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to view cities.'], 403); } // Retrieve data from the database @@ -161,11 +189,18 @@ class CitiesController extends Controller public function export() { + if (is_null($this->user) || !$this->user->can('location.read')) { + abort(403, 'Sorry! You are not allowed to export cities.'); + } + return Excel::download(new CitiesExport, 'cities.xlsx'); } public function getCitiesByProvinceId($id) { + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to view cities.'], 403); + } $query = City::query(); diff --git a/app/Http/Controllers/DistrictsController.php b/app/Http/Controllers/DistrictsController.php index c5d9ee0..21de9e8 100644 --- a/app/Http/Controllers/DistrictsController.php +++ b/app/Http/Controllers/DistrictsController.php @@ -10,27 +10,45 @@ use Modules\Location\Http\Requests\DistrictRequest; use Modules\Location\Models\City; use Modules\Location\Models\District; use Modules\Location\Models\Province; +use Illuminate\Support\Facades\Auth; + class DistrictsController extends Controller { - public $user; + protected $user; + + public function __construct() + { + $this->user = Auth::guard('web')->user(); + } public function index(){ - $provinces = Province::all(); - return view('location::districts.index', compact('provinces')); + if (is_null($this->user) || !$this->user->can('location.read')) { + abort(403, 'Sorry! You are not allowed to view districts.'); + } + + return view('location::districts.index'); } public function create(){ + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create districts.'); + } + $provinces = Province::all(); return view('location::districts.create', compact('provinces')); } public function store(DistrictRequest $request){ + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create districts.'); + } + $validate = $request->validated(); if($validate){ try{ - $district = District::create($validate); + District::create($validate); return redirect()->route('locations.districts.index')->with('success', 'District created successfully'); } catch(\Exception $e){ return redirect()->back()->with('error', 'Failed to create district. '.$e->getMessage()); @@ -39,6 +57,10 @@ class DistrictsController extends Controller } public function edit($id){ + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to edit districts.'); + } + $district = District::find($id); $provinces = Province::all(); $cities = City::where('province_code', $district->province_code)->get(); @@ -46,6 +68,10 @@ class DistrictsController extends Controller } public function update(DistrictRequest $request, $id){ + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to update districts.'); + } + $validate = $request->validated(); if($validate){ @@ -60,17 +86,22 @@ class DistrictsController extends Controller } public function destroy($id){ + if (is_null($this->user) || !$this->user->can('location.delete')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to delete districts.'], 403); + } + try{ District::destroy($id); - echo json_encode(['message' => 'District deleted successfully','success'=>true ]); + return response()->json(['message' => 'District deleted successfully', 'success' => true]); } catch(\Exception $e){ - echo json_encode(['message' => 'Failed to delete District', 'success' => false]); + return response()->json(['message' => 'Failed to delete District', 'success' => false]); } } public function dataForDatatables(Request $request){ - if (is_null($this->user) || !$this->user->can('provinces.view')) { - //abort(403, 'Sorry! You are not allowed to view users.'); + // Check if the authenticated user has the required permission to view audit logs + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to view districts.'], 403); } // Retrieve data from the database @@ -159,10 +190,18 @@ class DistrictsController extends Controller } public function export(Request $request){ + if (is_null($this->user) || !$this->user->can('location.export')) { + abort(403, 'Sorry! You are not allowed to export districts.'); + } + return Excel::download(new DistrictsExport, 'districts.xlsx'); } public function getDistrictsByCityId($id){ + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to view districts.'], 403); + } + return response()->json(District::where('city_code', $id)->get()); } } diff --git a/app/Http/Controllers/ProvincesController.php b/app/Http/Controllers/ProvincesController.php index be29da0..4928eb6 100644 --- a/app/Http/Controllers/ProvincesController.php +++ b/app/Http/Controllers/ProvincesController.php @@ -2,32 +2,50 @@ namespace Modules\Location\Http\Controllers; -use App\Http\Controllers\Controller; use Illuminate\Http\Request; +use App\Http\Controllers\Controller; +use Illuminate\Support\Facades\Auth; use Maatwebsite\Excel\Facades\Excel; +use Modules\Location\Models\Province; use Modules\Location\Exports\ProvincesExport; use Modules\Location\Http\Requests\ProvinceRequest; -use Modules\Location\Models\Province; class ProvincesController extends Controller { - public $user; + protected $user; + + public function __construct() + { + $this->user = Auth::guard('web')->user(); + } public function index(){ + if (is_null($this->user) || !$this->user->can('location.read')) { + abort(403, 'Sorry! You are not allowed to view provinces.'); + } + return view('location::provinces.index'); } public function create(){ + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create provinces.'); + } + return view('location::provinces.create'); } public function store(ProvinceRequest $request){ + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create provinces.'); + } + $validate = $request->validated(); if($validate){ try{ // Save to database - $province = Province::create($validate); + Province::create($validate); return redirect()->route('locations.provinces.index')->with('success', 'Province created successfully'); } catch (\Exception $e){ return redirect()->route('locations.provinces.create')->with('error', 'Failed to create province'); @@ -36,11 +54,19 @@ class ProvincesController extends Controller } public function edit($id){ + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to update provinces.'); + } + $province = Province::find($id); return view('location::provinces.create', compact('province')); } public function update(ProvinceRequest $request, $id){ + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to update provinces.'); + } + $validate = $request->validated(); if($validate){ @@ -56,20 +82,24 @@ class ProvincesController extends Controller } public function destroy($id){ + if (is_null($this->user) || !$this->user->can('location.delete')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to delete provinces.']); + } + try{ // Delete from database $province = Province::find($id); $province->delete(); - echo json_encode(['success' => true, 'message' => 'Province deleted successfully']); + return response()->json(['success' => true, 'message' => 'Province deleted successfully']); } catch (\Exception $e){ - echo json_encode(['success' => false, 'message' => 'Failed to delete province']); + return response()->json(['success' => false, 'message' => 'Failed to delete province']); } } public function dataForDatatables(Request $request){ - if (is_null($this->user) || !$this->user->can('provinces.view')) { - //abort(403, 'Sorry! You are not allowed to view users.'); + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to view provinces.']); } // Retrieve data from the database @@ -129,6 +159,10 @@ class ProvincesController extends Controller public function export() { + if (is_null($this->user) || !$this->user->can('location.export')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to export provinces.']); + } + return Excel::download(new ProvincesExport, 'provinces.xlsx'); } } diff --git a/app/Http/Controllers/VillagesController.php b/app/Http/Controllers/VillagesController.php index 7f6dcdf..7126d4e 100644 --- a/app/Http/Controllers/VillagesController.php +++ b/app/Http/Controllers/VillagesController.php @@ -2,6 +2,7 @@ namespace Modules\Location\Http\Controllers; + use Illuminate\Support\Facades\Auth; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Maatwebsite\Excel\Facades\Excel; @@ -15,21 +16,37 @@ class VillagesController extends Controller { - public $user; + protected $user; + public function __construct() + { + $this->user = Auth::guard('web')->user(); + } + + /** + * Display a listing of the resource. + */ public function index() { + if (is_null($this->user) || !$this->user->can('location.read')) { + abort(403, 'Sorry! You are not allowed to view villages.'); + } + $provinces = Province::all(); return view('location::villages.index',compact('provinces')); } public function store(VillageRequest $request) { + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create villages.'); + } + $validate = $request->validated(); if ($validate) { try { - $village = Village::create($validate); + Village::create($validate); return redirect() ->route('locations.villages.index') ->with('success', 'Village created successfully'); @@ -41,12 +58,20 @@ public function create() { + if (is_null($this->user) || !$this->user->can('location.create')) { + abort(403, 'Sorry! You are not allowed to create villages.'); + } + $provinces = Province::all(); return view('location::villages.create', compact('provinces')); } public function edit($id) { + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to update villages.'); + } + $village = Village::find($id); $provinces = Province::all(); $cities = City::where('province_code', $village->province_code)->get(); @@ -56,6 +81,10 @@ public function update(VillageRequest $request, $id) { + if (is_null($this->user) || !$this->user->can('location.update')) { + abort(403, 'Sorry! You are not allowed to update villages.'); + } + $validate = $request->validated(); if ($validate) { @@ -73,23 +102,31 @@ public function destroy($id) { + if (is_null($this->user) || !$this->user->can('location.delete')) { + return response()->json(['success' => false,'message' => 'Sorry! You are not allowed to delete villages.'], 403); + } + try { Village::destroy($id); - echo json_encode(['message' => 'Village deleted successfully', 'success' => true]); + return json_encode(['message' => 'Village deleted successfully', 'success' => true]); } catch (Exception $e) { - echo json_encode(['message' => 'Failed to delete Village', 'success' => false]); + return json_encode(['message' => 'Failed to delete Village', 'success' => false]); } } public function export(Request $request) { + if (is_null($this->user) || !$this->user->can('location.export')) { + abort(403, 'Sorry! You are not allowed to export villages.'); + } + return Excel::download(new VillagesExport, 'villages.xlsx'); } public function dataForDatatables(Request $request) { - if (is_null($this->user) || !$this->user->can('provinces.view')) { - //abort(403, 'Sorry! You are not allowed to view users.'); + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false,'message' => 'Sorry! You are not allowed to view villages.'], 403); } // Retrieve data from the database @@ -181,10 +218,18 @@ } public function getVillagesByDistrictId($id){ + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false,'message' => 'Sorry! You are not allowed to view villages.'], 403); + } + return response()->json(Village::where('district_code', $id)->get()); } public function getPostalCodesByVillageId($id){ + if (is_null($this->user) || !$this->user->can('location.read')) { + return response()->json(['success' => false,'message' => 'Sorry! You are not allowed to view villages.'], 403); + } + return response()->json(Village::where('code', $id)->first()); } diff --git a/database/seeders/LocationDatabaseSeeder.php b/database/seeders/LocationDatabaseSeeder.php index 3437d1f..d59b3b9 100644 --- a/database/seeders/LocationDatabaseSeeder.php +++ b/database/seeders/LocationDatabaseSeeder.php @@ -13,6 +13,7 @@ class LocationDatabaseSeeder extends Seeder public function run(): void { $this->call([ + PermissionSeeder::class, ProvinceSeeder::class, CitySeeder::class, DistrictSeeder::class, diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php new file mode 100644 index 0000000..e6addbd --- /dev/null +++ b/database/seeders/PermissionSeeder.php @@ -0,0 +1,50 @@ +data(); + + foreach ($data as $value) { + $group = PermissionGroup::updateOrCreate([ + 'name' => $value['name'], + 'slug' => Str::slug($value['name']) + ]); + + foreach ($this->crudActions($group->name) as $action) { + $data[] = ['name' => $action, 'group' => $group->id]; + } + } + } + + public function data() + { + return [ + ['name' => 'location'] + ]; + } + + public function crudActions($name) + { + $actions = []; + // list of permission actions + $crud = ['create', 'read', 'update', 'delete','export', 'authorize', 'report','restore']; + + + foreach ($crud as $value) { + $actions[] = $name . '.' . $value; + } + + return $actions; + } + }