Sindbad~EG File Manager

Current Path : /opt/nginxhttpd_/vendor/extensions-cpanel/cpanel-development-lib/src/Client/
Upload File :
Current File : //opt/nginxhttpd_/vendor/extensions-cpanel/cpanel-development-lib/src/Client/NginxVarnish.php

<?php


namespace O2switch\CpanelLib\Client;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use O2switch\CpanelLib\DataEntity\ApiVhost;
use O2switch\CpanelLib\DataEntity\NginxVarnishConfig;
use O2switch\CpanelLib\Exception\InvalidApiArgument;
use O2switch\CpanelLib\Exception\InvalidApiResponse;
use O2switch\CpanelLib\Exception\UnsuccessfulApiResponse;
use O2switch\CpanelLib\Helper\Truncator;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;

class NginxVarnish
{
    // Routes
    const R_NGINX_DELETE = '/api/nginx/delete';
    const R_NGINX_VHOST = '/api/nginx/'; // + templateName
    const R_NGINX_USER_DELETE = '/api/nginx/delete-all/'; // + username

    const R_VARNISH_DELETE = '/api/varnish/delete';
    const R_VARNISH_VHOST = "/api/varnish/"; // + templateName
    const R_VARNISH_USER_DELETE = '/api/varnish/delete-all/'; // + username

    const R_LSLB_DELETE = '/api/lslb/delete';
    const R_LSLB_VHOST = '/api/lslb/vhost';
    const R_LSLB_USER_DELETE = '/api/varnish/delete-all/'; // + username

    const R_HEALTH = '/api/health/'; // + appName

    const APP_NGINX = 1;
    const APP_VARNISH = 2;
    const APP_LSCACHE = 3;

    /** @var NginxVarnishConfig */
    protected $config;
    /** @var Client */
    private $httpClient;
    /** @var LoggerInterface */
    private $logger;
    /** @var int */
    private $timeout = 120;

    public function __construct(Client $httpClient, LoggerInterface $logger){
        $this->httpClient = $httpClient;
        $this->logger = $logger;
    }

    /**
     * Remove all vhosts for a given user. For instance, to clean up on account deletion.
     * @param string $appType
     * @param string $cpUser
     * @throws InvalidApiArgument
     * @throws InvalidApiResponse
     * @throws UnsuccessfulApiResponse
     */
    public function removeVhostsByUser(string $appType, string $cpUser){
        // NOTE : UNTESTED.
        switch($appType){
            case 'nginx':
            case 'forwarder':
                $route = self::R_NGINX_USER_DELETE;
                break;
            case 'varnish':
            case 'xtremcache':
                $route = self::R_VARNISH_USER_DELETE;
                break;
            case 'litespeed':
            case 'lslb':
                $route = self::R_LSLB_USER_DELETE;
                break;
            default:
                throw new InvalidApiArgument(sprintf("The appType '%s' provided to '%s' is invalid.", $appType, __METHOD__));
        }

        $route .= $cpUser;

        $response = $this->rawCall($route, ['cpUser' => $cpUser]);

        if(!isset($response['status']) || !$response['status']){
            throw new UnsuccessfulApiResponse(sprintf("The call to '%s' returned json but the status flag indicate an error occurred.", $route));
        }
    }

    /**
     * Remove a Vhost
     * @param string $appType One of nginx, forwarder, varnish (or xtremcache), litespeed (or lslb)
     * @param string $domain
     * @param string $cpUser
     * @throws InvalidApiArgument
     * @throws InvalidApiResponse
     * @throws UnsuccessfulApiResponse
     */
    public function removeVhost(string $appType, string $domain, string $cpUser) : void {
        switch($appType){
            case 'nginx':
            case 'forwarder':
                $route = self::R_NGINX_DELETE;
                break;
            case 'varnish':
            case 'xtremcache':
                $route = self::R_VARNISH_DELETE;
                break;
            case 'litespeed':
            case 'lslb':
                $route = self::R_LSLB_DELETE;
                break;
            default:
                throw new InvalidApiArgument(sprintf("The appType '%s' provided to '%s' is invalid.", $appType, __METHOD__));
        }

        $response = $this->rawCall($route, [
            'mainDomain' => $domain,
            'cpUser' => $cpUser,
        ]);

        if(!isset($response['status']) || !$response['status']){
            throw new UnsuccessfulApiResponse(sprintf("The call to '%s' returned json but the status flag indicate an error occurred.", $route));
        }
    }

    /**
     * Configure a Vhost.
     * @param string $appType Possible values are nginx, forwarder, varnish, litespeed, lslb.
     * @param ApiVhost $data
     * @throws InvalidApiArgument
     * @throws InvalidApiResponse
     * @throws UnsuccessfulApiResponse
     */
    public function configureVhost(string $appType, ApiVhost $data) : ApiVhost {
        switch($appType){
            case 'nginx':
            case 'forwarder':
                $route = self::R_NGINX_VHOST . $data->getTemplateName();
                break;
            case 'varnish':
                $route = self::R_VARNISH_VHOST . $data->getTemplateName();
                break;
            case 'litespeed':
            case 'lslb':
                $route = self::R_LSLB_VHOST;
                break;
            default:
                throw new InvalidApiArgument(sprintf("The appType '%s' provided to '%s' is invalid.", $appType, __METHOD__));
        }

        $response = $this->rawCall($route, $data->toArray());

        if(!isset($response['status']) || !$response['status']){
            throw new UnsuccessfulApiResponse(sprintf("The call to '%s' returned json but the status flag indicate an error occurred.", $route));
        }

        return new ApiVhost($response['response']);
    }

    /**
     * Return true if the $appType API is online and seems OK.
     * @param string $appType
     * @return bool
     */
    public function health(string $appType) : bool{
        try {
            $response = $this->rawCall(self::R_HEALTH . $appType);
        } catch (\Exception $e){
            return false;
        }
        return isset($response['status']) && $response['status'] === true;
    }

    /**
     * Low level function to make a custom call to the API. Please dont use this directory and instead use the shortcuts
     * methods or higher level API Call functions.
     * @param string $route
     * @param array $params
     * @param array $query
     * @param string $method
     * @return array
     * @throws InvalidApiResponse
     * @throws \RuntimeException
     */
    public function rawCall(string $route, array $params = [], array $query = [], string $method = 'POST') : array {
        if(!$this->config instanceof NginxVarnishConfig){
            throw new \RuntimeException(sprintf("Before calling the '%s' method you must first set the '%s' property with the appropriate setter.", __METHOD__, 'config'));
        }

        try {
            $response = $this->httpClient->request(
                $method,
                $this->getEndpoint($route, $query),
                [
                    'connect_timeout' => $this->timeout,
                    'form_params' => $this->getParams($params),
                    'verify' => false,
                ]
            );
        } catch (\Exception | GuzzleException $e) {
            $context = [
                'exception' => $e->getMessage(),
                'params' => $this->getParams($params, true),
            ];

            $this->logger->warning(
                sprintf("NginxVarnish [KO] (exception) %s %s", $method, $this->getEndpoint($route, $query)),
                $context
            );
            throw new InvalidApiResponse(sprintf("NginxVarnish %s %s. Error received: %s", $method, $this->getEndpoint($route, $query), $e->getMessage()));
        }

        $response = $response->getBody()->getContents();

        $context = [
            'params' => $this->getParams($params, true),
            'response' => Truncator::truncate($response, 200),
        ];

        $response = json_decode($response, true);

        if($response === false || !is_array($response) || empty($response)){
            $this->logger->warning(
                sprintf("NginxVarnish [KO] (!json) %s %s", $method, $this->getEndpoint($route, $query)),
                $context
            );
            throw new InvalidApiResponse(sprintf("NginxVarnish %s %s. Error received: Not a Json Response.", $method, $this->getEndpoint($route, $query)));
        }

        $context['response'] = Truncator::truncate($response);

        $this->logger->info(
            sprintf("NginxVarnish [OK] %s %s", $method, $this->getEndpoint($route, $query)),
            $context
        );

        return $response;
    }

    /**
     * @param NginxVarnishConfig $config
     * @return NginxVarnish
     */
    public function setConfig(NginxVarnishConfig $config): NginxVarnish
    {
        $this->config = $config;
        return $this;
    }

    /**
     * @param int $timeout
     * @return NginxVarnish
     */
    public function setTimeout(int $timeout): NginxVarnish
    {
        $this->timeout = $timeout;
        return $this;
    }

    private function getEndpoint(string $route, array $query = []){
        $q = http_build_query($query);
        return
            'https://'
            . $this->config->getServerIp()
            . ':' . $this->config->getPort()
            . (strpos($route, '/') === 0 ? '' : '/') . $route
            . (!empty($q) ? ('?') .  $q : '')
        ;
    }

    // TODO : Initially, this was public ... find out why. Not sure it's needed anymore, maybe for the hook system ?
    private function getParams(array $params = [], bool $debug = false) : array
    {
        $params['token'] = $this->config->getToken();
        $params['hash'] = $this->createHash($params);
        if($debug){
            $params = Truncator::truncate($params);
        }
        return $params;
    }

    private function createHash(array $data=[]) : string
    {
        ksort($data);
        $json = json_encode($data);
        $hash = hash_hmac($this->config->getAlgo(), $json, $this->config->getSecretHash());

        return $hash;
    }

}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists