mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2026-04-05 12:33:42 +00:00
139 lines
4.8 KiB
PHP
139 lines
4.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* Chill is a software for social workers
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the LICENSE file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Chill\ZimbraBundle\Calendar\Connector\ZimbraConnector;
|
|
|
|
use Symfony\Component\Clock\ClockInterface;
|
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
|
use Symfony\Component\HttpClient\Psr18Client;
|
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|
use Zimbra\Admin\AdminApi;
|
|
use Zimbra\Common\Enum\AccountBy;
|
|
use Zimbra\Common\Soap\ClientFactory;
|
|
use Zimbra\Common\Struct\AccountSelector;
|
|
use Zimbra\Common\Struct\Header\AccountInfo;
|
|
use Zimbra\Mail\MailApi;
|
|
|
|
final class SoapClientBuilder
|
|
{
|
|
private readonly string $username;
|
|
|
|
private readonly string $password;
|
|
|
|
private readonly string $url;
|
|
|
|
private readonly string $adminUrl;
|
|
|
|
private readonly bool $verifyHost;
|
|
|
|
private readonly bool $verifyPeer;
|
|
|
|
private readonly bool $adminVerifyHost;
|
|
|
|
private readonly bool $adminVerifyPeer;
|
|
|
|
/**
|
|
* Keep the cache of the tokens.
|
|
*
|
|
* @var array<string, array{token: string, expirationTime: \DateTimeImmutable}>
|
|
*/
|
|
private array $tokenCache = [];
|
|
|
|
public function __construct(
|
|
private readonly ParameterBagInterface $parameterBag,
|
|
private readonly HttpClientInterface $client,
|
|
private readonly ClockInterface $clock,
|
|
) {
|
|
$dsn = $this->parameterBag->get('chill_calendar.remote_calendar_dsn');
|
|
$url = parse_url($dsn);
|
|
|
|
$this->username = urldecode($url['user']);
|
|
$this->password = urldecode($url['pass']);
|
|
if ('zimbra+http' === $url['scheme']) {
|
|
$scheme = 'http';
|
|
$port = $url['port'] ?? 80;
|
|
} elseif ('zimbra+https' === $url['scheme']) {
|
|
$scheme = 'https';
|
|
$port = $url['port'] ?? 443;
|
|
} else {
|
|
throw new \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException('Unsupported remote calendar scheme: '.$url['scheme']);
|
|
}
|
|
|
|
// get attributes for adminUrl
|
|
$query = [];
|
|
parse_str($url['query'] ?? '', $query);
|
|
$adminPort = $query['adminPort'] ?? '7071';
|
|
$adminHost = $query['adminHost'] ?? $url['host'];
|
|
$adminScheme = $query['adminScheme'] ?? $scheme;
|
|
|
|
$this->verifyPeer = (bool) ($query['verifyPeer'] ?? true);
|
|
$this->verifyHost = (bool) ($query['verifyHost'] ?? true);
|
|
$this->adminVerifyHost = (bool) ($query['adminVerifyHost'] ?? $this->verifyPeer);
|
|
$this->adminVerifyPeer = (bool) ($query['adminVerifyPeer'] ?? $this->verifyHost);
|
|
|
|
$this->url = $scheme.'://'.$url['host'].':'.$port;
|
|
$this->adminUrl = $adminScheme.'://'.$adminHost.':'.$adminPort;
|
|
}
|
|
|
|
private function buildApi(): MailApi
|
|
{
|
|
$baseClient = $this->client->withOptions([
|
|
'base_uri' => $location = $this->url.'/service/soap',
|
|
'verify_host' => $this->verifyHost,
|
|
'verify_peer' => $this->verifyPeer,
|
|
]);
|
|
$psr18Client = new Psr18Client($baseClient);
|
|
$api = new MailApi();
|
|
$client = ClientFactory::create($location, $psr18Client);
|
|
$api->setClient($client);
|
|
|
|
return $api;
|
|
}
|
|
|
|
private function buildAdminApi(): AdminApi
|
|
{
|
|
$baseClient = $this->client->withOptions([
|
|
'base_uri' => $location = $this->adminUrl.'/service/admin/soap',
|
|
'verify_host' => $this->adminVerifyHost,
|
|
'verify_peer' => $this->adminVerifyPeer,
|
|
]);
|
|
$psr18Client = new Psr18Client($baseClient);
|
|
$api = new AdminApi();
|
|
$client = ClientFactory::create($location, $psr18Client);
|
|
$api->setClient($client);
|
|
|
|
return $api;
|
|
}
|
|
|
|
public function getApiForAccount(string $accountName): MailApi
|
|
{
|
|
['token' => $token, 'expirationTime' => $expirationTime] = $this->tokenCache[$accountName]
|
|
?? ['token' => null, 'expirationTime' => null];
|
|
|
|
if (null === $token || null === $expirationTime || $expirationTime <= $this->clock->now()) {
|
|
$adminApi = $this->buildAdminApi();
|
|
$adminApi->auth($this->username, $this->password);
|
|
|
|
$delegateResponse = $adminApi->delegateAuth(new AccountSelector(AccountBy::NAME, $accountName));
|
|
$token = $delegateResponse->getAuthToken();
|
|
$expiration = $delegateResponse->getLifetime();
|
|
$expirationTime = $this->clock->now()->add(new \DateInterval('PT'.$expiration.'S'));
|
|
$this->tokenCache[$accountName] = ['token' => $token, 'expirationTime' => $expirationTime];
|
|
}
|
|
|
|
$apiBy = $this->buildApi();
|
|
$apiBy->setAuthToken($token);
|
|
$apiBy->setTargetAccount(new AccountInfo(AccountBy::NAME, $accountName));
|
|
|
|
return $apiBy;
|
|
}
|
|
}
|