mirror of
https://github.com/pelican-dev/panel.git
synced 2025-06-11 19:38:59 +02:00
Add endpoints
This commit is contained in:
parent
30051ab0d7
commit
4cba1540ac
41
app/Casts/EndpointCollection.php
Normal file
41
app/Casts/EndpointCollection.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Casts;
|
||||||
|
|
||||||
|
use App\Models\Objects\Endpoint;
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\Castable;
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Stringable;
|
||||||
|
use TypeError;
|
||||||
|
|
||||||
|
class EndpointCollection implements Castable
|
||||||
|
{
|
||||||
|
public static function castUsing(array $arguments)
|
||||||
|
{
|
||||||
|
return new class() implements CastsAttributes
|
||||||
|
{
|
||||||
|
public function get($model, $key, $value, $attributes)
|
||||||
|
{
|
||||||
|
if (! isset($attributes[$key])) {
|
||||||
|
return new Collection();
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode($attributes[$key], true);
|
||||||
|
|
||||||
|
return (new Collection($data))->map(function ($value) {
|
||||||
|
return new Endpoint($value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set($model, $key, $value, $attributes)
|
||||||
|
{
|
||||||
|
if (!$value instanceof Collection) {
|
||||||
|
return new Collection();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value->map(fn ($endpoint) => (string) $endpoint);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
26
app/Livewire/EndpointSynth.php
Normal file
26
app/Livewire/EndpointSynth.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire;
|
||||||
|
|
||||||
|
use App\Models\Objects\Endpoint;
|
||||||
|
use Livewire\Mechanisms\HandleComponents\Synthesizers\Synth;
|
||||||
|
|
||||||
|
class EndpointSynth extends Synth
|
||||||
|
{
|
||||||
|
public static $key = 'endpoint';
|
||||||
|
|
||||||
|
public static function match($target)
|
||||||
|
{
|
||||||
|
return $target instanceof Endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dehydrate($target)
|
||||||
|
{
|
||||||
|
return (string) $target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hydrate($value)
|
||||||
|
{
|
||||||
|
return new Endpoint($value);
|
||||||
|
}
|
||||||
|
}
|
@ -12,28 +12,30 @@ class Endpoint
|
|||||||
public const PORT_CEIL = 65535;
|
public const PORT_CEIL = 65535;
|
||||||
public const PORT_RANGE_LIMIT = 1000;
|
public const PORT_RANGE_LIMIT = 1000;
|
||||||
public const PORT_RANGE_REGEX = '/^(\d{4,5})-(\d{4,5})$/';
|
public const PORT_RANGE_REGEX = '/^(\d{4,5})-(\d{4,5})$/';
|
||||||
|
public const INADDR_ANY = '0.0.0.0';
|
||||||
|
|
||||||
public int $port;
|
public int $port;
|
||||||
public string $ip;
|
public string $ip;
|
||||||
|
|
||||||
public function __construct(string $address = null, int $port = null) {
|
public function __construct(string|int $port, string $ip = null) {
|
||||||
if ($address === null) {
|
$this->ip = $ip ?? self::INADDR_ANY;
|
||||||
$address = '0.0.0.0';
|
$this->port = (int) $port;
|
||||||
|
|
||||||
|
if (str_contains($port, ':')) {
|
||||||
|
[$this->ip, $this->port] = explode(':', $port);
|
||||||
}
|
}
|
||||||
|
|
||||||
$ip = $address;
|
throw_unless(filter_var($this->ip, FILTER_VALIDATE_IP) !== false, new InvalidArgumentException("$this->ip is an invalid IP address"));
|
||||||
if (str_contains($address, ':')) {
|
throw_unless($this->port > self::PORT_FLOOR, "Port $this->port must be greater than " . self::PORT_FLOOR);
|
||||||
[$ip, $port] = explode(':', $address);
|
throw_unless($this->port < self::PORT_CEIL, "Port $this->port must be less than " . self::PORT_CEIL);
|
||||||
|
}
|
||||||
|
|
||||||
throw_unless(is_numeric($port), new InvalidArgumentException("Port ($port) must be a number"));
|
public function __toString()
|
||||||
|
{
|
||||||
$port = (int) $port;
|
if ($this->ip === self::INADDR_ANY) {
|
||||||
|
return (string) $this->port;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_unless(is_int($port), new InvalidArgumentException("Port ($port) must be an integer"));
|
return "$this->ip:$this->port";
|
||||||
throw_unless(filter_var($ip, FILTER_VALIDATE_IP) !== false, new InvalidArgumentException("$ip is an invalid IP address"));
|
|
||||||
|
|
||||||
$this->ip = $ip;
|
|
||||||
$this->port = $port;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Casts\EndpointCollection;
|
||||||
use App\Enums\ServerState;
|
use App\Enums\ServerState;
|
||||||
use App\Exceptions\Http\Connection\DaemonConnectionException;
|
use App\Exceptions\Http\Connection\DaemonConnectionException;
|
||||||
|
use App\Models\Objects\Endpoint;
|
||||||
use GuzzleHttp\Exception\GuzzleException;
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
@ -67,7 +69,6 @@ class Server extends Model
|
|||||||
'database_limit' => 'present|nullable|integer|min:0',
|
'database_limit' => 'present|nullable|integer|min:0',
|
||||||
'allocation_limit' => 'sometimes|nullable|integer|min:0',
|
'allocation_limit' => 'sometimes|nullable|integer|min:0',
|
||||||
'backup_limit' => 'present|nullable|integer|min:0',
|
'backup_limit' => 'present|nullable|integer|min:0',
|
||||||
'ports' => 'array',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
protected function casts(): array
|
protected function casts(): array
|
||||||
@ -90,7 +91,7 @@ class Server extends Model
|
|||||||
'deleted_at' => 'datetime',
|
'deleted_at' => 'datetime',
|
||||||
'installed_at' => 'datetime',
|
'installed_at' => 'datetime',
|
||||||
'docker_labels' => 'array',
|
'docker_labels' => 'array',
|
||||||
'ports' => 'array',
|
'ports' => EndpointCollection::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,9 +310,16 @@ class Server extends Model
|
|||||||
return cache()->get("servers.$this->uuid.container.status") ?? 'missing';
|
return cache()->get("servers.$this->uuid.container.status") ?? 'missing';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPrimaryEndpoint()
|
public function getPrimaryEndpoint(): ?Endpoint
|
||||||
{
|
{
|
||||||
dd($this->ports);
|
$endpoint = $this->ports->first();
|
||||||
dd($this->variables);
|
|
||||||
|
$portEggVariable = $this->variables->firstWhere('env_variable', 'SERVER_PORT');
|
||||||
|
if ($portEggVariable) {
|
||||||
|
$portServerVariable = $this->serverVariables->firstWhere('variable_id', $portEggVariable->id);
|
||||||
|
$endpoint = new Endpoint($portServerVariable->variable_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $endpoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Extensions\Themes\Theme;
|
use App\Extensions\Themes\Theme;
|
||||||
|
use App\Livewire\EndpointSynth;
|
||||||
use App\Models;
|
use App\Models;
|
||||||
use App\Models\ApiKey;
|
use App\Models\ApiKey;
|
||||||
use App\Models\Node;
|
use App\Models\Node;
|
||||||
@ -21,6 +22,7 @@ use Illuminate\Support\Facades\View;
|
|||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Laravel\Sanctum\Sanctum;
|
use Laravel\Sanctum\Sanctum;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
@ -72,6 +74,8 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
$this->bootAuth();
|
$this->bootAuth();
|
||||||
$this->bootBroadcast();
|
$this->bootBroadcast();
|
||||||
|
|
||||||
|
Livewire::propertySynthesizer(EndpointSynth::class);
|
||||||
|
|
||||||
$bearerTokens = fn (OpenApi $openApi) => $openApi->secure(SecurityScheme::http('bearer'));
|
$bearerTokens = fn (OpenApi $openApi) => $openApi->secure(SecurityScheme::http('bearer'));
|
||||||
Gate::define('viewApiDocs', fn () => true);
|
Gate::define('viewApiDocs', fn () => true);
|
||||||
Scramble::registerApi('application', ['api_path' => 'api/application', 'info' => ['version' => '1.0']]);
|
Scramble::registerApi('application', ['api_path' => 'api/application', 'info' => ['version' => '1.0']]);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Services\Servers;
|
namespace App\Services\Servers;
|
||||||
|
|
||||||
|
use App\Models\Objects\Endpoint;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
|
|
||||||
class StartupCommandService
|
class StartupCommandService
|
||||||
@ -13,9 +14,8 @@ class StartupCommandService
|
|||||||
{
|
{
|
||||||
$endpoint = $server->getPrimaryEndpoint();
|
$endpoint = $server->getPrimaryEndpoint();
|
||||||
|
|
||||||
|
|
||||||
$find = ['{{SERVER_MEMORY}}', '{{SERVER_IP}}', '{{SERVER_PORT}}'];
|
$find = ['{{SERVER_MEMORY}}', '{{SERVER_IP}}', '{{SERVER_PORT}}'];
|
||||||
$replace = [$server->memory, $server->allocation->ip, $server->allocation->port];
|
$replace = [$server->memory, $endpoint->ip ?? Endpoint::INADDR_ANY, $endpoint->port ?? ''];
|
||||||
|
|
||||||
foreach ($server->variables as $variable) {
|
foreach ($server->variables as $variable) {
|
||||||
$find[] = '{{' . $variable->env_variable . '}}';
|
$find[] = '{{' . $variable->env_variable . '}}';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user