mirror of
https://github.com/mivodev/mivo.git
synced 2026-01-26 13:31:56 +07:00
Chore: Bump version to v1.1.0 and implement automated release system
This commit is contained in:
@@ -32,7 +32,8 @@ class ApiController extends Controller {
|
||||
$configModel = new Config();
|
||||
$session = $configModel->getSessionById($id);
|
||||
if ($session && !empty($session['password'])) {
|
||||
$pass = EncryptionHelper::decrypt($session['password']);
|
||||
// Config::getSessionById already decrypts the password
|
||||
$pass = $session['password'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use App\Core\Middleware;
|
||||
class DashboardController extends Controller {
|
||||
|
||||
public function __construct() {
|
||||
Middleware::auth();
|
||||
// Auth handled by Router Middleware
|
||||
}
|
||||
|
||||
public function index($session) {
|
||||
@@ -101,6 +101,7 @@ class DashboardController extends Controller {
|
||||
'hotspot_users' => 'Hotspot Users',
|
||||
'hotspot_users' => 'Hotspot Users',
|
||||
],
|
||||
'reload_interval' => $creds['reload'] ?? 5, // Default 5s if not set
|
||||
'interface' => $creds['interface'] ?? 'ether1'
|
||||
];
|
||||
// Pass Users Link (Optional: could be part of layout or card link)
|
||||
@@ -108,7 +109,9 @@ class DashboardController extends Controller {
|
||||
return $this->view('dashboard', $data);
|
||||
|
||||
} else {
|
||||
echo "Connection Failed to " . $creds['ip'];
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@ class DhcpController extends Controller
|
||||
if ($API->connect($config['ip_address'], $config['username'], $config['password'])) {
|
||||
// Fetch DHCP Leases
|
||||
$leases = $API->comm("/ip/dhcp-server/lease/print");
|
||||
$API->disconnect();
|
||||
} else {
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $config['ip_address']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Add index for viewing
|
||||
|
||||
@@ -34,8 +34,9 @@ class GeneratorController extends Controller {
|
||||
|
||||
$this->view('hotspot/generate', $data);
|
||||
} else {
|
||||
// Handle connection error (flash message ideally, but for now redirect or show error)
|
||||
echo "Connection failed to " . $creds['ip'];
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class HotspotController extends Controller {
|
||||
|
||||
$userId = $session; // For view context
|
||||
$users = [];
|
||||
$servers = [];
|
||||
$error = null;
|
||||
|
||||
$API = new RouterOSAPI();
|
||||
@@ -40,17 +41,20 @@ class HotspotController extends Controller {
|
||||
// Get all hotspot users
|
||||
$users = $API->comm("/ip/hotspot/user/print");
|
||||
|
||||
// Get active users to mark status (optional, can be done later for optimization)
|
||||
// $active = $API->comm("/ip/hotspot/active/print");
|
||||
// Get servers for dropdown
|
||||
$servers = $API->comm("/ip/hotspot/server/print");
|
||||
|
||||
$API->disconnect();
|
||||
} else {
|
||||
$error = "Connection Failed to " . $creds['ip'];
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'session' => $session,
|
||||
'users' => $users,
|
||||
'servers' => $servers,
|
||||
'error' => $error
|
||||
];
|
||||
|
||||
@@ -389,7 +393,9 @@ class HotspotController extends Controller {
|
||||
$items = $API->comm("/ip/hotspot/active/print");
|
||||
$API->disconnect();
|
||||
} else {
|
||||
$error = "Connection Failed to " . $creds['ip'];
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [
|
||||
@@ -451,7 +457,9 @@ class HotspotController extends Controller {
|
||||
$items = $API->comm("/ip/hotspot/host/print");
|
||||
$API->disconnect();
|
||||
} else {
|
||||
$error = "Connection Failed to " . $creds['ip'];
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [
|
||||
@@ -484,7 +492,9 @@ class HotspotController extends Controller {
|
||||
$items = $API->comm("/ip/hotspot/ip-binding/print");
|
||||
$API->disconnect();
|
||||
} else {
|
||||
$error = "Connection Failed to " . $creds['ip'];
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [
|
||||
@@ -606,7 +616,9 @@ class HotspotController extends Controller {
|
||||
$items = $API->comm("/ip/hotspot/walled-garden/ip/print");
|
||||
$API->disconnect();
|
||||
} else {
|
||||
$error = "Connection Failed to " . $creds['ip'];
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [
|
||||
@@ -837,8 +849,9 @@ class HotspotController extends Controller {
|
||||
$templateContent = $tpl['content'];
|
||||
$viewName = 'print/custom';
|
||||
} else {
|
||||
// Fallback if ID invalid
|
||||
$currentTemplate = 'default';
|
||||
\App\Helpers\FlashHelper::set('error', 'Template Not Found', 'The selected print template could not be found.');
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/hotspot/users'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,10 @@ class LogController extends Controller
|
||||
$logs = array_reverse($logs);
|
||||
}
|
||||
|
||||
$API->disconnect();
|
||||
} else {
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $config['ip_address']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
|
||||
return $this->view('reports/user_log', [
|
||||
|
||||
@@ -21,6 +21,21 @@ class ProfileController extends Controller
|
||||
// Use default port 8728 if not specified
|
||||
if ($API->connect($creds['ip'], $creds['user'], $creds['password'])) {
|
||||
$profiles = $API->comm('/ip/hotspot/user/profile/print');
|
||||
|
||||
// Fetch Pools & Queues for the Modal Form
|
||||
$pools = $API->comm('/ip/pool/print');
|
||||
$simple = $API->comm('/queue/simple/print');
|
||||
$tree = $API->comm('/queue/tree/print');
|
||||
|
||||
$queues = [];
|
||||
foreach ($simple as $q) {
|
||||
if(isset($q['name'])) $queues[] = $q['name'];
|
||||
}
|
||||
foreach ($tree as $q) {
|
||||
if(isset($q['name'])) $queues[] = $q['name'];
|
||||
}
|
||||
sort($queues);
|
||||
|
||||
$API->disconnect();
|
||||
|
||||
// Process profiles to add metadata from on-login script
|
||||
@@ -33,15 +48,14 @@ class ProfileController extends Controller
|
||||
$this->view('hotspot/profiles/index', [
|
||||
'session' => $session,
|
||||
'profiles' => $profiles,
|
||||
'pools' => $pools,
|
||||
'queues' => $queues,
|
||||
'title' => 'User Profiles'
|
||||
]);
|
||||
} else {
|
||||
$this->view('hotspot/profiles/index', [
|
||||
'session' => $session,
|
||||
'profiles' => [],
|
||||
'error' => 'Connection Failed to ' . $creds['ip'],
|
||||
'title' => 'User Profiles'
|
||||
]);
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/dashboard'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,9 @@ class PublicStatusController extends Controller {
|
||||
// View: Show Search Page
|
||||
public function index($session) {
|
||||
// Just verify session existence to display Hotspot Name
|
||||
// Session verified by RouterCheckMiddleware
|
||||
$configModel = new Config();
|
||||
$creds = $configModel->getSession($session);
|
||||
|
||||
if (!$creds) {
|
||||
// If session invalid, maybe show 404 or generic error
|
||||
echo "Session not found.";
|
||||
return;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'session' => $session,
|
||||
@@ -92,9 +87,6 @@ class PublicStatusController extends Controller {
|
||||
if (!empty($user)) {
|
||||
$u = $user[0];
|
||||
|
||||
// DEBUG: Log the user data to see raw values
|
||||
error_log("Status Debug: " . json_encode($u));
|
||||
|
||||
// --- SECURITY CHECK: Hide Unused Vouchers ---
|
||||
$uptimeRaw = $u['uptime'] ?? '0s';
|
||||
$bytesIn = intval($u['bytes-in'] ?? 0);
|
||||
|
||||
@@ -19,7 +19,14 @@ class QuickPrintController extends Controller {
|
||||
// Dashboard: List Cards
|
||||
public function index($session) {
|
||||
$qpModel = new QuickPrintModel();
|
||||
$packages = $qpModel->getAllBySession($session);
|
||||
|
||||
$configModel = new Config();
|
||||
$creds = $configModel->getSession($session);
|
||||
$routerId = $creds['id'] ?? null;
|
||||
|
||||
// If no ID (Legacy), fallback to empty list or handle gracefully.
|
||||
// For now, we assume ID exists as per migration plan.
|
||||
$packages = $routerId ? $qpModel->getAllByRouterId($routerId) : [];
|
||||
|
||||
$data = [
|
||||
'session' => $session,
|
||||
@@ -32,11 +39,12 @@ class QuickPrintController extends Controller {
|
||||
// List/Manage Packages (CRUD)
|
||||
public function manage($session) {
|
||||
$qpModel = new QuickPrintModel();
|
||||
$packages = $qpModel->getAllBySession($session);
|
||||
|
||||
// Need profiles for the Add/Edit Modal
|
||||
|
||||
$configModel = new Config();
|
||||
$creds = $configModel->getSession($session);
|
||||
$routerId = $creds['id'] ?? null;
|
||||
|
||||
$packages = $routerId ? $qpModel->getAllByRouterId($routerId) : [];
|
||||
$profiles = [];
|
||||
if ($creds) {
|
||||
$API = new RouterOSAPI();
|
||||
@@ -63,7 +71,13 @@ class QuickPrintController extends Controller {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return;
|
||||
|
||||
$session = $_POST['session'] ?? '';
|
||||
|
||||
$configModel = new Config();
|
||||
$creds = $configModel->getSession($session);
|
||||
$routerId = $creds['id'] ?? 0;
|
||||
|
||||
$data = [
|
||||
'router_id' => $routerId,
|
||||
'session_name' => $session,
|
||||
'name' => $_POST['name'] ?? 'Package',
|
||||
'server' => $_POST['server'] ?? 'all',
|
||||
@@ -71,6 +85,7 @@ class QuickPrintController extends Controller {
|
||||
'prefix' => $_POST['prefix'] ?? '',
|
||||
'char_length' => $_POST['char_length'] ?? 4,
|
||||
'price' => $_POST['price'] ?? 0,
|
||||
'selling_price' => $_POST['selling_price'] ?? ($_POST['price'] ?? 0),
|
||||
'time_limit' => $_POST['time_limit'] ?? '',
|
||||
'data_limit' => $_POST['data_limit'] ?? '',
|
||||
'comment' => $_POST['comment'] ?? '',
|
||||
@@ -85,6 +100,40 @@ class QuickPrintController extends Controller {
|
||||
exit;
|
||||
}
|
||||
|
||||
// CRUD: Update
|
||||
public function update() {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return;
|
||||
|
||||
$session = $_POST['session'] ?? '';
|
||||
$id = $_POST['id'] ?? '';
|
||||
|
||||
if (empty($id)) {
|
||||
\App\Helpers\FlashHelper::set('error', 'common.error', 'toasts.error_missing_id', [], true);
|
||||
header("Location: /" . $session . "/quick-print/manage");
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $_POST['name'] ?? 'Package',
|
||||
'profile' => $_POST['profile'] ?? 'default',
|
||||
'prefix' => $_POST['prefix'] ?? '',
|
||||
'char_length' => $_POST['char_length'] ?? 4,
|
||||
'price' => $_POST['price'] ?? 0,
|
||||
'selling_price' => $_POST['selling_price'] ?? ($_POST['price'] ?? 0),
|
||||
'time_limit' => $_POST['time_limit'] ?? '',
|
||||
'data_limit' => $_POST['data_limit'] ?? '',
|
||||
'comment' => $_POST['comment'] ?? '',
|
||||
'color' => $_POST['color'] ?? 'bg-blue-500'
|
||||
];
|
||||
|
||||
$qpModel = new QuickPrintModel();
|
||||
$qpModel->update($id, $data); // Assuming update method exists in simple JSON model
|
||||
|
||||
\App\Helpers\FlashHelper::set('success', 'toasts.package_updated', 'toasts.package_updated_desc', [], true);
|
||||
header("Location: /" . $session . "/quick-print/manage");
|
||||
exit;
|
||||
}
|
||||
|
||||
// CRUD: Delete
|
||||
public function delete() {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return;
|
||||
@@ -158,7 +207,9 @@ class QuickPrintController extends Controller {
|
||||
$API->comm("/ip/hotspot/user/add", $userData);
|
||||
$API->disconnect();
|
||||
} else {
|
||||
die("Connection failed");
|
||||
\App\Helpers\FlashHelper::set('error', 'Connection Failed', 'Could not connect to router at ' . $creds['ip']);
|
||||
header('Location: ' . ($_SERVER['HTTP_REFERER'] ?? '/' . $session . '/quick-print/manage'));
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use App\Helpers\FormatHelper;
|
||||
class SettingsController extends Controller {
|
||||
|
||||
public function __construct() {
|
||||
Middleware::auth();
|
||||
// Auth handled by Router Middleware
|
||||
}
|
||||
|
||||
public function system() {
|
||||
@@ -33,10 +33,6 @@ class SettingsController extends Controller {
|
||||
return $this->view('settings/index', ['routers' => $routers]);
|
||||
}
|
||||
|
||||
public function add() {
|
||||
return $this->view('settings/form');
|
||||
}
|
||||
|
||||
// ... (Existing Store methods) ...
|
||||
public function store() {
|
||||
// Sanitize Session Name (Duplicate Frontend Logic)
|
||||
@@ -102,33 +98,7 @@ class SettingsController extends Controller {
|
||||
}
|
||||
|
||||
|
||||
public function edit() {
|
||||
// ID passed via query param or route param?
|
||||
// Our router supports {id} but let's check how we handle it.
|
||||
// Router: /settings/edit/{id}
|
||||
// In Router.php, params are passed to method.
|
||||
// So method signature should be edit($id)
|
||||
|
||||
// Wait, Router.php passes matches as params array to invokeCallback.
|
||||
// So we need to capture arguments here.
|
||||
$args = func_get_args();
|
||||
$id = $args[0] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
header('Location: /settings/routers');
|
||||
exit;
|
||||
}
|
||||
|
||||
$configModel = new Config();
|
||||
$session = $configModel->getSessionById($id);
|
||||
|
||||
if (!$session) {
|
||||
header('Location: /settings/routers');
|
||||
exit;
|
||||
}
|
||||
|
||||
return $this->view('settings/form', ['router' => $session]);
|
||||
}
|
||||
|
||||
public function update() {
|
||||
$id = $_POST['id'];
|
||||
@@ -316,7 +286,7 @@ class SettingsController extends Controller {
|
||||
// Restore Logos
|
||||
if (isset($json['logos'])) {
|
||||
$logoModel = new \App\Models\Logo();
|
||||
$uploadDir = ROOT . '/public/assets/img/logos/';
|
||||
$uploadDir = ROOT . '/public/uploads/logos/';
|
||||
if (!file_exists($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
@@ -341,7 +311,7 @@ class SettingsController extends Controller {
|
||||
ON CONFLICT(id) DO UPDATE SET name=excluded.name, path=excluded.path, type=excluded.type, size=excluded.size", [
|
||||
'id' => $logo['id'],
|
||||
'name' => $logo['name'],
|
||||
'path' => '/assets/img/logos/' . $filename,
|
||||
'path' => '/uploads/logos/' . $filename,
|
||||
'type' => $extension,
|
||||
'size' => $logo['size']
|
||||
]);
|
||||
@@ -371,22 +341,24 @@ class SettingsController extends Controller {
|
||||
}
|
||||
|
||||
public function uploadLogo() {
|
||||
if (!isset($_FILES['logo_file'])) {
|
||||
if (!isset($_FILES['logo_file']) || $_FILES['logo_file']['error'] !== UPLOAD_ERR_OK) {
|
||||
\App\Helpers\FlashHelper::set('error', 'toasts.upload_failed', 'toasts.no_file_selected', [], true);
|
||||
header('Location: /settings/logos');
|
||||
exit;
|
||||
}
|
||||
|
||||
$logoModel = new \App\Models\Logo();
|
||||
try {
|
||||
$logoModel->add($_FILES['logo_file']);
|
||||
$result = $logoModel->add($_FILES['logo_file']);
|
||||
if ($result) {
|
||||
\App\Helpers\FlashHelper::set('success', 'toasts.logo_uploaded', 'toasts.logo_uploaded_desc', [], true);
|
||||
} else {
|
||||
\App\Helpers\FlashHelper::set('error', 'toasts.upload_failed', 'Generic upload error', [], true);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Ideally flash error message to session
|
||||
// For now, redirect (logging error via debug or ignoring as per simple req)
|
||||
// session_start() is implicit in Middleware usually or index
|
||||
// $_SESSION['error'] = $e->getMessage();
|
||||
\App\Helpers\FlashHelper::set('error', 'toasts.upload_failed', $e->getMessage(), [], true);
|
||||
}
|
||||
|
||||
\App\Helpers\FlashHelper::set('success', 'toasts.logo_uploaded', 'toasts.logo_uploaded_desc', [], true);
|
||||
header('Location: /settings/logos');
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use App\Core\Controller;
|
||||
use App\Models\VoucherTemplateModel;
|
||||
use App\Core\Middleware;
|
||||
|
||||
class TemplateController extends Controller {
|
||||
class VoucherTemplateController extends Controller {
|
||||
|
||||
public function __construct() {
|
||||
Middleware::auth();
|
||||
@@ -19,7 +19,7 @@ class TemplateController extends Controller {
|
||||
$data = [
|
||||
'templates' => $templates
|
||||
];
|
||||
return $this->view('settings/templates/index', $data);
|
||||
return $this->view('settings/voucher_templates/index', $data);
|
||||
}
|
||||
|
||||
public function preview($id) {
|
||||
@@ -48,7 +48,7 @@ class TemplateController extends Controller {
|
||||
$data = [
|
||||
'logoMap' => $logoMap
|
||||
];
|
||||
return $this->view('settings/templates/add', $data); // Note: add.php likely includes edit.php or is alias. View above says 'Template Editor (Shared)'
|
||||
return $this->view('settings/voucher_templates/add', $data);
|
||||
}
|
||||
|
||||
public function store() {
|
||||
@@ -62,6 +62,7 @@ class TemplateController extends Controller {
|
||||
// I will use 'global' for templates created in Settings.
|
||||
|
||||
$data = [
|
||||
'router_id' => 0, // Global templates
|
||||
'session_name' => 'global',
|
||||
'name' => $name,
|
||||
'content' => $content
|
||||
@@ -71,7 +72,7 @@ class TemplateController extends Controller {
|
||||
$templateModel->add($data);
|
||||
|
||||
\App\Helpers\FlashHelper::set('success', 'toasts.template_created', 'toasts.template_created_desc', ['name' => $name], true);
|
||||
header("Location: /settings/templates");
|
||||
header("Location: /settings/voucher-templates");
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -80,7 +81,7 @@ class TemplateController extends Controller {
|
||||
$template = $templateModel->getById($id);
|
||||
|
||||
if (!$template) {
|
||||
header("Location: /settings/templates");
|
||||
header("Location: /settings/voucher-templates");
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ class TemplateController extends Controller {
|
||||
'template' => $template,
|
||||
'logoMap' => $logoMap
|
||||
];
|
||||
return $this->view('settings/templates/edit', $data);
|
||||
return $this->view('settings/voucher_templates/edit', $data);
|
||||
}
|
||||
|
||||
public function update() {
|
||||
@@ -114,7 +115,7 @@ class TemplateController extends Controller {
|
||||
$templateModel->update($id, $data);
|
||||
|
||||
\App\Helpers\FlashHelper::set('success', 'toasts.template_updated', 'toasts.template_updated_desc', ['name' => $name], true);
|
||||
header("Location: /settings/templates");
|
||||
header("Location: /settings/voucher-templates");
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -126,7 +127,7 @@ class TemplateController extends Controller {
|
||||
$templateModel->delete($id);
|
||||
|
||||
\App\Helpers\FlashHelper::set('success', 'toasts.template_deleted', 'toasts.template_deleted_desc', [], true);
|
||||
header("Location: /settings/templates");
|
||||
header("Location: /settings/voucher-templates");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user