Complete adaptation from BukidBountyApp to Philippine barangay governance: - Barangay models: Resident, Household, HouseholdMember, Blotter, BlotterHearing, DocumentRequest, RequestPayment, RequestType, BarangayProject, BarangayBudget - Controllers: ResidentController, HouseholdController, BlotterController, BlotterHearingController, DocumentRequestController, RequestTypeController, ProjectController, BudgetController, QRPHController, AdminConsoleController, UserController, FileController, ChapterController, LoginController - Vue pages: Home, ManageResidents, ResidentProfile, ManageHouseholds, ManageBlotters, BlotterDetail, RequestDocument, ManageDocumentRequests, DocumentRequestDetail, ManageRequestTypes, ManageProjects, BudgetLedger, AdminConsole - Barangay roles: PunongBarangay, Kagawad, Secretary, Treasurer, SK, Tanod, BHW, Staff, Resident - UserPermissions matrix rewritten with barangay-specific permission mappings - VueRouteMap replaced with barangay SPA routes - UserActions enum references corrected across all controllers - Removed all market/cooperative/POS/subscription code and models
163 lines
6.6 KiB
PHP
163 lines
6.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Enums\UserActions;
|
|
use App\Enums\UserTypes;
|
|
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
|
|
use App\Http\Controllers\Helpers\ResponseHelper;
|
|
use App\Models\User;
|
|
use App\Models\DbBackup;
|
|
use Hyperf\Stringable\Str;
|
|
use Hypervel\Http\Request;
|
|
use Hypervel\Support\Facades\Auth;
|
|
use Hypervel\Support\Facades\DB;
|
|
use Hypervel\Support\Facades\Redis;
|
|
use Hypervel\Support\Facades\Response;
|
|
|
|
class AdminConsoleController
|
|
{
|
|
private function checkAccess(): bool
|
|
{
|
|
if (!Auth::check()) return false;
|
|
return UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::UltimateConsole);
|
|
}
|
|
|
|
public function getSystemStats()
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
|
|
$globalMessage = Redis::get('system:global_message');
|
|
$redisStatus = ['connected' => false, 'ping_ms' => null, 'used_memory_human' => null, 'version' => null, 'error' => null];
|
|
|
|
try {
|
|
$start = microtime(true);
|
|
$pong = Redis::ping();
|
|
$redisStatus['ping_ms'] = round((microtime(true) - $start) * 1000, 2);
|
|
$redisStatus['connected'] = in_array($pong, [true, 'PONG', '+PONG'], true) || (is_string($pong) && stripos($pong, 'PONG') !== false);
|
|
$info = Redis::info();
|
|
if (is_array($info)) {
|
|
$flat = isset($info['Memory']) ? $info['Memory'] : $info;
|
|
$redisStatus['used_memory_human'] = $flat['used_memory_human'] ?? null;
|
|
$serverInfo = isset($info['Server']) ? $info['Server'] : $info;
|
|
$redisStatus['version'] = $serverInfo['redis_version'] ?? null;
|
|
}
|
|
} catch (\Throwable $e) {
|
|
$redisStatus['error'] = $e->getMessage();
|
|
}
|
|
|
|
$stats = [
|
|
'users' => User::count(),
|
|
'active_users' => User::where('active', true)->count(),
|
|
'residents' => DB::table('barangay_residents')->count(),
|
|
'households' => DB::table('barangay_households')->count(),
|
|
'blotters' => DB::table('barangay_blotters')->count(),
|
|
'document_requests' => DB::table('barangay_document_requests')->count(),
|
|
'projects' => DB::table('barangay_projects')->count(),
|
|
'announcements' => DB::table('announcements')->count(),
|
|
'php_version' => PHP_VERSION,
|
|
'server_time' => date('Y-m-d H:i:s'),
|
|
'maintenance_mode' => Redis::get('system:maintenance_mode') === 'true',
|
|
'global_message' => $globalMessage ? json_decode($globalMessage, true) : null,
|
|
'logs_count' => DB::table('logs')->count(),
|
|
'table_logs_count' => DB::table('table_logs')->count(),
|
|
'redis' => $redisStatus,
|
|
];
|
|
|
|
return Response::json(['success' => true, 'data' => $stats]);
|
|
}
|
|
|
|
public function runQuery(Request $request)
|
|
{
|
|
if (Auth::user()->acct_type !== UserTypes::SUPER_ADMIN || !UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::UltimateQuery)) {
|
|
return ResponseHelper::returnUnauthorized();
|
|
}
|
|
|
|
$query = $request->input('query');
|
|
if (empty($query)) return ResponseHelper::returnError('Query cannot be empty');
|
|
|
|
$lower = strtolower(trim($query));
|
|
$allowed = str_starts_with($lower, 'select') || str_starts_with($lower, 'show') || str_starts_with($lower, 'describe') || str_starts_with($lower, 'explain');
|
|
if (!$allowed) {
|
|
return ResponseHelper::returnError('Only SELECT, SHOW, DESCRIBE, EXPLAIN queries are allowed');
|
|
}
|
|
|
|
try {
|
|
$results = DB::select($query);
|
|
return Response::json(['success' => true, 'data' => $results, 'count' => count($results)]);
|
|
} catch (\Throwable $e) {
|
|
return ResponseHelper::returnError('Query error: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function setMaintenanceMode(Request $request)
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
$enabled = (bool) $request->input('enabled', false);
|
|
Redis::set('system:maintenance_mode', $enabled ? 'true' : 'false');
|
|
return Response::json(['success' => true, 'maintenance_mode' => $enabled]);
|
|
}
|
|
|
|
public function setGlobalMessage(Request $request)
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
$message = $request->input('message');
|
|
if ($message) {
|
|
Redis::set('system:global_message', json_encode([
|
|
'text' => $message,
|
|
'type' => $request->input('type', 'info'),
|
|
'updated_at' => now()->toDateTimeString(),
|
|
]));
|
|
} else {
|
|
Redis::del('system:global_message');
|
|
}
|
|
return Response::json(['success' => true]);
|
|
}
|
|
|
|
public function clearCache(Request $request)
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
Redis::flushDB();
|
|
return Response::json(['success' => true, 'message' => 'Cache cleared']);
|
|
}
|
|
|
|
public function getLogs(Request $request)
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
$limit = min((int) $request->input('limit', 50), 200);
|
|
$logs = DB::table('logs')->orderByDesc('id')->limit($limit)->get();
|
|
return Response::json(['success' => true, 'data' => $logs]);
|
|
}
|
|
|
|
public function getTableLogs(Request $request)
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
$limit = min((int) $request->input('limit', 50), 200);
|
|
$logs = DB::table('table_logs')->orderByDesc('id')->limit($limit)->get();
|
|
return Response::json(['success' => true, 'data' => $logs]);
|
|
}
|
|
|
|
public function backupDatabase(Request $request)
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
|
|
$name = $request->input('name', 'backup_' . date('Y_m_d_His'));
|
|
$backup = DbBackup::create([
|
|
'name' => $name,
|
|
'status' => 'pending',
|
|
'created_by' => Auth::id(),
|
|
]);
|
|
|
|
return Response::json(['success' => true, 'data' => $backup, 'message' => 'Backup queued']);
|
|
}
|
|
|
|
public function listBackups()
|
|
{
|
|
if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
|
|
$backups = DbBackup::orderByDesc('id')->limit(20)->get();
|
|
return Response::json(['success' => true, 'data' => $backups]);
|
|
}
|
|
}
|