Skip to content

Commit

Permalink
Merge branch 'main' into feature/health
Browse files Browse the repository at this point in the history
  • Loading branch information
Boy132 committed Nov 8, 2024
2 parents 934554a + 47bd728 commit 6cb8bba
Show file tree
Hide file tree
Showing 98 changed files with 1,107 additions and 554 deletions.
6 changes: 3 additions & 3 deletions .github/docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ crond -L /var/log/crond -l 5
export SUPERVISORD_CADDY=false

## disable caddy if SKIP_CADDY is set
if [[ -z $SKIP_CADDY ]]; then
if [[ "${SKIP_CADDY:-}" == "true" ]]; then
echo "Starting PHP-FPM only"
else
echo "Starting PHP-FPM and Caddy"
export SUPERVISORD_CADDY=true
else
echo "Starting PHP-FPM only"
fi

chown -R www-data:www-data /pelican-data/.env /pelican-data/database
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
fail-fast: false
matrix:
php: [8.2, 8.3]
database: ["mariadb:10.3", "mariadb:10.11", "mariadb:11.4"]
database: ["mariadb:10.6", "mariadb:10.11", "mariadb:11.4"]
services:
database:
image: ${{ matrix.database }}
Expand Down
5 changes: 5 additions & 0 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Console\Commands\Schedule\ProcessRunnableCommand;
use App\Jobs\NodeStatistics;
use App\Models\ActivityLog;
use App\Models\Webhook;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Database\Console\PruneCommand;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
Expand Down Expand Up @@ -51,6 +52,10 @@ protected function schedule(Schedule $schedule): void
$schedule->command(PruneCommand::class, ['--model' => [ActivityLog::class]])->daily();
}

if (config('panel.webhook.prune_days')) {
$schedule->command(PruneCommand::class, ['--model' => [Webhook::class]])->daily();
}

$schedule->command(ScheduleCheckHeartbeatCommand::class)->everyMinute();
$schedule->command(RunHealthChecksCommand::class)->everyFiveMinutes();
}
Expand Down
2 changes: 1 addition & 1 deletion app/Events/Auth/FailedCaptcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class FailedCaptcha extends Event
/**
* Create a new event instance.
*/
public function __construct(public string $ip, public string $domain)
public function __construct(public string $ip, public ?string $message)
{
}
}
36 changes: 36 additions & 0 deletions app/Filament/Pages/Auth/Login.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Filament\Pages\Auth;

use Coderflex\FilamentTurnstile\Forms\Components\Turnstile;
use Filament\Pages\Auth\Login as BaseLogin;

class Login extends BaseLogin
{
protected function getForms(): array
{
return [
'form' => $this->form(
$this->makeForm()
->schema([
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getRememberFormComponent(),
Turnstile::make('captcha')
->hidden(!config('turnstile.turnstile_enabled'))
->validationMessages([
'required' => config('turnstile.error_messages.turnstile_check_message'),
]),
])
->statePath('data'),
),
];
}

protected function throwFailureValidationException(): never
{
$this->dispatch('reset-captcha');

parent::throwFailureValidationException();
}
}
23 changes: 13 additions & 10 deletions app/Filament/Pages/Installer/Steps/RedisStep.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
use Filament\Forms\Get;
use Filament\Notifications\Notification;
use Filament\Support\Exceptions\Halt;
use Illuminate\Support\Facades\Redis;
use Illuminate\Foundation\Application;
use Illuminate\Redis\RedisManager;

class RedisStep
{
Expand Down Expand Up @@ -47,26 +48,28 @@ public static function make(PanelInstaller $installer): Step
->revealable()
->default(config('database.redis.default.password')),
])
->afterValidation(function (Get $get) use ($installer) {
if (!self::testConnection($get('env_redis.REDIS_HOST'), $get('env_redis.REDIS_PORT'), $get('env_redis.REDIS_USERNAME'), $get('env_redis.REDIS_PASSWORD'))) {
->afterValidation(function (Get $get, Application $app) use ($installer) {
if (!self::testConnection($app, $get('env_redis.REDIS_HOST'), $get('env_redis.REDIS_PORT'), $get('env_redis.REDIS_USERNAME'), $get('env_redis.REDIS_PASSWORD'))) {
throw new Halt('Redis connection failed');
}

$installer->writeToEnv('env_redis');
});
}

private static function testConnection(string $host, null|string|int $port, ?string $username, ?string $password): bool
private static function testConnection(Application $app, string $host, null|string|int $port, ?string $username, ?string $password): bool
{
try {
config()->set('database.redis._panel_install_test', [
'host' => $host,
'port' => $port,
'username' => $username,
'password' => $password,
$redis = new RedisManager($app, 'predis', [
'default' => [
'host' => $host,
'port' => $port,
'username' => $username,
'password' => $password,
],
]);

Redis::connection('_panel_install_test')->command('ping');
$redis->connection()->command('ping');
} catch (Exception $exception) {
Notification::make()
->title('Redis connection failed')
Expand Down
112 changes: 73 additions & 39 deletions app/Filament/Pages/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Exception;
use Filament\Actions\Action;
use Filament\Forms\Components\Actions\Action as FormAction;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Tabs;
use Filament\Forms\Components\Tabs\Tab;
Expand All @@ -24,8 +25,11 @@
use Filament\Pages\Concerns\HasUnsavedDataChangesAlert;
use Filament\Pages\Concerns\InteractsWithHeaderActions;
use Filament\Pages\Page;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Notification as MailNotification;
use Illuminate\Support\HtmlString;

/**
* @property Form $form
Expand Down Expand Up @@ -67,10 +71,11 @@ protected function getFormSchema(): array
->label('General')
->icon('tabler-home')
->schema($this->generalSettings()),
Tab::make('recaptcha')
->label('reCAPTCHA')
Tab::make('captcha')
->label('Captcha')
->icon('tabler-shield')
->schema($this->recaptchaSettings()),
->schema($this->captchaSettings())
->columns(3),
Tab::make('mail')
->label('Mail')
->icon('tabler-mail')
Expand Down Expand Up @@ -146,7 +151,7 @@ private function generalSettings(): array
->separator()
->splitKeys(['Tab', ' '])
->placeholder('New IP or IP Range')
->default(env('TRUSTED_PROXIES', config('trustedproxy.proxies')))
->default(env('TRUSTED_PROXIES', implode(',', config('trustedproxy.proxies'))))
->hintActions([
FormAction::make('clear')
->label('Clear')
Expand All @@ -159,56 +164,71 @@ private function generalSettings(): array
->label('Set to Cloudflare IPs')
->icon('tabler-brand-cloudflare')
->authorize(fn () => auth()->user()->can('update settings'))
->action(fn (Set $set) => $set('TRUSTED_PROXIES', [
'173.245.48.0/20',
'103.21.244.0/22',
'103.22.200.0/22',
'103.31.4.0/22',
'141.101.64.0/18',
'108.162.192.0/18',
'190.93.240.0/20',
'188.114.96.0/20',
'197.234.240.0/22',
'198.41.128.0/17',
'162.158.0.0/15',
'104.16.0.0/13',
'104.24.0.0/14',
'172.64.0.0/13',
'131.0.72.0/22',
])),
->action(function (Client $client, Set $set) {
$ips = collect();
try {
$response = $client->request(
'GET',
'https://api.cloudflare.com/client/v4/ips',
config('panel.guzzle')
);
if ($response->getStatusCode() === 200) {
$result = json_decode($response->getBody(), true)['result'];
foreach (['ipv4_cidrs', 'ipv6_cidrs'] as $value) {
$ips->push(...data_get($result, $value));
}
$ips->unique();
}
} catch (GuzzleException $e) {
}

$set('TRUSTED_PROXIES', $ips->values()->all());
}),
]),
];
}

private function recaptchaSettings(): array
private function captchaSettings(): array
{
return [
Toggle::make('RECAPTCHA_ENABLED')
->label('Enable reCAPTCHA?')
Toggle::make('TURNSTILE_ENABLED')
->label('Enable Turnstile Captcha?')
->inline(false)
->columnSpan(1)
->onIcon('tabler-check')
->offIcon('tabler-x')
->onColor('success')
->offColor('danger')
->live()
->formatStateUsing(fn ($state): bool => (bool) $state)
->afterStateUpdated(fn ($state, Set $set) => $set('RECAPTCHA_ENABLED', (bool) $state))
->default(env('RECAPTCHA_ENABLED', config('recaptcha.enabled'))),
TextInput::make('RECAPTCHA_DOMAIN')
->label('Domain')
->afterStateUpdated(fn ($state, Set $set) => $set('TURNSTILE_ENABLED', (bool) $state))
->default(env('TURNSTILE_ENABLED', config('turnstile.turnstile_enabled'))),
Placeholder::make('info')
->columnSpan(2)
->content(new HtmlString('<p>You can generate the keys on your <u><a href="https://developers.cloudflare.com/turnstile/get-started/#get-a-sitekey-and-secret-key" target="_blank">Cloudflare Dashboard</a></u>. A Cloudflare account is required.</p>')),
TextInput::make('TURNSTILE_SITE_KEY')
->label('Site Key')
->required()
->visible(fn (Get $get) => $get('RECAPTCHA_ENABLED'))
->default(env('RECAPTCHA_DOMAIN', config('recaptcha.domain'))),
TextInput::make('RECAPTCHA_WEBSITE_KEY')
->label('Website Key')
->required()
->visible(fn (Get $get) => $get('RECAPTCHA_ENABLED'))
->default(env('RECAPTCHA_WEBSITE_KEY', config('recaptcha.website_key'))),
TextInput::make('RECAPTCHA_SECRET_KEY')
->visible(fn (Get $get) => $get('TURNSTILE_ENABLED'))
->default(env('TURNSTILE_SITE_KEY', config('turnstile.turnstile_site_key')))
->placeholder('1x00000000000000000000AA'),
TextInput::make('TURNSTILE_SECRET_KEY')
->label('Secret Key')
->required()
->visible(fn (Get $get) => $get('RECAPTCHA_ENABLED'))
->default(env('RECAPTCHA_SECRET_KEY', config('recaptcha.secret_key'))),
->visible(fn (Get $get) => $get('TURNSTILE_ENABLED'))
->default(env('TURNSTILE_SECRET_KEY', config('turnstile.secret_key')))
->placeholder('1x0000000000000000000000000000000AA'),
Toggle::make('TURNSTILE_VERIFY_DOMAIN')
->label('Verify domain?')
->inline(false)
->onIcon('tabler-check')
->offIcon('tabler-x')
->onColor('success')
->offColor('danger')
->visible(fn (Get $get) => $get('TURNSTILE_ENABLED'))
->formatStateUsing(fn ($state): bool => (bool) $state)
->afterStateUpdated(fn ($state, Set $set) => $set('TURNSTILE_VERIFY_DOMAIN', (bool) $state))
->default(env('TURNSTILE_VERIFY_DOMAIN', config('turnstile.turnstile_verify_domain'))),
];
}

Expand Down Expand Up @@ -540,7 +560,21 @@ private function miscSettings(): array
->afterStateUpdated(fn ($state, Set $set) => $set('PANEL_EDITABLE_SERVER_DESCRIPTIONS', (bool) $state))
->default(env('PANEL_EDITABLE_SERVER_DESCRIPTIONS', config('panel.editable_server_descriptions'))),
]),

Section::make('Webhook')
->description('Configure how often old webhook logs should be pruned.')
->columns()
->collapsible()
->collapsed()
->schema([
TextInput::make('APP_WEBHOOK_PRUNE_DAYS')
->label('Prune age')
->required()
->numeric()
->minValue(1)
->maxValue(365)
->suffix('Days')
->default(env('APP_WEBHOOK_PRUNE_DAYS', config('panel.webhook.prune_days'))),
]),
];
}

Expand Down
19 changes: 18 additions & 1 deletion app/Filament/Resources/ApiKeyResource/Pages/CreateApiKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Filament\Forms\Components\ToggleButtons;
use Filament\Forms\Form;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Database\Eloquent\Model;

class CreateApiKey extends CreateRecord
{
Expand Down Expand Up @@ -41,7 +42,7 @@ public function form(Form $form): Form
'md' => 2,
])
->schema(
collect(ApiKey::RESOURCES)->map(fn ($resource) => ToggleButtons::make("r_$resource")
collect(ApiKey::getPermissionList())->map(fn ($resource) => ToggleButtons::make('permissions_' . $resource)
->label(str($resource)->replace('_', ' ')->title())->inline()
->options([
0 => 'None',
Expand Down Expand Up @@ -87,4 +88,20 @@ public function form(Form $form): Form
->columnSpanFull(),
]);
}

protected function handleRecordCreation(array $data): Model
{
$permissions = [];

foreach (ApiKey::getPermissionList() as $permission) {
if (isset($data['permissions_' . $permission])) {
$permissions[$permission] = intval($data['permissions_' . $permission]);
unset($data['permissions_' . $permission]);
}
}

$data['permissions'] = $permissions;

return parent::handleRecordCreation($data);
}
}
2 changes: 2 additions & 0 deletions app/Filament/Resources/EggResource/Pages/ListEggs.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ protected function getHeaderActions(): array
} catch (Exception $exception) {
Notification::make()
->title('Import Failed')
->body($exception->getMessage())
->danger()
->send();

Expand All @@ -158,6 +159,7 @@ protected function getHeaderActions(): array
} catch (Exception $exception) {
Notification::make()
->title('Import Failed')
->body($exception->getMessage())
->danger()
->send();

Expand Down
3 changes: 1 addition & 2 deletions app/Filament/Resources/RoleResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use App\Enums\RolePermissionPrefixes;
use App\Filament\Resources\RoleResource\Pages;
use App\Models\Role;
use Filament\Facades\Filament;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Component;
Expand Down Expand Up @@ -71,7 +70,7 @@ public static function form(Form $form): Form
->disabled(fn (Get $get) => $get('name') === Role::ROOT_ADMIN),
TextInput::make('guard_name')
->label('Guard Name')
->default(Filament::getCurrentPanel()?->getAuthGuard() ?? '')
->default(Role::DEFAULT_GUARD_NAME)
->nullable()
->hidden(),
Fieldset::make('Permissions')
Expand Down
5 changes: 3 additions & 2 deletions app/Filament/Resources/ServerResource/Pages/EditServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Http\Controllers\Admin\ServersController;
use App\Models\Database;
use App\Models\Egg;
use App\Models\Mount;
use App\Models\Server;
use App\Models\ServerVariable;
use App\Services\Databases\DatabaseManagementService;
Expand Down Expand Up @@ -599,8 +600,8 @@ public function form(Form $form): Form
->schema([
CheckboxList::make('mounts')
->relationship('mounts')
->options(fn (Server $server) => $server->node->mounts->mapWithKeys(fn ($mount) => [$mount->id => $mount->name]))
->descriptions(fn (Server $server) => $server->node->mounts->mapWithKeys(fn ($mount) => [$mount->id => "$mount->source -> $mount->target"]))
->options(fn (Server $server) => $server->node->mounts->filter(fn (Mount $mount) => $mount->eggs->contains($server->egg))->mapWithKeys(fn (Mount $mount) => [$mount->id => $mount->name]))
->descriptions(fn (Server $server) => $server->node->mounts->mapWithKeys(fn (Mount $mount) => [$mount->id => "$mount->source -> $mount->target"]))
->label('Mounts')
->helperText(fn (Server $server) => $server->node->mounts->isNotEmpty() ? '' : 'No Mounts exist for this Node')
->columnSpanFull(),
Expand Down
Loading

0 comments on commit 6cb8bba

Please sign in to comment.