Sunucu Modülü Araçları

1.8k görüntülenme Markdown

Araçlar, müşterinin hizmetin içinde gördüğü sayfalardır: dosya yöneticisi, veritabanları, DNS, zamanlanmış görevler. Etrafındaki her şeyi taban sınıf üstlenir; siz iki metot ve bir şablon verirsiniz.

Genel Bakış

ServerModule, gruplanmış ve sıralanmış bir araç tanımı kataloğu taşır; hepsi kapalı gelir. Birini açmak, onu desteklenir ilan etmek ve iki soruyu yanıtlamak demektir: sayfa neyi gösteriyor ve buton ne yapıyor.

Tarayıcı ile o iki yanıt arasındaki her şey taban sınıfa aittir.

get_tool_data() Okuma yolu: tanımı doğrular, tool_data() metodunuzu çağırır, satırları normalleştirir, filtre kancasını çalıştırır, istek başına önbelleğe alır.
handle_tool_action() Yazma yolu: her alanı temizler ve doğrular, yeteneği denetler, tool_action() metodunuzu çağırır, sırları maskeleyerek hizmet geçmişine yazar.
create_tool_table() Listeleme tablosunu bildirilmiş kolonlardan ve satır geri çağrısından kurar.
has_client_management() Müşterinin Yönetim sekmesi alıp almayacağı: etkin bir araç ya da müşteri alanında kalan bir kart varken true.
yetenek Aracın sunduğu tek fiil: izin kapısı ve arayüz işareti.

Ön Koşullar

  • Çalışan bir sunucu modülü (Sunucu Modülü Yazma). Araçlar ancak create() hesap kimliğini sakladıktan sonra açılır.
  • Ana varlığın canlı sağlayıcıda hem oluşturmayı hem silmeyi desteklediğini doğrulayın.
  • Sağlayıcının ücretlendirdiği bir şey oluşturuluyorsa önce kotayı planlayın.

Yapı

Altı katman, üçü sizin.

KatmanNeredeNe tutar
Katalogcoremio/classes/ServerModule.phpTanım, filtreler, kurallar, kolonlar, satır geri çağrıları
Aracı açmaconfig.php ya da configure_features()Desteklenen araçlar ve yetenekleri
OkumaModülünüz, tool_data()Araç başına bir dal, sonra bir fetch metodu
YazmaModülünüz, tool_action()Araç başına bir dal, sonra bir aksiyon yönlendiricisi
Arayüztemplates/system/module/service/hosting/toolsAraç adı başına paylaşılan şablon
Metincoremio/locale/en/cm/system/module.phpPaylaşılan etiketler ve mesajlar

Adım Adım

Aracı Açın

Adı yapılandırmada bildirmek aracı varsayılan yetenekleriyle açar.

config.php
// config.php: bildirimsel yarı.
return [
    // ... modül yapılandırmasının geri kalanı
    'supported' => [
        'tools' => ['file-manager', 'ftp-accounts', 'databases', 'cron-jobs'],

        // Araç başına seçenek ezmeleri; set_tool() metodunun yazacağı anahtarların aynısı.
        'tool_options' => [
            'file-manager' => ['allow_upload_overwrite' => true, 'allow_chmod_recursive' => true],
        ],
    ],
];
configure_features()
public function configure_features(): void
{
    // Yapılandırma listesiyle aynı etki; karar canlı duruma bağlı olduğunda işe yarar.
    $this->support_tools(['cron-jobs' => ['list', 'create', 'delete']]);

    // Sağlayıcıda hesap başına kota ve zamanlanmış görevlerde e-posta alanı yok,
    // bu yüzden karşılayamadığımız yetenekleri ve besledikleri kolonu kaldırın.
    $this->remove_tool_capability('ftp-accounts', ['quota']);
    $this->remove_tool_column('ftp-accounts', ['quota']);

    $this->set_tool_order('databases', 5);
}

Okuma Yolu

tool_data() tek bir dağıtıcıdır; araca özgü işi özel fetch metotlarında tutun.

  1. ['items' => [...]] döndürün; her satır kolon adıyla anahtarlanır, yanına şablonun okuduğu ek anahtarları koyun.

Yazma Yolu

tool_action() aynı biçimdedir; aksiyon fiiline göre eşleştiren bir yönlendiriciye dağıtır.

  1. Sağlayıcı reddederse fırlatın; mesaj müşteriye kırmızı uyarı olarak ulaşır.
  2. [] döndürün ya da arayüz bir değer bekliyorsa bir yük döndürün.

Kolonlar ve Metin

Kolon başlıkları, etiketler ve başarı mesajları paylaşılan dil dosyasından gelir. Şablon paylaşılır, yani bir alan adı sözleşmedir. Sağlayıcıya özgü dizeler kendi modül dil dosyanızda durur.

Etkinlik günlüğü her işlemi activity_action_label() ile adlandırır: taban sınıf yaygın sanal sunucu işlemleri için system/module/al-action/{kod} anahtarına bakar, bulamazsa kodu okunur biçimde gösterir. Kodun kendisi süzgeç değeri olarak kalır. Sağlayıcınız kendi işlem adlarını kullanıyorsa metodu ezip etiketleri modül dil dosyanızdan döndürün.

Referans

Araç Tanımı

katalog kaydı
$this->tools['ftp-accounts'] = [
    'name'         => 'FTP Accounts',
    // Grup adları config.php'de bildirilen modül tipine bağlıdır:
    //   hosting: files, databases, domains, email, software, security
    //   server:  power, system, network, storage
    'group'        => 'files',
    'order'        => 20,               // grup içindeki konum
    'icon'         => 'bi bi-hdd-network',   // bir Bootstrap simgesi ya da uzak bir görsel için 'img:<url>'
    'page'         => 'ftp-accounts',   // tools/ altındaki şablon dosyasının adı
    'type'         => 'page-loader',    // 'page-loader' bir sayfa basar, 'action' tek bir düğmedir
    'supported'    => false,            // modülünüz bunu açar
    'capabilities' => ['list', 'create', 'edit', 'delete', 'quota', 'directory'],
];
supported false gelir. Desteklenmeyen bir araca gelen istek, kodunuz çalışmadan reddedilir.
capabilities Hem izin listesi hem arayüz işareti; buton görünmeden önce denetlenir.
type 'page-loader', page ile adlandırılan şablonu yükler; 'action' araç ızgarasındaki tek butondur, isteğe bağlı 'confirm' => true ile.
options Şablonun okuduğu araç başına anahtarlar. Yapılandırmadan ya da çalışma anında ayarlanır.
yetenek takma adları get_content ve save_content edit sayılır; update_email ise email sayılır.

Modül İmzaları

tam imzalar
// Taban sınıfın çağırdığı iki metot. $params temizlenmiş sorgu parametrelerini,
// $data ise temizlenmiş POST gövdesini taşır.
public function tool_data(string $tool, string $action = 'index', array $params = []): array;
public function tool_action(string $tool, string $action, array $data = []): array;

// İsteğe bağlı: kataloğu bu modüle göre düzenler. Sunucu kaydı bağlandığında
// (yapıcıdan, set_server üzerinden) ve bir kez de set_service içinden koşar.
public function configure_features(): void;

// İsteğe bağlı: yalnız parola sıfırlama aracının parolayı panele ürettirmesi gerektiğinde.
protected function panel_generated_password(): string;

Taban Sınıf Yardımcıları

katalog düzenleyicileri
public function support_tools(array $tools): static;
public function add_tool(string $key, array $config): static;
public function set_tool(string $key, array $config): static;
public function remove_tool(string $key): static;
public function set_tool_order(string $key, int $order): static;

public function add_tool_capability(string $key, array|string $capabilities): static;
public function remove_tool_capability(string $key, array|string $capabilities): static;

public function add_tool_column(string $tool, string $column, array $config): static;
public function remove_tool_column(string $tool, array|string $columns): static;

public function add_tool_group(string $key, array $config): static;
public function set_tool_group_order(string $key, int $order): static;

public function get_tool(string $key): ?array;
public function get_tools(): array;
public function get_effective_tools(): array;
public function get_disabled_features(): array;
public function has_client_management(): bool;
support_tools() argümanını iki türlü okur

Düz bir liste elemanı aracı varsayılan yetenekleriyle açar. Bir diziye işaret eden anahtar ise o listeyi geçtiğinizle değiştirir.

Doğrulama Katmanları

Üçü de taban sınıfta bildirilir ve aksiyon metodunuzdan önce çalışır.

imza ve biçim
// 1. Temizleme. Listede olmayan her alan 'hclear' filtresine düşer.
protected function get_tool_action_data_filters(): array;
// Bu araç için ürünle gelen kural, birebir. FTP kullanıcı adının e-posta gibi
// filtrelendiğine dikkat edin: paneller user@domain biçimini kabul eder.
// 'ftp-accounts' => ['username' => 'email', 'password' => null,
//                    'directory' => 'path', 'quota' => 'numeric']
// Filtreler: hclear, numeric, route, identifier, domain, subdomain, hostname,
//            email, email_list, ip, url, path, json_filenames, null (dokunmadan geçer)

// 2. Aksiyon başına zorunlu alanlar. Kırpma sonrası boş dize fırlatır.
protected function get_tool_action_rules(): array;
// 'ftp-accounts' => ['create' => ['username', 'password'],
//                    'edit' => ['username'], 'delete' => ['username']]

// 3. Biçim denetimleri; zorunluluk denetiminden sonra koşar (işlemin zorunlu alanı
//    olmasa da), boş değerlerde atlanır.
protected function get_tool_action_field_validations(): array;
// 'mx-entry' => ['create' => ['domain' => ['domain'], 'priority' => ['numeric']]]
// Kurallar: url, email, email_list, email_local, ip, ipv4, ipv6, ip_or_wildcard,
//           domain, dns_label, dns_name, numeric, cron_field, enum:a,b,c, min:N, max:N
// Tanınmayan kural adı atlanır ve hata kütüğüne uyarı olarak yazılır.
Parola alanı null filtresiyle bildirilmelidir

Diğer her filtre parolayı güçlü kılan karakterleri siler: hesap, müşterinin yazmadığı bir sırla açılır.

tool_action() Dönüşleri

[] Sıradan başarı: taban sınıf önce action-success-{tool}-{action}, sonra action-success-{action}, sonra üretilmiş bir etiket arar.
['status' => 'successful', 'message' => '...'] Kendi metninizle başarı, olduğu gibi döner.
['stream' => ...] Dosya indirme; taban sınıf yanıtı akıtır ve istek orada biter.
['redirect' => ...] Ayrılmış: aynı sekmede anında tam sayfa yönlendirme.
fırlatma Başarısızlık. Mesaj müşteriye ulaşır, bu yüzden çevrilmiş yazın.

Şablon Değişkenleri

şablon değişkenleri
/** @var ServerModule $module      canlı örnek, yani $module->service erişilebilir */
/** @var string       $tool        slug */
/** @var array        $tool_config tanım; yetenekler ve seçenekler dahil */
/** @var string       $tool_label  çevrilmiş araç adı */
/** @var string       $action      sayfa bir alt aksiyonla açılmadıysa 'index' */
/** @var array        $data        fetch metodunuzun döndürdüğünün aynısı */
/** @var mixed        $table       hazırlanmış listeleme tablosu, aracın kolonu yoksa null */
/** @var array        $tables      alt tablolar, kendi slug'larıyla anahtarlanır */
/** @var bool         $admin_view  admin panelde true, müşteri panelinde false */
/** @var string|null  $error       fetch başarısız olduğunda dolar */
Tarayıcı fonksiyonuAmacı
request_tool_action(tool, action, data, options)Tek bir aksiyonu gönderir, buton göstergesi ve bildirimle
reload_module_content(tool)Araç sayfasını değişiklikten sonra yeniden yükler
open_modal(id, {title, body, footer})Bir pencere kurar ve açar
confirmDeleteModal({message, description, buttonText, onConfirm})Standart silme onayı
watchRequired(selector)Zorunlu alanlar dolunca gönderi etkinleştirir
passwordInput(id, placeholder, options)Üret, göster ve kopyala butonlu parola alanı

Örnek

Baştan sona tek bir araç: okuma, yönlendirici ve taban sınıf.

modül tarafı
public function tool_data(string $tool, string $action = 'index', array $params = []): array
{
    $username = $this->options['config']['user'] ?? '';
    $domain   = $this->options['domain'] ?? '';

    return match ($tool) {
        'ftp-accounts' => $this->fetch_ftp_accounts($username, $domain),
        'databases'    => $this->fetch_databases($username),
        default        => [],
    };
}

private function fetch_ftp_accounts(string $username, string $domain): array
{
    $response = $this->api->call('ftp/list', ['username' => $username]);

    $items = [];
    foreach ($response['data'] ?? [] as $row)
        $items[] = [
            'username'  => $row['user'] ?? '',
            'directory' => $row['dir'] ?? '/',
            'quota'     => (int) ($row['quota'] ?? 0),
        ];

    // 'items' tabloyu besler; geri kalan her şeyi şablon okur.
    return ['items' => $items, 'domain' => $domain];
}

public function tool_action(string $tool, string $action, array $data = []): array
{
    $username = $this->options['config']['user'] ?? '';

    return match ($tool) {
        'ftp-accounts' => $this->action_ftp_accounts($action, $data, $username),
        default        => throw new Exception($this->lang['err-tool-unknown']),
    };
}

private function action_ftp_accounts(string $action, array $data, string $username): array
{
    return match ($action) {
        'create' => $this->ftp_create($data, $username),
        'delete' => $this->ftp_delete($data, $username),
        default  => throw new Exception($this->lang['err-action-unknown']),
    };
}

private function ftp_create(array $data, string $username): array
{
    $this->api->call('ftp/create', [
        'account'   => $username,

        // Bildirilen filtrelerle zaten temizlendi ve varlığı zaten denetlendi.
        'user'      => $data['username'] ?? '',
        'password'  => $data['password'] ?? '',
        'directory' => $data['directory'] ?? '/',
    ], 'POST');

    // Boş dizi: çevrilmiş başarı mesajını taban sınıf yazar.
    return [];
}
taban sınıf
// ServerModule::handle_tool_action, önemli olan sıraya indirgenmiş hali.
$tool   = Filter::init("REQUEST/tool", "route");
$action = Filter::init("REQUEST/action", "route") ?: 'index';
$data   = !empty($_POST) ? $_POST : $_GET;
unset($data['operation'], $data['method'], $data['tool'], $data['action']);

$data = $this->sanitize_tool_action_data($tool, $data);

$tool_config = $this->get_tool($tool);
if (!$tool_config) throw new \Exception('Tool not found');
if (empty($tool_config['supported'])) throw new \Exception('Tool not supported');

$this->check_tool_capability($tool_config, $action);
$this->validate_tool_action($tool, $action, $data);

$result = $this->tool_action($tool, $action, $data);

// Aksiyon hizmet geçmişine ulaşmadan önce sırlar maskelenir.
foreach ($data as $k => $v)
    if (is_string($v) && $v !== '' && preg_match('/pass(word)?|secret|token/i', (string) $k))
        $data[$k] = '***';

if (empty($result)) return $this->tool_action_success_response($tool, $action);

return $result;
tarayıcı tarafı
var TOOL = 'ftp-accounts';

window.ftpCreateSubmit = function (btn) {
    request_tool_action(TOOL, 'create', {
        username:  document.getElementById('ftpUser').value,
        password:  document.getElementById('ftpPass').value,
        directory: document.getElementById('ftpDir').value,
    }, {
        button: btn,
        buttonLoader: creating_loader,
        successToast: true,
        afterDone: function () {
            close_modal(document.querySelector('.modal.show'));
            reload_module_content(TOOL);
        },
    });
};

Tuzaklar

Uygulanmamış bir yetenek, hata fırlatan bir butondur

Arayüz her varsayılan yetenek için bir denetim gösterir. Yönlendiricinizin karşılamadığını kaldırın, yoksa müşteri Düzenle'ye tıklar ve "Action not available" alır.

Ücretli kaynak kota kapısı ister

Açık bir oluştur butonu merakı sizin faturanıza dönüştürür. Kaynağı bir eklentiye bağlayın ve hak tükendiğinde aksiyonu reddedin.

Bir form alanına asla action, operation, method ya da tool adını vermeyin

Tarayıcı yardımcısı gövdeyi araç aksiyonuyla kurar, sonra verinizi üzerine birleştirir. action adlı bir alan fiili ezer ve dağıtıcı hata fırlatır. Ön ek verin (task_action) ve adı şablonda, zorunlu alan kurallarında ve aksiyon metodunuzda değiştirin.

redirect anında sayfadan çıkarır

Yardımcı o anahtarı aynı sekmede, geri çağrınız bitmeden işler. Bir pencerede ya da yeni sekmede açmak istediğiniz URL için console_url gibi nötr bir ad kullanın.

Yalnız listeleyen araç yayınlanmaz

Sağlayıcı aracın ana varlığını hem oluşturamıyor hem silemiyorsa araç yayınlanmaz. Yapılandırmadan çıkarın ve ölü metotları silin.

Aracı olmayan modülde Yönetim sekmesi açılmaz

Müşterinin Yönetim sekmesi yalnız has_client_management() true iken açılır: en az bir etkin araç ya da müşteri alanında kalan bir kart. Göstergeler, hesap bilgisi, kaynaklar ve bağlantılar Genel Bakış sekmesinde durduğu için sayılmaz. Çekirdek bu soruyu operatörün kısıtlamaları uygulanmış hâlde sorar; Tercihler'de her aracı gizlemek de sekmeyi kaldırır. Yalnız tek tıkla giriş sunan bir panelin başlatıcısı Hızlı İşlemler'de kalır.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.