feat: add AuthController, protect routes, move API to web middleware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class AuthController extends Controller
|
||||||
|
{
|
||||||
|
public function showLogin()
|
||||||
|
{
|
||||||
|
return view('auth.login');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
$credentials = $request->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');
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-11
@@ -1,15 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\IbadahController;
|
|
||||||
use App\Http\Controllers\MiskinController;
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::get('/ibadah', [IbadahController::class, 'index']);
|
// API routes are handled in routes/web.php under /api prefix with session auth
|
||||||
Route::post('/ibadah', [IbadahController::class, 'store']);
|
|
||||||
Route::put('/ibadah/{id}', [IbadahController::class, 'update']);
|
|
||||||
Route::delete('/ibadah/{id}', [IbadahController::class, 'destroy']);
|
|
||||||
|
|
||||||
Route::get('/miskin', [MiskinController::class, 'index']);
|
|
||||||
Route::post('/miskin', [MiskinController::class, 'store']);
|
|
||||||
Route::put('/miskin/{id}', [MiskinController::class, 'update']);
|
|
||||||
Route::delete('/miskin/{id}', [MiskinController::class, 'destroy']);
|
|
||||||
|
|||||||
+33
-8
@@ -1,15 +1,40 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\AuthController;
|
||||||
|
use App\Http\Controllers\IbadahController;
|
||||||
|
use App\Http\Controllers\MiskinController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::get('/', function () {
|
// Auth routes (public, redirect to /map if already logged in)
|
||||||
return view('welcome');
|
Route::get('/login', [AuthController::class, 'showLogin'])->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 () {
|
// All other routes require authentication
|
||||||
return view('map');
|
Route::middleware('auth')->group(function () {
|
||||||
});
|
|
||||||
|
|
||||||
Route::get('/data', function () {
|
// Web pages
|
||||||
return view('data');
|
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']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,4 +46,63 @@ class AuthTest extends TestCase
|
|||||||
$this->assertNotNull($user);
|
$this->assertNotNull($user);
|
||||||
$this->assertTrue($user->hasRole('administrator'));
|
$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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user