diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php new file mode 100644 index 0000000..e38699a --- /dev/null +++ b/app/Http/Controllers/AuthController.php @@ -0,0 +1,39 @@ +validate([ + 'email' => 'required|email', + 'password' => 'required', + ]); + + if (Auth::attempt($credentials, $request->boolean('remember'))) { + $request->session()->regenerate(); + return redirect()->intended('/map'); + } + + return back() + ->withErrors(['email' => 'Email atau password salah.']) + ->onlyInput('email'); + } + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } +} diff --git a/routes/api.php b/routes/api.php index 94f8d6f..495582e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,15 +1,5 @@ name('login')->middleware('guest'); +Route::post('/login', [AuthController::class, 'login'])->middleware('guest'); +Route::post('/logout', [AuthController::class, 'logout'])->name('logout')->middleware('auth'); -Route::get('/map', function () { - return view('map'); -}); +// All other routes require authentication +Route::middleware('auth')->group(function () { -Route::get('/data', function () { - return view('data'); + // Web pages + Route::get('/', fn() => view('welcome')); + Route::get('/map', fn() => view('map')); + Route::get('/data', fn() => view('data')); + + // API routes moved here for session + CSRF middleware + Route::prefix('api')->group(function () { + + // Rumah Ibadah — read: all roles, write: administrator + pengurus_ibadah + Route::get('/ibadah', [IbadahController::class, 'index']); + Route::middleware('role:administrator|pengurus_ibadah')->group(function () { + Route::post('/ibadah', [IbadahController::class, 'store']); + Route::put('/ibadah/{id}', [IbadahController::class, 'update']); + Route::delete('/ibadah/{id}', [IbadahController::class, 'destroy']); + }); + + // Rumah Miskin — read: all roles, write: administrator + petugas_pendataan + Route::get('/miskin', [MiskinController::class, 'index']); + Route::middleware('role:administrator|petugas_pendataan')->group(function () { + Route::post('/miskin', [MiskinController::class, 'store']); + Route::put('/miskin/{id}', [MiskinController::class, 'update']); + Route::delete('/miskin/{id}', [MiskinController::class, 'destroy']); + }); + }); }); diff --git a/tests/Feature/AuthTest.php b/tests/Feature/AuthTest.php index fb9e132..8709ca0 100644 --- a/tests/Feature/AuthTest.php +++ b/tests/Feature/AuthTest.php @@ -46,4 +46,63 @@ class AuthTest extends TestCase $this->assertNotNull($user); $this->assertTrue($user->hasRole('administrator')); } + + public function test_login_page_is_accessible(): void + { + $response = $this->get('/login'); + $response->assertStatus(200); + $response->assertViewIs('auth.login'); + } + + public function test_login_with_valid_credentials_redirects_to_map(): void + { + $this->artisan('db:seed', ['--class' => 'RolesAndAdminSeeder']); + + $response = $this->post('/login', [ + 'email' => 'admin@webgis.local', + 'password' => 'admin123', + ]); + + $response->assertRedirect('/map'); + } + + public function test_login_with_invalid_credentials_returns_error(): void + { + $response = $this->post('/login', [ + 'email' => 'wrong@email.com', + 'password' => 'wrongpass', + ]); + + $response->assertSessionHasErrors('email'); + } + + public function test_logout_redirects_to_login(): void + { + $this->artisan('db:seed', ['--class' => 'RolesAndAdminSeeder']); + $user = User::where('email', 'admin@webgis.local')->first(); + + $response = $this->actingAs($user)->post('/logout'); + + $response->assertRedirect('/login'); + } + + public function test_unauthenticated_user_cannot_access_map(): void + { + $response = $this->get('/map'); + $response->assertRedirect('/login'); + } + + public function test_pemangku_kebijakan_cannot_delete_ibadah(): void + { + $this->artisan('db:seed', ['--class' => 'RolesAndAdminSeeder']); + + $viewer = User::firstOrCreate( + ['email' => 'viewer@test.com'], + ['name' => 'Viewer', 'password' => bcrypt('password')] + ); + $viewer->syncRoles(['pemangku_kebijakan']); + + $response = $this->actingAs($viewer)->delete('/api/ibadah/999'); + $response->assertStatus(403); + } }