feat: machine mode, ECH subscriptions, batch ops & security hardening
This commit is contained in:
@@ -7,31 +7,60 @@ use App\Services\NodeSyncService;
|
||||
|
||||
class ServerObserver
|
||||
{
|
||||
public bool $afterCommit = true;
|
||||
|
||||
public function created(Server $server): void
|
||||
{
|
||||
$this->notifyMachineNodesChanged($server->machine_id);
|
||||
}
|
||||
|
||||
public function updated(Server $server): void
|
||||
{
|
||||
if (
|
||||
$server->isDirty([
|
||||
'group_ids',
|
||||
])
|
||||
) {
|
||||
NodeSyncService::notifyUsersUpdatedByGroup($server->id);
|
||||
} else if (
|
||||
$server->isDirty([
|
||||
'server_port',
|
||||
'protocol_settings',
|
||||
'type',
|
||||
'route_ids',
|
||||
'custom_outbounds',
|
||||
'custom_routes',
|
||||
'cert_config',
|
||||
])
|
||||
) {
|
||||
if ($server->wasChanged('group_ids')) {
|
||||
NodeSyncService::notifyFullSync($server->id);
|
||||
} elseif ($server->wasChanged([
|
||||
'server_port',
|
||||
'protocol_settings',
|
||||
'type',
|
||||
'route_ids',
|
||||
'custom_outbounds',
|
||||
'custom_routes',
|
||||
'cert_config',
|
||||
])) {
|
||||
NodeSyncService::notifyConfigUpdated($server->id);
|
||||
}
|
||||
|
||||
if ($server->wasChanged(['machine_id', 'enabled'])) {
|
||||
$this->notifyMachineChange(
|
||||
$server->machine_id,
|
||||
$server->getOriginal('machine_id')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleted(Server $server): void
|
||||
{
|
||||
NodeSyncService::notifyConfigUpdated($server->id);
|
||||
$this->notifyMachineChange(null, $server->getOriginal('machine_id') ?: $server->machine_id);
|
||||
}
|
||||
|
||||
private function notifyMachineChange(?int $newMachineId, ?int $oldMachineId): void
|
||||
{
|
||||
$notified = [];
|
||||
|
||||
if ($newMachineId) {
|
||||
NodeSyncService::notifyMachineNodesChanged($newMachineId);
|
||||
$notified[] = $newMachineId;
|
||||
}
|
||||
|
||||
if ($oldMachineId && !in_array($oldMachineId, $notified, true)) {
|
||||
NodeSyncService::notifyMachineNodesChanged($oldMachineId);
|
||||
}
|
||||
}
|
||||
|
||||
private function notifyMachineNodesChanged(?int $machineId): void
|
||||
{
|
||||
if ($machineId) {
|
||||
NodeSyncService::notifyMachineNodesChanged($machineId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ use App\Services\TrafficResetService;
|
||||
|
||||
class UserObserver
|
||||
{
|
||||
public bool $afterCommit = true;
|
||||
|
||||
public function __construct(
|
||||
private readonly TrafficResetService $trafficResetService
|
||||
) {
|
||||
@@ -15,12 +17,17 @@ class UserObserver
|
||||
|
||||
public function updated(User $user): void
|
||||
{
|
||||
if ($user->isDirty(['plan_id', 'expired_at'])) {
|
||||
// With $afterCommit = true, isDirty() is always false after commit.
|
||||
// Use wasChanged() to detect what was actually modified.
|
||||
$syncFields = ['group_id', 'uuid', 'speed_limit', 'device_limit', 'banned', 'expired_at', 'transfer_enable', 'u', 'd', 'plan_id'];
|
||||
$needsSync = $user->wasChanged($syncFields);
|
||||
$oldGroupId = $user->wasChanged('group_id') ? $user->getOriginal('group_id') : null;
|
||||
|
||||
if ($user->wasChanged(['plan_id', 'expired_at'])) {
|
||||
$this->recalculateNextResetAt($user);
|
||||
}
|
||||
|
||||
if ($user->isDirty(['group_id', 'uuid', 'speed_limit', 'device_limit', 'banned', 'expired_at', 'transfer_enable', 'u', 'd', 'plan_id'])) {
|
||||
$oldGroupId = $user->isDirty('group_id') ? $user->getOriginal('group_id') : null;
|
||||
if ($needsSync) {
|
||||
NodeUserSyncJob::dispatch($user->id, 'updated', $oldGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user