198 lines
6.5 KiB
PHP

<?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);
/*
* 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\CalendarBundle\RemoteCalendar\Connector\MSGraph;
use Chill\MainBundle\Entity\User;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
/**
* Write metadata to user, which allow to find his default calendar.
*/
class MapCalendarToUser
{
final public const EXPIRATION_SUBSCRIPTION_EVENT = 'subscription_events_expiration';
final public const ID_SUBSCRIPTION_EVENT = 'subscription_events_id';
final public const METADATA_KEY = 'msgraph';
final public const SECRET_SUBSCRIPTION_EVENT = 'subscription_events_secret';
public function __construct(private readonly HttpClientInterface $machineHttpClient, private readonly LoggerInterface $logger) {}
public function getActiveSubscriptionId(User $user): string
{
if (!\array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
throw new \LogicException('do not contains msgraph metadata');
}
if (!\array_key_exists(self::ID_SUBSCRIPTION_EVENT, $user->getAttributes()[self::METADATA_KEY])) {
throw new \LogicException('do not contains metadata for subscription id');
}
return $user->getAttributes()[self::METADATA_KEY][self::ID_SUBSCRIPTION_EVENT];
}
public function getCalendarId(User $user): ?string
{
if (null === $msKey = ($user->getAttributes()[self::METADATA_KEY] ?? null)) {
return null;
}
return $msKey['defaultCalendarId'] ?? null;
}
public function getDefaultUserCalendar(string $idOrUserPrincipalName): ?array
{
try {
$value = $this->machineHttpClient->request('GET', "users/{$idOrUserPrincipalName}/calendars", [
'query' => ['$filter' => 'isDefaultCalendar eq true'],
])->toArray()['value'];
} catch (ClientExceptionInterface $e) {
$this->logger->error('[MapCalendarToUser] Error while listing calendars for a user', [
'http_status_code' => $e->getResponse()->getStatusCode(),
'id_user' => $idOrUserPrincipalName,
]);
return null;
}
return $value[0] ?? null;
}
public function getSubscriptionSecret(User $user): string
{
if (!\array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
throw new \LogicException('do not contains msgraph metadata');
}
if (!\array_key_exists(self::SECRET_SUBSCRIPTION_EVENT, $user->getAttributes()[self::METADATA_KEY])) {
throw new \LogicException('do not contains secret in msgraph');
}
return $user->getAttributes()[self::METADATA_KEY][self::SECRET_SUBSCRIPTION_EVENT];
}
public function getUserByEmail(string $email): ?array
{
$value = $this->machineHttpClient->request('GET', 'users', [
'query' => ['$filter' => "mail eq '{$email}'"],
])->toArray()['value'];
return $value[0] ?? null;
}
public function getUserId(User $user): ?string
{
if (null === $msKey = ($user->getAttributes()[self::METADATA_KEY] ?? null)) {
return null;
}
return $msKey['id'] ?? null;
}
public function hasActiveSubscription(User $user): bool
{
if (!\array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
return false;
}
if (!\array_key_exists(self::EXPIRATION_SUBSCRIPTION_EVENT, $user->getAttributes()[self::METADATA_KEY])) {
return false;
}
return $user->getAttributes()[self::METADATA_KEY][self::EXPIRATION_SUBSCRIPTION_EVENT]
>= (new \DateTimeImmutable('now'))->getTimestamp();
}
public function hasSubscriptionSecret(User $user): bool
{
if (!\array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
return false;
}
return \array_key_exists(self::SECRET_SUBSCRIPTION_EVENT, $user->getAttributes()[self::METADATA_KEY]);
}
public function hasUserId(User $user): bool
{
if (null === $user->getEmail() || '' === $user->getEmail()) {
return false;
}
if (!\array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
return false;
}
return \array_key_exists('id', $user->getAttributes()[self::METADATA_KEY]);
}
public function writeMetadata(User $user): User
{
if (null === $user->getEmail() || '' === $user->getEmail()) {
return $user;
}
if (null === $userData = $this->getUserByEmail($user->getEmailCanonical())) {
$this->logger->warning('[MapCalendarToUser] could not find user on msgraph', ['userId' => $user->getId(), 'email' => $user->getEmailCanonical()]);
return $this->writeNullData($user);
}
if (null === $defaultCalendar = $this->getDefaultUserCalendar($userData['id'])) {
$this->logger->warning('[MapCalendarToUser] could not 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'],
]]);
}
/**
* @param int $expiration the expiration time as unix timestamp
*/
public function writeSubscriptionMetadata(
User $user,
int $expiration,
string $id = null,
string $secret = null
): void {
$user->setAttributeByDomain(self::METADATA_KEY, self::EXPIRATION_SUBSCRIPTION_EVENT, $expiration);
if (null !== $id) {
$user->setAttributeByDomain(self::METADATA_KEY, self::ID_SUBSCRIPTION_EVENT, $id);
}
if (null !== $secret) {
$user->setAttributeByDomain(self::METADATA_KEY, self::SECRET_SUBSCRIPTION_EVENT, $secret);
}
}
private function writeNullData(User $user): User
{
return $user->unsetAttribute(self::METADATA_KEY);
}
}