mengubah sistem menjadi lebih terfokus ke poverty
This commit is contained in:
@@ -6,10 +6,11 @@ mysqli_report(MYSQLI_REPORT_OFF);
|
||||
if (!function_exists('loadDatabaseConfig')) {
|
||||
function loadDatabaseConfig(): array {
|
||||
$config = [
|
||||
'host' => getenv('DB_HOST') ?: 'localhost',
|
||||
'host' => getenv('DB_HOST') ?: '127.0.0.1',
|
||||
'user' => getenv('DB_USER') ?: 'root',
|
||||
'pass' => getenv('DB_PASS') ?: '',
|
||||
'name' => getenv('DB_NAME') ?: 'webgis_poverty',
|
||||
'port' => (int)(getenv('DB_PORT') ?: 3306),
|
||||
'charset' => getenv('DB_CHARSET') ?: 'utf8mb4',
|
||||
];
|
||||
|
||||
@@ -31,12 +32,13 @@ define('DB_HOST', $dbConfig['host']);
|
||||
define('DB_USER', $dbConfig['user']);
|
||||
define('DB_PASS', $dbConfig['pass']);
|
||||
define('DB_NAME', $dbConfig['name']);
|
||||
define('DB_PORT', (int)$dbConfig['port']);
|
||||
define('DB_CHARSET', $dbConfig['charset']);
|
||||
|
||||
function getDB(): mysqli {
|
||||
static $conn = null;
|
||||
if ($conn === null) {
|
||||
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
|
||||
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT);
|
||||
if ($conn->connect_error) {
|
||||
error_log('DB connection failed: ' . $conn->connect_error);
|
||||
http_response_code(500);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
// api/config/setup_users.php
|
||||
require_once __DIR__ . '/database.php';
|
||||
|
||||
$db = getDB();
|
||||
|
||||
// Create users table
|
||||
$sql = "CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`username` VARCHAR(50) NOT NULL UNIQUE,
|
||||
`password` VARCHAR(255) NOT NULL,
|
||||
`role` ENUM('admin', 'petugas_lapangan', 'guest') NOT NULL,
|
||||
`rumah_ibadah_id` INT DEFAULT NULL,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`rumah_ibadah_id`) REFERENCES `rumah_ibadah` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
|
||||
|
||||
if ($db->query($sql)) {
|
||||
echo "Tabel 'users' berhasil dibuat atau sudah ada.\n";
|
||||
} else {
|
||||
echo "Gagal membuat tabel 'users': " . $db->error . "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Insert default users if they don't exist
|
||||
$defaultUsers = [
|
||||
[
|
||||
'username' => 'admin',
|
||||
'password' => password_hash('admin123', PASSWORD_BCRYPT),
|
||||
'role' => 'admin'
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($defaultUsers as $user) {
|
||||
$stmt = $db->prepare("SELECT id FROM users WHERE username = ?");
|
||||
$stmt->bind_param('s', $user['username']);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
if ($result->num_rows === 0) {
|
||||
$stmtInsert = $db->prepare("INSERT INTO users (username, password, role) VALUES (?, ?, ?)");
|
||||
$stmtInsert->bind_param('sss', $user['username'], $user['password'], $user['role']);
|
||||
if ($stmtInsert->execute()) {
|
||||
echo "User '" . $user['username'] . "' berhasil ditambahkan.\n";
|
||||
} else {
|
||||
echo "Gagal menambahkan user '" . $user['username'] . "': " . $stmtInsert->error . "\n";
|
||||
}
|
||||
} else {
|
||||
echo "User '" . $user['username'] . "' sudah ada.\n";
|
||||
}
|
||||
}
|
||||
echo "Setup database selesai.\n";
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
// api/dashboard_stats.php
|
||||
require_once __DIR__ . '/config/database.php';
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
// CORS and RBAC are already processed globally in response.php
|
||||
|
||||
$db = getDB();
|
||||
$stats = [];
|
||||
|
||||
// 1. Penduduk Miskin (Total KK & Total Jiwa)
|
||||
$resPm = $db->query("SELECT COUNT(*) AS total_kk, IFNULL(SUM(jumlah_anggota), 0) AS total_jiwa FROM penduduk_miskin");
|
||||
$stats['penduduk_miskin'] = $resPm->fetch_assoc();
|
||||
|
||||
// 2. Rumah Ibadah (Total)
|
||||
$resRi = $db->query("SELECT COUNT(*) AS total FROM rumah_ibadah");
|
||||
$stats['rumah_ibadah'] = $resRi->fetch_assoc();
|
||||
|
||||
|
||||
// 6. Log Bantuan (Total log & Nilai total bantuan)
|
||||
$resLb = $db->query("SELECT COUNT(*) AS total_count, IFNULL(SUM(nilai_bantuan), 0) AS total_nilai FROM log_bantuan");
|
||||
$stats['log_bantuan'] = $resLb->fetch_assoc();
|
||||
|
||||
// 7. Proximity (Dalam vs Luar Radius)
|
||||
$resProx = $db->query("SELECT status_proximity, COUNT(*) AS count FROM penduduk_miskin GROUP BY status_proximity");
|
||||
$proximity = ['dalam_radius' => 0, 'luar_radius' => 0];
|
||||
while ($row = $resProx->fetch_assoc()) {
|
||||
$key = $row['status_proximity'] === 'dalam_radius' ? 'dalam_radius' : 'luar_radius';
|
||||
$proximity[$key] += (int)$row['count'];
|
||||
}
|
||||
$stats['proximity'] = $proximity;
|
||||
|
||||
// 8. Tipe Bantuan (Pemberdayaan vs Konsumtif)
|
||||
$resTipe = $db->query("SELECT tipe_bantuan, COUNT(*) AS count FROM log_bantuan GROUP BY tipe_bantuan");
|
||||
$tipeBantuan = ['Pemberdayaan' => 0, 'Konsumtif' => 0];
|
||||
while ($row = $resTipe->fetch_assoc()) {
|
||||
$key = $row['tipe_bantuan'] === 'Pemberdayaan' ? 'Pemberdayaan' : 'Konsumtif';
|
||||
$tipeBantuan[$key] = (int)$row['count'];
|
||||
}
|
||||
$stats['tipe_bantuan'] = $tipeBantuan;
|
||||
|
||||
// 9. Rumah Ibadah Teraktif (Top 5)
|
||||
$resRiAktif = $db->query("
|
||||
SELECT ri.nama, COUNT(lb.id) AS count, IFNULL(SUM(lb.nilai_bantuan), 0) AS nilai
|
||||
FROM log_bantuan lb
|
||||
JOIN rumah_ibadah ri ON ri.id = lb.rumah_ibadah_id
|
||||
GROUP BY lb.rumah_ibadah_id
|
||||
ORDER BY count DESC LIMIT 5
|
||||
");
|
||||
$riAktif = [];
|
||||
while ($row = $resRiAktif->fetch_assoc()) {
|
||||
$row['count'] = (int)$row['count'];
|
||||
$row['nilai'] = (float)$row['nilai'];
|
||||
$riAktif[] = $row;
|
||||
}
|
||||
$stats['ri_teraktif'] = $riAktif;
|
||||
|
||||
// 10. Bantuan Terbaru (Top 5)
|
||||
$resBantuanBaru = $db->query("
|
||||
SELECT lb.id, lb.tipe_bantuan, lb.sub_kategori, lb.keterangan, lb.tanggal_bantuan, lb.nilai_bantuan,
|
||||
pm.nama AS nama_penduduk, ri.nama AS nama_rumah_ibadah
|
||||
FROM log_bantuan lb
|
||||
JOIN penduduk_miskin pm ON pm.id = lb.penduduk_miskin_id
|
||||
JOIN rumah_ibadah ri ON ri.id = lb.rumah_ibadah_id
|
||||
ORDER BY lb.tanggal_bantuan DESC, lb.id DESC LIMIT 5
|
||||
");
|
||||
$bantuanBaru = [];
|
||||
while ($row = $resBantuanBaru->fetch_assoc()) {
|
||||
$row['nilai_bantuan'] = $row['nilai_bantuan'] ? (float)$row['nilai_bantuan'] : 0;
|
||||
$bantuanBaru[] = $row;
|
||||
}
|
||||
$stats['bantuan_terbaru'] = $bantuanBaru;
|
||||
|
||||
sendSuccess($stats);
|
||||
@@ -1,112 +0,0 @@
|
||||
<?php
|
||||
// api/data_jalan.php
|
||||
require_once __DIR__ . '/config/database.php';
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
setCORSHeaders();
|
||||
|
||||
$db = getDB();
|
||||
$method = getMethod();
|
||||
requireWriteAuth($method);
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
|
||||
switch ($method) {
|
||||
|
||||
case 'GET':
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare(
|
||||
"SELECT id, nama_jalan, status_jalan,
|
||||
panjang_meter, keterangan,
|
||||
CAST(geojson AS CHAR) AS geojson,
|
||||
created_at
|
||||
FROM data_jalan WHERE id = ?"
|
||||
);
|
||||
$stmt->bind_param('i', $id);
|
||||
$stmt->execute();
|
||||
$row = $stmt->get_result()->fetch_assoc();
|
||||
if (!$row) sendError('Data tidak ditemukan', 404);
|
||||
// Parse geojson string menjadi object
|
||||
$row['geojson'] = json_decode($row['geojson']);
|
||||
$row['panjang_meter'] = (float)$row['panjang_meter'];
|
||||
sendSuccess($row);
|
||||
} else {
|
||||
$rows = [];
|
||||
$res = $db->query(
|
||||
"SELECT id, nama_jalan, status_jalan,
|
||||
panjang_meter, keterangan,
|
||||
CAST(geojson AS CHAR) AS geojson,
|
||||
created_at
|
||||
FROM data_jalan ORDER BY created_at DESC"
|
||||
);
|
||||
while ($r = $res->fetch_assoc()) {
|
||||
$r['geojson'] = json_decode($r['geojson']);
|
||||
$r['panjang_meter'] = (float)$r['panjang_meter'];
|
||||
$rows[] = $r;
|
||||
}
|
||||
sendSuccess($rows);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$body = getBody();
|
||||
foreach (['nama_jalan','status_jalan','geojson','panjang_meter'] as $f) {
|
||||
if (!isset($body[$f])) sendError("Field '$f' wajib diisi");
|
||||
}
|
||||
// Validasi GeoJSON LineString
|
||||
$geo = is_array($body['geojson'])
|
||||
? $body['geojson']
|
||||
: json_decode($body['geojson'], true);
|
||||
if (!$geo || $geo['type'] !== 'LineString') {
|
||||
sendError('GeoJSON harus bertipe LineString');
|
||||
}
|
||||
$geoStr = json_encode($geo);
|
||||
$panjang = (float)$body['panjang_meter'];
|
||||
|
||||
$stmt = $db->prepare(
|
||||
"INSERT INTO data_jalan
|
||||
(nama_jalan, status_jalan, panjang_meter, keterangan, geojson)
|
||||
VALUES (?, ?, ?, ?, ?)"
|
||||
);
|
||||
$stmt->bind_param('ssdss',
|
||||
$body['nama_jalan'], $body['status_jalan'],
|
||||
$panjang, $body['keterangan'], $geoStr
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal menyimpan data jalan');
|
||||
sendSuccess(['id' => $db->insert_id], 'Data jalan berhasil disimpan', 201);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$body = getBody();
|
||||
$geo = is_array($body['geojson'])
|
||||
? $body['geojson']
|
||||
: json_decode($body['geojson'], true);
|
||||
$geoStr = json_encode($geo);
|
||||
$panjang = (float)$body['panjang_meter'];
|
||||
|
||||
$stmt = $db->prepare(
|
||||
"UPDATE data_jalan
|
||||
SET nama_jalan=?, status_jalan=?,
|
||||
panjang_meter=?, keterangan=?, geojson=?
|
||||
WHERE id=?"
|
||||
);
|
||||
$stmt->bind_param('ssdssi',
|
||||
$body['nama_jalan'], $body['status_jalan'],
|
||||
$panjang, $body['keterangan'], $geoStr, $id
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal memperbarui data jalan');
|
||||
sendSuccess(null, 'Data jalan berhasil diperbarui');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$stmt = $db->prepare("DELETE FROM data_jalan WHERE id=?");
|
||||
$stmt->bind_param('i', $id);
|
||||
executeOrFail($stmt, 'Gagal menghapus data jalan');
|
||||
$stmt->affected_rows > 0
|
||||
? sendSuccess(null, 'Data jalan berhasil dihapus')
|
||||
: sendError('Data tidak ditemukan', 404);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method tidak diizinkan', 405);
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
<?php
|
||||
// api/data_parsil.php
|
||||
require_once __DIR__ . '/config/database.php';
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
setCORSHeaders();
|
||||
|
||||
$db = getDB();
|
||||
$method = getMethod();
|
||||
requireWriteAuth($method);
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
|
||||
switch ($method) {
|
||||
|
||||
case 'GET':
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare(
|
||||
"SELECT id, nama_pemilik, no_sertifikat, jenis_hak,
|
||||
luas_m2, keterangan,
|
||||
CAST(geojson AS CHAR) AS geojson,
|
||||
created_at
|
||||
FROM data_parsil WHERE id = ?"
|
||||
);
|
||||
$stmt->bind_param('i', $id);
|
||||
$stmt->execute();
|
||||
$row = $stmt->get_result()->fetch_assoc();
|
||||
if (!$row) sendError('Data tidak ditemukan', 404);
|
||||
$row['geojson'] = json_decode($row['geojson']);
|
||||
$row['luas_m2'] = (float)$row['luas_m2'];
|
||||
sendSuccess($row);
|
||||
} else {
|
||||
$rows = [];
|
||||
$res = $db->query(
|
||||
"SELECT id, nama_pemilik, no_sertifikat, jenis_hak,
|
||||
luas_m2, keterangan,
|
||||
CAST(geojson AS CHAR) AS geojson,
|
||||
created_at
|
||||
FROM data_parsil ORDER BY created_at DESC"
|
||||
);
|
||||
while ($r = $res->fetch_assoc()) {
|
||||
$r['geojson'] = json_decode($r['geojson']);
|
||||
$r['luas_m2'] = (float)$r['luas_m2'];
|
||||
$rows[] = $r;
|
||||
}
|
||||
sendSuccess($rows);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$body = getBody();
|
||||
foreach (['nama_pemilik','jenis_hak','geojson','luas_m2'] as $f) {
|
||||
if (!isset($body[$f])) sendError("Field '$f' wajib diisi");
|
||||
}
|
||||
$geo = is_array($body['geojson'])
|
||||
? $body['geojson']
|
||||
: json_decode($body['geojson'], true);
|
||||
if (!$geo || $geo['type'] !== 'Polygon') {
|
||||
sendError('GeoJSON harus bertipe Polygon');
|
||||
}
|
||||
$geoStr = json_encode($geo);
|
||||
$luas = (float)$body['luas_m2'];
|
||||
|
||||
$stmt = $db->prepare(
|
||||
"INSERT INTO data_parsil
|
||||
(nama_pemilik, no_sertifikat, jenis_hak, luas_m2, keterangan, geojson)
|
||||
VALUES (?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$stmt->bind_param('sssdss',
|
||||
$body['nama_pemilik'], $body['no_sertifikat'],
|
||||
$body['jenis_hak'], $luas,
|
||||
$body['keterangan'], $geoStr
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal menyimpan data parsil');
|
||||
sendSuccess(['id' => $db->insert_id], 'Data parsil berhasil disimpan', 201);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$body = getBody();
|
||||
$geo = is_array($body['geojson'])
|
||||
? $body['geojson']
|
||||
: json_decode($body['geojson'], true);
|
||||
$geoStr = json_encode($geo);
|
||||
$luas = (float)$body['luas_m2'];
|
||||
|
||||
$stmt = $db->prepare(
|
||||
"UPDATE data_parsil
|
||||
SET nama_pemilik=?, no_sertifikat=?, jenis_hak=?,
|
||||
luas_m2=?, keterangan=?, geojson=?
|
||||
WHERE id=?"
|
||||
);
|
||||
$stmt->bind_param('sssdssi',
|
||||
$body['nama_pemilik'], $body['no_sertifikat'],
|
||||
$body['jenis_hak'], $luas,
|
||||
$body['keterangan'], $geoStr, $id
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal memperbarui data parsil');
|
||||
sendSuccess(null, 'Data parsil berhasil diperbarui');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$stmt = $db->prepare("DELETE FROM data_parsil WHERE id=?");
|
||||
$stmt->bind_param('i', $id);
|
||||
executeOrFail($stmt, 'Gagal menghapus data parsil');
|
||||
$stmt->affected_rows > 0
|
||||
? sendSuccess(null, 'Data parsil berhasil dihapus')
|
||||
: sendError('Data tidak ditemukan', 404);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method tidak diizinkan', 405);
|
||||
}
|
||||
+179
-20
@@ -49,28 +49,178 @@ function sendError(string $message, int $code = 400): void {
|
||||
}
|
||||
|
||||
function requireWriteAuth(string $method): void {
|
||||
if (!in_array($method, ['POST', 'PUT', 'DELETE'], true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$expected = (string)(getenv('API_WRITE_TOKEN') ?: '');
|
||||
if ($expected === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$provided = (string)($_SERVER['HTTP_X_API_TOKEN'] ?? '');
|
||||
if ($provided === '') {
|
||||
$auth = (string)($_SERVER['HTTP_AUTHORIZATION'] ?? '');
|
||||
if (preg_match('/Bearer\s+(.+)/i', $auth, $m)) {
|
||||
$provided = trim($m[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($provided === '' || !hash_equals($expected, $provided)) {
|
||||
sendError('Unauthorized', 401);
|
||||
}
|
||||
// Deprecated: Menggunakan checkRBAC() secara global untuk semua request.
|
||||
}
|
||||
|
||||
function checkRBAC(): void {
|
||||
if (PHP_SAPI === 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
$script = basename($_SERVER['SCRIPT_FILENAME']);
|
||||
if (in_array($script, ['login.php', 'logout.php', 'me.php'], true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
session_start();
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
sendError('Unauthorized - Silakan login terlebih dahulu', 401);
|
||||
}
|
||||
|
||||
$role = $_SESSION['role'] ?? 'guest';
|
||||
$method = getMethod();
|
||||
|
||||
if ($method === 'GET') {
|
||||
// Semua role diizinkan membaca data (GET)
|
||||
return;
|
||||
}
|
||||
|
||||
// Operasi Tulis (POST, PUT, DELETE)
|
||||
if ($role === 'admin') {
|
||||
// Admin diizinkan melakukan semua aksi tulis
|
||||
return;
|
||||
}
|
||||
|
||||
if ($role === 'petugas_lapangan') {
|
||||
$user_ri_id = isset($_SESSION['rumah_ibadah_id']) ? (int)$_SESSION['rumah_ibadah_id'] : 0;
|
||||
if ($user_ri_id <= 0) {
|
||||
sendError('Forbidden - Akun petugas lapangan tidak dikaitkan dengan rumah ibadah manapun', 403);
|
||||
}
|
||||
|
||||
if ($method === 'DELETE') {
|
||||
sendError('Forbidden - Petugas Lapangan tidak diizinkan menghapus data', 403);
|
||||
}
|
||||
|
||||
if ($script === 'rumah_ibadah.php') {
|
||||
if ($method === 'PUT') {
|
||||
$req_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
if ($req_id !== $user_ri_id) {
|
||||
sendError('Forbidden - Petugas Lapangan hanya dapat mengedit rumah ibadah mereka sendiri', 403);
|
||||
}
|
||||
return; // Allowed
|
||||
}
|
||||
sendError('Forbidden - Aksi tidak diizinkan untuk petugas lapangan pada rumah ibadah', 403);
|
||||
}
|
||||
|
||||
if ($script === 'penduduk_miskin.php') {
|
||||
if ($method === 'POST') {
|
||||
if (isset($_GET['action']) && $_GET['action'] === 'recalc_all') {
|
||||
sendError('Forbidden - Petugas Lapangan tidak dapat memperbarui proximity masal', 403);
|
||||
}
|
||||
|
||||
$body = getBody();
|
||||
$lat = isset($body['latitude']) ? (float)$body['latitude'] : null;
|
||||
$lng = isset($body['longitude']) ? (float)$body['longitude'] : null;
|
||||
if ($lat === null || $lng === null) {
|
||||
sendError('Field latitude dan longitude wajib diisi');
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
$stmt = $db->prepare("SELECT latitude, longitude, radius_meter FROM rumah_ibadah WHERE id = ?");
|
||||
$stmt->bind_param('i', $user_ri_id);
|
||||
$stmt->execute();
|
||||
$ri = $stmt->get_result()->fetch_assoc();
|
||||
if (!$ri) {
|
||||
sendError('Rumah ibadah petugas tidak ditemukan', 404);
|
||||
}
|
||||
|
||||
$dist = haversine_distance((float)$ri['latitude'], (float)$ri['longitude'], $lat, $lng);
|
||||
if ($dist > (int)$ri['radius_meter']) {
|
||||
sendError('Forbidden - Titik koordinat penduduk miskin di luar radius jangkauan rumah ibadah Anda', 403);
|
||||
}
|
||||
return; // Allowed
|
||||
}
|
||||
|
||||
if ($method === 'PUT') {
|
||||
$req_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
if ($req_id <= 0) {
|
||||
sendError('ID penduduk miskin wajib disertakan');
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
$stmtCheck = $db->prepare("SELECT rumah_ibadah_id FROM penduduk_miskin WHERE id = ?");
|
||||
$stmtCheck->bind_param('i', $req_id);
|
||||
$stmtCheck->execute();
|
||||
$pm = $stmtCheck->get_result()->fetch_assoc();
|
||||
if (!$pm) {
|
||||
sendError('Penduduk miskin tidak ditemukan', 404);
|
||||
}
|
||||
|
||||
if ($pm['rumah_ibadah_id'] === null || (int)$pm['rumah_ibadah_id'] !== $user_ri_id) {
|
||||
sendError('Forbidden - Penduduk miskin ini tidak berada di wilayah rumah ibadah Anda', 403);
|
||||
}
|
||||
|
||||
$body = getBody();
|
||||
$lat = isset($body['latitude']) ? (float)$body['latitude'] : null;
|
||||
$lng = isset($body['longitude']) ? (float)$body['longitude'] : null;
|
||||
if ($lat === null || $lng === null) {
|
||||
sendError('Field latitude dan longitude wajib diisi');
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT latitude, longitude, radius_meter FROM rumah_ibadah WHERE id = ?");
|
||||
$stmt->bind_param('i', $user_ri_id);
|
||||
$stmt->execute();
|
||||
$ri = $stmt->get_result()->fetch_assoc();
|
||||
if (!$ri) {
|
||||
sendError('Rumah ibadah petugas tidak ditemukan', 404);
|
||||
}
|
||||
|
||||
$dist = haversine_distance((float)$ri['latitude'], (float)$ri['longitude'], $lat, $lng);
|
||||
if ($dist > (int)$ri['radius_meter']) {
|
||||
sendError('Forbidden - Titik koordinat baru di luar radius jangkauan rumah ibadah Anda', 403);
|
||||
}
|
||||
return; // Allowed
|
||||
}
|
||||
|
||||
sendError('Forbidden - Aksi tidak diizinkan untuk petugas lapangan pada penduduk miskin', 403);
|
||||
}
|
||||
|
||||
if ($script === 'log_bantuan.php') {
|
||||
if ($method === 'POST') {
|
||||
$body = getBody();
|
||||
$req_pm_id = isset($body['penduduk_miskin_id']) ? (int)$body['penduduk_miskin_id'] : 0;
|
||||
$req_ri_id = isset($body['rumah_ibadah_id']) ? (int)$body['rumah_ibadah_id'] : 0;
|
||||
|
||||
if ($req_ri_id !== $user_ri_id) {
|
||||
sendError('Forbidden - Anda hanya dapat mencatat log bantuan dari rumah ibadah Anda sendiri', 403);
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
$stmtPm = $db->prepare("SELECT rumah_ibadah_id, status_proximity FROM penduduk_miskin WHERE id = ?");
|
||||
$stmtPm->bind_param('i', $req_pm_id);
|
||||
$stmtPm->execute();
|
||||
$pm = $stmtPm->get_result()->fetch_assoc();
|
||||
if (!$pm) {
|
||||
sendError('Penduduk miskin tidak ditemukan', 404);
|
||||
}
|
||||
|
||||
if ($pm['rumah_ibadah_id'] === null || (int)$pm['rumah_ibadah_id'] !== $user_ri_id || $pm['status_proximity'] !== 'dalam_radius') {
|
||||
sendError('Forbidden - Penduduk miskin tidak berada di dalam radius rumah ibadah Anda', 403);
|
||||
}
|
||||
return; // Allowed
|
||||
}
|
||||
sendError('Forbidden - Aksi tidak diizinkan untuk petugas lapangan pada log bantuan', 403);
|
||||
}
|
||||
|
||||
sendError('Forbidden', 403);
|
||||
}
|
||||
|
||||
if ($role === 'guest') {
|
||||
sendError('Forbidden - Guest hanya memiliki akses lihat (read-only)', 403);
|
||||
}
|
||||
|
||||
sendError('Forbidden', 403);
|
||||
}
|
||||
|
||||
// Jalankan pemeriksaan CORS dan RBAC secara global saat file di-load
|
||||
setCORSHeaders();
|
||||
checkRBAC();
|
||||
|
||||
function executeOrFail(mysqli_stmt $stmt, string $defaultMessage = 'Operasi database gagal'): void {
|
||||
if ($stmt->execute()) {
|
||||
return;
|
||||
@@ -97,4 +247,13 @@ function getBody(): array {
|
||||
|
||||
function getMethod(): string {
|
||||
return strtoupper($_SERVER['REQUEST_METHOD']);
|
||||
}
|
||||
|
||||
function haversine_distance(float $lat1, float $lng1, float $lat2, float $lng2): float {
|
||||
$R = 6371000; // radius bumi dalam meter
|
||||
$dLat = deg2rad($lat2 - $lat1);
|
||||
$dLng = deg2rad($lng2 - $lng1);
|
||||
$a = sin($dLat/2)**2
|
||||
+ cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLng/2)**2;
|
||||
return $R * 2 * atan2(sqrt($a), sqrt(1-$a));
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
// api/login.php
|
||||
require_once __DIR__ . '/config/database.php';
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
setCORSHeaders();
|
||||
|
||||
$method = getMethod();
|
||||
if ($method !== 'POST') {
|
||||
sendError('Method tidak diizinkan', 405);
|
||||
}
|
||||
|
||||
$body = getBody();
|
||||
$username = trim($body['username'] ?? '');
|
||||
$password = trim($body['password'] ?? '');
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
sendError('Username dan Password wajib diisi');
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
$stmt = $db->prepare("SELECT id, username, password, role, rumah_ibadah_id FROM users WHERE username = ?");
|
||||
if (!$stmt) {
|
||||
sendError('Gagal menyiapkan query database', 500);
|
||||
}
|
||||
$stmt->bind_param('s', $username);
|
||||
$stmt->execute();
|
||||
$user = $stmt->get_result()->fetch_assoc();
|
||||
|
||||
if (!$user || !password_verify($password, $user['password'])) {
|
||||
sendError('Username atau Password salah', 401);
|
||||
}
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
// Session settings for security
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
session_start();
|
||||
}
|
||||
|
||||
$_SESSION['user_id'] = $user['id'];
|
||||
$_SESSION['username'] = $user['username'];
|
||||
$_SESSION['role'] = $user['role'];
|
||||
$_SESSION['rumah_ibadah_id'] = $user['rumah_ibadah_id'] ? (int)$user['rumah_ibadah_id'] : null;
|
||||
|
||||
sendSuccess([
|
||||
'id' => $user['id'],
|
||||
'username' => $user['username'],
|
||||
'role' => $user['role'],
|
||||
'rumah_ibadah_id' => $user['rumah_ibadah_id'] ? (int)$user['rumah_ibadah_id'] : null
|
||||
], 'Login berhasil');
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
// api/logout.php
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
setCORSHeaders();
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$_SESSION = [];
|
||||
|
||||
if (ini_get("session.use_cookies")) {
|
||||
$params = session_get_cookie_params();
|
||||
setcookie(session_name(), '', time() - 42000,
|
||||
$params["path"], $params["domain"],
|
||||
$params["secure"], $params["httponly"]
|
||||
);
|
||||
}
|
||||
|
||||
session_destroy();
|
||||
|
||||
sendSuccess(null, 'Logout berhasil');
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
// api/manajemen_akun.php
|
||||
// Endpoint khusus admin untuk mendapatkan data manajemen akun rumah ibadah
|
||||
require_once __DIR__ . '/config/database.php';
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
// CORS dan RBAC sudah diproses secara global di response.php
|
||||
|
||||
// Hanya admin yang boleh mengakses
|
||||
if ($_SESSION['role'] !== 'admin') {
|
||||
sendError('Forbidden - Hanya admin yang dapat mengakses halaman ini', 403);
|
||||
}
|
||||
|
||||
$db = getDB();
|
||||
$method = getMethod();
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
|
||||
switch ($method) {
|
||||
|
||||
// GET: Ambil semua rumah ibadah beserta statistik dan info akun
|
||||
case 'GET':
|
||||
if ($id > 0) {
|
||||
// Detail satu rumah ibadah
|
||||
$stmt = $db->prepare("
|
||||
SELECT ri.id, ri.nama, ri.jenis, ri.alamat, ri.no_wa,
|
||||
ri.latitude, ri.longitude, ri.radius_meter, ri.created_at,
|
||||
u.id AS user_id, u.username, u.password_plain, u.created_at AS akun_dibuat,
|
||||
(SELECT COUNT(*) FROM penduduk_miskin pm WHERE pm.rumah_ibadah_id = ri.id AND pm.status_proximity = 'dalam_radius') AS pm_dalam_radius,
|
||||
(SELECT COUNT(*) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id) AS total_penyaluran,
|
||||
(SELECT COUNT(*) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id AND lb.tipe_bantuan = 'Pemberdayaan') AS bantuan_pemberdayaan,
|
||||
(SELECT COUNT(*) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id AND lb.tipe_bantuan = 'Konsumtif') AS bantuan_konsumtif,
|
||||
(SELECT IFNULL(SUM(lb.nilai_bantuan), 0) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id) AS total_nilai_bantuan,
|
||||
(SELECT COUNT(DISTINCT lb.penduduk_miskin_id) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id) AS jumlah_penerima_unik,
|
||||
(SELECT lb.tanggal_bantuan FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id ORDER BY lb.tanggal_bantuan DESC LIMIT 1) AS tanggal_bantuan_terakhir
|
||||
FROM rumah_ibadah ri
|
||||
LEFT JOIN users u ON u.rumah_ibadah_id = ri.id
|
||||
WHERE ri.id = ?
|
||||
");
|
||||
$stmt->bind_param('i', $id);
|
||||
$stmt->execute();
|
||||
$row = $stmt->get_result()->fetch_assoc();
|
||||
|
||||
if (!$row) sendError('Data tidak ditemukan', 404);
|
||||
|
||||
// Cast types
|
||||
$row['latitude'] = (float)$row['latitude'];
|
||||
$row['longitude'] = (float)$row['longitude'];
|
||||
$row['radius_meter'] = (int)$row['radius_meter'];
|
||||
$row['pm_dalam_radius'] = (int)$row['pm_dalam_radius'];
|
||||
$row['total_penyaluran'] = (int)$row['total_penyaluran'];
|
||||
$row['bantuan_pemberdayaan'] = (int)$row['bantuan_pemberdayaan'];
|
||||
$row['bantuan_konsumtif'] = (int)$row['bantuan_konsumtif'];
|
||||
$row['total_nilai_bantuan'] = (float)$row['total_nilai_bantuan'];
|
||||
$row['jumlah_penerima_unik'] = (int)$row['jumlah_penerima_unik'];
|
||||
// password_plain: null if no account
|
||||
if ($row['password_plain'] === null) $row['password_plain'] = null;
|
||||
|
||||
// Ambil 5 riwayat bantuan terbaru
|
||||
$stmtLog = $db->prepare("
|
||||
SELECT lb.tipe_bantuan, lb.sub_kategori, lb.tanggal_bantuan, lb.nilai_bantuan,
|
||||
pm.nama AS nama_penerima
|
||||
FROM log_bantuan lb
|
||||
JOIN penduduk_miskin pm ON pm.id = lb.penduduk_miskin_id
|
||||
WHERE lb.rumah_ibadah_id = ?
|
||||
ORDER BY lb.tanggal_bantuan DESC, lb.id DESC
|
||||
LIMIT 10
|
||||
");
|
||||
$stmtLog->bind_param('i', $id);
|
||||
$stmtLog->execute();
|
||||
$logs = [];
|
||||
$resLog = $stmtLog->get_result();
|
||||
while ($l = $resLog->fetch_assoc()) {
|
||||
$l['nilai_bantuan'] = $l['nilai_bantuan'] ? (float)$l['nilai_bantuan'] : null;
|
||||
$logs[] = $l;
|
||||
}
|
||||
$row['riwayat_bantuan'] = $logs;
|
||||
|
||||
sendSuccess($row);
|
||||
} else {
|
||||
// Semua rumah ibadah dengan ringkasan statistik
|
||||
$sql = "
|
||||
SELECT ri.id, ri.nama, ri.jenis, ri.alamat, ri.no_wa,
|
||||
ri.latitude, ri.longitude, ri.radius_meter, ri.created_at,
|
||||
u.id AS user_id, u.username,
|
||||
(SELECT COUNT(*) FROM penduduk_miskin pm WHERE pm.rumah_ibadah_id = ri.id AND pm.status_proximity = 'dalam_radius') AS pm_dalam_radius,
|
||||
(SELECT COUNT(*) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id) AS total_penyaluran,
|
||||
(SELECT IFNULL(SUM(lb.nilai_bantuan), 0) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id) AS total_nilai_bantuan,
|
||||
(SELECT COUNT(DISTINCT lb.penduduk_miskin_id) FROM log_bantuan lb WHERE lb.rumah_ibadah_id = ri.id) AS jumlah_penerima_unik
|
||||
FROM rumah_ibadah ri
|
||||
LEFT JOIN users u ON u.rumah_ibadah_id = ri.id
|
||||
ORDER BY ri.created_at DESC
|
||||
";
|
||||
$result = $db->query($sql);
|
||||
$rows = [];
|
||||
while ($r = $result->fetch_assoc()) {
|
||||
$r['latitude'] = (float)$r['latitude'];
|
||||
$r['longitude'] = (float)$r['longitude'];
|
||||
$r['radius_meter'] = (int)$r['radius_meter'];
|
||||
$r['pm_dalam_radius'] = (int)$r['pm_dalam_radius'];
|
||||
$r['total_penyaluran'] = (int)$r['total_penyaluran'];
|
||||
$r['total_nilai_bantuan'] = (float)$r['total_nilai_bantuan'];
|
||||
$r['jumlah_penerima_unik'] = (int)$r['jumlah_penerima_unik'];
|
||||
$rows[] = $r;
|
||||
}
|
||||
sendSuccess($rows);
|
||||
}
|
||||
break;
|
||||
|
||||
// DELETE: Hapus akun user rumah ibadah (tidak hapus rumah ibadahnya)
|
||||
case 'DELETE':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$stmt = $db->prepare("DELETE FROM users WHERE rumah_ibadah_id = ?");
|
||||
$stmt->bind_param('i', $id);
|
||||
if ($stmt->execute()) {
|
||||
sendSuccess(null, $stmt->affected_rows > 0 ? 'Akun berhasil dihapus' : 'Tidak ada akun untuk dihapus');
|
||||
} else {
|
||||
sendError('Gagal menghapus akun');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method tidak diizinkan', 405);
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
// api/me.php
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
setCORSHeaders();
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
session_start();
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
sendError('Unauthorized', 401);
|
||||
}
|
||||
|
||||
sendSuccess([
|
||||
'id' => $_SESSION['user_id'],
|
||||
'username' => $_SESSION['username'],
|
||||
'role' => $_SESSION['role'],
|
||||
'rumah_ibadah_id' => isset($_SESSION['rumah_ibadah_id']) ? (int)$_SESSION['rumah_ibadah_id'] : null
|
||||
]);
|
||||
+139
-41
@@ -15,10 +15,12 @@ switch ($method) {
|
||||
case 'GET':
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare(
|
||||
"SELECT id, nama, jenis, alamat, no_wa,
|
||||
latitude, longitude, radius_meter,
|
||||
created_at
|
||||
FROM rumah_ibadah WHERE id = ?"
|
||||
"SELECT ri.id, ri.nama, ri.jenis, ri.alamat, ri.no_wa,
|
||||
ri.latitude, ri.longitude, ri.radius_meter,
|
||||
ri.created_at, u.username
|
||||
FROM rumah_ibadah ri
|
||||
LEFT JOIN users u ON u.rumah_ibadah_id = ri.id
|
||||
WHERE ri.id = ?"
|
||||
);
|
||||
$stmt->bind_param('i', $id);
|
||||
$stmt->execute();
|
||||
@@ -30,10 +32,12 @@ switch ($method) {
|
||||
}
|
||||
$row ? sendSuccess($row) : sendError('Data tidak ditemukan', 404);
|
||||
} else {
|
||||
$sql = "SELECT id, nama, jenis, alamat, no_wa,
|
||||
latitude, longitude, radius_meter,
|
||||
created_at
|
||||
FROM rumah_ibadah ORDER BY created_at DESC";
|
||||
$sql = "SELECT ri.id, ri.nama, ri.jenis, ri.alamat, ri.no_wa,
|
||||
ri.latitude, ri.longitude, ri.radius_meter,
|
||||
ri.created_at, u.username
|
||||
FROM rumah_ibadah ri
|
||||
LEFT JOIN users u ON u.rumah_ibadah_id = ri.id
|
||||
ORDER BY ri.created_at DESC";
|
||||
$result = $db->query($sql);
|
||||
$rows = [];
|
||||
while ($r = $result->fetch_assoc()) {
|
||||
@@ -55,45 +59,139 @@ switch ($method) {
|
||||
sendError("Field '$field' wajib diisi");
|
||||
}
|
||||
}
|
||||
$stmt = $db->prepare(
|
||||
"INSERT INTO rumah_ibadah
|
||||
(nama, jenis, alamat, no_wa, latitude, longitude, radius_meter)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$stmt->bind_param(
|
||||
'ssssddi',
|
||||
$body['nama'],
|
||||
$body['jenis'],
|
||||
$body['alamat'],
|
||||
$body['no_wa'],
|
||||
$body['latitude'],
|
||||
$body['longitude'],
|
||||
$body['radius_meter']
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal menyimpan rumah ibadah');
|
||||
$newId = $db->insert_id;
|
||||
sendSuccess(['id' => $newId], 'Rumah Ibadah berhasil disimpan', 201);
|
||||
|
||||
$db->begin_transaction();
|
||||
try {
|
||||
$stmt = $db->prepare(
|
||||
"INSERT INTO rumah_ibadah
|
||||
(nama, jenis, alamat, no_wa, latitude, longitude, radius_meter)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$stmt->bind_param(
|
||||
'ssssddi',
|
||||
$body['nama'],
|
||||
$body['jenis'],
|
||||
$body['alamat'],
|
||||
$body['no_wa'],
|
||||
$body['latitude'],
|
||||
$body['longitude'],
|
||||
$body['radius_meter']
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal menyimpan rumah ibadah');
|
||||
$newId = $db->insert_id;
|
||||
|
||||
// Handle user account creation
|
||||
$username = isset($body['username']) ? trim($body['username']) : '';
|
||||
$password = isset($body['password']) ? trim($body['password']) : '';
|
||||
if ($username !== '') {
|
||||
// Check if username already exists
|
||||
$stmtUserCheck = $db->prepare("SELECT id FROM users WHERE username = ?");
|
||||
$stmtUserCheck->bind_param('s', $username);
|
||||
$stmtUserCheck->execute();
|
||||
if ($stmtUserCheck->get_result()->num_rows > 0) {
|
||||
throw new Exception('Username sudah digunakan');
|
||||
}
|
||||
|
||||
if ($password === '') {
|
||||
throw new Exception('Password wajib diisi jika username ditentukan');
|
||||
}
|
||||
|
||||
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
|
||||
$stmtUser = $db->prepare(
|
||||
"INSERT INTO users (username, password, password_plain, role, rumah_ibadah_id) VALUES (?, ?, ?, 'petugas_lapangan', ?)"
|
||||
);
|
||||
$stmtUser->bind_param('sssi', $username, $hashedPassword, $password, $newId);
|
||||
executeOrFail($stmtUser, 'Gagal membuat akun petugas lapangan');
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
sendSuccess(['id' => $newId], 'Rumah Ibadah dan Akun Petugas berhasil disimpan', 201);
|
||||
} catch (Exception $e) {
|
||||
$db->rollback();
|
||||
sendError($e->getMessage());
|
||||
}
|
||||
break;
|
||||
|
||||
// ── PUT: update data ──────────────────────────────────────────────
|
||||
case 'PUT':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$body = getBody();
|
||||
$stmt = $db->prepare(
|
||||
"UPDATE rumah_ibadah
|
||||
SET nama=?, jenis=?, alamat=?, no_wa=?,
|
||||
latitude=?, longitude=?, radius_meter=?
|
||||
WHERE id=?"
|
||||
);
|
||||
$stmt->bind_param(
|
||||
'ssssddii',
|
||||
$body['nama'], $body['jenis'],
|
||||
$body['alamat'], $body['no_wa'],
|
||||
$body['latitude'], $body['longitude'],
|
||||
$body['radius_meter'], $id
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal memperbarui rumah ibadah');
|
||||
sendSuccess(null, 'Rumah Ibadah berhasil diperbarui');
|
||||
|
||||
$db->begin_transaction();
|
||||
try {
|
||||
$stmt = $db->prepare(
|
||||
"UPDATE rumah_ibadah
|
||||
SET nama=?, jenis=?, alamat=?, no_wa=?,
|
||||
latitude=?, longitude=?, radius_meter=?
|
||||
WHERE id=?"
|
||||
);
|
||||
$stmt->bind_param(
|
||||
'ssssddii',
|
||||
$body['nama'], $body['jenis'],
|
||||
$body['alamat'], $body['no_wa'],
|
||||
$body['latitude'], $body['longitude'],
|
||||
$body['radius_meter'], $id
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal memperbarui rumah ibadah');
|
||||
|
||||
// Handle user account creation/update (only if user is admin)
|
||||
if (isset($_SESSION['role']) && $_SESSION['role'] === 'admin') {
|
||||
$username = isset($body['username']) ? trim($body['username']) : '';
|
||||
$password = isset($body['password']) ? trim($body['password']) : '';
|
||||
|
||||
if ($username !== '') {
|
||||
// Check if username belongs to another user
|
||||
$stmtUserCheck = $db->prepare("SELECT id, rumah_ibadah_id FROM users WHERE username = ?");
|
||||
$stmtUserCheck->bind_param('s', $username);
|
||||
$stmtUserCheck->execute();
|
||||
$resUserCheck = $stmtUserCheck->get_result()->fetch_assoc();
|
||||
if ($resUserCheck && (int)$resUserCheck['rumah_ibadah_id'] !== $id) {
|
||||
throw new Exception('Username sudah digunakan oleh akun lain');
|
||||
}
|
||||
|
||||
// Check if account already exists for this rumah_ibadah
|
||||
$stmtExisting = $db->prepare("SELECT id FROM users WHERE rumah_ibadah_id = ?");
|
||||
$stmtExisting->bind_param('i', $id);
|
||||
$stmtExisting->execute();
|
||||
$existing = $stmtExisting->get_result()->fetch_assoc();
|
||||
|
||||
if ($existing) {
|
||||
// Update existing user
|
||||
if ($password !== '') {
|
||||
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
|
||||
$stmtUpdate = $db->prepare("UPDATE users SET username = ?, password = ?, password_plain = ? WHERE id = ?");
|
||||
$stmtUpdate->bind_param('sssi', $username, $hashedPassword, $password, $existing['id']);
|
||||
} else {
|
||||
$stmtUpdate = $db->prepare("UPDATE users SET username = ? WHERE id = ?");
|
||||
$stmtUpdate->bind_param('si', $username, $existing['id']);
|
||||
}
|
||||
executeOrFail($stmtUpdate, 'Gagal memperbarui akun petugas lapangan');
|
||||
} else {
|
||||
// Create new user for this rumah ibadah
|
||||
if ($password === '') {
|
||||
throw new Exception('Password wajib diisi untuk pembuatan akun baru');
|
||||
}
|
||||
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
|
||||
$stmtUser = $db->prepare(
|
||||
"INSERT INTO users (username, password, password_plain, role, rumah_ibadah_id) VALUES (?, ?, ?, 'petugas_lapangan', ?)"
|
||||
);
|
||||
$stmtUser->bind_param('sssi', $username, $hashedPassword, $password, $id);
|
||||
executeOrFail($stmtUser, 'Gagal membuat akun petugas lapangan');
|
||||
}
|
||||
} else {
|
||||
// Delete the associated user account if username is cleared
|
||||
$stmtDeleteUser = $db->prepare("DELETE FROM users WHERE rumah_ibadah_id = ?");
|
||||
$stmtDeleteUser->bind_param('i', $id);
|
||||
$stmtDeleteUser->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
sendSuccess(null, 'Rumah Ibadah berhasil diperbarui');
|
||||
} catch (Exception $e) {
|
||||
$db->rollback();
|
||||
sendError($e->getMessage());
|
||||
}
|
||||
break;
|
||||
|
||||
// ── DELETE: hapus data ────────────────────────────────────────────
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
<?php
|
||||
// api/spbu.php
|
||||
require_once __DIR__ . '/config/database.php';
|
||||
require_once __DIR__ . '/helpers/response.php';
|
||||
setCORSHeaders();
|
||||
|
||||
$db = getDB();
|
||||
$method = getMethod();
|
||||
requireWriteAuth($method);
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
|
||||
switch ($method) {
|
||||
|
||||
case 'GET':
|
||||
if ($id > 0) {
|
||||
$stmt = $db->prepare(
|
||||
"SELECT id, nama, no_wa, alamat, buka_24jam,
|
||||
latitude, longitude, created_at
|
||||
FROM spbu WHERE id = ?"
|
||||
);
|
||||
$stmt->bind_param('i', $id);
|
||||
$stmt->execute();
|
||||
$row = $stmt->get_result()->fetch_assoc();
|
||||
if (!$row) sendError('Data tidak ditemukan', 404);
|
||||
$row['latitude'] = (float)$row['latitude'];
|
||||
$row['longitude'] = (float)$row['longitude'];
|
||||
$row['buka_24jam']= (bool)$row['buka_24jam'];
|
||||
sendSuccess($row);
|
||||
} else {
|
||||
$rows = [];
|
||||
if (isset($_GET['buka_24jam'])) {
|
||||
$val = (int)$_GET['buka_24jam'];
|
||||
$stmt = $db->prepare(
|
||||
"SELECT id, nama, no_wa, alamat, buka_24jam,
|
||||
latitude, longitude, created_at
|
||||
FROM spbu WHERE buka_24jam = ? ORDER BY nama"
|
||||
);
|
||||
$stmt->bind_param('i', $val);
|
||||
$stmt->execute();
|
||||
$res = $stmt->get_result();
|
||||
} else {
|
||||
$res = $db->query(
|
||||
"SELECT id, nama, no_wa, alamat, buka_24jam,
|
||||
latitude, longitude, created_at
|
||||
FROM spbu ORDER BY nama"
|
||||
);
|
||||
}
|
||||
while ($r = $res->fetch_assoc()) {
|
||||
$r['latitude'] = (float)$r['latitude'];
|
||||
$r['longitude'] = (float)$r['longitude'];
|
||||
$r['buka_24jam']= (bool)$r['buka_24jam'];
|
||||
$rows[] = $r;
|
||||
}
|
||||
sendSuccess($rows);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$body = getBody();
|
||||
foreach (['nama','latitude','longitude'] as $f) {
|
||||
if (empty($body[$f]) && $body[$f] !== 0) sendError("Field '$f' wajib diisi");
|
||||
}
|
||||
$buka = isset($body['buka_24jam']) ? (int)(bool)$body['buka_24jam'] : 0;
|
||||
$stmt = $db->prepare(
|
||||
"INSERT INTO spbu (nama, no_wa, alamat, buka_24jam, latitude, longitude)
|
||||
VALUES (?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$stmt->bind_param('sssidd',
|
||||
$body['nama'], $body['no_wa'], $body['alamat'],
|
||||
$buka, $body['latitude'], $body['longitude']
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal menyimpan data SPBU');
|
||||
sendSuccess(['id' => $db->insert_id], 'SPBU berhasil disimpan', 201);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$body = getBody();
|
||||
$buka = isset($body['buka_24jam']) ? (int)(bool)$body['buka_24jam'] : 0;
|
||||
$stmt = $db->prepare(
|
||||
"UPDATE spbu
|
||||
SET nama=?, no_wa=?, alamat=?, buka_24jam=?, latitude=?, longitude=?
|
||||
WHERE id=?"
|
||||
);
|
||||
$stmt->bind_param('sssiddi',
|
||||
$body['nama'], $body['no_wa'], $body['alamat'],
|
||||
$buka, $body['latitude'], $body['longitude'], $id
|
||||
);
|
||||
executeOrFail($stmt, 'Gagal memperbarui data SPBU');
|
||||
sendSuccess(null, 'SPBU berhasil diperbarui');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if ($id <= 0) sendError('ID wajib disertakan');
|
||||
$stmt = $db->prepare("DELETE FROM spbu WHERE id=?");
|
||||
$stmt->bind_param('i', $id);
|
||||
executeOrFail($stmt, 'Gagal menghapus data SPBU');
|
||||
$stmt->affected_rows > 0
|
||||
? sendSuccess(null, 'SPBU berhasil dihapus')
|
||||
: sendError('Data tidak ditemukan', 404);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method tidak diizinkan', 405);
|
||||
}
|
||||
Reference in New Issue
Block a user