diff --git a/config/authentication.yaml b/config/authentication.yaml index 278fa4ac945..53a1980092f 100644 --- a/config/authentication.yaml +++ b/config/authentication.yaml @@ -12,7 +12,10 @@ parameters: urlAccessToken: '' urlResourceOwnerDetails: '' responseResourceOwnerId: 'sub' - accessTokenMethod: 'POST' + # accessTokenMethod: 'POST' + # responseError: 'error' + # responseCode: '' + # scopeSeparator: ' ' scopes: - openid allow_create_new_users: true @@ -27,6 +30,7 @@ parameters: resource_owner_hr_status_field: null resource_owner_status_status_field: null resource_owner_anon_status_field: null + resource_owner_urls_field: null facebook: enabled: false diff --git a/src/CoreBundle/Repository/Node/AccessUrlRepository.php b/src/CoreBundle/Repository/Node/AccessUrlRepository.php index 4bf3e7d5790..717ccb9e20b 100644 --- a/src/CoreBundle/Repository/Node/AccessUrlRepository.php +++ b/src/CoreBundle/Repository/Node/AccessUrlRepository.php @@ -7,9 +7,11 @@ namespace Chamilo\CoreBundle\Repository\Node; use Chamilo\CoreBundle\Entity\AccessUrl; +use Chamilo\CoreBundle\Entity\User; use Chamilo\CoreBundle\Repository\ResourceRepository; use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\NoResultException; +use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; class AccessUrlRepository extends ResourceRepository @@ -36,4 +38,21 @@ public function getFirstId(): int return 0; } } + + /** + * @return array + */ + public function findByUser(User $user): array + { + /** @var QueryBuilder $qb */ + $qb = $this->createQueryBuilder('url'); + + return $qb + ->join('url.users', 'users') + ->where($qb->expr()->eq('users.user', ':user')) + ->setParameter('user', $user->getId()) + ->getQuery() + ->getResult() + ; + } } diff --git a/src/CoreBundle/Security/Authenticator/OAuth2/GenericAuthenticator.php b/src/CoreBundle/Security/Authenticator/OAuth2/GenericAuthenticator.php index f4dfd087e90..28ab0944a12 100644 --- a/src/CoreBundle/Security/Authenticator/OAuth2/GenericAuthenticator.php +++ b/src/CoreBundle/Security/Authenticator/OAuth2/GenericAuthenticator.php @@ -6,12 +6,16 @@ namespace Chamilo\CoreBundle\Security\Authenticator\OAuth2; +use Chamilo\CoreBundle\Entity\AccessUrl; +use Chamilo\CoreBundle\Entity\AccessUrlRelUser; use Chamilo\CoreBundle\Entity\User; use Chamilo\CoreBundle\Repository\ExtraFieldRepository; use Chamilo\CoreBundle\Repository\ExtraFieldValuesRepository; +use Chamilo\CoreBundle\Repository\Node\AccessUrlRepository; use Chamilo\CoreBundle\Repository\Node\UserRepository; use Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper; use Chamilo\CoreBundle\ServiceHelper\AuthenticationConfigHelper; +use Doctrine\ORM\EntityManagerInterface; use ExtraField; use KnpU\OAuth2ClientBundle\Client\ClientRegistry; use League\OAuth2\Client\Provider\GenericResourceOwner; @@ -38,6 +42,8 @@ public function __construct( AccessUrlHelper $urlHelper, protected readonly ExtraFieldRepository $extraFieldRepository, protected readonly ExtraFieldValuesRepository $extraFieldValuesRepository, + protected readonly AccessUrlRepository $accessUrlRepository, + protected readonly EntityManagerInterface $entityManager, ) { parent::__construct( $clientRegistry, @@ -108,6 +114,8 @@ protected function userLoader(AccessToken $accessToken): User $user, $resourceOwnerId ); + + $this->updateUrls($user, $resourceOwnerData, $providerParams); } else { /** @var User $user */ $user = $this->userRepository->find( @@ -116,6 +124,8 @@ protected function userLoader(AccessToken $accessToken): User if ($providerParams['allow_update_user_info']) { $this->saveUserInfo($user, $resourceOwnerData, $providerParams); + + $this->updateUrls($user, $resourceOwnerData, $providerParams); } } @@ -203,4 +213,61 @@ private function getUserStatus(array $resourceOwnerData, int $defaultStatus, arr return $map[$status] ?? $status; } + + private function updateUrls(User $user, array $resourceOwnerData, array $providerParams): void + { + if (!($urlsField = $providerParams['resource_owner_urls_field'])) { + return; + } + + $availableUrls = []; + + $urls = $this->accessUrlRepository->findAll(); + + /** @var AccessUrl $existingUrl */ + foreach ($urls as $existingUrl) { + $availableUrls[(string) $existingUrl->getId()] = $existingUrl->getId(); + $availableUrls[$existingUrl->getUrl()] = $existingUrl->getId(); + } + + $allowedUrlIds = []; + + foreach ($this->getValueByKey($resourceOwnerData, $urlsField) as $value) { + if (array_key_exists($value, $availableUrls)) { + $allowedUrlIds[] = $availableUrls[$value]; + } else { + $newValue = ($value[-1] === '/') ? substr($value, 0, -1) : $value.'/'; + + if (array_key_exists($newValue, $availableUrls)) { + $allowedUrlIds[] = $availableUrls[$newValue]; + } + } + } + + $grantedUrlIds = []; + + foreach ($this->accessUrlRepository->findByUser($user) as $grantedUrl) { + $grantedUrlIds[] = $grantedUrl->getId(); + } + + $urlRelUserRepo = $this->entityManager->getRepository(AccessUrlRelUser::class); + + foreach (array_diff($grantedUrlIds, $allowedUrlIds) as $extraUrlId) { + $urlRelUser = $urlRelUserRepo->findOneBy(['user' => $user, 'url' => $extraUrlId]); + + if ($urlRelUser) { + $this->entityManager->remove($urlRelUser); + } + } + + $this->entityManager->flush(); + + foreach (array_diff($allowedUrlIds, $grantedUrlIds) as $missingUrlId) { + /** @var AccessUrl $missingUrl */ + $missingUrl = $this->accessUrlRepository->find($missingUrlId); + $missingUrl->addUser($user); + } + + $this->entityManager->flush(); + } }