# 🔐 Sistem Autentikasi Admin-Only - Dokumentasi
## 📋 Ringkas Perubahan
Sistem autentikasi telah dirapi menjadi **ADMIN-ONLY** yang konsisten dan aman untuk Tugas Akhir:
✅ Hanya 1 tipe pengguna: ADMIN
✅ Tidak ada public registration
✅ Login hanya untuk admin
✅ Admin baru ditambah melalui dashboard
✅ Role otomatis 'admin', tidak dapat dipilih
✅ Query hanya admin
✅ Kode lebih rapi dan aman
---
## 🔧 Perubahan di Controller
### 1. **AdminController.php** - store() method
**Sebelum:**
```php
'role' => 'required|in:admin' // Role dari input
'password' => 'required|string|min:6', // Min 6 karakter
$role = $request->role // Ambil dari input
```
**Sesudah:**
```php
// Role TIDAK ada di validation, tidak ada di request
'password' => 'required|string|min:8', // Min 8 karakter (lebih aman)
'role' => 'admin' // SELALU hardcoded 'admin'
```
**Alasan:**
- Role tidak bisa dipilih user, otomatis 'admin'
- Password lebih kuat (8 karakter)
- Mencegah user mengirim role dengan nilai lain
---
### 2. **AdminController.php** - update() method
**Sebelum:**
```php
'role' => 'required|in:admin' // Dari input
$role = $request->role // Bisa diubah
```
**Sesudah:**
```php
// Role TIDAK ada di validation
// Role TIDAK diupdate (hanya name & email)
if ($admin->role !== 'admin') {
return error; // Cek pastikan role admin
}
```
**Alasan:**
- Role tidak boleh diubah
- Hanya admin yang bisa dikelola
- Pastikan integritas data
---
### 3. **AdminController.php** - destroy() method
**Sebelum:**
```php
// Cek hanya id yang sedang login
```
**Sesudah:**
```php
if ($admin->role !== 'admin') {
return error; // Hanya admin yang bisa dihapus
}
// Plus: Cek id yang sedang login
```
**Alasan:**
- Extra validation: pastikan yang dihapus hanya admin
- Keamanan berlapis
---
### 4. **AdminController.php** - index() method
**Sebelum:**
```php
User::where('role', 'admin')->get();
\Log::info('Admins fetched...'); // Debug log
```
**Sesudah:**
```php
User::where('role', 'admin')
->orderBy('created_at', 'desc') // Sort terbaru
->get();
// Log dihapus (clean code)
```
**Alasan:**
- Lebih rapi tanpa debug log
- Sorting lebih user-friendly (admin terbaru di atas)
---
### 5. **UploadController.php** - adminLogin() method
**Sebelum:**
```php
$user = DB::table('users')->where('email', $email)->first();
// Ambil user dengan email apapun
```
**Sesudah:**
```php
$user = DB::table('users')
->where('email', $email)
->where('role', 'admin') // HANYA admin
->first();
```
**Alasan:**
- Double-check: query hanya ambil admin
- Jika ada user non-admin, tidak bisa login
- Keamanan berlapis
---
## 🎨 Perubahan di View
### **manage-admin.blade.php** - Form Modal
**Sebelum:**
```blade
```
**Sesudah:**
```blade
```
**Alasan:**
- User tidak perlu memilih role
- Otomatis 'admin'
- Form lebih simple dan fokus
- Tidak ada kebingungan
---
## 📝 Ringkas Baris-Baris Penting
### AdminController.php
**Line 19 (store method):**
```php
'role' => 'admin', // SELALU 'admin', bukan dari request
```
**Line 40 (update method):**
```php
if ($admin->role !== 'admin') {
return response()->json(['error' => 'Hanya admin yang dapat dikelola'], 422);
}
// Pastikan hanya admin yang update
```
**Line 59 (update method):**
```php
$admin->update([
'name' => $request->name,
'email' => $request->email,
// Role TIDAK diupdate
]);
```
**Line 72 (destroy method):**
```php
if ($admin->role !== 'admin') {
return response()->json(['error' => 'Hanya admin yang dapat dihapus'], 422);
}
```
---
### UploadController.php
**Line 211 (adminLogin method):**
```php
$user = \DB::table('users')
->where('email', $email)
->where('role', 'admin') // HANYA admin bisa login
->first();
```
---
### manage-admin.blade.php
**Line 145:**
```blade
```
---
## ✅ Validasi Sistem
### Admin Creation Flow
```
User (Admin yang login)
↓
Click "Tambah Admin"
↓
Form Modal terbuka
├─ Input: Nama
├─ Input: Email
├─ Input: Password
├─ Role: HIDDEN (selalu 'admin')
↓
Submit form
↓
AdminController::store()
├─ Cek session (login?)
├─ Validasi input
├─ SET role = 'admin' (hardcoded)
├─ Create user
↓
Success: Admin baru dengan role 'admin'
```
### Admin Update Flow
```
User (Admin yang login)
↓
Click "Edit Admin"
↓
Form Modal terbuka
├─ Input: Nama (bisa diubah)
├─ Input: Email (bisa diubah)
├─ Input: Password (optional)
├─ Role: HIDDEN
↓
Submit form
↓
AdminController::update()
├─ Cek session
├─ Validasi input (role TIDAK ada)
├─ Cek $admin->role === 'admin'
├─ Update hanya name & email
↓
Success: Admin updated (role tetap 'admin')
```
### Admin Delete Flow
```
User (Admin yang login)
↓
Click "Hapus Admin"
↓
Confirm dialog
↓
AdminController::destroy()
├─ Cek session
├─ Cek role === 'admin'
├─ Cek tidak sedang login
├─ Delete
↓
Success: Admin deleted
```
### Admin Login Flow
```
User (belum login)
↓
Go to /admin/login
↓
Form input:
├─ Email
├─ Password
↓
Submit
↓
UploadController::adminLogin()
├─ Validasi input
├─ Query: WHERE email & WHERE role='admin'
├─ Cek password & role
├─ Set session
↓
Success: Login ke dashboard (atau error jika bukan admin)
```
---
## 🔒 Keamanan
### Validasi Berlapis
| Layer | Check |
|-------|-------|
| 1 | Session check (logged in?) |
| 2 | Input validation |
| 3 | Role validation (role === 'admin') |
| 4 | Permission check (current user check) |
### Password Security
| Aspek | Implementasi |
|-------|---------------|
| Minimum length | 8 karakter (naik dari 6) |
| Hashing | bcrypt (Laravel default) |
| Storing | Hashed, tidak plain text |
| Reset | Tidak ada (manual via admin) |
### Query Safety
```php
// Sebelum
WHERE role = 'admin' // Tergantung role user
// Sesudah
WHERE email = $email AND role = 'admin' // Hanya admin
```
---
## 📋 Checklist Implementasi
- [x] AdminController::store() - role hardcoded 'admin'
- [x] AdminController::update() - role tidak bisa diubah
- [x] AdminController::destroy() - validasi role
- [x] AdminController::index() - query dengan role filter
- [x] UploadController::adminLogin() - query hanya admin
- [x] manage-admin.blade.php - role hidden field
- [x] Password minimum 8 karakter
- [x] Debug log dihapus
- [x] Kode lebih rapi dan konsisten
---
## 🎯 Testing
### Test 1: Tambah Admin
```
1. Login sebagai admin
2. Pergi ke "Kelola Admin"
3. Click "Tambah Admin"
4. Isi form (name, email, password)
5. Cek di database: role harus 'admin'
✅ Expected: Admin baru dengan role='admin'
```
### Test 2: Edit Admin
```
1. Click "Edit" admin
2. Ubah name & email
3. Submit
4. Cek database: role tetap 'admin'
✅ Expected: Name & email updated, role unchanged
```
### Test 3: Hapus Admin
```
1. Click "Hapus" admin (bukan yang logged in)
2. Confirm
✅ Expected: Admin deleted
❌ Should fail: Jika admin yang logged in
```
### Test 4: Login Admin
```
1. Logout
2. Login dengan email admin
3. Masukkan password
✅ Expected: Login berhasil
❌ Should fail: Email yang bukan admin
```
---
## 📊 Database Structure (Setelah Implementasi)
```sql
users table:
├─ id: INT
├─ name: VARCHAR
├─ email: VARCHAR (UNIQUE)
├─ email_verified_at: TIMESTAMP
├─ password: VARCHAR (hashed)
├─ role: VARCHAR = 'admin' (SELALU admin)
├─ remember_token: VARCHAR
├─ created_at: TIMESTAMP
└─ updated_at: TIMESTAMP
PENTING:
- role SELALU 'admin' untuk semua user
- Tidak ada user dengan role 'user'
- Email UNIQUE (tidak bisa duplikat)
```
---
## 🎓 Best Practices yang Diterapkan
✅ **Validation**: Input divalidasi sebelum proses
✅ **Authorization**: Session & role check
✅ **Secure Password**: Minimum 8 karakter
✅ **Consistent Query**: Role filter di semua query
✅ **Clean Code**: Log debug dihapus
✅ **Single Responsibility**: Setiap method fokus satu tugas
✅ **Error Handling**: Return proper HTTP status & messages
✅ **DRY**: Tidak ada duplikasi logic
---
## 🚀 Next Steps
### Optional Enhancements
1. **Password Reset**
- Tambah forgot password untuk admin
- Reset via email link (secure token)
2. **Activity Logging**
- Log setiap action admin (create, update, delete)
- Simpan di activity_logs table
3. **Audit Trail**
- Track siapa yang membuat/update/delete admin
- Timestamp untuk setiap action
4. **Session Timeout**
- Auto logout setelah N menit idle
- Config di config/session.php
5. **2FA (Two-Factor Authentication)**
- SMS atau email OTP
- Extra security untuk admin
---
## 📞 Ringkas Perubahan File
| File | Baris | Perubahan |
|------|-------|-----------|
| AdminController.php | 23-24 | Hapus debug log, add sorting |
| AdminController.php | 30-34 | Hapus role validation, min 8 pass |
| AdminController.php | 38 | Role hardcoded 'admin' |
| AdminController.php | 40-47 | Add role check, hapus role update |
| AdminController.php | 72-74 | Add role validation pada destroy |
| UploadController.php | 211-213 | Add role='admin' to query |
| manage-admin.blade.php | 145 | Change select to hidden input |
---
**Status:** ✅ IMPLEMENTASI SELESAI & SIAP UNTUK TA
**Tanggal:** February 2026
Sistem autentikasi Anda sekarang **CLEAN, SECURE, dan ADMIN-ONLY**! 🎉