feat: Initial commit - WebGIS Smart City Project by Naufal Zaky Ramadhan (D1041231071)

This commit is contained in:
naukyy
2026-06-13 00:00:33 +07:00
commit 2c123f5af2
163 changed files with 13007 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
<?php
/**
* Singleton PDO connection.
*
* Coolify: set DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, and DB_PASSWORD
* from the database service credentials.
*/
require_once __DIR__ . '/env_loader.php';
class Database {
private static $conn = null;
private static function env(string $key, string $default = ''): string {
$value = getenv($key);
return ($value === false || $value === '') ? $default : $value;
}
public static function getConnection() {
if (self::$conn === null) {
$dbUrl = self::env('DATABASE_URL');
if ($dbUrl) {
$parsed = parse_url($dbUrl);
$host = $parsed['host'] ?? '127.0.0.1';
$port = $parsed['port'] ?? '3306';
$username = $parsed['user'] ?? 'root';
$password = $parsed['pass'] ?? '';
$dbName = ltrim($parsed['path'], '/');
} else {
$host = self::env('DB_HOST', '127.0.0.1');
$port = self::env('DB_PORT', '3306');
$dbName = self::env('DB_DATABASE', 'webgis_db');
$username = self::env('DB_USERNAME', 'root');
$password = self::env('DB_PASSWORD', '');
}
self::$conn = new PDO(
"mysql:host={$host};port={$port};dbname={$dbName};charset=utf8mb4",
$username,
$password
);
self::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
self::$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// Disable strict mode for GROUP BY to prevent 1055 errors in Coolify's MariaDB
self::$conn->exec("SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''))");
// Auto-initialize database if empty
$stmt = self::$conn->query("SHOW TABLES LIKE 'users'");
if ($stmt->rowCount() == 0) {
$sqlFile = __DIR__ . '/../../db_scripts/webgis_naufal_zaky.sql';
if (file_exists($sqlFile)) {
$sql = file_get_contents($sqlFile);
self::$conn->exec($sql);
}
}
}
return self::$conn;
}
}
+56
View File
@@ -0,0 +1,56 @@
<?php
/**
* Simple .env loader.
* Reads the .env file from the repository root and sets environment variables
* via putenv() so getenv() calls throughout the app work correctly.
* Only loads once per request.
*/
function loadEnv(): void {
static $loaded = false;
if ($loaded) return;
// Walk up from webgis_app/config to the repository root
$envFile = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . '.env';
if (!file_exists($envFile)) {
$loaded = true;
return;
}
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!empty($lines)) {
if (substr($lines[0], 0, 3) === "\xEF\xBB\xBF") {
$lines[0] = substr($lines[0], 3);
}
}
foreach ($lines as $line) {
$line = trim($line);
// Skip comments
if ($line === '' || $line[0] === '#') continue;
if (strpos($line, '=') === false) continue;
[$key, $value] = explode('=', $line, 2);
$key = trim($key);
$value = trim($value);
// Remove surrounding quotes if present
if (strlen($value) >= 2 &&
(($value[0] === '"' && $value[-1] === '"') ||
($value[0] === "'" && $value[-1] === "'"))) {
$value = substr($value, 1, -1);
}
// Only set if not already defined in the environment (server env wins)
if (getenv($key) === false) {
putenv("{$key}={$value}");
$_ENV[$key] = $value;
$_SERVER[$key] = $value;
}
}
$loaded = true;
}
// Auto-load on include
loadEnv();
@@ -0,0 +1,66 @@
<?php
/**
* auth_check.php — Middleware: pastikan user sudah login dan role sesuai.
* Usage: require_once __DIR__ . '/../core_config/middleware_auth.php';
* requireRole('admin'); // atau 'user'
*/
require_once __DIR__ . '/session_mgr.php';
if (session_status() === PHP_SESSION_NONE) {
startAppSession();
}
function isLoggedIn(): bool {
return isset($_SESSION['user_id']) && isset($_SESSION['role']);
}
function requireLogin(?string $redirect = null): void {
if (!isLoggedIn()) {
$redirect = $redirect ?? app_url('login.php');
header("Location: $redirect");
exit;
}
}
function requireRole(string $role, ?string $redirect = null): void {
requireLogin($redirect);
if ($_SESSION['role'] !== $role) {
// Redirect ke dashboard yang sesuai role-nya
if ($_SESSION['role'] === 'admin') {
header('Location: ' . app_url('panel_admin/index.php'));
} else {
header('Location: ' . app_url('panel_user/index.php'));
}
exit;
}
}
function currentUser(): array {
return [
'id' => $_SESSION['user_id'] ?? null,
'username' => $_SESSION['username'] ?? '',
'role' => $_SESSION['role'] ?? '',
'nama_lengkap'=> $_SESSION['nama_lengkap']?? '',
];
}
/**
* API-safe auth helpers: return JSON 401/403 instead of redirecting.
* Use these in endpoints called via fetch/AJAX.
*/
function requireApiLogin(): void {
if (!isLoggedIn()) {
http_response_code(401);
echo json_encode(['status' => 'error', 'message' => 'Autentikasi diperlukan']);
exit;
}
}
function requireApiRole(string $role): void {
requireApiLogin();
if ($_SESSION['role'] !== $role) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Akses ditolak: role tidak sesuai']);
exit;
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
require_once __DIR__ . '/settings.php';
function startAppSession(): void {
if (session_status() === PHP_SESSION_ACTIVE) {
return;
}
$secureEnv = strtolower((string)getenv('SESSION_SECURE'));
$isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https')
|| $secureEnv === 'true'
|| $secureEnv === '1';
session_set_cookie_params([
'lifetime' => 0,
'path' => app_base_path() ?: '/',
'secure' => $isHttps,
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
}
+29
View File
@@ -0,0 +1,29 @@
<?php
/**
* Application path helpers.
*
* Set APP_BASE_PATH to the subdirectory that serves webgis_app.
* In this repository's Coolify image the final app runs at /webgis_app.
*/
require_once __DIR__ . '/env_loader.php';
function app_base_path(): string {
$basePath = getenv('APP_BASE_PATH');
if ($basePath === false) {
$basePath = '/project/webgis_app';
}
$basePath = trim($basePath);
if ($basePath === '' || $basePath === '/') {
return '';
}
return '/' . trim($basePath, '/');
}
function app_url(string $path = ''): string {
if ($path === '') {
return app_base_path();
}
$path = '/' . ltrim($path, '/');
return app_base_path() . $path;
}