mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-23 19:37:35 +08:00
feat: machine mode, ECH subscriptions, batch ops & security hardening
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V2\Server;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ServerMachine;
|
||||
use App\Models\ServerMachineLoadHistory;
|
||||
use App\Services\ServerService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* machine controller
|
||||
*/
|
||||
class MachineController extends Controller
|
||||
{
|
||||
/**
|
||||
* get nodes list for machine
|
||||
*/
|
||||
public function nodes(Request $request): JsonResponse
|
||||
{
|
||||
$machine = $this->authenticateMachine($request);
|
||||
|
||||
$nodes = ServerService::getMachineNodes($machine)
|
||||
->map(fn($node) => [
|
||||
'id' => $node->id,
|
||||
'type' => $node->type,
|
||||
'name' => $node->name,
|
||||
])->values();
|
||||
|
||||
return response()->json([
|
||||
'nodes' => $nodes,
|
||||
'base_config' => [
|
||||
'push_interval' => (int) admin_setting('server_push_interval', 60),
|
||||
'pull_interval' => (int) admin_setting('server_pull_interval', 60),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* report machine status
|
||||
*/
|
||||
public function status(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'cpu' => 'required|numeric|min:0|max:100',
|
||||
'mem.total' => 'required|integer|min:0',
|
||||
'mem.used' => 'required|integer|min:0',
|
||||
'swap.total' => 'nullable|integer|min:0',
|
||||
'swap.used' => 'nullable|integer|min:0',
|
||||
'disk.total' => 'nullable|integer|min:0',
|
||||
'disk.used' => 'nullable|integer|min:0',
|
||||
]);
|
||||
|
||||
$machine = $this->authenticateMachine($request);
|
||||
$recordedAt = now()->timestamp;
|
||||
|
||||
$machine->forceFill([
|
||||
'load_status' => [
|
||||
'cpu' => (float) $request->input('cpu'),
|
||||
'mem' => [
|
||||
'total' => (int) $request->input('mem.total'),
|
||||
'used' => (int) $request->input('mem.used'),
|
||||
],
|
||||
'swap' => [
|
||||
'total' => (int) $request->input('swap.total', 0),
|
||||
'used' => (int) $request->input('swap.used', 0),
|
||||
],
|
||||
'disk' => [
|
||||
'total' => (int) $request->input('disk.total', 0),
|
||||
'used' => (int) $request->input('disk.used', 0),
|
||||
],
|
||||
'updated_at' => $recordedAt,
|
||||
],
|
||||
'last_seen_at' => $recordedAt,
|
||||
])->save();
|
||||
|
||||
ServerMachineLoadHistory::create([
|
||||
'machine_id' => $machine->id,
|
||||
'cpu' => (float) $request->input('cpu'),
|
||||
'mem_total' => (int) $request->input('mem.total'),
|
||||
'mem_used' => (int) $request->input('mem.used'),
|
||||
'disk_total' => (int) $request->input('disk.total', 0),
|
||||
'disk_used' => (int) $request->input('disk.used', 0),
|
||||
'recorded_at' => $recordedAt,
|
||||
]);
|
||||
|
||||
// Time-based cleanup: keep 24h of data, runs on ~5% of requests
|
||||
if (random_int(1, 20) === 1) {
|
||||
ServerMachineLoadHistory::query()
|
||||
->where('machine_id', $machine->id)
|
||||
->where('recorded_at', '<', now()->subDay()->timestamp)
|
||||
->delete();
|
||||
}
|
||||
|
||||
return response()->json(['data' => true]);
|
||||
}
|
||||
|
||||
private function authenticateMachine(Request $request): ServerMachine
|
||||
{
|
||||
$request->validate([
|
||||
'machine_id' => 'required|integer',
|
||||
'token' => 'required|string',
|
||||
]);
|
||||
|
||||
$machine = ServerMachine::where('id', $request->input('machine_id'))
|
||||
->where('token', $request->input('token'))
|
||||
->first();
|
||||
|
||||
if (!$machine || !$machine->is_active) {
|
||||
abort(403, 'Machine not found or disabled');
|
||||
}
|
||||
|
||||
$machine->forceFill(['last_seen_at' => now()->timestamp])->saveQuietly();
|
||||
|
||||
return $machine;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user