Merge branch 'develop' into matthewpi/security-keys-backport
This commit is contained in:
commit
f631ac1946
1153 changed files with 25099 additions and 37002 deletions
|
@ -3,7 +3,6 @@
|
|||
namespace Pterodactyl\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use LogicException;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Pterodactyl\Events\ActivityLogged;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
@ -124,7 +123,7 @@ class ActivityLog extends Model
|
|||
public function prunable()
|
||||
{
|
||||
if (is_null(config('activity.prune_days'))) {
|
||||
throw new LogicException('Cannot prune activity logs: no "prune_days" configuration value is set.');
|
||||
throw new \LogicException('Cannot prune activity logs: no "prune_days" configuration value is set.');
|
||||
}
|
||||
|
||||
return static::where('timestamp', '<=', Carbon::now()->subDays(config('activity.prune_days')));
|
||||
|
|
59
app/Models/AdminRole.php
Normal file
59
app/Models/AdminRole.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string|null $description
|
||||
* @property int $sort_id
|
||||
* @property array $permissions
|
||||
*/
|
||||
class AdminRole extends Model
|
||||
{
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'admin_role';
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*/
|
||||
protected $table = 'admin_roles';
|
||||
|
||||
/**
|
||||
* Fields that are mass assignable.
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'sort_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Cast values to correct type.
|
||||
*/
|
||||
protected $casts = [
|
||||
'sort_id' => 'int',
|
||||
'permissions' => 'array',
|
||||
];
|
||||
|
||||
public static array $validationRules = [
|
||||
'name' => 'required|string|max:64',
|
||||
'description' => 'nullable|string|max:255',
|
||||
'sort_id' => 'sometimes|numeric',
|
||||
];
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* Gets the permissions associated with an admin role.
|
||||
*/
|
||||
public function permissions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Permission::class);
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Models;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @deprecated — this class will be dropped in a future version, use the activity log
|
||||
*/
|
||||
class AuditLog extends Model
|
||||
{
|
||||
public const UPDATED_AT = null;
|
||||
|
||||
public static array $validationRules = [
|
||||
'uuid' => 'required|uuid',
|
||||
'action' => 'required|string|max:191',
|
||||
'subaction' => 'nullable|string|max:191',
|
||||
'device' => 'array',
|
||||
'device.ip_address' => 'ip',
|
||||
'device.user_agent' => 'string',
|
||||
'metadata' => 'array',
|
||||
];
|
||||
|
||||
protected $table = 'audit_logs';
|
||||
|
||||
protected bool $immutableDates = true;
|
||||
|
||||
protected $casts = [
|
||||
'is_system' => 'bool',
|
||||
'device' => 'array',
|
||||
'metadata' => 'array',
|
||||
];
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
'created_at',
|
||||
];
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AuditLog model and returns it, attaching device information and the
|
||||
* currently authenticated user if available. This model is not saved at this point, so
|
||||
* you can always make modifications to it as needed before saving.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function instance(string $action, array $metadata, bool $isSystem = false): self
|
||||
{
|
||||
/** @var \Illuminate\Http\Request $request */
|
||||
$request = Container::getInstance()->make('request');
|
||||
if ($isSystem || !$request instanceof Request) {
|
||||
$request = null;
|
||||
}
|
||||
|
||||
return (new self())->fill([
|
||||
'uuid' => Uuid::uuid4()->toString(),
|
||||
'is_system' => $isSystem,
|
||||
'user_id' => ($request && $request->user()) ? $request->user()->id : null,
|
||||
'server_id' => null,
|
||||
'action' => $action,
|
||||
'device' => $request ? [
|
||||
'ip_address' => $request->getClientIp() ?? '127.0.0.1',
|
||||
'user_agent' => $request->userAgent() ?? '',
|
||||
] : [],
|
||||
'metadata' => $metadata,
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property \Carbon\CarbonImmutable $updated_at
|
||||
* @property \Carbon\CarbonImmutable|null $deleted_at
|
||||
* @property \Pterodactyl\Models\Server $server
|
||||
* @property \Pterodactyl\Models\AuditLog[] $audits
|
||||
*/
|
||||
class Backup extends Model
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Pterodactyl\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
|
@ -13,7 +13,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property string $username
|
||||
* @property string $password
|
||||
* @property int|null $max_databases
|
||||
* @property int|null $node_id
|
||||
* @property \Carbon\CarbonImmutable $created_at
|
||||
* @property \Carbon\CarbonImmutable $updated_at
|
||||
*/
|
||||
|
@ -41,7 +40,7 @@ class DatabaseHost extends Model
|
|||
* Fields that are mass assignable.
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'host', 'port', 'username', 'password', 'max_databases', 'node_id',
|
||||
'name', 'host', 'port', 'username', 'password', 'max_databases',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -50,7 +49,6 @@ class DatabaseHost extends Model
|
|||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'max_databases' => 'integer',
|
||||
'node_id' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -62,17 +60,8 @@ class DatabaseHost extends Model
|
|||
'port' => 'required|numeric|between:1,65535',
|
||||
'username' => 'required|string|max:32',
|
||||
'password' => 'nullable|string',
|
||||
'node_id' => 'sometimes|nullable|integer|exists:nodes,id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets the node associated with a database host.
|
||||
*/
|
||||
public function node(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Node::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the databases associated with this host.
|
||||
*/
|
||||
|
@ -80,4 +69,12 @@ class DatabaseHost extends Model
|
|||
{
|
||||
return $this->hasMany(Database::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nodes that a database host is assigned to.
|
||||
*/
|
||||
public function nodes(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Node::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,15 +20,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property array|null $file_denylist
|
||||
* @property string|null $config_files
|
||||
* @property string|null $config_startup
|
||||
* @property string|null $config_logs
|
||||
* @property string|null $config_stop
|
||||
* @property int|null $config_from
|
||||
* @property string|null $startup
|
||||
* @property bool $script_is_privileged
|
||||
* @property string|null $script_install
|
||||
* @property string $script_entry
|
||||
* @property string $script_container
|
||||
* @property int|null $copy_script_from
|
||||
* @property ?string $script_entry
|
||||
* @property ?string $script_container
|
||||
* @property ?int $copy_script_from
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property string|null $copy_script_install
|
||||
|
@ -36,7 +35,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||
* @property string $copy_script_container
|
||||
* @property string|null $inherit_config_files
|
||||
* @property string|null $inherit_config_startup
|
||||
* @property string|null $inherit_config_logs
|
||||
* @property string|null $inherit_config_stop
|
||||
* @property string $inherit_file_denylist
|
||||
* @property array|null $inherit_features
|
||||
|
@ -88,7 +86,6 @@ class Egg extends Model
|
|||
'file_denylist',
|
||||
'config_files',
|
||||
'config_startup',
|
||||
'config_logs',
|
||||
'config_stop',
|
||||
'config_from',
|
||||
'startup',
|
||||
|
@ -128,7 +125,6 @@ class Egg extends Model
|
|||
'config_from' => 'sometimes|bail|nullable|numeric|exists:eggs,id',
|
||||
'config_stop' => 'required_without:config_from|nullable|string|max:191',
|
||||
'config_startup' => 'required_without:config_from|nullable|json',
|
||||
'config_logs' => 'required_without:config_from|nullable|json',
|
||||
'config_files' => 'required_without:config_from|nullable|json',
|
||||
'update_url' => 'sometimes|nullable|string',
|
||||
'force_outgoing_ip' => 'sometimes|boolean',
|
||||
|
@ -139,7 +135,6 @@ class Egg extends Model
|
|||
'file_denylist' => null,
|
||||
'config_stop' => null,
|
||||
'config_startup' => null,
|
||||
'config_logs' => null,
|
||||
'config_files' => null,
|
||||
'update_url' => null,
|
||||
];
|
||||
|
@ -207,18 +202,6 @@ class Egg extends Model
|
|||
return $this->configFrom->config_startup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the log reading configuration for an egg.
|
||||
*/
|
||||
public function getInheritConfigLogsAttribute(): ?string
|
||||
{
|
||||
if (!is_null($this->config_logs) || is_null($this->config_from)) {
|
||||
return $this->config_logs;
|
||||
}
|
||||
|
||||
return $this->configFrom->config_logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the stop command configuration for an egg.
|
||||
*/
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Pterodactyl\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
|
@ -18,8 +18,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
* @property \Carbon\CarbonImmutable $created_at
|
||||
* @property \Carbon\CarbonImmutable $updated_at
|
||||
* @property bool $required
|
||||
* @property \Pterodactyl\Models\Egg $egg
|
||||
* @property \Pterodactyl\Models\ServerVariable $serverVariable
|
||||
* @property Egg $egg
|
||||
* @property ServerVariable $serverVariables
|
||||
* @property string $field_type
|
||||
*
|
||||
* The "server_value" variable is only present on the object if you've loaded this model
|
||||
* using the server relationship.
|
||||
|
@ -80,15 +81,18 @@ class EggVariable extends Model
|
|||
return in_array('required', explode('|', $this->rules));
|
||||
}
|
||||
|
||||
public function egg(): HasOne
|
||||
/**
|
||||
* Returns the egg that this variable belongs to.
|
||||
*/
|
||||
public function egg(): BelongsTo
|
||||
{
|
||||
return $this->hasOne(Egg::class);
|
||||
return $this->belongsTo(Egg::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return server variables associated with this variable.
|
||||
*/
|
||||
public function serverVariable(): HasMany
|
||||
public function serverVariables(): HasMany
|
||||
{
|
||||
return $this->hasMany(ServerVariable::class, 'variable_id');
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Pterodactyl\Models\Filters;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Spatie\QueryBuilder\Filters\Filter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
|
@ -17,7 +16,7 @@ class AdminServerFilter implements Filter
|
|||
public function __invoke(Builder $query, $value, string $property)
|
||||
{
|
||||
if ($query->getQuery()->from !== 'servers') {
|
||||
throw new BadMethodCallException('Cannot use the AdminServerFilter against a non-server model.');
|
||||
throw new \BadMethodCallException('Cannot use the AdminServerFilter against a non-server model.');
|
||||
}
|
||||
$query
|
||||
->select('servers.*')
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Pterodactyl\Models\Filters;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\QueryBuilder\Filters\Filter;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
@ -25,7 +24,7 @@ class MultiFieldServerFilter implements Filter
|
|||
public function __invoke(Builder $query, $value, string $property)
|
||||
{
|
||||
if ($query->getQuery()->from !== 'servers') {
|
||||
throw new BadMethodCallException('Cannot use the MultiFieldServerFilter against a non-server model.');
|
||||
throw new \BadMethodCallException('Cannot use the MultiFieldServerFilter against a non-server model.');
|
||||
}
|
||||
|
||||
if (preg_match(self::IPV4_REGEX, $value) || preg_match('/^:\d{1,5}$/', $value)) {
|
||||
|
|
|
@ -155,6 +155,7 @@ abstract class Model extends IlluminateModel
|
|||
return;
|
||||
}
|
||||
|
||||
/** @var \Illuminate\Validation\Validator $validator */
|
||||
$validator = $this->getValidator();
|
||||
$validator->setData(
|
||||
// Trying to do self::toArray() here will leave out keys based on the whitelist/blacklist
|
||||
|
|
|
@ -6,6 +6,7 @@ use Illuminate\Support\Str;
|
|||
use Symfony\Component\Yaml\Yaml;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
@ -18,26 +19,34 @@ use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
|||
* @property string $name
|
||||
* @property string|null $description
|
||||
* @property int $location_id
|
||||
* @property string $fqdn
|
||||
* @property int|null $database_host_id
|
||||
* @property string $scheme
|
||||
* @property string $fqdn
|
||||
* @property int $listen_port_http
|
||||
* @property int $listen_port_sftp
|
||||
* @property int $public_port_http
|
||||
* @property int $public_port_sftp
|
||||
* @property bool $behind_proxy
|
||||
* @property bool $maintenance_mode
|
||||
* @property int $memory
|
||||
* @property int $memory_overallocate
|
||||
* @property int $sum_memory
|
||||
* @property int $disk
|
||||
* @property int $disk_overallocate
|
||||
* @property int $sum_disk
|
||||
* @property int $upload_size
|
||||
* @property string $daemon_token_id
|
||||
* @property string $daemon_token
|
||||
* @property int $daemonListen
|
||||
* @property int $daemonSFTP
|
||||
* @property string $daemonBase
|
||||
* @property string $daemon_base
|
||||
* @property int $servers_count
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property \Pterodactyl\Models\Location $location
|
||||
* @property \Pterodactyl\Models\Mount[]|\Illuminate\Database\Eloquent\Collection $mounts
|
||||
* @property \Pterodactyl\Models\Server[]|\Illuminate\Database\Eloquent\Collection $servers
|
||||
* @property \Pterodactyl\Models\Allocation[]|\Illuminate\Database\Eloquent\Collection $allocations
|
||||
* @property Allocation[]|Collection $allocations
|
||||
* @property \Pterodactyl\Models\DatabaseHost|null $databaseHost
|
||||
* @property Location $location
|
||||
* @property Mount[]|Collection $mounts
|
||||
* @property int[]|\Illuminate\Support\Collection $ports
|
||||
* @property Server[]|Collection $servers
|
||||
*/
|
||||
class Node extends Model
|
||||
{
|
||||
|
@ -49,6 +58,11 @@ class Node extends Model
|
|||
*/
|
||||
public const RESOURCE_NAME = 'node';
|
||||
|
||||
/**
|
||||
* The default location of server files on the Wings instance.
|
||||
*/
|
||||
public const DEFAULT_DAEMON_BASE = '/var/lib/pterodactyl/volumes';
|
||||
|
||||
public const DAEMON_TOKEN_ID_LENGTH = 16;
|
||||
public const DAEMON_TOKEN_LENGTH = 64;
|
||||
|
||||
|
@ -67,10 +81,13 @@ class Node extends Model
|
|||
*/
|
||||
protected $casts = [
|
||||
'location_id' => 'integer',
|
||||
'database_host_id' => 'integer',
|
||||
'listen_port_http' => 'integer',
|
||||
'listen_port_sftp' => 'integer',
|
||||
'public_port_http' => 'integer',
|
||||
'public_port_sftp' => 'integer',
|
||||
'memory' => 'integer',
|
||||
'disk' => 'integer',
|
||||
'daemonListen' => 'integer',
|
||||
'daemonSFTP' => 'integer',
|
||||
'behind_proxy' => 'boolean',
|
||||
'public' => 'boolean',
|
||||
'maintenance_mode' => 'boolean',
|
||||
|
@ -80,11 +97,11 @@ class Node extends Model
|
|||
* Fields that are mass assignable.
|
||||
*/
|
||||
protected $fillable = [
|
||||
'public', 'name', 'location_id',
|
||||
'public', 'name', 'location_id', 'database_host_id',
|
||||
'listen_port_http', 'listen_port_sftp', 'public_port_http', 'public_port_sftp',
|
||||
'fqdn', 'scheme', 'behind_proxy',
|
||||
'memory', 'memory_overallocate', 'disk',
|
||||
'disk_overallocate', 'upload_size', 'daemonBase',
|
||||
'daemonSFTP', 'daemonListen',
|
||||
'disk_overallocate', 'upload_size', 'daemon_base',
|
||||
'description', 'maintenance_mode',
|
||||
];
|
||||
|
||||
|
@ -92,17 +109,20 @@ class Node extends Model
|
|||
'name' => 'required|regex:/^([\w .-]{1,100})$/',
|
||||
'description' => 'string|nullable',
|
||||
'location_id' => 'required|exists:locations,id',
|
||||
'database_host_id' => 'sometimes|nullable|exists:database_hosts,id',
|
||||
'public' => 'boolean',
|
||||
'fqdn' => 'required|string',
|
||||
'listen_port_http' => 'required|numeric|between:1,65535',
|
||||
'listen_port_sftp' => 'required|numeric|between:1,65535',
|
||||
'public_port_http' => 'required|numeric|between:1,65535',
|
||||
'public_port_sftp' => 'required|numeric|between:1,65535',
|
||||
'scheme' => 'required',
|
||||
'behind_proxy' => 'boolean',
|
||||
'memory' => 'required|numeric|min:1',
|
||||
'memory_overallocate' => 'required|numeric|min:-1',
|
||||
'disk' => 'required|numeric|min:1',
|
||||
'disk_overallocate' => 'required|numeric|min:-1',
|
||||
'daemonBase' => 'sometimes|required|regex:/^([\/][\d\w.\-\/]+)$/',
|
||||
'daemonSFTP' => 'required|numeric|between:1,65535',
|
||||
'daemonListen' => 'required|numeric|between:1,65535',
|
||||
'daemon_base' => 'sometimes|required|regex:/^([\/][\d\w.\-\/]+)$/',
|
||||
'maintenance_mode' => 'boolean',
|
||||
'upload_size' => 'int|between:1,1024',
|
||||
];
|
||||
|
@ -111,13 +131,15 @@ class Node extends Model
|
|||
* Default values for specific columns that are generally not changed on base installs.
|
||||
*/
|
||||
protected $attributes = [
|
||||
'listen_port_http' => 8080,
|
||||
'listen_port_sftp' => 2022,
|
||||
'public_port_http' => 8080,
|
||||
'public_port_sftp' => 2022,
|
||||
'public' => true,
|
||||
'behind_proxy' => false,
|
||||
'memory_overallocate' => 0,
|
||||
'disk_overallocate' => 0,
|
||||
'daemonBase' => '/var/lib/pterodactyl/volumes',
|
||||
'daemonSFTP' => 2022,
|
||||
'daemonListen' => 8080,
|
||||
'daemon_base' => self::DEFAULT_DAEMON_BASE,
|
||||
'maintenance_mode' => false,
|
||||
];
|
||||
|
||||
|
@ -126,7 +148,7 @@ class Node extends Model
|
|||
*/
|
||||
public function getConnectionAddress(): string
|
||||
{
|
||||
return sprintf('%s://%s:%s', $this->scheme, $this->fqdn, $this->daemonListen);
|
||||
return sprintf('%s://%s:%s', $this->scheme, $this->fqdn, $this->public_port_http);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,7 +163,7 @@ class Node extends Model
|
|||
'token' => Container::getInstance()->make(Encrypter::class)->decrypt($this->daemon_token),
|
||||
'api' => [
|
||||
'host' => '0.0.0.0',
|
||||
'port' => $this->daemonListen,
|
||||
'port' => $this->listen_port_http,
|
||||
'ssl' => [
|
||||
'enabled' => (!$this->behind_proxy && $this->scheme === 'https'),
|
||||
'cert' => '/etc/letsencrypt/live/' . Str::lower($this->fqdn) . '/fullchain.pem',
|
||||
|
@ -150,9 +172,9 @@ class Node extends Model
|
|||
'upload_limit' => $this->upload_size,
|
||||
],
|
||||
'system' => [
|
||||
'data' => $this->daemonBase,
|
||||
'data' => $this->daemon_base,
|
||||
'sftp' => [
|
||||
'bind_port' => $this->daemonSFTP,
|
||||
'bind_port' => $this->listen_port_sftp,
|
||||
],
|
||||
],
|
||||
'allowed_mounts' => $this->mounts->pluck('source')->toArray(),
|
||||
|
@ -186,25 +208,9 @@ class Node extends Model
|
|||
);
|
||||
}
|
||||
|
||||
public function mounts(): HasManyThrough
|
||||
public function isUnderMaintenance(): bool
|
||||
{
|
||||
return $this->hasManyThrough(Mount::class, MountNode::class, 'node_id', 'id', 'id', 'mount_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location associated with a node.
|
||||
*/
|
||||
public function location(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Location::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the servers associated with a node.
|
||||
*/
|
||||
public function servers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Server::class);
|
||||
return $this->maintenance_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,13 +221,55 @@ class Node extends Model
|
|||
return $this->hasMany(Allocation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database host associated with a node.
|
||||
*/
|
||||
public function databaseHost(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DatabaseHost::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location associated with a node.
|
||||
*/
|
||||
public function location(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Location::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a HasManyThrough relationship for all the mounts associated with a node.
|
||||
*/
|
||||
public function mounts(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(Mount::class, MountNode::class, 'node_id', 'id', 'id', 'mount_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the servers associated with a node.
|
||||
*/
|
||||
public function servers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Server::class);
|
||||
}
|
||||
|
||||
public function loadServerSums(): self
|
||||
{
|
||||
$this->loadSum('servers as sum_memory', 'memory');
|
||||
$this->loadSum('servers as sum_disk', 'disk');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean if the node is viable for an additional server to be placed on it.
|
||||
*/
|
||||
public function isViable(int $memory, int $disk): bool
|
||||
public function isViable(int $memory = 0, int $disk = 0): bool
|
||||
{
|
||||
$memoryLimit = $this->memory * (1 + ($this->memory_overallocate / 100));
|
||||
$diskLimit = $this->disk * (1 + ($this->disk_overallocate / 100));
|
||||
$this->loadServerSums();
|
||||
|
||||
$memoryLimit = $this->memory * (1.0 + ($this->memory_overallocate / 100.0));
|
||||
$diskLimit = $this->disk * (1.0 + ($this->disk_overallocate / 100.0));
|
||||
|
||||
return ($this->sum_memory + $memory) <= $memoryLimit && ($this->sum_disk + $disk) <= $diskLimit;
|
||||
}
|
||||
|
|
|
@ -31,11 +31,11 @@ use Pterodactyl\Exceptions\Http\Server\ServerStateConflictException;
|
|||
* @property int $io
|
||||
* @property int $cpu
|
||||
* @property string|null $threads
|
||||
* @property bool $oom_disabled
|
||||
* @property bool $oom_killer
|
||||
* @property int $allocation_id
|
||||
* @property int $nest_id
|
||||
* @property int $egg_id
|
||||
* @property string $startup
|
||||
* @property string|null $startup
|
||||
* @property string $image
|
||||
* @property int|null $allocation_limit
|
||||
* @property int|null $database_limit
|
||||
|
@ -55,6 +55,7 @@ use Pterodactyl\Exceptions\Http\Server\ServerStateConflictException;
|
|||
* @property \Pterodactyl\Models\Egg|null $egg
|
||||
* @property \Illuminate\Database\Eloquent\Collection|\Pterodactyl\Models\Mount[] $mounts
|
||||
* @property int|null $mounts_count
|
||||
* @property \Pterodactyl\Models\Location $location
|
||||
* @property \Pterodactyl\Models\Nest $nest
|
||||
* @property \Pterodactyl\Models\Node $node
|
||||
* @property \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
|
||||
|
@ -89,7 +90,7 @@ use Pterodactyl\Exceptions\Http\Server\ServerStateConflictException;
|
|||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereNestId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereNodeId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereOomDisabled($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereOomKiller($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereOwnerId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereSkipScripts($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Server whereStartup($value)
|
||||
|
@ -115,6 +116,7 @@ class Server extends Model
|
|||
|
||||
public const STATUS_INSTALLING = 'installing';
|
||||
public const STATUS_INSTALL_FAILED = 'install_failed';
|
||||
public const STATUS_REINSTALL_FAILED = 'reinstall_failed';
|
||||
public const STATUS_SUSPENDED = 'suspended';
|
||||
public const STATUS_RESTORING_BACKUP = 'restoring_backup';
|
||||
|
||||
|
@ -129,7 +131,7 @@ class Server extends Model
|
|||
*/
|
||||
protected $attributes = [
|
||||
'status' => self::STATUS_INSTALLING,
|
||||
'oom_disabled' => true,
|
||||
'oom_killer' => false,
|
||||
'installed_at' => null,
|
||||
];
|
||||
|
||||
|
@ -160,7 +162,7 @@ class Server extends Model
|
|||
'io' => 'required|numeric|between:10,1000',
|
||||
'cpu' => 'required|numeric|min:0',
|
||||
'threads' => 'nullable|regex:/^[0-9-,]+$/',
|
||||
'oom_disabled' => 'sometimes|boolean',
|
||||
'oom_killer' => 'sometimes|boolean',
|
||||
'disk' => 'required|numeric|min:0',
|
||||
'allocation_id' => 'required|bail|unique:servers|exists:allocations,id',
|
||||
'nest_id' => 'required|exists:nests,id',
|
||||
|
@ -185,7 +187,7 @@ class Server extends Model
|
|||
'disk' => 'integer',
|
||||
'io' => 'integer',
|
||||
'cpu' => 'integer',
|
||||
'oom_disabled' => 'boolean',
|
||||
'oom_killer' => 'boolean',
|
||||
'allocation_id' => 'integer',
|
||||
'nest_id' => 'integer',
|
||||
'egg_id' => 'integer',
|
||||
|
@ -354,6 +356,7 @@ class Server extends Model
|
|||
{
|
||||
if (
|
||||
$this->isSuspended() ||
|
||||
$this->node->isUnderMaintenance() ||
|
||||
!$this->isInstalled() ||
|
||||
$this->status === self::STATUS_RESTORING_BACKUP ||
|
||||
!is_null($this->transfer)
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
namespace Pterodactyl\Models;
|
||||
|
||||
/**
|
||||
* Pterodactyl\Models\Setting.
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $key
|
||||
* @property string $value
|
||||
*/
|
||||
class Setting extends Model
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,8 @@ use Illuminate\Database\Eloquent\Builder;
|
|||
use Webauthn\PublicKeyCredentialUserEntity;
|
||||
use Pterodactyl\Models\Traits\HasAccessTokens;
|
||||
use Illuminate\Auth\Passwords\CanResetPassword;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Pterodactyl\Traits\Helpers\AvailableLanguages;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Foundation\Auth\Access\Authorizable;
|
||||
|
@ -29,11 +31,10 @@ use Pterodactyl\Notifications\SendPasswordReset as ResetPasswordNotification;
|
|||
* @property string $uuid
|
||||
* @property string $username
|
||||
* @property string $email
|
||||
* @property string|null $name_first
|
||||
* @property string|null $name_last
|
||||
* @property string $password
|
||||
* @property string|null $remember_token
|
||||
* @property string $language
|
||||
* @property int|null $admin_role_id
|
||||
* @property bool $root_admin
|
||||
* @property bool $use_totp
|
||||
* @property string|null $totp_secret
|
||||
|
@ -41,9 +42,12 @@ use Pterodactyl\Notifications\SendPasswordReset as ResetPasswordNotification;
|
|||
* @property bool $gravatar
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property string $avatar_url
|
||||
* @property string|null $admin_role_name
|
||||
* @property string $md5
|
||||
* @property \Pterodactyl\Models\AdminRole|null $adminRole
|
||||
* @property \Illuminate\Database\Eloquent\Collection|\Pterodactyl\Models\ApiKey[] $apiKeys
|
||||
* @property int|null $api_keys_count
|
||||
* @property string $name
|
||||
* @property \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
|
||||
* @property int|null $notifications_count
|
||||
* @property \Illuminate\Database\Eloquent\Collection|\Pterodactyl\Models\RecoveryToken[] $recoveryTokens
|
||||
|
@ -79,7 +83,9 @@ use Pterodactyl\Notifications\SendPasswordReset as ResetPasswordNotification;
|
|||
* @method static Builder|User whereUsername($value)
|
||||
* @method static Builder|User whereUuid($value)
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
* @mixin \Barryvdh\LaravelIdeHelper\Eloquent
|
||||
* @mixin \Illuminate\Database\Query\Builder
|
||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
class User extends Model implements
|
||||
AuthenticatableContract,
|
||||
|
@ -119,8 +125,6 @@ class User extends Model implements
|
|||
'external_id',
|
||||
'username',
|
||||
'email',
|
||||
'name_first',
|
||||
'name_last',
|
||||
'password',
|
||||
'language',
|
||||
'use_totp',
|
||||
|
@ -165,8 +169,6 @@ class User extends Model implements
|
|||
'email' => 'required|email|between:1,191|unique:users,email',
|
||||
'external_id' => 'sometimes|nullable|string|max:191|unique:users,external_id',
|
||||
'username' => 'required|between:1,191|unique:users,username',
|
||||
'name_first' => 'required|string|between:1,191',
|
||||
'name_last' => 'required|string|between:1,191',
|
||||
'password' => 'sometimes|nullable|string',
|
||||
'root_admin' => 'boolean',
|
||||
'language' => 'string',
|
||||
|
@ -193,7 +195,9 @@ class User extends Model implements
|
|||
*/
|
||||
public function toReactObject(): array
|
||||
{
|
||||
return Collection::make($this->toArray())->except(['id', 'external_id'])->toArray();
|
||||
return Collection::make($this->append(['avatar_url', 'admin_role_name'])->toArray())
|
||||
->except(['id', 'external_id', 'admin_role', 'admin_role_id'])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,20 +223,39 @@ class User extends Model implements
|
|||
$this->attributes['username'] = mb_strtolower($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a concatenated result for the accounts full name.
|
||||
*/
|
||||
public function getNameAttribute(): string
|
||||
public function avatarUrl(): Attribute
|
||||
{
|
||||
return trim($this->name_first . ' ' . $this->name_last);
|
||||
return Attribute::make(
|
||||
get: fn () => 'https://www.gravatar.com/avatar/' . $this->md5 . '.jpg',
|
||||
);
|
||||
}
|
||||
|
||||
public function adminRoleName(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => is_null($this->adminRole) ? ($this->root_admin ? 'None' : null) : $this->adminRole->name,
|
||||
);
|
||||
}
|
||||
|
||||
public function md5(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => md5(strtolower($this->email)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all servers that a user owns.
|
||||
* Returns all the activity logs where this user is the subject — not to
|
||||
* be confused by activity logs where this user is the _actor_.
|
||||
*/
|
||||
public function servers(): HasMany
|
||||
public function activity(): MorphToMany
|
||||
{
|
||||
return $this->hasMany(Server::class, 'owner_id');
|
||||
return $this->morphToMany(ActivityLog::class, 'subject', 'activity_log_subjects');
|
||||
}
|
||||
|
||||
public function adminRole(): HasOne
|
||||
{
|
||||
return $this->hasOne(AdminRole::class, 'id', 'admin_role_id');
|
||||
}
|
||||
|
||||
public function apiKeys(): HasMany
|
||||
|
@ -246,6 +269,11 @@ class User extends Model implements
|
|||
return $this->hasMany(RecoveryToken::class);
|
||||
}
|
||||
|
||||
public function servers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Server::class, 'owner_id');
|
||||
}
|
||||
|
||||
public function sshKeys(): HasMany
|
||||
{
|
||||
return $this->hasMany(UserSSHKey::class);
|
||||
|
@ -256,15 +284,6 @@ class User extends Model implements
|
|||
return $this->hasMany(SecurityKey::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the activity logs where this user is the subject — not to
|
||||
* be confused by activity logs where this user is the _actor_.
|
||||
*/
|
||||
public function activity(): MorphToMany
|
||||
{
|
||||
return $this->morphToMany(ActivityLog::class, 'subject', 'activity_log_subjects');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the servers that a user can access by way of being the owner of the
|
||||
* server, or because they are assigned as a subuser for that server.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue