mengupdate database.sql

This commit is contained in:
2026-06-10 17:10:53 +07:00
parent a6543643a8
commit 073b9ac895
3 changed files with 502 additions and 342 deletions
+34 -21
View File
@@ -5,10 +5,11 @@
// ============================================================
// Konfigurasi database
define('DB_HOST', 'vg4so4ccs0444o4cgkssgos8');
define('DB_NAME', 'default');
define('DB_USER', 'mysql');
define('DB_PASS', 'tg9lvPlr4hgUhgtT7aPq9XelkCEvvMGtsoV8eB4dD5FAkz891PwkJT340xmaEWxL');
define('DB_HOST', 'vg4so4ccs0444o4cgkssgos8');
define('DB_PORT', 3306);
define('DB_NAME', 'default');
define('DB_USER', 'mysql');
define('DB_PASS', 'tg9lvPlr4hgUhgtT7aPq9XelkCEvvMGtsoV8eB4dD5FAkz891PwkJT340xmaEWxL');
define('DB_CHARSET', 'utf8mb4');
// Direktori upload foto laporan
@@ -22,13 +23,14 @@ if (session_status() === PHP_SESSION_NONE) {
// ── Koneksi PDO ──────────────────────────────────────────────
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
"mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
]
);
} catch (PDOException $e) {
@@ -61,7 +63,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
* Kirim respon JSON standar lalu hentikan eksekusi.
* Format: {"success": true/false, "data": ..., "message": "..."}
*/
function jsonResponse($data = null, string $message = '', bool $success = true, int $httpCode = 200, array $extra = []): void {
function jsonResponse($data = null, string $message = '', bool $success = true, int $httpCode = 200, array $extra = []): void
{
http_response_code($httpCode);
header('Content-Type: application/json; charset=utf-8');
$response = [
@@ -80,20 +83,22 @@ function jsonResponse($data = null, string $message = '', bool $success = true,
/**
* Bersihkan input string dari tag HTML.
*/
function clean(string $value): string {
function clean(string $value): string
{
return htmlspecialchars(strip_tags(trim($value)), ENT_QUOTES, 'UTF-8');
}
/**
* Hitung jarak Haversine antara dua koordinat dalam kilometer.
*/
function haversine(float $lat1, float $lng1, float $lat2, float $lng2): float {
function haversine(float $lat1, float $lng1, float $lat2, float $lng2): float
{
$R = 6371; // Radius bumi dalam km
$dLat = deg2rad($lat2 - $lat1);
$dLng = deg2rad($lng2 - $lng1);
$a = sin($dLat / 2) * sin($dLat / 2) +
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
sin($dLng / 2) * sin($dLng / 2);
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
sin($dLng / 2) * sin($dLng / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return round($R * $c, 4);
}
@@ -102,7 +107,8 @@ function haversine(float $lat1, float $lng1, float $lat2, float $lng2): float {
* Auto-assign: cari rumah ibadah terdekat yang radius-nya mencakup lokasi KK.
* Mengembalikan ['rumah_ibadah_id' => int|null, 'jarak_km' => float|null]
*/
function autoAssign(PDO $pdo, float $lat, float $lng): array {
function autoAssign(PDO $pdo, float $lat, float $lng): array
{
$result = ['rumah_ibadah_id' => null, 'jarak_km' => null];
$stmt = $pdo->query("SELECT id, lat, lng, radius_km FROM rumah_ibadah");
@@ -132,7 +138,8 @@ function autoAssign(PDO $pdo, float $lat, float $lng): array {
* Cek apakah user sudah login. Jika belum, kirim 401.
* Mengembalikan data session user.
*/
function requireLogin(): array {
function requireLogin(): array
{
if (empty($_SESSION['user'])) {
jsonResponse(null, 'Tidak diizinkan. Silakan login terlebih dahulu.', false, 401);
}
@@ -143,7 +150,8 @@ function requireLogin(): array {
* Cek apakah role user termasuk dalam daftar yang diizinkan.
* Jika tidak, kirim 403.
*/
function requireRole(array $allowedRoles): array {
function requireRole(array $allowedRoles): array
{
$user = requireLogin();
if (!in_array($user['role'], $allowedRoles)) {
jsonResponse(null, 'Akses ditolak. Role Anda tidak memiliki izin.', false, 403);
@@ -155,7 +163,8 @@ function requireRole(array $allowedRoles): array {
* Blokir aksi tulis (POST/PUT/DELETE) untuk role walikota.
* Walikota hanya boleh GET.
*/
function blockWalikotaWrite(): void {
function blockWalikotaWrite(): void
{
if (!empty($_SESSION['user']) && $_SESSION['user']['role'] === 'walikota') {
$method = $_SERVER['REQUEST_METHOD'];
if (in_array($method, ['POST', 'PUT', 'DELETE'])) {
@@ -168,7 +177,8 @@ function blockWalikotaWrite(): void {
* Generate kode pengurus dengan format: RI-[JENIS 3 HURUF]-[RANDOM 4 DIGIT]
* Contoh: RI-MSJ-4821, RI-GRJ-7153
*/
function generateKodePengurus(PDO $pdo, string $jenis): string {
function generateKodePengurus(PDO $pdo, string $jenis): string
{
// Mapping jenis ke 3 huruf
$map = [
'Masjid' => 'MSJ',
@@ -199,7 +209,8 @@ function generateKodePengurus(PDO $pdo, string $jenis): string {
* Cek rate limit untuk IP tertentu. Maks 5 submit per jam.
* Mengembalikan true jika masih diizinkan, false jika melebihi batas.
*/
function checkRateLimit(PDO $pdo, string $ip): bool {
function checkRateLimit(PDO $pdo, string $ip): bool
{
// Hapus record yang lebih dari 1 jam
$pdo->prepare("DELETE FROM rate_limit WHERE created_at < NOW() - INTERVAL 1 HOUR")->execute();
@@ -222,7 +233,8 @@ function checkRateLimit(PDO $pdo, string $ip): bool {
/**
* Handle upload file foto. Mengembalikan path relatif file atau null.
*/
function handleUpload(string $fieldName): ?string {
function handleUpload(string $fieldName): ?string
{
if (!isset($_FILES[$fieldName]) || $_FILES[$fieldName]['error'] !== UPLOAD_ERR_OK) {
return null;
}
@@ -259,7 +271,8 @@ function handleUpload(string $fieldName): ?string {
/**
* Dapatkan IP address client (mendukung proxy).
*/
function getClientIP(): string {
function getClientIP(): string
{
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
}