Import postgresql plugin
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
final class DirectAdminUser
|
||||
{
|
||||
private string $username;
|
||||
private string $prefix;
|
||||
|
||||
/** @var array<string,string> */
|
||||
private array $userConf;
|
||||
|
||||
/** @var array<string,string> */
|
||||
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<string,string>
|
||||
*/
|
||||
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<string,string> $userConf
|
||||
* @return array<string,string>
|
||||
*/
|
||||
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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user