Passed
Pull Request — master (#7302)
by Angel Fernando Quiroz
09:27
created

UserCollectionController   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 64
dl 0
loc 121
rs 10
c 1
b 0
f 0
wmc 10

3 Methods

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