*/ private array $userConf; /** @var array */ private array $packageConf; private Settings $settings; private function __construct(string $username, array $userConf, array $packageConf, Settings $settings) { $this->username = $username; $this->prefix = $username . '_'; $this->userConf = $userConf; $this->packageConf = $packageConf; $this->settings = $settings; } public static function fromEnvironment(Settings $settings): self { $username = Http::server('USER'); if ($username === '') { $username = Http::server('USERNAME'); } if ($username === '' || !preg_match('/^[A-Za-z0-9._-]+$/', $username)) { throw new RuntimeException('Nie można ustalić użytkownika DirectAdmin.'); } $userConfPath = '/usr/local/directadmin/data/users/' . $username . '/user.conf'; $userConf = self::loadSimpleConf($userConfPath); $packageConf = self::loadPackageConf($username, $userConf); return new self($username, $userConf, $packageConf, $settings); } public function username(): string { return $this->username; } public function prefix(): string { return $this->prefix; } public function language(): string { $lang = strtolower(trim((string)($this->userConf['language'] ?? $this->userConf['lang'] ?? 'en'))); if ($lang === '' || strpos($lang, 'en') === 0) { return 'en'; } if (strpos($lang, 'pl') === 0) { return 'pl'; } return 'en'; } public function skin(): string { $skin = strtolower(trim((string)($this->userConf['skin'] ?? 'enhanced'))); if (strpos($skin, 'evolution') !== false) { return 'evolution'; } if (strpos($skin, 'enhanced') !== false) { return 'enhanced'; } return 'enhanced'; } public function hasPluginAccess(): bool { return $this->isPluginEnabledByCustomItem() && $this->isDatabaseQuotaEnabled() && $this->isPluginAllowedByPluginRules(); } public function pluginAccessErrorMessage(): string { if (!$this->isPluginEnabledByCustomItem()) { return 'Plugin PostgreSQL jest wyłączony dla tego konta lub pakietu.'; } if (!$this->isDatabaseQuotaEnabled()) { return 'Plugin PostgreSQL jest wyłączony: limit baz danych PostgreSQL ustawiono na 0 i nie zaznaczono opcji Bez Ograniczeń.'; } if (!$this->isPluginAllowedByPluginRules()) { return 'Plugin PostgreSQL jest zablokowany przez reguły plugins_allow/plugins_deny.'; } return 'Brak dostępu do pluginu PostgreSQL.'; } public function maxDatabases(): int { if ($this->isUnlimitedDatabasesByCustomItem()) { return 0; } $rawValue = $this->rawDatabasesLimitValue(); if ($rawValue === null || trim($rawValue) === '') { $default = $this->settings->defaultDatabasesLimit(); return $default < 0 ? 0 : $default; } $raw = trim($rawValue); $normalized = strtolower(trim($raw)); if ($normalized === 'unlimited') { return 0; } if (!preg_match('/^[0-9]+$/', trim($raw))) { $default = $this->settings->defaultDatabasesLimit(); return $default < 0 ? 0 : $default; } $limit = (int)trim($raw); return $limit < 0 ? 0 : $limit; } private function isPluginEnabledByCustomItem(): bool { $raw = $this->readScopedValue('postgresql_enabled'); if ($raw === null) { return false; } return Settings::toBool($raw, false); } private function isUnlimitedDatabasesByCustomItem(): bool { $unlimitedFlags = [ $this->readScopedValue('upostgresql'), $this->readScopedValue('upostgresql_max_databases'), $this->readScopedValue('postgresql_unlimited'), // backward compatibility ]; foreach ($unlimitedFlags as $raw) { if ($raw !== null && Settings::toBool($raw, false)) { return true; } } $rawLimit = $this->rawDatabasesLimitValue(); if ($rawLimit !== null && strtolower(trim($rawLimit)) === 'unlimited') { return true; } return false; } private function isDatabaseQuotaEnabled(): bool { if ($this->isUnlimitedDatabasesByCustomItem()) { return true; } return $this->maxDatabases() > 0; } private function rawDatabasesLimitValue(): ?string { $raw = $this->readScopedValue('postgresql_max_databases'); if ($raw === null || trim($raw) === '') { $raw = $this->readScopedValue('postgresql'); } return $raw; } private function isPluginAllowedByPluginRules(): bool { $pluginId = 'da-postgresql'; foreach ([$this->packageConf, $this->userConf] as $conf) { if (!empty($conf['plugins_allow'])) { $allow = self::parsePluginsList($conf['plugins_allow']); return in_array($pluginId, $allow, true); } } foreach ([$this->packageConf, $this->userConf] as $conf) { if (!empty($conf['plugins_deny'])) { $deny = self::parsePluginsList($conf['plugins_deny']); return !in_array($pluginId, $deny, true); } } return true; } private function readScopedValue(string $key): ?string { if (array_key_exists($key, $this->userConf)) { return $this->userConf[$key]; } if (array_key_exists($key, $this->packageConf)) { return $this->packageConf[$key]; } return null; } /** * @return array */ private static function loadSimpleConf(string $path): array { $data = []; if (!is_readable($path)) { return $data; } $lines = file($path, FILE_IGNORE_NEW_LINES); if ($lines === false) { return $data; } foreach ($lines as $line) { $line = trim($line); if ($line === '' || $line[0] === '#') { continue; } if (!preg_match('/^([A-Za-z0-9_]+)=(.*)$/', $line, $m)) { continue; } $data[strtolower($m[1])] = trim((string)$m[2]); } return $data; } /** * @param array $userConf * @return array */ private static function loadPackageConf(string $username, array $userConf): array { $package = trim((string)($userConf['package'] ?? $userConf['user_package'] ?? '')); if ($package === '' || !preg_match('/^[A-Za-z0-9._-]+$/', $package)) { return []; } $candidates = []; $owners = []; foreach (['creator', 'owner', 'reseller', 'username'] as $k) { if (!empty($userConf[$k]) && preg_match('/^[A-Za-z0-9._-]+$/', $userConf[$k])) { $owners[] = $userConf[$k]; } } $owners[] = $username; $owners[] = 'admin'; $owners = array_values(array_unique($owners)); foreach ($owners as $owner) { $candidates[] = '/usr/local/directadmin/data/users/' . $owner . '/packages/' . $package; $candidates[] = '/usr/local/directadmin/data/users/' . $owner . '/packages/' . $package . '.conf'; } foreach ($candidates as $path) { $conf = self::loadSimpleConf($path); if (!empty($conf)) { return $conf; } } return []; } /** * @return string[] */ private static function parsePluginsList(string $value): array { $value = trim($value); if ($value === '') { return []; } $items = []; foreach (explode(':', strtolower($value)) as $item) { $item = trim($item); if ($item !== '') { $items[] = $item; } } return array_values(array_unique($items)); } }