user()->can('create', Customer::class); } protected function prepareForValidation(): void { $behindTraefik = $this->resolveBehindTraefik(); $merge = ['behind_traefik' => $behindTraefik]; if (! $behindTraefik) { $merge['subdomain'] = null; } if ($this->has('devices') && is_array($this->input('devices'))) { $devices = collect($this->input('devices')) ->filter(fn ($device) => is_array($device) && ! empty($device['type'])) ->values() ->all(); $merge['devices'] = $devices === [] ? null : $devices; } $this->merge($merge); } public function wantsTraefik(): bool { return $this->boolean('behind_traefik'); } private function resolveBehindTraefik(): bool { if (! $this->has('behind_traefik')) { return false; } $value = $this->input('behind_traefik'); if (is_array($value)) { return in_array('1', $value, true) || in_array(1, $value, true) || in_array(true, $value, true); } return filter_var($value, FILTER_VALIDATE_BOOLEAN); } public function rules(): array { return [ 'name' => ['required', 'string', 'max:100', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/'], 'subdomain' => [ Rule::excludeIf(fn () => ! $this->wantsTraefik()), Rule::requiredIf(fn () => $this->wantsTraefik()), 'nullable', 'string', 'max:63', 'regex:/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/', ], 'behind_traefik' => ['boolean'], 'user_id' => [ 'nullable', 'exists:users,id', ], 'ip_pool_id' => ['nullable', 'exists:ip_pools,id'], 'cpu' => ['required', 'integer', 'min:1', 'max:32'], 'ram' => ['required', 'integer', 'min:512', 'max:131072'], 'disk' => ['required', 'integer', 'min:10', 'max:2048'], 'devices' => ['nullable', 'array'], 'devices.*.type' => ['required_with:devices', Rule::in(array_keys(\App\Models\VmDevice::typesFor($this->user())))], 'devices.*.slot' => ['nullable', 'string', 'max:32'], 'devices.*.config' => ['nullable', 'array'], 'install_iso' => ['nullable', 'string', 'max:255'], ]; } public function domain(): ?string { if (! $this->wantsTraefik() || ! $this->filled('subdomain')) { return null; } return strtolower($this->input('subdomain')).'.'.config('hosting.plesk.base_domain'); } public function ownerId(): int { if ($this->user()->isAdmin() && $this->filled('user_id')) { return (int) $this->input('user_id'); } return $this->user()->id; } /** * @return array */ public function attributes(): array { return [ 'name' => 'VM-Name', 'subdomain' => 'Subdomain', 'user_id' => 'Kunde', 'cpu' => 'vCPUs', 'ram' => 'RAM', 'disk' => 'Festplatte', 'install_iso' => 'Installations-ISO', 'devices.*.type' => 'Gerätetyp', ]; } /** * @return array */ public function messages(): array { return [ 'required' => ':attribute ist erforderlich.', 'regex' => ':attribute hat ein ungültiges Format.', 'exists' => 'Der gewählte :attribute ist ungültig.', ]; } }