Backend: real endpoints for role-permission overview, MQTT broker settings (with live reachability check), and SQLite backup download/restore (new system.manage permission, super-admin only; restore validates the SQLite file header and keeps a pre-restore safety copy). Desktop frontend: Roles (read-only permissions view), MQTT Settings, Backup & Restore wired to those endpoints; plus static AdminLTE-matching shells for Profile, Settings (embeds the real 2FA flow in its Security tab), Invoice, Calendar (FullCalendar), Chat, File Manager, and Projects. Mobile frontend: new frontend/src/styles/mobile.css, a from-scratch design system (purple theme, cards, slide-out sidebar, bottom tab bar) scoped entirely under a .mob-app root and mob- prefixed classes so it can never collide with the desktop Bootstrap/AdminLTE styling. Rebuilt TopBar/ BottomNav, added a new SlideOutNav, and reskinned the Dashboard and Users pages to it with real data.
78 lines
2.4 KiB
PHP
78 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use PhpMqtt\Client\ConnectionSettings;
|
|
use PhpMqtt\Client\MqttClient;
|
|
|
|
class MqttController extends Controller
|
|
{
|
|
public function token(Request $request)
|
|
{
|
|
$user = $request->user();
|
|
|
|
$roleKey = match (true) {
|
|
$user->hasAnyRole(['super-admin', 'admin']) => 'admin',
|
|
$user->hasRole('manager') => 'manager',
|
|
default => 'user',
|
|
};
|
|
|
|
$credentials = config("mqtt.role_credentials.{$roleKey}");
|
|
|
|
return response()->json([
|
|
'ws_url' => config('mqtt.ws_url'),
|
|
'username' => $credentials['username'],
|
|
'password' => $credentials['password'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Read-only broker configuration + a live reachability check, for the
|
|
* MQTT settings page. Never exposes the publisher/role credentials.
|
|
*/
|
|
public function settings(Request $request)
|
|
{
|
|
abort_unless($request->user()->can('system.manage'), 403);
|
|
|
|
$host = config('mqtt-client.connections.default.host');
|
|
$port = config('mqtt-client.connections.default.port');
|
|
$tls = (bool) config('mqtt-client.connections.default.connection_settings.tls.enabled');
|
|
$username = config('mqtt-client.connections.default.connection_settings.auth.username');
|
|
$password = config('mqtt-client.connections.default.connection_settings.auth.password');
|
|
|
|
$connected = $this->checkBrokerReachable($host, $port, $tls, $username, $password);
|
|
|
|
return response()->json([
|
|
'host' => $host,
|
|
'port' => $port,
|
|
'ws_url' => config('mqtt.ws_url'),
|
|
'tls_enabled' => $tls,
|
|
'connected' => $connected,
|
|
]);
|
|
}
|
|
|
|
private function checkBrokerReachable(?string $host, ?int $port, bool $tls, ?string $username, ?string $password): bool
|
|
{
|
|
if (! $host || ! $port) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
$client = new MqttClient($host, $port, 'health-check-'.uniqid());
|
|
$settings = (new ConnectionSettings)
|
|
->setConnectTimeout(2)
|
|
->setUseTls($tls)
|
|
->setUsername($username)
|
|
->setPassword($password);
|
|
$client->connect($settings, true);
|
|
$client->disconnect();
|
|
|
|
return true;
|
|
} catch (\Throwable) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|