$expect
* @return T
*
* @noinspection PhpDocSignatureInspection
diff --git a/app/Http/Requests/Api/Application/DatabaseHosts/StoreDatabaseHostRequest.php b/app/Http/Requests/Api/Application/DatabaseHosts/StoreDatabaseHostRequest.php
index aedd5109b..435a6d86b 100644
--- a/app/Http/Requests/Api/Application/DatabaseHosts/StoreDatabaseHostRequest.php
+++ b/app/Http/Requests/Api/Application/DatabaseHosts/StoreDatabaseHostRequest.php
@@ -12,7 +12,7 @@ class StoreDatabaseHostRequest extends ApplicationApiRequest
protected int $permission = AdminAcl::WRITE;
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
return $rules ?? DatabaseHost::getRules();
}
diff --git a/app/Http/Requests/Api/Application/DatabaseHosts/UpdateDatabaseHostRequest.php b/app/Http/Requests/Api/Application/DatabaseHosts/UpdateDatabaseHostRequest.php
index 111560bbf..f14b9b90f 100644
--- a/app/Http/Requests/Api/Application/DatabaseHosts/UpdateDatabaseHostRequest.php
+++ b/app/Http/Requests/Api/Application/DatabaseHosts/UpdateDatabaseHostRequest.php
@@ -6,11 +6,11 @@ use App\Models\DatabaseHost;
class UpdateDatabaseHostRequest extends StoreDatabaseHostRequest
{
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
/** @var DatabaseHost $databaseHost */
$databaseHost = $this->route()->parameter('database_host');
- return $rules ?? DatabaseHost::getRulesForUpdate($databaseHost->id);
+ return $rules ?? DatabaseHost::getRulesForUpdate($databaseHost);
}
}
diff --git a/app/Http/Requests/Api/Application/Mounts/UpdateMountRequest.php b/app/Http/Requests/Api/Application/Mounts/UpdateMountRequest.php
index 7f76ec420..05e7d0a23 100644
--- a/app/Http/Requests/Api/Application/Mounts/UpdateMountRequest.php
+++ b/app/Http/Requests/Api/Application/Mounts/UpdateMountRequest.php
@@ -9,11 +9,11 @@ class UpdateMountRequest extends StoreMountRequest
/**
* Apply validation rules to this request.
*/
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
/** @var Mount $mount */
$mount = $this->route()->parameter('mount');
- return Mount::getRulesForUpdate($mount->id);
+ return Mount::getRulesForUpdate($mount);
}
}
diff --git a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php
index 913204b83..eae324233 100644
--- a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php
+++ b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php
@@ -15,7 +15,7 @@ class StoreNodeRequest extends ApplicationApiRequest
/**
* Validation rules to apply to this request.
*/
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
return collect($rules ?? Node::getRules())->only([
'public',
diff --git a/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php b/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php
index ab636dff0..5907860a2 100644
--- a/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php
+++ b/app/Http/Requests/Api/Application/Nodes/UpdateNodeRequest.php
@@ -10,11 +10,11 @@ class UpdateNodeRequest extends StoreNodeRequest
* Apply validation rules to this request. Uses the parent class rules()
* function but passes in the rules for updating rather than creating.
*/
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
/** @var Node $node */
$node = $this->route()->parameter('node');
- return parent::rules(Node::getRulesForUpdate($node->id));
+ return parent::rules(Node::getRulesForUpdate($node));
}
}
diff --git a/app/Http/Requests/Api/Application/Roles/StoreRoleRequest.php b/app/Http/Requests/Api/Application/Roles/StoreRoleRequest.php
index 7968449a7..4cf01400e 100644
--- a/app/Http/Requests/Api/Application/Roles/StoreRoleRequest.php
+++ b/app/Http/Requests/Api/Application/Roles/StoreRoleRequest.php
@@ -11,7 +11,7 @@ class StoreRoleRequest extends ApplicationApiRequest
protected int $permission = AdminAcl::WRITE;
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
return [
'name' => 'required|string',
diff --git a/app/Http/Requests/Api/Application/Users/AssignUserRolesRequest.php b/app/Http/Requests/Api/Application/Users/AssignUserRolesRequest.php
index c0af95102..61e191c20 100644
--- a/app/Http/Requests/Api/Application/Users/AssignUserRolesRequest.php
+++ b/app/Http/Requests/Api/Application/Users/AssignUserRolesRequest.php
@@ -7,7 +7,7 @@ class AssignUserRolesRequest extends StoreUserRequest
/**
* Return the validation rules for this request.
*/
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
return [
'roles' => 'array',
diff --git a/app/Http/Requests/Api/Application/Users/StoreUserRequest.php b/app/Http/Requests/Api/Application/Users/StoreUserRequest.php
index 43603639c..cf1b6c244 100644
--- a/app/Http/Requests/Api/Application/Users/StoreUserRequest.php
+++ b/app/Http/Requests/Api/Application/Users/StoreUserRequest.php
@@ -15,7 +15,7 @@ class StoreUserRequest extends ApplicationApiRequest
/**
* Return the validation rules for this request.
*/
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
$rules = $rules ?? User::getRules();
diff --git a/app/Http/Requests/Api/Application/Users/UpdateUserRequest.php b/app/Http/Requests/Api/Application/Users/UpdateUserRequest.php
index ecccbdd5a..9ec5067a5 100644
--- a/app/Http/Requests/Api/Application/Users/UpdateUserRequest.php
+++ b/app/Http/Requests/Api/Application/Users/UpdateUserRequest.php
@@ -9,10 +9,10 @@ class UpdateUserRequest extends StoreUserRequest
/**
* Return the validation rules for this request.
*/
- public function rules(array $rules = null): array
+ public function rules(?array $rules = null): array
{
- $userId = $this->parameter('user', User::class)->id;
+ $user = $this->parameter('user', User::class);
- return parent::rules(User::getRulesForUpdate($userId));
+ return parent::rules(User::getRulesForUpdate($user));
}
}
diff --git a/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php b/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php
index bd68fb890..349db0616 100644
--- a/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php
+++ b/app/Http/Requests/Api/Client/Servers/Subusers/SubuserRequest.php
@@ -49,7 +49,7 @@ abstract class SubuserRequest extends ClientApiRequest
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
- protected function validatePermissionsCanBeAssigned(array $permissions)
+ protected function validatePermissionsCanBeAssigned(array $permissions): void
{
$user = $this->user();
/** @var \App\Models\Server $server */
diff --git a/app/Jobs/NodeStatistics.php b/app/Jobs/NodeStatistics.php
index 19fae9b9d..9546f0ba0 100644
--- a/app/Jobs/NodeStatistics.php
+++ b/app/Jobs/NodeStatistics.php
@@ -42,5 +42,4 @@ class NodeStatistics implements ShouldQueue
}
}
}
-
}
diff --git a/app/Jobs/Schedule/RunTaskJob.php b/app/Jobs/Schedule/RunTaskJob.php
index 6a660e5c0..158950c45 100644
--- a/app/Jobs/Schedule/RunTaskJob.php
+++ b/app/Jobs/Schedule/RunTaskJob.php
@@ -90,7 +90,7 @@ class RunTaskJob extends Job implements ShouldQueue
/**
* Handle a failure while sending the action to the daemon or otherwise processing the job.
*/
- public function failed(\Exception $exception = null)
+ public function failed(?\Exception $exception = null): void
{
$this->markTaskNotQueued();
$this->markScheduleComplete();
@@ -99,7 +99,7 @@ class RunTaskJob extends Job implements ShouldQueue
/**
* Get the next task in the schedule and queue it for running after the defined period of wait time.
*/
- private function queueNextTask()
+ private function queueNextTask(): void
{
/** @var \App\Models\Task|null $nextTask */
$nextTask = Task::query()->where('schedule_id', $this->task->schedule_id)
@@ -121,7 +121,7 @@ class RunTaskJob extends Job implements ShouldQueue
/**
* Marks the parent schedule as being complete.
*/
- private function markScheduleComplete()
+ private function markScheduleComplete(): void
{
$this->task->schedule()->update([
'is_processing' => false,
@@ -132,7 +132,7 @@ class RunTaskJob extends Job implements ShouldQueue
/**
* Mark a specific task as no longer being queued.
*/
- private function markTaskNotQueued()
+ private function markTaskNotQueued(): void
{
$this->task->update(['is_queued' => false]);
}
diff --git a/app/Livewire/NodeSystemInformation.php b/app/Livewire/NodeSystemInformation.php
index b29190251..55f71f7ce 100644
--- a/app/Livewire/NodeSystemInformation.php
+++ b/app/Livewire/NodeSystemInformation.php
@@ -3,19 +3,21 @@
namespace App\Livewire;
use App\Models\Node;
+use Illuminate\View\View;
use Livewire\Component;
class NodeSystemInformation extends Component
{
public Node $node;
+
public string $sizeClasses;
- public function render()
+ public function render(): View
{
return view('livewire.node-system-information');
}
- public function placeholder()
+ public function placeholder(): string
{
return <<<'HTML'
diff --git a/app/Models/ActivityLog.php b/app/Models/ActivityLog.php
index bb6149c14..20fb579e0 100644
--- a/app/Models/ActivityLog.php
+++ b/app/Models/ActivityLog.php
@@ -123,7 +123,7 @@ class ActivityLog extends Model
*
* @see https://laravel.com/docs/9.x/eloquent#pruning-models
*/
- public function prunable()
+ public function prunable(): Builder
{
if (is_null(config('activity.prune_days'))) {
throw new \LogicException('Cannot prune activity logs: no "prune_days" configuration value is set.');
@@ -136,7 +136,7 @@ class ActivityLog extends Model
* Boots the model event listeners. This will trigger an activity log event every
* time a new model is inserted which can then be captured and worked with as needed.
*/
- protected static function boot()
+ protected static function boot(): void
{
parent::boot();
@@ -149,7 +149,7 @@ class ActivityLog extends Model
});
}
- public function htmlable()
+ public function htmlable(): string
{
$user = $this->actor;
if (!$user instanceof User) {
diff --git a/app/Models/ActivityLogSubject.php b/app/Models/ActivityLogSubject.php
index 037d344f0..f6a7291fa 100644
--- a/app/Models/ActivityLogSubject.php
+++ b/app/Models/ActivityLogSubject.php
@@ -3,8 +3,9 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
-use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Eloquent\SoftDeletingScope;
/**
* \App\Models\ActivityLogSubject.
@@ -25,6 +26,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
class ActivityLogSubject extends Pivot
{
public $incrementing = true;
+
public $timestamps = false;
protected $table = 'activity_log_subjects';
@@ -36,15 +38,8 @@ class ActivityLogSubject extends Pivot
return $this->belongsTo(ActivityLog::class);
}
- public function subject()
+ public function subject(): MorphTo
{
- $morph = $this->morphTo();
-
- if (in_array(SoftDeletes::class, class_uses_recursive($morph::class))) {
- /** @var self|Backup|UserSSHKey $morph - cannot use traits in doc blocks */
- return $morph->withTrashed();
- }
-
- return $morph;
+ return $this->morphTo()->withoutGlobalScope(SoftDeletingScope::class);
}
}
diff --git a/app/Models/ApiKey.php b/app/Models/ApiKey.php
index 52d78a97b..96c714f24 100644
--- a/app/Models/ApiKey.php
+++ b/app/Models/ApiKey.php
@@ -63,21 +63,28 @@ class ApiKey extends Model
* API representation using fractal.
*/
public const RESOURCE_NAME = 'api_key';
+
/**
* Different API keys that can exist on the system.
*/
public const TYPE_NONE = 0;
+
public const TYPE_ACCOUNT = 1;
+
/* @deprecated */
public const TYPE_APPLICATION = 2;
+
/* @deprecated */
public const TYPE_DAEMON_USER = 3;
+
/* @deprecated */
public const TYPE_DAEMON_APPLICATION = 4;
+
/**
* The length of API key identifiers.
*/
public const IDENTIFIER_LENGTH = 16;
+
/**
* The length of the actual API key that is encrypted and stored
* in the database.
diff --git a/app/Models/Backup.php b/app/Models/Backup.php
index 00381fbdf..8798cd55d 100644
--- a/app/Models/Backup.php
+++ b/app/Models/Backup.php
@@ -31,6 +31,7 @@ class Backup extends Model
public const RESOURCE_NAME = 'backup';
public const ADAPTER_DAEMON = 'wings';
+
public const ADAPTER_AWS_S3 = 's3';
protected $table = 'backups';
diff --git a/app/Models/Egg.php b/app/Models/Egg.php
index 721324c87..25a1cd0ef 100644
--- a/app/Models/Egg.php
+++ b/app/Models/Egg.php
@@ -70,6 +70,7 @@ class Egg extends Model
* than leaving it null.
*/
public const FEATURE_EULA_POPUP = 'eula';
+
public const FEATURE_FASTDL = 'fastdl';
/**
diff --git a/app/Models/Filters/AdminServerFilter.php b/app/Models/Filters/AdminServerFilter.php
index d3c1eea60..e90f17e08 100644
--- a/app/Models/Filters/AdminServerFilter.php
+++ b/app/Models/Filters/AdminServerFilter.php
@@ -11,9 +11,9 @@ class AdminServerFilter implements Filter
* A multi-column filter for the servers table that allows an administrative user to search
* across UUID, name, owner username, and owner email.
*
- * @param string $value
+ * @param string $value
*/
- public function __invoke(Builder $query, $value, string $property)
+ public function __invoke(Builder $query, $value, string $property): void
{
if ($query->getQuery()->from !== 'servers') {
throw new \BadMethodCallException('Cannot use the AdminServerFilter against a non-server model.');
diff --git a/app/Models/Filters/MultiFieldServerFilter.php b/app/Models/Filters/MultiFieldServerFilter.php
index 92495af47..b2f8ae539 100644
--- a/app/Models/Filters/MultiFieldServerFilter.php
+++ b/app/Models/Filters/MultiFieldServerFilter.php
@@ -18,9 +18,9 @@ class MultiFieldServerFilter implements Filter
* search across multiple columns. This allows us to provide a very generic search ability for
* the frontend.
*
- * @param string $value
+ * @param string $value
*/
- public function __invoke(Builder $query, $value, string $property)
+ public function __invoke(Builder $query, $value, string $property): void
{
if ($query->getQuery()->from !== 'servers') {
throw new \BadMethodCallException('Cannot use the MultiFieldServerFilter against a non-server model.');
diff --git a/app/Models/Model.php b/app/Models/Model.php
index 536edf9b5..20bc2bf33 100644
--- a/app/Models/Model.php
+++ b/app/Models/Model.php
@@ -38,7 +38,7 @@ abstract class Model extends IlluminateModel
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
- protected static function boot()
+ protected static function boot(): void
{
parent::boot();
@@ -69,7 +69,7 @@ abstract class Model extends IlluminateModel
return 'uuid';
}
- protected function asDateTime($value)
+ protected function asDateTime($value): Carbon
{
$timezone = auth()->user()?->timezone ?? config('app.timezone', 'UTC');
@@ -135,11 +135,9 @@ abstract class Model extends IlluminateModel
* Returns the rules associated with the model, specifically for updating the given model
* rather than just creating it.
*/
- public static function getRulesForUpdate($model, string $column = 'id'): array
+ public static function getRulesForUpdate(self $model): array
{
- if ($model instanceof Model) {
- [$id, $column] = [$model->getKey(), $model->getKeyName()];
- }
+ [$id, $column] = [$model->getKey(), $model->getKeyName()];
$rules = static::getRules();
foreach ($rules as $key => &$data) {
diff --git a/app/Models/Mount.php b/app/Models/Mount.php
index 223603805..60cb2b436 100644
--- a/app/Models/Mount.php
+++ b/app/Models/Mount.php
@@ -70,7 +70,7 @@ class Mount extends Model
/**
* Blacklisted source paths.
*/
- public static $invalidSourcePaths = [
+ public static array $invalidSourcePaths = [
'/etc/pelican',
'/var/lib/pelican/volumes',
'/srv/daemon-data',
@@ -79,7 +79,7 @@ class Mount extends Model
/**
* Blacklisted target paths.
*/
- public static $invalidTargetPaths = [
+ public static array $invalidTargetPaths = [
'/home/container',
];
diff --git a/app/Models/Permission.php b/app/Models/Permission.php
index ab9fef260..29cbd826d 100644
--- a/app/Models/Permission.php
+++ b/app/Models/Permission.php
@@ -16,51 +16,81 @@ class Permission extends Model
* Constants defining different permissions available.
*/
public const ACTION_WEBSOCKET_CONNECT = 'websocket.connect';
+
public const ACTION_CONTROL_CONSOLE = 'control.console';
+
public const ACTION_CONTROL_START = 'control.start';
+
public const ACTION_CONTROL_STOP = 'control.stop';
+
public const ACTION_CONTROL_RESTART = 'control.restart';
public const ACTION_DATABASE_READ = 'database.read';
+
public const ACTION_DATABASE_CREATE = 'database.create';
+
public const ACTION_DATABASE_UPDATE = 'database.update';
+
public const ACTION_DATABASE_DELETE = 'database.delete';
+
public const ACTION_DATABASE_VIEW_PASSWORD = 'database.view_password';
public const ACTION_SCHEDULE_READ = 'schedule.read';
+
public const ACTION_SCHEDULE_CREATE = 'schedule.create';
+
public const ACTION_SCHEDULE_UPDATE = 'schedule.update';
+
public const ACTION_SCHEDULE_DELETE = 'schedule.delete';
public const ACTION_USER_READ = 'user.read';
+
public const ACTION_USER_CREATE = 'user.create';
+
public const ACTION_USER_UPDATE = 'user.update';
+
public const ACTION_USER_DELETE = 'user.delete';
public const ACTION_BACKUP_READ = 'backup.read';
+
public const ACTION_BACKUP_CREATE = 'backup.create';
+
public const ACTION_BACKUP_DELETE = 'backup.delete';
+
public const ACTION_BACKUP_DOWNLOAD = 'backup.download';
+
public const ACTION_BACKUP_RESTORE = 'backup.restore';
public const ACTION_ALLOCATION_READ = 'allocation.read';
+
public const ACTION_ALLOCATION_CREATE = 'allocation.create';
+
public const ACTION_ALLOCATION_UPDATE = 'allocation.update';
+
public const ACTION_ALLOCATION_DELETE = 'allocation.delete';
public const ACTION_FILE_READ = 'file.read';
+
public const ACTION_FILE_READ_CONTENT = 'file.read-content';
+
public const ACTION_FILE_CREATE = 'file.create';
+
public const ACTION_FILE_UPDATE = 'file.update';
+
public const ACTION_FILE_DELETE = 'file.delete';
+
public const ACTION_FILE_ARCHIVE = 'file.archive';
+
public const ACTION_FILE_SFTP = 'file.sftp';
public const ACTION_STARTUP_READ = 'startup.read';
+
public const ACTION_STARTUP_UPDATE = 'startup.update';
+
public const ACTION_STARTUP_DOCKER_IMAGE = 'startup.docker-image';
public const ACTION_SETTINGS_RENAME = 'settings.rename';
+
public const ACTION_SETTINGS_REINSTALL = 'settings.reinstall';
public const ACTION_ACTIVITY_READ = 'activity.read';
diff --git a/app/Models/Server.php b/app/Models/Server.php
index e8ebca219..12bec8a3a 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -74,6 +74,7 @@ use App\Exceptions\Http\Server\ServerStateConflictException;
* @property \App\Models\User $user
* @property \Illuminate\Database\Eloquent\Collection|\App\Models\EggVariable[] $variables
* @property int|null $variables_count
+ *
* @method static \Database\Factories\ServerFactory factory(...$parameters)
* @method static \Illuminate\Database\Eloquent\Builder|Server newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Server newQuery()
@@ -104,6 +105,7 @@ use App\Exceptions\Http\Server\ServerStateConflictException;
* @method static \Illuminate\Database\Eloquent\Builder|Server whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Server whereUuid($value)
* @method static \Illuminate\Database\Eloquent\Builder|Server whereuuid_short($value)
+ *
* @property array|null $docker_labels
* @property Collection|null $ports
* @property-read mixed $condition
@@ -111,10 +113,12 @@ use App\Exceptions\Http\Server\ServerStateConflictException;
* @property-read int|null $egg_variables_count
* @property-read \Illuminate\Database\Eloquent\Collection $serverVariables
* @property-read int|null $server_variables_count
+ *
* @method static \Illuminate\Database\Eloquent\Builder|Server whereDockerLabels($value)
* @method static \Illuminate\Database\Eloquent\Builder|Server whereInstalledAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Server wherePorts($value)
* @method static \Illuminate\Database\Eloquent\Builder|Server whereUuidShort($value)
+ *
* @mixin \Eloquent
*/
class Server extends Model
@@ -342,7 +346,7 @@ class Server extends Model
*
* @throws ServerStateConflictException
*/
- public function validateCurrentState()
+ public function validateCurrentState(): void
{
if (
$this->isSuspended() ||
@@ -361,7 +365,7 @@ class Server extends Model
* sure the server can be transferred and is not currently being transferred
* or installed.
*/
- public function validateTransferState()
+ public function validateTransferState(): void
{
if (
!$this->isInstalled() ||
diff --git a/app/Models/Task.php b/app/Models/Task.php
index 254d38ece..202a3165a 100644
--- a/app/Models/Task.php
+++ b/app/Models/Task.php
@@ -31,8 +31,11 @@ class Task extends Model
* The default actions that can exist for a task
*/
public const ACTION_POWER = 'power';
+
public const ACTION_COMMAND = 'command';
+
public const ACTION_BACKUP = 'backup';
+
public const ACTION_DELETE_FILES = 'delete_files';
/**
diff --git a/app/Models/User.php b/app/Models/User.php
index 395f4994f..45545db34 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -99,6 +99,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
use Notifiable;
public const USER_LEVEL_USER = 0;
+
public const USER_LEVEL_ADMIN = 1;
/**
@@ -233,9 +234,9 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
/**
* Send the password reset notification.
*
- * @param string $token
+ * @param string $token
*/
- public function sendPasswordResetNotification($token)
+ public function sendPasswordResetNotification($token): void
{
Activity::event('auth:reset-password')
->withRequestMetadata()
@@ -248,7 +249,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
/**
* Store the username as a lowercase string.
*/
- public function setUsernameAttribute(string $value)
+ public function setUsernameAttribute(string $value): void
{
$this->attributes['username'] = mb_strtolower($value);
}
diff --git a/app/PHPStan/ForbiddenGlobalFunctionsRule.php b/app/PHPStan/ForbiddenGlobalFunctionsRule.php
new file mode 100644
index 000000000..545cc60fb
--- /dev/null
+++ b/app/PHPStan/ForbiddenGlobalFunctionsRule.php
@@ -0,0 +1,38 @@
+forbiddenFunctions = $forbiddenFunctions;
+ }
+
+ public function getNodeType(): string
+ {
+ return FuncCall::class;
+ }
+
+ public function processNode(Node $node, Scope $scope): array
+ {
+ /** @var FuncCall $node */
+ if ($node->name instanceof Node\Name) {
+ $functionName = (string) $node->name;
+ if (in_array($functionName, $this->forbiddenFunctions, true)) {
+ return [
+ sprintf('Usage of global function "%s" is forbidden.', $functionName),
+ ];
+ }
+ }
+
+ return [];
+ }
+}
diff --git a/app/Policies/ServerPolicy.php b/app/Policies/ServerPolicy.php
index dbc2ae402..dfa72c9b9 100644
--- a/app/Policies/ServerPolicy.php
+++ b/app/Policies/ServerPolicy.php
@@ -41,7 +41,7 @@ class ServerPolicy
* not call the before() function if there isn't a function matching the
* policy permission.
*/
- public function __call(string $name, mixed $arguments)
+ public function __call(string $name, mixed $arguments): void
{
// do nothing
}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 1dfdf607a..638fd9dc5 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -15,6 +15,7 @@ use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
use Illuminate\Database\Eloquent\Relations\Relation;
+use Illuminate\Foundation\Application;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\Facades\Event;
@@ -34,7 +35,7 @@ class AppServiceProvider extends ServiceProvider
/**
* Bootstrap any application services.
*/
- public function boot(): void
+ public function boot(Application $app): void
{
// TODO: remove when old admin area gets yeeted
View::share('appVersion', config('app.version'));
@@ -68,7 +69,7 @@ class AppServiceProvider extends ServiceProvider
->asJson()
->withToken($node->daemon_token)
->withHeaders($headers)
- ->withOptions(['verify' => (bool) app()->environment('production')])
+ ->withOptions(['verify' => (bool) $app->environment('production')])
->timeout(config('panel.guzzle.timeout'))
->connectTimeout(config('panel.guzzle.connect_timeout'))
->baseUrl($node->getConnectionAddress())
diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php
index 0aef2f030..f6b7c568b 100644
--- a/app/Providers/Filament/AdminPanelProvider.php
+++ b/app/Providers/Filament/AdminPanelProvider.php
@@ -9,6 +9,7 @@ use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Panel;
use Filament\PanelProvider;
+use Filament\Support\Enums\MaxWidth;
use Filament\Support\Facades\FilamentAsset;
use Filament\Widgets;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
@@ -21,7 +22,7 @@ use Illuminate\View\Middleware\ShareErrorsFromSession;
class AdminPanelProvider extends PanelProvider
{
- public function boot()
+ public function boot(): void
{
FilamentAsset::registerCssVariables([
'sidebar-width' => '16rem !important',
@@ -43,6 +44,8 @@ class AdminPanelProvider extends PanelProvider
->brandLogo(config('app.logo'))
->brandLogoHeight('2rem')
->profile(EditProfile::class, false)
+ ->maxContentWidth(MaxWidth::ScreenTwoExtraLarge)
+ ->spa()
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
->discoverClusters(in: app_path('Filament/Clusters'), for: 'App\\Filament\\Clusters')
diff --git a/app/Repositories/Daemon/DaemonBackupRepository.php b/app/Repositories/Daemon/DaemonBackupRepository.php
index bbe852e80..ff34c2acd 100644
--- a/app/Repositories/Daemon/DaemonBackupRepository.php
+++ b/app/Repositories/Daemon/DaemonBackupRepository.php
@@ -2,6 +2,7 @@
namespace App\Repositories\Daemon;
+use Illuminate\Http\Client\Response;
use Webmozart\Assert\Assert;
use App\Models\Backup;
use App\Models\Server;
@@ -27,7 +28,7 @@ class DaemonBackupRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function backup(Backup $backup)
+ public function backup(Backup $backup): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -50,7 +51,7 @@ class DaemonBackupRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function restore(Backup $backup, string $url = null, bool $truncate = false)
+ public function restore(Backup $backup, ?string $url = null, bool $truncate = false): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -73,7 +74,7 @@ class DaemonBackupRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function delete(Backup $backup)
+ public function delete(Backup $backup): Response
{
Assert::isInstanceOf($this->server, Server::class);
diff --git a/app/Repositories/Daemon/DaemonConfigurationRepository.php b/app/Repositories/Daemon/DaemonConfigurationRepository.php
index 52cda56dd..910e95e58 100644
--- a/app/Repositories/Daemon/DaemonConfigurationRepository.php
+++ b/app/Repositories/Daemon/DaemonConfigurationRepository.php
@@ -5,6 +5,7 @@ namespace App\Repositories\Daemon;
use App\Models\Node;
use GuzzleHttp\Exception\TransferException;
use App\Exceptions\Http\Connection\DaemonConnectionException;
+use Illuminate\Http\Client\Response;
class DaemonConfigurationRepository extends DaemonRepository
{
@@ -13,7 +14,7 @@ class DaemonConfigurationRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function getSystemInformation(?int $version = null, $connectTimeout = 5): array
+ public function getSystemInformation(?int $version = null, int $connectTimeout = 5): array
{
try {
$response = $this
@@ -34,7 +35,7 @@ class DaemonConfigurationRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function update(Node $node)
+ public function update(Node $node): Response
{
try {
return $this->getHttpClient()->post(
diff --git a/app/Repositories/Daemon/DaemonFileRepository.php b/app/Repositories/Daemon/DaemonFileRepository.php
index 7667f482e..a65013fb3 100644
--- a/app/Repositories/Daemon/DaemonFileRepository.php
+++ b/app/Repositories/Daemon/DaemonFileRepository.php
@@ -3,6 +3,7 @@
namespace App\Repositories\Daemon;
use Carbon\CarbonInterval;
+use Illuminate\Http\Client\Response;
use Webmozart\Assert\Assert;
use App\Models\Server;
use GuzzleHttp\Exception\ClientException;
@@ -15,13 +16,13 @@ class DaemonFileRepository extends DaemonRepository
/**
* Return the contents of a given file.
*
- * @param int|null $notLargerThan the maximum content length in bytes
+ * @param int|null $notLargerThan the maximum content length in bytes
*
* @throws \GuzzleHttp\Exception\TransferException
* @throws \App\Exceptions\Http\Server\FileSizeTooLargeException
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function getContent(string $path, int $notLargerThan = null): string
+ public function getContent(string $path, ?int $notLargerThan = null): string
{
Assert::isInstanceOf($this->server, Server::class);
@@ -48,7 +49,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function putContent(string $path, string $content)
+ public function putContent(string $path, string $content): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -88,7 +89,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function createDirectory(string $name, string $path)
+ public function createDirectory(string $name, string $path): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -110,7 +111,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function renameFiles(?string $root, array $files)
+ public function renameFiles(?string $root, array $files): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -132,7 +133,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function copyFile(string $location)
+ public function copyFile(string $location): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -153,7 +154,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function deleteFiles(?string $root, array $files)
+ public function deleteFiles(?string $root, array $files): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -203,7 +204,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function decompressFile(?string $root, string $file)
+ public function decompressFile(?string $root, string $file): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -229,7 +230,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function chmodFiles(?string $root, array $files)
+ public function chmodFiles(?string $root, array $files): Response
{
Assert::isInstanceOf($this->server, Server::class);
@@ -251,7 +252,7 @@ class DaemonFileRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function pull(string $url, ?string $directory, array $params = [])
+ public function pull(string $url, ?string $directory, array $params = []): Response
{
Assert::isInstanceOf($this->server, Server::class);
diff --git a/app/Repositories/Daemon/DaemonPowerRepository.php b/app/Repositories/Daemon/DaemonPowerRepository.php
index ca3e03c44..3b701be34 100644
--- a/app/Repositories/Daemon/DaemonPowerRepository.php
+++ b/app/Repositories/Daemon/DaemonPowerRepository.php
@@ -2,6 +2,7 @@
namespace App\Repositories\Daemon;
+use Illuminate\Http\Client\Response;
use Webmozart\Assert\Assert;
use App\Models\Server;
use GuzzleHttp\Exception\TransferException;
@@ -14,7 +15,7 @@ class DaemonPowerRepository extends DaemonRepository
*
* @throws \App\Exceptions\Http\Connection\DaemonConnectionException
*/
- public function send(string $action)
+ public function send(string $action): Response
{
Assert::isInstanceOf($this->server, Server::class);
diff --git a/app/Rules/Username.php b/app/Rules/Username.php
index 591df389c..f888da103 100644
--- a/app/Rules/Username.php
+++ b/app/Rules/Username.php
@@ -17,8 +17,8 @@ class Username implements Rule
*
* Allowed characters: a-z0-9_-.
*
- * @param string $attribute
- * @param mixed $value
+ * @param string $attribute
+ * @param mixed $value
*/
public function passes($attribute, $value): bool
{
diff --git a/app/Services/Acl/Api/AdminAcl.php b/app/Services/Acl/Api/AdminAcl.php
index dd58e317c..90ec6480a 100644
--- a/app/Services/Acl/Api/AdminAcl.php
+++ b/app/Services/Acl/Api/AdminAcl.php
@@ -17,7 +17,9 @@ class AdminAcl
* implements a read/write/none permissions scheme for all endpoints.
*/
public const NONE = 0;
+
public const READ = 1;
+
public const WRITE = 2;
/**
@@ -25,13 +27,21 @@ class AdminAcl
* set for each key. These are stored in the database as r_{resource}.
*/
public const RESOURCE_SERVERS = 'servers';
+
public const RESOURCE_NODES = 'nodes';
+
public const RESOURCE_ALLOCATIONS = 'allocations';
+
public const RESOURCE_USERS = 'users';
+
public const RESOURCE_EGGS = 'eggs';
+
public const RESOURCE_DATABASE_HOSTS = 'database_hosts';
+
public const RESOURCE_SERVER_DATABASES = 'server_databases';
+
public const RESOURCE_MOUNTS = 'mounts';
+
public const RESOURCE_ROLES = 'roles';
/**
diff --git a/app/Services/Activity/ActivityLogBatchService.php b/app/Services/Activity/ActivityLogBatchService.php
index cb2e91b5c..df237286f 100644
--- a/app/Services/Activity/ActivityLogBatchService.php
+++ b/app/Services/Activity/ActivityLogBatchService.php
@@ -7,6 +7,7 @@ use Ramsey\Uuid\Uuid;
class ActivityLogBatchService
{
protected int $transaction = 0;
+
protected ?string $uuid = null;
/**
diff --git a/app/Services/Activity/ActivityLogService.php b/app/Services/Activity/ActivityLogService.php
index 37b7ae43b..7de267a3e 100644
--- a/app/Services/Activity/ActivityLogService.php
+++ b/app/Services/Activity/ActivityLogService.php
@@ -64,7 +64,7 @@ class ActivityLogService
*
* @template T extends \Illuminate\Database\Eloquent\Model|\Illuminate\Contracts\Auth\Authenticatable
*
- * @param T|T[]|null $subjects
+ * @param T|T[]|null $subjects
*/
public function subject(...$subjects): self
{
@@ -100,8 +100,8 @@ class ActivityLogService
/**
* Sets a custom property on the activity log instance.
*
- * @param string|array $key
- * @param mixed $value
+ * @param string|array $key
+ * @param mixed $value
*/
public function property($key, $value = null): self
{
@@ -130,7 +130,7 @@ class ActivityLogService
* performing this action it will be logged to the disk but will not interrupt
* the code flow.
*/
- public function log(string $description = null): ActivityLog
+ public function log(?string $description = null): ActivityLog
{
$activity = $this->getActivity();
@@ -168,7 +168,7 @@ class ActivityLogService
*
* @throws \Throwable
*/
- public function transaction(\Closure $callback)
+ public function transaction(\Closure $callback): mixed
{
return $this->connection->transaction(function () use ($callback) {
$response = $callback($this);
diff --git a/app/Services/Backups/InitiateBackupService.php b/app/Services/Backups/InitiateBackupService.php
index 447c57535..fa15db88a 100644
--- a/app/Services/Backups/InitiateBackupService.php
+++ b/app/Services/Backups/InitiateBackupService.php
@@ -43,7 +43,7 @@ class InitiateBackupService
/**
* Sets the files to be ignored by this backup.
*
- * @param string[]|null $ignored
+ * @param string[]|null $ignored
*/
public function setIgnoredFiles(?array $ignored): self
{
@@ -70,7 +70,7 @@ class InitiateBackupService
* @throws \App\Exceptions\Service\Backup\TooManyBackupsException
* @throws \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException
*/
- public function handle(Server $server, string $name = null, bool $override = false): Backup
+ public function handle(Server $server, ?string $name = null, bool $override = false): Backup
{
$limit = config('backups.throttles.limit');
$period = config('backups.throttles.period');
diff --git a/app/Services/Deployment/FindViableNodesService.php b/app/Services/Deployment/FindViableNodesService.php
index 4cffc71d2..d95c08c64 100644
--- a/app/Services/Deployment/FindViableNodesService.php
+++ b/app/Services/Deployment/FindViableNodesService.php
@@ -17,7 +17,7 @@ class FindViableNodesService
* are tossed out, as are any nodes marked as non-public, meaning automatic
* deployments should not be done against them.
*/
- public function handle(int $memory = 0, int $disk = 0, int $cpu = 0, $tags = []): Collection
+ public function handle(int $memory = 0, int $disk = 0, int $cpu = 0, array $tags = []): Collection
{
$nodes = Node::query()
->withSum('servers', 'memory')
diff --git a/app/Services/Eggs/Sharing/EggImporterService.php b/app/Services/Eggs/Sharing/EggImporterService.php
index dc54525a6..e539a7f28 100644
--- a/app/Services/Eggs/Sharing/EggImporterService.php
+++ b/app/Services/Eggs/Sharing/EggImporterService.php
@@ -34,7 +34,7 @@ class EggImporterService
*
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
*/
- public function fromFile(UploadedFile $file, Egg $egg = null): Egg
+ public function fromFile(UploadedFile $file, ?Egg $egg = null): Egg
{
$parsed = $this->parseFile($file);
@@ -75,7 +75,7 @@ class EggImporterService
*
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
*/
- public function fromUrl(string $url, Egg $egg = null): Egg
+ public function fromUrl(string $url, ?Egg $egg = null): Egg
{
$info = pathinfo($url);
$tmpDir = TemporaryDirectory::make()->deleteWhenDestroyed();
diff --git a/app/Services/Files/DeleteFilesService.php b/app/Services/Files/DeleteFilesService.php
index 2b1be5fda..1692923ed 100644
--- a/app/Services/Files/DeleteFilesService.php
+++ b/app/Services/Files/DeleteFilesService.php
@@ -19,6 +19,7 @@ class DeleteFilesService
/**
* Deletes the given files.
+ *
* @throws DaemonConnectionException
*/
public function handle(Server $server, array $files): void
diff --git a/app/Services/Servers/ServerConfigurationStructureService.php b/app/Services/Servers/ServerConfigurationStructureService.php
index b004263f6..ca9e5455d 100644
--- a/app/Services/Servers/ServerConfigurationStructureService.php
+++ b/app/Services/Servers/ServerConfigurationStructureService.php
@@ -93,5 +93,4 @@ class ServerConfigurationStructureService
return $response;
}
-
}
diff --git a/app/Services/Servers/ServerCreationService.php b/app/Services/Servers/ServerCreationService.php
index e35c6f798..5392e5011 100644
--- a/app/Services/Servers/ServerCreationService.php
+++ b/app/Services/Servers/ServerCreationService.php
@@ -38,7 +38,7 @@ class ServerCreationService
* @throws \Illuminate\Validation\ValidationException
* @throws \App\Exceptions\Service\Deployment\NoViableAllocationException
*/
- public function handle(array $data, DeploymentObject $deployment = null, $validateVariables = true): Server
+ public function handle(array $data, ?DeploymentObject $deployment = null, $validateVariables = true): Server
{
if (!isset($data['oom_killer']) && isset($data['oom_disabled'])) {
$data['oom_killer'] = !$data['oom_disabled'];
diff --git a/app/Services/Servers/SuspensionService.php b/app/Services/Servers/SuspensionService.php
index aef02b7b2..0209db3fc 100644
--- a/app/Services/Servers/SuspensionService.php
+++ b/app/Services/Servers/SuspensionService.php
@@ -12,6 +12,7 @@ use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
class SuspensionService
{
public const ACTION_SUSPEND = 'suspend';
+
public const ACTION_UNSUSPEND = 'unsuspend';
/**
@@ -27,7 +28,7 @@ class SuspensionService
*
* @throws \Throwable
*/
- public function toggle(Server $server, string $action = self::ACTION_SUSPEND)
+ public function toggle(Server $server, string $action = self::ACTION_SUSPEND): void
{
Assert::oneOf($action, [self::ACTION_SUSPEND, self::ACTION_UNSUSPEND]);
@@ -36,7 +37,9 @@ class SuspensionService
// suspended in the database. Additionally, nothing needs to happen if the server
// is not suspended, and we try to un-suspend the instance.
if ($isSuspending === $server->isSuspended()) {
- return Notification::make()->danger()->title('Failed!')->body('Server is already suspended!')->send();
+ Notification::make()->danger()->title('Failed!')->body('Server is already suspended!')->send();
+
+ return;
}
// Check if the server is currently being transferred.
diff --git a/app/Services/Users/ToggleTwoFactorService.php b/app/Services/Users/ToggleTwoFactorService.php
index 64518e39b..ca5df2dcb 100644
--- a/app/Services/Users/ToggleTwoFactorService.php
+++ b/app/Services/Users/ToggleTwoFactorService.php
@@ -30,7 +30,7 @@ class ToggleTwoFactorService
* @throws \PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException
* @throws \App\Exceptions\Service\User\TwoFactorAuthenticationTokenInvalid
*/
- public function handle(User $user, string $token, bool $toggleState = null): array
+ public function handle(User $user, string $token, ?bool $toggleState = null): array
{
$isValidToken = $this->google2FA->verifyKey($user->totp_secret, $token, config()->get('panel.auth.2fa.window'));
diff --git a/app/Traits/CheckMigrationsTrait.php b/app/Traits/CheckMigrationsTrait.php
index ee2de8f3a..1f849e8aa 100644
--- a/app/Traits/CheckMigrationsTrait.php
+++ b/app/Traits/CheckMigrationsTrait.php
@@ -12,7 +12,7 @@ trait CheckMigrationsTrait
protected function hasCompletedMigrations(): bool
{
/** @var Migrator $migrator */
- $migrator = app()->make('migrator');
+ $migrator = app()->make('migrator'); // @phpstan-ignore-line
$files = $migrator->getMigrationFiles(database_path('migrations'));
diff --git a/app/Traits/Controllers/PlainJavascriptInjection.php b/app/Traits/Controllers/PlainJavascriptInjection.php
index 4b5169296..e77686776 100644
--- a/app/Traits/Controllers/PlainJavascriptInjection.php
+++ b/app/Traits/Controllers/PlainJavascriptInjection.php
@@ -9,7 +9,7 @@ trait PlainJavascriptInjection
/**
* Injects statistics into javascript.
*/
- public function injectJavascript($data)
+ public function injectJavascript($data): void
{
\JavaScript::put($data);
}
diff --git a/app/Traits/EnvironmentWriterTrait.php b/app/Traits/EnvironmentWriterTrait.php
index 460d8000e..cb5bef047 100644
--- a/app/Traits/EnvironmentWriterTrait.php
+++ b/app/Traits/EnvironmentWriterTrait.php
@@ -22,6 +22,7 @@ trait EnvironmentWriterTrait
/**
* Update the .env file for the application using the passed in values.
+ *
* @throws Exception
*/
public function writeToEnvironment(array $values = []): void
diff --git a/app/Traits/Helpers/AvailableLanguages.php b/app/Traits/Helpers/AvailableLanguages.php
index 53b45c5a6..aafffbbab 100644
--- a/app/Traits/Helpers/AvailableLanguages.php
+++ b/app/Traits/Helpers/AvailableLanguages.php
@@ -51,6 +51,7 @@ trait AvailableLanguages
*/
private function getFilesystemInstance(): Filesystem
{
+ // @phpstan-ignore-next-line
return $this->filesystem = $this->filesystem ?: app()->make(Filesystem::class);
}
}
diff --git a/app/Transformers/Api/Application/BaseTransformer.php b/app/Transformers/Api/Application/BaseTransformer.php
index 62ee4ceeb..ec4bb9d3c 100644
--- a/app/Transformers/Api/Application/BaseTransformer.php
+++ b/app/Transformers/Api/Application/BaseTransformer.php
@@ -54,6 +54,7 @@ abstract class BaseTransformer extends TransformerAbstract
*/
public static function fromRequest(Request $request): self
{
+ // @phpstan-ignore-next-line
return app(static::class)->setRequest($request);
}
@@ -89,8 +90,7 @@ abstract class BaseTransformer extends TransformerAbstract
*
* @template T of \App\Transformers\Api\Application\BaseTransformer
*
- * @param class-string $abstract
- *
+ * @param class-string $abstract
* @return T
*
* @throws \App\Exceptions\Transformer\InvalidTransformerLevelException
diff --git a/app/Transformers/Api/Application/EggVariableTransformer.php b/app/Transformers/Api/Application/EggVariableTransformer.php
index 381b3102e..d70299787 100644
--- a/app/Transformers/Api/Application/EggVariableTransformer.php
+++ b/app/Transformers/Api/Application/EggVariableTransformer.php
@@ -15,7 +15,7 @@ class EggVariableTransformer extends BaseTransformer
return Egg::RESOURCE_NAME;
}
- public function transform(EggVariable $model)
+ public function transform(EggVariable $model): array
{
return $model->toArray();
}
diff --git a/app/Transformers/Api/Application/MountTransformer.php b/app/Transformers/Api/Application/MountTransformer.php
index c658f30fa..18dbe36dc 100644
--- a/app/Transformers/Api/Application/MountTransformer.php
+++ b/app/Transformers/Api/Application/MountTransformer.php
@@ -22,7 +22,7 @@ class MountTransformer extends BaseTransformer
return Mount::RESOURCE_NAME;
}
- public function transform(Mount $model)
+ public function transform(Mount $model): array
{
return $model->toArray();
}
diff --git a/app/Transformers/Api/Application/ServerTransformer.php b/app/Transformers/Api/Application/ServerTransformer.php
index e754b9452..378cea65f 100644
--- a/app/Transformers/Api/Application/ServerTransformer.php
+++ b/app/Transformers/Api/Application/ServerTransformer.php
@@ -29,7 +29,7 @@ class ServerTransformer extends BaseTransformer
/**
* Perform dependency injection.
*/
- public function handle(EnvironmentService $environmentService)
+ public function handle(EnvironmentService $environmentService): void
{
$this->environmentService = $environmentService;
}
diff --git a/app/Transformers/Api/Client/ActivityLogTransformer.php b/app/Transformers/Api/Client/ActivityLogTransformer.php
index 58d5f13ae..a54cb1f30 100644
--- a/app/Transformers/Api/Client/ActivityLogTransformer.php
+++ b/app/Transformers/Api/Client/ActivityLogTransformer.php
@@ -6,6 +6,7 @@ use Illuminate\Support\Str;
use App\Models\User;
use App\Models\ActivityLog;
use Illuminate\Database\Eloquent\Model;
+use League\Fractal\Resource\ResourceAbstract;
class ActivityLogTransformer extends BaseClientTransformer
{
@@ -34,7 +35,7 @@ class ActivityLogTransformer extends BaseClientTransformer
];
}
- public function includeActor(ActivityLog $model)
+ public function includeActor(ActivityLog $model): ResourceAbstract
{
if (!$model->actor instanceof User) {
return $this->null();
@@ -111,7 +112,7 @@ class ActivityLogTransformer extends BaseClientTransformer
* Determines if the user can view the IP address in the output either because they are the
* actor that performed the action, or because they are an administrator on the Panel.
*/
- protected function canViewIP(Model $actor = null): bool
+ protected function canViewIP(?Model $actor = null): bool
{
return $actor?->is($this->request->user()) || $this->request->user()->isRootAdmin();
}
diff --git a/app/Transformers/Api/Client/BaseClientTransformer.php b/app/Transformers/Api/Client/BaseClientTransformer.php
index c490d1bfd..9ee56cfaf 100644
--- a/app/Transformers/Api/Client/BaseClientTransformer.php
+++ b/app/Transformers/Api/Client/BaseClientTransformer.php
@@ -24,7 +24,7 @@ abstract class BaseClientTransformer extends BaseApplicationTransformer
*
* @noinspection PhpParameterNameChangedDuringInheritanceInspection
*/
- protected function authorize(string $ability, Server $server = null): bool
+ protected function authorize(string $ability, ?Server $server = null): bool
{
Assert::isInstanceOf($server, Server::class);
diff --git a/database/Seeders/DatabaseSeeder.php b/database/Seeders/DatabaseSeeder.php
index 2f7f6694e..b2e7c20e4 100644
--- a/database/Seeders/DatabaseSeeder.php
+++ b/database/Seeders/DatabaseSeeder.php
@@ -10,7 +10,7 @@ class DatabaseSeeder extends Seeder
/**
* Run the database seeds.
*/
- public function run()
+ public function run(): void
{
$this->call(EggSeeder::class);
diff --git a/database/Seeders/EggSeeder.php b/database/Seeders/EggSeeder.php
index dcbc4f25c..d6a3743b7 100644
--- a/database/Seeders/EggSeeder.php
+++ b/database/Seeders/EggSeeder.php
@@ -34,7 +34,7 @@ class EggSeeder extends Seeder
/**
* Run the egg seeder.
*/
- public function run()
+ public function run(): void
{
foreach (static::$imports as $import) {
/* @noinspection PhpParamsInspection */
@@ -45,7 +45,7 @@ class EggSeeder extends Seeder
/**
* Loop through the list of egg files and import them.
*/
- protected function parseEggFiles($name)
+ protected function parseEggFiles($name): void
{
$files = new \DirectoryIterator(database_path('Seeders/eggs/' . kebab_case($name)));
diff --git a/phpstan.neon b/phpstan.neon
index 58b6c8e91..e5c462230 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,20 +1,20 @@
includes:
- vendor/larastan/larastan/extension.neon
+rules:
+ - App\PHPStan\ForbiddenGlobalFunctionsRule
+
parameters:
paths:
- - app/
+ - app
- # Level 9 is the highest level
- level: 5
+ level: 6
ignoreErrors:
# Prologue\Alerts defines its methods from its configuration file dynamically
- '#^Call to an undefined method Prologue\\Alerts\\AlertsMessageBag::(danger|success|info|warning)\(\)\.$#'
-# excludePaths:
-# - ./*/*/FileToBeExcluded.php
-#
-# checkMissingIterableValueType: false
-
+ - '#no value type specified in iterable#'
+ - '#Unable to resolve the template type#'
+ - '#does not specify its types#'
diff --git a/pint.json b/pint.json
index ac6e43389..99fa80d3a 100644
--- a/pint.json
+++ b/pint.json
@@ -1,14 +1,8 @@
{
"preset": "laravel",
"rules": {
- "class_attributes_separation": false,
"concat_space": false,
- "new_with_parentheses": false,
"not_operator_with_successor_space": false,
- "nullable_type_declaration_for_default_null_value": false,
- "ordered_imports": false,
- "phpdoc_align": false,
- "phpdoc_separation": false,
- "single_line_empty_body": false
+ "ordered_imports": false
}
}
diff --git a/tests/Assertions/AssertsActivityLogged.php b/tests/Assertions/AssertsActivityLogged.php
index db352bc97..23a3461b1 100644
--- a/tests/Assertions/AssertsActivityLogged.php
+++ b/tests/Assertions/AssertsActivityLogged.php
@@ -11,7 +11,7 @@ use App\Models\ActivityLogSubject;
trait AssertsActivityLogged
{
/**
- * @param \Illuminate\Database\Eloquent\Model|array $subjects
+ * @param \Illuminate\Database\Eloquent\Model|array $subjects
*/
public function assertActivityFor(string $event, ?Model $actor, ...$subjects): void
{
diff --git a/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php b/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php
index 1090eae47..cc98921a7 100644
--- a/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php
+++ b/tests/Integration/Api/Client/ClientApiIntegrationTestCase.php
@@ -45,7 +45,7 @@ abstract class ClientApiIntegrationTestCase extends IntegrationTestCase
/**
* Returns a link to the specific resource using the client API.
*/
- protected function link(mixed $model, string $append = null): string
+ protected function link(mixed $model, ?string $append = null): string
{
switch (get_class($model)) {
case Server::class:
@@ -71,7 +71,7 @@ abstract class ClientApiIntegrationTestCase extends IntegrationTestCase
* Asserts that the data passed through matches the output of the data from the transformer. This
* will remove the "relationships" key when performing the comparison.
*/
- protected function assertJsonTransformedWith(array $data, Model|EloquentModel $model)
+ protected function assertJsonTransformedWith(array $data, Model|EloquentModel $model): void
{
$reflect = new \ReflectionClass($model);
$transformer = sprintf('\\App\\Transformers\\Api\\Client\\%sTransformer', $reflect->getShortName());
diff --git a/tests/Integration/Api/Client/Server/PowerControllerTest.php b/tests/Integration/Api/Client/Server/PowerControllerTest.php
index 5cadb3772..94d3e7326 100644
--- a/tests/Integration/Api/Client/Server/PowerControllerTest.php
+++ b/tests/Integration/Api/Client/Server/PowerControllerTest.php
@@ -14,7 +14,7 @@ class PowerControllerTest extends ClientApiIntegrationTestCase
* an error in response. This checks against the specific permission needed to send
* the command to the server.
*
- * @param string[] $permissions
+ * @param string[] $permissions
*
* @dataProvider invalidPermissionDataProvider
*/
diff --git a/tests/Integration/Api/Remote/SftpAuthenticationControllerTest.php b/tests/Integration/Api/Remote/SftpAuthenticationControllerTest.php
index 031eedce7..3236266dc 100644
--- a/tests/Integration/Api/Remote/SftpAuthenticationControllerTest.php
+++ b/tests/Integration/Api/Remote/SftpAuthenticationControllerTest.php
@@ -226,7 +226,7 @@ class SftpAuthenticationControllerTest extends IntegrationTestCase
/**
* Sets the authorization header for the rest of the test.
*/
- protected function setAuthorization(Node $node = null): void
+ protected function setAuthorization(?Node $node = null): void
{
$node = $node ?? $this->server->node;
diff --git a/tests/Traits/Http/RequestMockHelpers.php b/tests/Traits/Http/RequestMockHelpers.php
index 22f60e74f..46a71e26a 100644
--- a/tests/Traits/Http/RequestMockHelpers.php
+++ b/tests/Traits/Http/RequestMockHelpers.php
@@ -27,7 +27,7 @@ trait RequestMockHelpers
/**
* Configure the user model that the request mock should return with.
*/
- public function setRequestUserModel(User $user = null): void
+ public function setRequestUserModel(?User $user = null): void
{
$this->request->shouldReceive('user')->andReturn($user);
}
@@ -80,7 +80,7 @@ trait RequestMockHelpers
*
* @deprecated
*/
- protected function setRequestUser(User $user = null): User
+ protected function setRequestUser(?User $user = null): User
{
$user = $user instanceof User ? $user : User::factory()->make();
$this->request->shouldReceive('user')->withNoArgs()->andReturn($user);
diff --git a/tests/Traits/Integration/CreatesTestModels.php b/tests/Traits/Integration/CreatesTestModels.php
index 68d54beda..f33fc63aa 100644
--- a/tests/Traits/Integration/CreatesTestModels.php
+++ b/tests/Traits/Integration/CreatesTestModels.php
@@ -56,8 +56,7 @@ trait CreatesTestModels
* Generates a user and a server for that user. If an array of permissions is passed it
* is assumed that the user is actually a subuser of the server.
*
- * @param string[] $permissions
- *
+ * @param string[] $permissions
* @return array{\App\Models\User, \App\Models\Server}
*/
public function generateTestAccount(array $permissions = []): array