198 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace App\Livewire\Settings;
 | 
						|
 | 
						|
use App\Models\InstanceSettings;
 | 
						|
use App\Models\Server;
 | 
						|
use App\Rules\ValidIpOrCidr;
 | 
						|
use Auth;
 | 
						|
use Hash;
 | 
						|
use Livewire\Attributes\Validate;
 | 
						|
use Livewire\Component;
 | 
						|
 | 
						|
class Advanced extends Component
 | 
						|
{
 | 
						|
    #[Validate('required')]
 | 
						|
    public Server $server;
 | 
						|
 | 
						|
    public InstanceSettings $settings;
 | 
						|
 | 
						|
    #[Validate('boolean')]
 | 
						|
    public bool $is_registration_enabled;
 | 
						|
 | 
						|
    #[Validate('boolean')]
 | 
						|
    public bool $do_not_track;
 | 
						|
 | 
						|
    #[Validate('boolean')]
 | 
						|
    public bool $is_dns_validation_enabled;
 | 
						|
 | 
						|
    #[Validate('nullable|string')]
 | 
						|
    public ?string $custom_dns_servers = null;
 | 
						|
 | 
						|
    #[Validate('boolean')]
 | 
						|
    public bool $is_api_enabled;
 | 
						|
 | 
						|
    public ?string $allowed_ips = null;
 | 
						|
 | 
						|
    #[Validate('boolean')]
 | 
						|
    public bool $is_sponsorship_popup_enabled;
 | 
						|
 | 
						|
    #[Validate('boolean')]
 | 
						|
    public bool $disable_two_step_confirmation;
 | 
						|
 | 
						|
    public function rules()
 | 
						|
    {
 | 
						|
        return [
 | 
						|
            'server' => 'required',
 | 
						|
            'is_registration_enabled' => 'boolean',
 | 
						|
            'do_not_track' => 'boolean',
 | 
						|
            'is_dns_validation_enabled' => 'boolean',
 | 
						|
            'custom_dns_servers' => 'nullable|string',
 | 
						|
            'is_api_enabled' => 'boolean',
 | 
						|
            'allowed_ips' => ['nullable', 'string', new ValidIpOrCidr],
 | 
						|
            'is_sponsorship_popup_enabled' => 'boolean',
 | 
						|
            'disable_two_step_confirmation' => 'boolean',
 | 
						|
        ];
 | 
						|
    }
 | 
						|
 | 
						|
    public function mount()
 | 
						|
    {
 | 
						|
        if (! isInstanceAdmin()) {
 | 
						|
            return redirect()->route('dashboard');
 | 
						|
        }
 | 
						|
        $this->server = Server::findOrFail(0);
 | 
						|
        $this->settings = instanceSettings();
 | 
						|
        $this->custom_dns_servers = $this->settings->custom_dns_servers;
 | 
						|
        $this->allowed_ips = $this->settings->allowed_ips;
 | 
						|
        $this->do_not_track = $this->settings->do_not_track;
 | 
						|
        $this->is_registration_enabled = $this->settings->is_registration_enabled;
 | 
						|
        $this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
 | 
						|
        $this->is_api_enabled = $this->settings->is_api_enabled;
 | 
						|
        $this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation;
 | 
						|
        $this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled;
 | 
						|
    }
 | 
						|
 | 
						|
    public function submit()
 | 
						|
    {
 | 
						|
        try {
 | 
						|
            $this->validate();
 | 
						|
 | 
						|
            $this->custom_dns_servers = str($this->custom_dns_servers)->replaceEnd(',', '')->trim();
 | 
						|
            $this->custom_dns_servers = str($this->custom_dns_servers)->trim()->explode(',')->map(function ($dns) {
 | 
						|
                return str($dns)->trim()->lower();
 | 
						|
            })->unique()->implode(',');
 | 
						|
 | 
						|
            // Handle allowed IPs with subnet support and 0.0.0.0 special case
 | 
						|
            $this->allowed_ips = str($this->allowed_ips)->replaceEnd(',', '')->trim();
 | 
						|
 | 
						|
            // Check if user entered 0.0.0.0 or left field empty (both allow access from anywhere)
 | 
						|
            $allowsFromAnywhere = false;
 | 
						|
            if (empty($this->allowed_ips)) {
 | 
						|
                $allowsFromAnywhere = true;
 | 
						|
            } elseif ($this->allowed_ips === '0.0.0.0' || str_contains($this->allowed_ips, '0.0.0.0')) {
 | 
						|
                $allowsFromAnywhere = true;
 | 
						|
            }
 | 
						|
 | 
						|
            // Check if it's 0.0.0.0 (allow all) or empty
 | 
						|
            if ($this->allowed_ips === '0.0.0.0' || empty($this->allowed_ips)) {
 | 
						|
                // Keep as is - empty means no restriction, 0.0.0.0 means allow all
 | 
						|
            } else {
 | 
						|
                // Validate and clean up the entries
 | 
						|
                $invalidEntries = [];
 | 
						|
                $validEntries = str($this->allowed_ips)->trim()->explode(',')->map(function ($entry) use (&$invalidEntries) {
 | 
						|
                    $entry = str($entry)->trim()->toString();
 | 
						|
 | 
						|
                    if (empty($entry)) {
 | 
						|
                        return null;
 | 
						|
                    }
 | 
						|
 | 
						|
                    // Check if it's valid CIDR notation
 | 
						|
                    if (str_contains($entry, '/')) {
 | 
						|
                        [$ip, $mask] = explode('/', $entry);
 | 
						|
                        if (filter_var($ip, FILTER_VALIDATE_IP) && is_numeric($mask) && $mask >= 0 && $mask <= 32) {
 | 
						|
                            return $entry;
 | 
						|
                        }
 | 
						|
                        $invalidEntries[] = $entry;
 | 
						|
 | 
						|
                        return null;
 | 
						|
                    }
 | 
						|
 | 
						|
                    // Check if it's a valid IP address
 | 
						|
                    if (filter_var($entry, FILTER_VALIDATE_IP)) {
 | 
						|
                        return $entry;
 | 
						|
                    }
 | 
						|
 | 
						|
                    $invalidEntries[] = $entry;
 | 
						|
 | 
						|
                    return null;
 | 
						|
                })->filter()->unique();
 | 
						|
 | 
						|
                if (! empty($invalidEntries)) {
 | 
						|
                    $this->dispatch('error', 'Invalid IP addresses or subnets: '.implode(', ', $invalidEntries));
 | 
						|
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
 | 
						|
                // Also check if we have no valid entries after filtering
 | 
						|
                if ($validEntries->isEmpty()) {
 | 
						|
                    $this->dispatch('error', 'No valid IP addresses or subnets provided');
 | 
						|
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
 | 
						|
                $this->allowed_ips = $validEntries->implode(',');
 | 
						|
            }
 | 
						|
 | 
						|
            $this->instantSave();
 | 
						|
 | 
						|
            // Show security warning if allowing access from anywhere
 | 
						|
            if ($allowsFromAnywhere) {
 | 
						|
                $message = empty($this->allowed_ips)
 | 
						|
                    ? 'Empty IP allowlist allows API access from anywhere.<br><br>This is not recommended for production environments!'
 | 
						|
                    : 'Using 0.0.0.0 allows API access from anywhere.<br><br>This is not recommended for production environments!';
 | 
						|
                $this->dispatch('warning', $message);
 | 
						|
            }
 | 
						|
        } catch (\Exception $e) {
 | 
						|
            return handleError($e, $this);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function instantSave()
 | 
						|
    {
 | 
						|
        try {
 | 
						|
            $this->settings->is_registration_enabled = $this->is_registration_enabled;
 | 
						|
            $this->settings->do_not_track = $this->do_not_track;
 | 
						|
            $this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled;
 | 
						|
            $this->settings->custom_dns_servers = $this->custom_dns_servers;
 | 
						|
            $this->settings->is_api_enabled = $this->is_api_enabled;
 | 
						|
            $this->settings->allowed_ips = $this->allowed_ips;
 | 
						|
            $this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled;
 | 
						|
            $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation;
 | 
						|
            $this->settings->save();
 | 
						|
            $this->dispatch('success', 'Settings updated!');
 | 
						|
        } catch (\Exception $e) {
 | 
						|
            return handleError($e, $this);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public function toggleTwoStepConfirmation($password): bool
 | 
						|
    {
 | 
						|
        if (! Hash::check($password, Auth::user()->password)) {
 | 
						|
            $this->addError('password', 'The provided password is incorrect.');
 | 
						|
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation = true;
 | 
						|
        $this->settings->save();
 | 
						|
        $this->dispatch('success', 'Two step confirmation has been disabled.');
 | 
						|
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    public function render()
 | 
						|
    {
 | 
						|
        return view('livewire.settings.advanced');
 | 
						|
    }
 | 
						|
}
 |