# πŸ“± 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/` | βœ“ | Ambil foto absensi | | POST | `/api/admin/reset-device` | Admin Key | Reset device binding mahasiswa | > Semua endpoint `βœ“` butuh header: `Authorization: Bearer ` --- ## πŸ” 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