Small updates

This commit is contained in:
Lance Pioch 2024-03-12 22:47:32 -04:00
parent c83dd86a41
commit 883314b74a
39 changed files with 682 additions and 1181 deletions

View File

@ -5,7 +5,7 @@ body:
- type: checkboxes
attributes:
label: Is there an existing feature request for this?
description: Please [search here](https://github.com/pterodactyl/panel/issues?q=is%3Aissue) to see if someone else has already suggested this.
description: Please search the issues to see if someone else has already suggested this.
options:
- label: I have searched the existing issues before opening this feature request.
required: true

View File

@ -20,7 +20,7 @@ server {
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/pterodactyl.app-error.log error;
error_log /var/log/nginx/panel.app-error.log error;
# allow larger file uploads and longer script runtimes
client_max_body_size 100m;

View File

@ -14,8 +14,8 @@ server {
root /app/public;
index index.php;
access_log /var/log/nginx/pterodactyl.app-access.log;
error_log /var/log/nginx/pterodactyl.app-error.log error;
access_log /var/log/nginx/panel.app-access.log;
error_log /var/log/nginx/panel.app-error.log error;
# allow larger file uploads and longer script runtimes
client_max_body_size 100m;

View File

@ -3,27 +3,25 @@ name: Build
on:
push:
branches:
- "develop"
- "1.0-develop"
- '**'
pull_request:
branches:
- "develop"
- "1.0-develop"
- '**'
jobs:
ui:
name: UI
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [16]
node-version: [18]
steps:
- name: Code Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"

View File

@ -3,17 +3,15 @@ name: Tests
on:
push:
branches:
- "develop"
- "1.0-develop"
- '**'
pull_request:
branches:
- "develop"
- "1.0-develop"
- '**'
jobs:
tests:
name: Tests
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
@ -30,7 +28,7 @@ jobs:
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Code Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Get cache directory
id: composer-cache
@ -38,7 +36,7 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
@ -54,11 +52,14 @@ jobs:
coverage: none
- name: Setup .env
run: cp .env.ci .env
run: cp .env.example .env
- name: Install dependencies
run: composer install --no-interaction --no-progress --no-suggest --prefer-dist
- name: Generate App Key
run: php artisan key:generate
- name: Unit tests
run: vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit
if: ${{ always() }}

View File

@ -3,20 +3,18 @@ name: Lint
on:
push:
branches:
- "develop"
- "1.0-develop"
- '**'
pull_request:
branches:
- "develop"
- "1.0-develop"
- '**'
jobs:
lint:
name: Lint
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Code Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
@ -27,10 +25,10 @@ jobs:
coverage: none
- name: Setup .env
run: cp .env.ci .env
run: cp .env.example .env
- name: Install dependencies
run: composer install --no-interaction --no-progress --no-suggest --prefer-dist
- name: PHP CS Fixer
run: vendor/bin/php-cs-fixer fix --dry-run --diff
- name: Pint
run: vendor/bin/pint --test

View File

@ -2,8 +2,10 @@
namespace App\Console\Commands\User;
use Exception;
use Illuminate\Console\Command;
use App\Services\Users\UserCreationService;
use Illuminate\Support\Facades\DB;
class MakeUserCommand extends Command
{
@ -22,11 +24,17 @@ class MakeUserCommand extends Command
/**
* Handle command request to create a new user.
*
* @throws \Exception
* @throws Exception
* @throws \App\Exceptions\Model\DataValidationException
*/
public function handle()
{
try {
DB::select('select 1 where 1');
} catch (Exception $exception) {
return $this->error($exception->getMessage()) ?? 0;
}
$root_admin = $this->option('admin') ?? $this->confirm(trans('command/messages.user.ask_admin'));
$email = $this->option('email') ?? $this->ask(trans('command/messages.user.ask_email'));
$username = $this->option('username') ?? $this->ask(trans('command/messages.user.ask_username'));

View File

@ -19,7 +19,7 @@ class Utilities
// Given a random string of characters, randomly loop through the characters and replace some
// with special characters to avoid issues with MySQL password requirements on some servers.
try {
for ($i = 0; $i < random_int(2, 6); ++$i) {
for ($i = 0; $i < random_int(2, 6); $i++) {
$character = ['!', '@', '=', '.', '+', '^'][random_int(0, 5)];
$string = substr_replace($string, $character, random_int(0, $length - 1), 1);

View File

@ -84,7 +84,7 @@ class BackupRemoteUploadController extends Controller
// Create as many UploadPart presigned urls as needed
$parts = [];
for ($i = 0; $i < ($size / $maxPartSize); ++$i) {
for ($i = 0; $i < ($size / $maxPartSize); $i++) {
$parts[] = $client->createPresignedRequest(
$client->getCommand('UploadPart', array_merge($params, ['PartNumber' => $i + 1])),
$expires

View File

@ -78,10 +78,7 @@ use App\Notifications\SendPasswordReset as ResetPasswordNotification;
*
* @mixin \Eloquent
*/
class User extends Model implements
AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract
{
use Authenticatable;
use Authorizable;

View File

@ -14,7 +14,7 @@ use App\Contracts\Core\ReceivesEvents;
use Illuminate\Contracts\Notifications\Dispatcher;
use Illuminate\Notifications\Messages\MailMessage;
class ServerInstalled extends Notification implements ShouldQueue, ReceivesEvents
class ServerInstalled extends Notification implements ReceivesEvents, ShouldQueue
{
use Queueable;

View File

@ -70,6 +70,7 @@ class AllocationRepository extends EloquentRepository implements AllocationRepos
foreach ($ports as $port) {
if (is_array($port)) {
$inner->orWhereBetween('port', $port);
continue;
}

View File

@ -6,7 +6,7 @@ use Illuminate\Support\Arr;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\DataAwareRule;
class Fqdn implements Rule, DataAwareRule
class Fqdn implements DataAwareRule, Rule
{
protected array $data = [];
protected string $message = '';

View File

@ -28,7 +28,7 @@ class ActivityLogBatchService
$this->uuid = Uuid::uuid4()->toString();
}
++$this->transaction;
$this->transaction++;
}
/**

View File

@ -190,6 +190,7 @@ class EggConfigurationService
$plucked = Arr::get($structure, preg_replace('/^server\./', '', $key), '');
$value = str_replace("{{{$key}}}", $plucked, $value);
continue;
}

View File

@ -56,7 +56,7 @@ class ToggleTwoFactorService
$tokens = [];
if ((!$toggleState && !$user->use_totp) || $toggleState) {
$inserts = [];
for ($i = 0; $i < 10; ++$i) {
for ($i = 0; $i < 10; $i++) {
$token = Str::random(10);
$inserts[] = [

View File

@ -33,7 +33,7 @@ class TwoFactorSetupService
{
$secret = '';
try {
for ($i = 0; $i < $this->config->get('panel.auth.2fa.bytes', 16); ++$i) {
for ($i = 0; $i < $this->config->get('panel.auth.2fa.bytes', 16); $i++) {
$secret .= substr(self::VALID_BASE32_CHARACTERS, random_int(0, 31), 1);
}
} catch (\Exception $exception) {

View File

@ -9,7 +9,7 @@
"ext-pdo_mysql": "*",
"ext-posix": "*",
"ext-zip": "*",
"aws/aws-sdk-php": "~3.260.1",
"aws/aws-sdk-php": "~3.288.1",
"doctrine/dbal": "~3.6.0",
"guzzlehttp/guzzle": "~7.5.0",
"hashids/hashids": "~5.0.0",
@ -41,8 +41,8 @@
"require-dev": {
"barryvdh/laravel-ide-helper": "~2.13.0",
"fakerphp/faker": "~1.21.0",
"friendsofphp/php-cs-fixer": "~3.14.4",
"itsgoingd/clockwork": "~5.1.12",
"laravel/pint": "^1.14",
"laravel/sail": "~1.21.0",
"mockery/mockery": "~1.5.1",
"nunomaduro/collision": "~7.0.5",

868
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -177,16 +177,4 @@ return [
// Should an email be sent to a server owner whenever their server is reinstalled?
'send_reinstall_notification' => env('PANEL_SEND_REINSTALL_NOTIFICATION', true),
],
/*
|--------------------------------------------------------------------------
| Telemetry Settings
|--------------------------------------------------------------------------
|
| This section controls the telemetry.
*/
'telemetry' => [
'enabled' => env('PANEL_TELEMETRY_ENABLED', true),
],
];

View File

@ -4,6 +4,7 @@ namespace Database\Seeders;
use App\Models\Egg;
use App\Models\Nest;
use Exception;
use Illuminate\Database\Seeder;
use Illuminate\Http\UploadedFile;
use App\Services\Eggs\Sharing\EggImporterService;
@ -63,7 +64,12 @@ class EggSeeder extends Seeder
continue;
}
$decoded = json_decode(file_get_contents($file->getRealPath()), true, 512, JSON_THROW_ON_ERROR);
try {
$decoded = json_decode(file_get_contents($file->getRealPath()), true, 512, JSON_THROW_ON_ERROR);
} catch (Exception) {
continue;
}
$file = new UploadedFile($file->getPathname(), $file->getFilename(), 'application/json');
$egg = $nest->eggs()

View File

@ -36,8 +36,8 @@ class UpgradeTaskSystem extends Migration
public function down()
{
Schema::table('tasks', function (Blueprint $table) {
// $table->dropForeign(['server_id']);
// $table->dropForeign(['user_id']);
// $table->dropForeign(['server_id']);
// $table->dropForeign(['user_id']);
$table->renameColumn('server_id', 'server');
$table->dropColumn('user_id');

View File

@ -24,7 +24,7 @@ class DropGoogleAnalytics extends Migration
{
DB::table('settings')->insert(
[
'key' => 'settings::app:analytics',
'key' => 'settings::app:analytics',
]
);
}

View File

@ -4,7 +4,8 @@ use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class () extends Migration {
return new class() extends Migration
{
/**
* Run the migrations.
*

View File

@ -4,7 +4,8 @@ use App\Models\Setting;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
return new class () extends Migration {
return new class() extends Migration
{
private array $keys = [
['mail:host', 'mail:mailers:smtp:host'],
['mail:port', 'mail:mailers:smtp:port'],

View File

@ -5,7 +5,8 @@ use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class () extends Migration {
return new class() extends Migration
{
/**
* Run the migrations.
*/

View File

@ -4,7 +4,8 @@ use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class () extends Migration {
return new class() extends Migration
{
/**
* Run the migrations.
*/

View File

@ -14,11 +14,11 @@
"@preact/signals-react": "^1.2.1",
"@tailwindcss/forms": "^0.5.2",
"@tailwindcss/line-clamp": "^0.4.0",
"axios": "^0.27.2",
"axios": "^1.6.7",
"boring-avatars": "^1.7.0",
"chart.js": "^3.8.0",
"classnames": "^2.3.1",
"codemirror": "^5.57.0",
"codemirror": "^5.58.2",
"copy-to-clipboard": "^3.3.1",
"date-fns": "^2.28.0",
"debounce": "^1.2.0",
@ -107,7 +107,7 @@
"fork-ts-checker-webpack-plugin": "^6.2.10",
"identity-obj-proxy": "^3.0.0",
"jest": "^28.1.1",
"postcss": "^8.4.14",
"postcss": "^8.4.35",
"postcss-import": "^14.1.0",
"postcss-loader": "^4.0.0",
"postcss-nesting": "^10.1.8",
@ -135,7 +135,7 @@
"lint": "eslint ./resources/scripts/**/*.{ts,tsx} --ext .ts,.tsx",
"watch": "cross-env NODE_ENV=development ./node_modules/.bin/webpack --watch --progress",
"build": "cross-env NODE_OPTIONS='--openssl-legacy-provider' NODE_ENV=development ./node_modules/.bin/webpack --progress",
"build:production": "yarn run clean && cross-env NODE_ENV=production ./node_modules/.bin/webpack --mode production",
"build:production": "yarn run clean && cross-env NODE_OPTIONS='--openssl-legacy-provider' NODE_ENV=production ./node_modules/.bin/webpack --mode production",
"serve": "yarn run clean && cross-env WEBPACK_PUBLIC_PATH=/webpack@hmr/ NODE_ENV=development webpack-dev-server --host 0.0.0.0 --port 8080 --public https://panel.test --hot"
},
"browserslist": [

12
pint.json Normal file
View File

@ -0,0 +1,12 @@
{
"preset": "laravel",
"rules": {
"class_attributes_separation": false,
"concat_space": false,
"not_operator_with_successor_space": false,
"nullable_type_declaration_for_default_null_value": false,
"ordered_imports": false,
"phpdoc_align": false,
"phpdoc_separation": false
}
}

View File

@ -38,6 +38,7 @@ export const rawDataToFileObject = (data: FractalResponseData): FileObject => ({
'application/x-lzip', // .tar.lz4, .lz4 (not sure if this mime type is correct)
'application/x-sz', // .tar.sz, .sz (not sure if this mime type is correct)
'application/x-xz', // .tar.xz, .xz
'application/x-7z-compressed', // .7z
'application/zstd', // .tar.zst, .zst
'application/zip', // .zip
].indexOf(this.mimetype) >= 0

View File

@ -19,7 +19,7 @@ interface Props {
function wrapProperties(value: unknown): any {
if (value === null || typeof value === 'string' || typeof value === 'number') {
return `<strong>${String(value)}</strong>`;
return `${String(value)}`;
}
if (isObject(value)) {

View File

@ -20,6 +20,7 @@ const ServerConsoleContainer = () => {
const isTransferring = ServerContext.useStoreState((state) => state.server.data!.isTransferring);
const eggFeatures = ServerContext.useStoreState((state) => state.server.data!.eggFeatures, isEqual);
const isNodeUnderMaintenance = ServerContext.useStoreState((state) => state.server.data!.isNodeUnderMaintenance);
const isSuspended = ServerContext.useStoreState((state) => state.server.data!.status === 'suspended');
return (
<ServerContentBlock title={'Console'}>
@ -32,15 +33,22 @@ const ServerConsoleContainer = () => {
: 'This server is currently being transferred to another node and all actions are unavailable.'}
</Alert>
)}
{isSuspended && (
<Alert type={'danger'} className={'mb-4'}>
This server is currently suspended.
</Alert>
)}
<div className={'grid grid-cols-4 gap-4 mb-4'}>
<div className={'hidden sm:block sm:col-span-2 lg:col-span-3 pr-4'}>
<h1 className={'font-header text-2xl text-gray-50 leading-relaxed line-clamp-1'}>{name}</h1>
<p className={'text-sm line-clamp-2'}>{description}</p>
</div>
<div className={'col-span-4 sm:col-span-2 lg:col-span-1 self-end'}>
<Can action={['control.start', 'control.stop', 'control.restart']} matchAny>
<PowerButtons className={'flex sm:justify-end space-x-2'} />
</Can>
{!isSuspended && (
<Can action={['control.start', 'control.stop', 'control.restart']} matchAny>
<PowerButtons className={'flex sm:justify-end space-x-2'} />
</Can>
)}
</div>
</div>
<div className={'grid grid-cols-4 gap-2 sm:gap-4 mb-4'}>

View File

@ -1,4 +1,4 @@
import axios from 'axios';
import axios, { AxiosProgressEvent } from 'axios';
import getFileUploadUrl from '@/api/server/files/getFileUploadUrl';
import tw from 'twin.macro';
import { Button } from '@/components/elements/button/index';
@ -57,7 +57,7 @@ export default ({ className }: WithClassname) => {
return () => timeouts.value.forEach(clearTimeout);
}, []);
const onUploadProgress = (data: ProgressEvent, name: string) => {
const onUploadProgress = (data: AxiosProgressEvent, name: string) => {
setUploadProgress({ name, loaded: data.loaded });
};
@ -82,6 +82,7 @@ export default ({ className }: WithClassname) => {
url,
{ files: file },
{
withCredentials: true,
signal: controller.signal,
headers: { 'Content-Type': 'multipart/form-data' },
params: { directory },

View File

@ -43,9 +43,9 @@ const modes: Mode[] = [
{
name: 'JSON',
mime: 'application/json',
mimes: ['application/json', 'application/x-json'],
mimes: ['application/json', 'application/x-json', 'application/json5'],
mode: 'javascript',
ext: ['json', 'map'],
ext: ['json', 'map', 'json5', 'jsonc'],
alias: ['json5'],
},
{ name: 'Lua', mime: 'text/x-lua', mode: 'lua', ext: ['lua'] },

View File

@ -82,7 +82,7 @@ class ApiKeyControllerTest extends ClientApiIntegrationTestCase
public function testApiKeyCannotSpecifyMoreThanFiftyIps()
{
$ips = [];
for ($i = 0; $i < 100; ++$i) {
for ($i = 0; $i < 100; $i++) {
$ips[] = '127.0.0.' . $i;
}
@ -140,9 +140,9 @@ class ApiKeyControllerTest extends ClientApiIntegrationTestCase
->assertJsonPath('errors.0.detail', 'The description may not be greater than 500 characters.');
$this->postJson('/api/client/account/api-keys', [
'description' => 'Foobar',
'allowed_ips' => ['hodor', '127.0.0.1', 'hodor/24'],
])
'description' => 'Foobar',
'allowed_ips' => ['hodor', '127.0.0.1', 'hodor/24'],
])
->assertUnprocessable()
->assertJsonPath('errors.0.detail', '"hodor" is not a valid IP address or CIDR range.')
->assertJsonPath('errors.0.meta.source_field', 'allowed_ips.0')

View File

@ -7,7 +7,6 @@ use App\Models\User;
use App\Models\Server;
use App\Models\Permission;
use App\Models\UserSSHKey;
use phpseclib3\Crypt\EC\PrivateKey;
use App\Tests\Integration\IntegrationTestCase;
class SftpAuthenticationControllerTest extends IntegrationTestCase
@ -99,7 +98,7 @@ class SftpAuthenticationControllerTest extends IntegrationTestCase
*/
public function testUserIsThrottledIfInvalidCredentialsAreProvided()
{
for ($i = 0; $i <= 10; ++$i) {
for ($i = 0; $i <= 10; $i++) {
$this->postJson('/api/remote/sftp/auth', [
'type' => 'public_key',
'username' => $i % 2 === 0 ? $this->user->username : $this->getUsername(),
@ -109,22 +108,6 @@ class SftpAuthenticationControllerTest extends IntegrationTestCase
}
}
/**
* Test that the user is not throttled so long as a valid public key is provided, even
* if it doesn't actually exist in the database for the user.
*/
public function testUserIsNotThrottledIfNoPublicKeyMatches()
{
for ($i = 0; $i <= 10; ++$i) {
$this->postJson('/api/remote/sftp/auth', [
'type' => 'public_key',
'username' => $this->getUsername(),
'password' => PrivateKey::createKey('Ed25519')->getPublicKey()->toString('OpenSSH'),
])
->assertForbidden();
}
}
/**
* Test that a request is rejected if the credentials are valid but the username indicates
* a server on a different node.

View File

@ -13,8 +13,8 @@ use App\Transformers\Api\Application\BaseTransformer;
abstract class IntegrationTestCase extends TestCase
{
use CreatesTestModels;
use AssertsActivityLogged;
use CreatesTestModels;
protected array $connectionsToTransact = ['mysql'];

View File

@ -90,7 +90,7 @@ class FindAssignableAllocationServiceTest extends IntegrationTestCase
config()->set('panel.client_features.allocations.range_start', 5000);
config()->set('panel.client_features.allocations.range_end', 5005);
for ($i = 5000; $i <= 5005; ++$i) {
for ($i = 5000; $i <= 5005; $i++) {
Allocation::factory()->create([
'ip' => $server->allocation->ip,
'port' => $i,

778
yarn.lock

File diff suppressed because it is too large Load Diff