Passed
Pull Request — master (#7302)
by Angel Fernando Quiroz
10:36
created

UserCollectionController::listUsers()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 46
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 27
c 1
b 0
f 0
nc 8
nop 3
dl 0
loc 46
rs 9.1768
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Controller\Scim;
8
9
use Chamilo\CoreBundle\Entity\User;
10
use Chamilo\CoreBundle\Entity\UserAuthSource;
11
use Chamilo\CoreBundle\Repository\Node\UserRepository;
12
use Chamilo\CoreBundle\Serializer\Denormalizer\Scim\UserDenormalizer;
13
use Chamilo\CoreBundle\Serializer\Normalizer\Scim\UserNormalizer;
14
use Doctrine\ORM\EntityManagerInterface;
15
use Doctrine\ORM\NonUniqueResultException;
16
use Doctrine\ORM\NoResultException;
17
use Symfony\Component\HttpFoundation\JsonResponse;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
21
use Symfony\Component\Routing\Attribute\Route;
22
use Symfony\Component\Serializer\SerializerInterface;
23
24
#[Route('/scim/v2/Users', name: 'scim_users', methods: ['GET', 'POST'])]
25
class UserCollectionController extends AbstractScimController
26
{
27
    public function __invoke(
28
        Request $request,
29
        EntityManagerInterface $entityManager,
30
        UserRepository $userRepository,
31
        SerializerInterface $serializer,
32
    ): JsonResponse {
33
        if ($request->isMethod('POST')) {
34
            return $this->createUser(
35
                $request,
36
                $entityManager,
37
                $userRepository,
38
                $serializer,
39
            );
40
        }
41
42
        return $this->listUsers(
43
            $request,
44
            $userRepository,
45
            $serializer,
46
        );
47
    }
48
49
    public function listUsers(
50
        Request $request,
51
        UserRepository $userRepository,
52
        SerializerInterface $serializer,
53
    ): JsonResponse {
54
        $startIndex = max(1, $request->query->getInt('startIndex', 1));
55
        $count = min(100, $request->query->getInt('count', 30));
56
        $filter = $request->query->get('filter');
57
58
        $qb = $userRepository->createQueryBuilder('u');
59
60
        if ($filter && preg_match('/userName\s+eq\s+"([^"]+)"/i', $filter, $matches)) {
61
            $qb
62
                ->andWhere('u.username = :username')
63
                ->setParameter('username', $matches[1])
64
            ;
65
        }
66
67
        try {
68
            $total = (clone $qb)->select('COUNT(u.id)')->getQuery()->getSingleScalarResult();
69
        } catch (NonUniqueResultException|NoResultException) {
70
            $total = 0;
71
        }
72
73
        $users = $qb
74
            ->setFirstResult($startIndex - 1)
75
            ->setMaxResults($count)
76
            ->getQuery()
77
            ->getResult()
78
        ;
79
80
        $resources = [];
81
82
        foreach ($users as $user) {
83
            $resources[] = $serializer->normalize($user, UserNormalizer::FORMAT);
84
        }
85
86
        $response = [
87
            'schemas' => ['urn:ietf:params:scim:api:messages:2.0:ListResponse'],
88
            'totalResults' => (int) $total,
89
            'itemsPerPage' => \count($resources),
90
            'startIndex' => $startIndex,
91
            'Resources' => $resources,
92
        ];
93
94
        return new JsonResponse($response, Response::HTTP_OK, ['Content-Type' => self::SCIM_CONTENT_TYPE]);
95
    }
96
97
    public function createUser(
98
        Request $request,
99
        EntityManagerInterface $entityManager,
100
        UserRepository $userRepository,
101
        SerializerInterface $serializer,
102
    ): JsonResponse {
103
        $data = $this->getAndValidateJson($request);
104
105
        /** @var User $user */
106
        $user = $serializer->denormalize($data, User::class, UserDenormalizer::FORMAT);
107
108
        if ($userRepository->findOneBy(['username' => $user->getUsername()])) {
109
            throw new ConflictHttpException($this->translator->trans('This login is already in use'));
110
        }
111
112
        $currentAccessUrl = $this->accessUrlHelper->getCurrent();
113
114
        $user
115
            ->setCreator($userRepository->findOnePlatformAdmin())
116
            ->addAuthSourceByAuthentication(UserAuthSource::SCIM, $currentAccessUrl)
117
            ->setPlainPassword('scim')
118
            ->setStatus(STUDENT)
119
            ->setRoleFromStatus(STUDENT)
120
        ;
121
122
        $userRepository->updateUser($user);
123
124
        $currentAccessUrl->addUser($user);
125
126
        $entityManager->flush();
127
128
        if (isset($data['externalId'])) {
129
            $this->scimHelper->saveExternalId($data['externalId'], $user);
130
        }
131
132
        $normalized = $serializer->normalize($user, UserNormalizer::FORMAT);
133
134
        return new JsonResponse(
135
            $normalized,
136
            Response::HTTP_CREATED,
137
            [
138
                'Content-Type' => self::SCIM_CONTENT_TYPE,
139
                'Location' => $normalized['meta']['location'],
140
            ]
141
        );
142
    }
143
}
144