refactor and rename classes

This commit is contained in:
2022-05-09 13:55:04 +02:00
parent 8abce5ab85
commit d570145385
21 changed files with 61 additions and 95 deletions

View File

@@ -0,0 +1,70 @@
<?php
/**
* 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.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph;
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
use LogicException;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
class MachineHttpClient implements HttpClientInterface
{
use BearerAuthorizationTrait;
private HttpClientInterface $decoratedClient;
private MachineTokenStorage $machineTokenStorage;
/**
* @param HttpClientInterface $decoratedClient
*/
public function __construct(MachineTokenStorage $machineTokenStorage, ?HttpClientInterface $decoratedClient = null)
{
$this->decoratedClient = $decoratedClient ?? \Symfony\Component\HttpClient\HttpClient::create();
$this->machineTokenStorage = $machineTokenStorage;
}
public function request(string $method, string $url, array $options = []): ResponseInterface
{
$options['headers'] = array_merge(
$options['headers'] ?? [],
$this->getAuthorizationHeaders($this->machineTokenStorage->getToken())
);
$options['base_uri'] = 'https://graph.microsoft.com/v1.0/';
switch ($method) {
case 'GET':
case 'HEAD':
$options['headers']['Accept'] = 'application/json';
break;
case 'POST':
case 'PUT':
case 'PATCH':
$options['headers']['Content-Type'] = 'application/json';
break;
default:
throw new LogicException("Method not supported: {$method}");
}
return $this->decoratedClient->request($method, $url, $options);
}
public function stream($responses, ?float $timeout = null): ResponseStreamInterface
{
return $this->decoratedClient->stream($responses, $timeout);
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* 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.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph;
use Chill\MainBundle\Redis\ChillRedis;
use League\OAuth2\Client\Token\AccessTokenInterface;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Token\AccessToken;
class MachineTokenStorage
{
private const KEY = 'msgraph_access_token';
private ?AccessTokenInterface $accessToken = null;
private Azure $azure;
private ChillRedis $chillRedis;
public function __construct(Azure $azure, ChillRedis $chillRedis)
{
$this->azure = $azure;
$this->chillRedis = $chillRedis;
}
public function getToken(): AccessTokenInterface
{
if (null === $this->accessToken || $this->accessToken->hasExpired()) {
$this->accessToken = $this->azure->getAccessToken('client_credentials', [
'scope' => 'https://graph.microsoft.com/.default',
]);
}
return $this->accessToken;
}
public function storeToken(AccessToken $token): void
{
$this->chillRedis->set(self::KEY, serialize($token));
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* 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.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph;
use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraphRemoteCalendarConnector;
use Chill\MainBundle\Entity\User;
use Psr\Log\LoggerInterface;
/**
* Write metadata to user, which allow to find his default calendar.
*/
class MapCalendarToUser
{
public const METADATA_KEY = 'msgraph';
private LoggerInterface $logger;
private MSGraphRemoteCalendarConnector $remoteCalendarConnector;
public function __construct(MSGraphRemoteCalendarConnector $remoteCalendarConnector, LoggerInterface $logger)
{
$this->remoteCalendarConnector = $remoteCalendarConnector;
$this->logger = $logger;
}
public function getCalendarId(User $user): ?string
{
if (null === $mskey = ($user->getAttributes()[self::METADATA_KEY] ?? null)) {
return null;
}
return $msKey['defaultCalendarId'] ?? null;
}
public function writeMetadata(User $user): User
{
if (null === $userData = $this->remoteCalendarConnector->getUserByEmail($user->getEmailCanonical())) {
$this->logger->warning('[MapCalendarToUser] could find user on msgraph', ['userId' => $user->getId(), 'email' => $user->getEmailCanonical()]);
return $this->writeNullData($user);
}
if (null === $defaultCalendar = $this->remoteCalendarConnector->getDefaultUserCalendar($userData['id'])) {
$this->logger->warning('[MapCalendarToUser] could find default calendar', ['userId' => $user->getId(), 'email' => $user->getEmailCanonical()]);
return $this->writeNullData($user);
}
return $user->setAttributes([self::METADATA_KEY => [
'id' => $userData['id'],
'userPrincipalName' => $userData['userPrincipalName'],
'defaultCalendarId' => $defaultCalendar['id'],
]]);
}
private function writeNullData(User $user): User
{
return $user->unsetAttribute(self::METADATA_KEY);
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* 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.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph;
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
use LogicException;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
class OnBehalfOfUserHttpClient
{
use BearerAuthorizationTrait;
private HttpClientInterface $decoratedClient;
private OnBehalfOfUserTokenStorage $tokenStorage;
/**
* @param HttpClientInterface $decoratedClient
*/
public function __construct(OnBehalfOfUserTokenStorage $tokenStorage, ?HttpClientInterface $decoratedClient = null)
{
$this->decoratedClient = $decoratedClient ?? \Symfony\Component\HttpClient\HttpClient::create();
$this->tokenStorage = $tokenStorage;
}
public function request(string $method, string $url, array $options = []): ResponseInterface
{
$options['headers'] = array_merge(
$options['headers'] ?? [],
$this->getAuthorizationHeaders($this->tokenStorage->getToken())
);
$options['base_uri'] = 'https://graph.microsoft.com/v1.0/';
switch ($method) {
case 'GET':
case 'HEAD':
$options['headers']['Accept'] = 'application/json';
break;
case 'POST':
case 'PUT':
case 'PATCH':
$options['headers']['Content-Type'] = 'application/json';
break;
default:
throw new LogicException("Method not supported: {$method}");
}
return $this->decoratedClient->request($method, $url, $options);
}
public function stream($responses, ?float $timeout = null): ResponseStreamInterface
{
return $this->decoratedClient->stream($responses, $timeout);
}
}

View File

@@ -0,0 +1,65 @@
<?php
/**
* 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.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph;
use LogicException;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use TheNetworg\OAuth2\Client\Provider\Azure;
use TheNetworg\OAuth2\Client\Token\AccessToken;
/**
* Store token obtained on behalf of a User.
*/
class OnBehalfOfUserTokenStorage
{
public const MS_GRAPH_ACCESS_TOKEN = 'msgraph_access_token';
private Azure $azure;
private SessionInterface $session;
public function __construct(Azure $azure, SessionInterface $session)
{
$this->azure = $azure;
$this->session = $session;
}
public function getToken(): AccessToken
{
/** @var ?AccessToken $token */
$token = $this->session->get(self::MS_GRAPH_ACCESS_TOKEN, null);
if (null === $token) {
throw new LogicException('unexisting token');
}
if ($token->hasExpired()) {
$token = $this->azure->getAccessToken('refresh_token', [
'refresh_token' => $token->getRefreshToken(),
]);
$this->setToken($token);
}
return $token;
}
public function hasToken(): bool
{
return $this->session->has(self::MS_GRAPH_ACCESS_TOKEN);
}
public function setToken(AccessToken $token): void
{
$this->session->set(self::MS_GRAPH_ACCESS_TOKEN, $token);
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* 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.
*/
declare(strict_types=1);
namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph;
use Chill\CalendarBundle\RemoteCalendar\Model\RemoteEvent;
use DateTimeImmutable;
use DateTimeZone;
/**
* Convert Chill Calendar event to Remote MS Graph event, and MS Graph
* event to RemoteEvent.
*/
class RemoteEventConverter
{
private const REMOTE_DATE_FORMAT = 'Y-m-d\TH:i:s.u0';
private DateTimeZone $defaultDateTimeZone;
private DateTimeZone $remoteDateTimeZone;
public function __construct()
{
$this->defaultDateTimeZone = (new DateTimeImmutable())->getTimezone();
$this->remoteDateTimeZone = new DateTimeZone('UTC');
}
public function convertToRemote(array $event): RemoteEvent
{
$startDate =
DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['start']['dateTime'])
->setTimezone($this->defaultDateTimeZone);
$endDate =
DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['end']['dateTime'], $this->remoteDateTimeZone)
->setTimezone($this->defaultDateTimeZone);
return new RemoteEvent(
$event['id'],
$event['subject'],
'',
$startDate,
$endDate
);
}
}