EAS-202310715297/README.md
2026-05-02 21:30:05 +07:00

179 lines
8.0 KiB
Markdown

# 📱 Aplikasi Absensi Akademik UBHARA Jaya
[📋 Changelog](./CHANGELOG.md)
## 📌 Deskripsi Proyek
Proyek ini merupakan **Tugas Project Akhir Mata Kuliah Pemrograman Mobile** yang mengimplementasikan sistem absensi akademik berbasis **Client-Server**. Aplikasi mobile dibangun menggunakan **Kotlin (Jetpack Compose)**, sedangkan sisi server menggunakan **Python Flask** dengan database **MySQL**.
Sistem ini dirancang dengan validasi ketat berlapis menggunakan **Geofencing (GPS)**, **Location Token**, **Device Binding**, dan **Deteksi Wajah (Face Detection)** untuk status kehadiran "Hadir", serta mendukung pengiriman bukti dokumen untuk status "Sakit/Izin". Seluruh data terintegrasi secara real-time ke **N8N Webhook** untuk pelaporan otomatis.
---
## 🎯 Tujuan Proyek
- Mengimplementasikan arsitektur **REST API** antara Android dan Python Flask.
- Menerapkan **Face Detection** menggunakan CameraX untuk memvalidasi kehadiran fisik mahasiswa.
- Mencegah kecurangan absensi dengan sistem keamanan berlapis (**8 Security Fix**).
- Mengelola status kehadiran otomatis (**Auto-Alfa**) pada server jika mahasiswa lupa absen.
- Melatih kemampuan Fullstack Mobile Development (Backend, Database, & Mobile UI).
---
## 🚀 Fitur Utama
### 📱 Sisi Mobile (Android - Jetpack Compose)
- **Modern UI**: Antarmuka modern menggunakan **Material3** & **Jetpack Compose**.
- **Smart Attendance**:
- **Hadir**: Wajib berada di radius kampus & wajib deteksi wajah (Real-time).
- **Sakit/Izin**: Wajib upload foto surat dokter/bukti (Tanpa validasi radius).
- **Anti-Fraud Berlapis**:
- Deteksi dan penolakan **Fake GPS / Mock Location** di sisi client.
- Validasi koordinat GPS di **sisi server** (tidak bisa di-bypass via Postman).
- **Location Token** — token sekali pakai valid 2 menit, diterbitkan server setelah GPS diverifikasi.
- **Device Binding** — akun terikat ke satu perangkat, token tidak bisa dibagikan ke HP lain.
- **Riwayat & Bukti**: Mahasiswa dapat melihat riwayat kehadiran beserta foto bukti yang tersimpan di server.
- **Profil Mahasiswa**: Menampilkan data akademik dan fitur logout.
### 💻 Sisi Backend (Python Flask)
- **JWT Authentication**: Keamanan berbasis token + device binding untuk setiap request.
- **8 Lapis Keamanan**: Validasi koordinat server-side, foto server-side, rate limiting, kepemilikan jadwal, jam kelas aktif, location token, dan deteksi anomali koordinat.
- **Auto-Alfa Trigger**: Sistem otomatis menandai "TIDAK HADIR" jika jam kuliah berakhir dan mahasiswa belum absen.
- **N8N Integration**: Data absensi yang valid dikirim otomatis ke webhook N8N untuk notifikasi/reporting.
- **Image Handling**: Kompresi foto (Base64) otomatis untuk efisiensi penyimpanan database.
---
## 🗺️ Mekanisme Absensi
### 1. Absensi Status "HADIR"
1. Mahasiswa memilih Jadwal Kelas yang aktif.
2. Sistem mengecek **GPS** di sisi client:
- Apakah di dalam radius **500m** dari kampus?
- Apakah terdeteksi aplikasi **Fake GPS / Mock Location**?
3. App meminta **Location Token** ke server `/api/absensi/request-location-token`:
- Server memvalidasi ulang koordinat (server-side GPS validation).
- Server mendeteksi anomali koordinat (presisi rendah, koordinat copy-paste, luar Indonesia).
- Server menerbitkan **Location Token** sekali pakai, valid **2 menit**.
4. Sistem membuka **Kamera Deteksi Wajah**:
- Tombol shutter hanya aktif jika wajah terdeteksi.
5. Data (Location Token + Foto Wajah) dikirim ke server `/api/absensi/submit`:
- Server memvalidasi Location Token (keaslian, kepemilikan, masa berlaku, one-time use).
- Server memvalidasi foto (format, ukuran minimum).
- Server memvalidasi kepemilikan jadwal & jam kelas aktif.
### 2. Absensi Status "SAKIT / IZIN"
1. Mahasiswa memilih status Sakit atau Izin.
2. Validasi lokasi dilewati (bisa absen dari rumah/RS).
3. Sistem membuka **Kamera Dokumen** (Tanpa deteksi wajah).
4. Mahasiswa memfoto surat keterangan.
5. Data dikirim ke server.
### 3. Logika Auto-Alfa (Server)
- Setiap kali jadwal dimuat, server mengecek jadwal yang `jam_selesai < jam_sekarang`.
- Jika mahasiswa belum ada record absensi pada jam tersebut, server otomatis menginput status **"TIDAK HADIR"**.
---
## 🔐 Security Architecture
Sistem mengimplementasikan **8 lapis keamanan** untuk mencegah kecurangan absensi:
| # | Fix | Deskripsi |
|---|---|---|
| 1 | **Server-side GPS Validation** | Koordinat divalidasi ulang di server, tidak hanya di client Android |
| 2 | **Server-side Foto Validation** | Foto divalidasi format (JPG/PNG/WEBP) & ukuran minimum di server |
| 3 | **JWT Device Binding** | Token JWT terikat ke `device_id` unik HP — tidak bisa dibagikan |
| 4 | **Rate Limiting** | Maks 5x login/menit, maks 3x submit absensi/menit per user |
| 5 | **Jadwal Ownership Validation** | Mahasiswa hanya bisa absen di jadwal jurusan & semesternya sendiri |
| 6 | **Jam Kelas Aktif Validation** | Absensi hanya diterima selama jam kelas berlangsung |
| 7 | **Location Token** | Token sekali pakai valid 2 menit — cegah bypass koordinat via Postman/curl |
| 8 | **Anomali Koordinat Detection** | Koordinat 0,0 / terlalu bulat / identik titik kampus / luar Indonesia ditolak |
---
## 🛠️ Teknologi yang Digunakan
- **Mobile Platform**: Android (Kotlin)
- **UI Framework**: Jetpack Compose + Material3
- **Camera Engine**: CameraX + ML Kit (Face Analysis)
- **Backend Framework**: Python Flask
- **Database**: MySQL
- **Security**: JWT + Device Binding + Location Token + Rate Limiting
- **Integrasi**: N8N Webhook
- **Protocol**: HTTP/REST (JSON)
- **AI**: Gemini & Claude (Sebagai Tools dalam Membantu Pengembangan)
---
## 📡 API Endpoints
| Method | Endpoint | Auth | Fungsi |
|---|---|---|---|
| GET | `/api/health` | ✗ | Cek server aktif |
| POST | `/api/auth/register` | ✗ | Daftar mahasiswa + device binding |
| POST | `/api/auth/login` | ✗ | Login + verifikasi device |
| GET | `/api/mahasiswa/profile` | ✓ | Profil mahasiswa |
| GET | `/api/jadwal/today` | ✓ | Jadwal hari ini + trigger auto-alfa |
| POST | `/api/absensi/request-location-token` | ✓ | Minta location token (wajib sebelum submit) |
| POST | `/api/absensi/submit` | ✓ | Kirim absensi + location token |
| GET | `/api/absensi/history` | ✓ | Riwayat absensi |
| GET | `/api/absensi/photo/<id>` | ✓ | Ambil foto absensi |
| POST | `/api/admin/reset-device` | Admin Key | Reset device binding mahasiswa |
> Semua endpoint `✓` butuh header: `Authorization: Bearer <token>`
---
## 🔐 Izin Aplikasi (Permissions)
Aplikasi memerlukan izin berikut:
- `INTERNET`: Koneksi ke Server API.
- `ACCESS_FINE_LOCATION`: Validasi koordinat presisi tinggi.
- `ACCESS_COARSE_LOCATION`: Validasi koordinat jaringan.
- `CAMERA`: Pengambilan foto bukti kehadiran & deteksi wajah.
---
## 📂 Mockup
![mockup](Mockup.png)
---
## ⚙️ Konfigurasi
### Backend
1. Install dependensi:
```bash
pip install flask flask-cors mysql-connector-python PyJWT bcrypt requests
```
2. Sesuaikan `DB_CONFIG` di `app_secured_v2.py`:
```python
DB_CONFIG = {
'host': 'localhost',
'user': 'root',
'password': '', # sesuaikan
'database': 'db_absensi_akademik'
}
```
3. Jalankan server:
```bash
python app_secured_v2.py
```
### Android
Sesuaikan `BASE_URL` pada `MainActivity.kt` (Object `AppConstants`) dengan IP laptop:
```kotlin
const val BASE_URL = "http://192.168.x.x:5000"
```
> ⚠️ HP Android & laptop harus terhubung ke **WiFi yang sama**.
### Fake GPS Testing
Pastikan mematikan aplikasi Mock Location saat pengujian fitur Hadir. Koordinat yang berasal dari Mock Location akan ditolak baik di sisi client maupun server.
---
## 📊 Pengecekan & Monitoring
- **Monitoring**: https://ntfy.ubharajaya.ac.id/EAS
- **Data Spreadsheet**: https://docs.google.com/spreadsheets/d/1jH15MfnNgpPGuGeid0hYfY7fFUHCEFbCmg8afTyyLZs/edit?gid=0#gid=0
## 🔗 Webhook N8N
- **Test**: https://n8n.lab.ubharajaya.ac.id/webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
- **Production**: https://n8n.lab.ubharajaya.ac.id/webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254