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

UserCollectionController::createUser()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 22
c 1
b 0
f 0
nc 3
nop 4
dl 0
loc 43
rs 9.568
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
        $this->authenticateRequest($request);
34
35
        if ($request->isMethod('POST')) {
36
            return $this->createUser(
37
                $request,
38
                $entityManager,
39
                $userRepository,
40
                $serializer,
41
            );
42
        }
43
44
        return $this->listUsers(
45
            $request,
46
            $userRepository,
47
            $serializer,
48
        );
49
    }
50
51
    public function listUsers(
52
        Request $request,
53
        UserRepository $userRepository,
54
        SerializerInterface $serializer,
55
    ): JsonResponse {
56
        $startIndex = max(1, $request->query->getInt('startIndex', 1));
57
        $count = min(100, $request->query->getInt('count', 30));
58
        $filter = $request->query->get('filter');
59
60
        $qb = $userRepository->createQueryBuilder('u');
61
62
        if ($filter && preg_match('/userName\s+eq\s+"([^"]+)"/i', $filter, $matches)) {
63
            $qb
64
                ->andWhere('u.username = :username')
65
                ->setParameter('username', $matches[1])
66
            ;
67
        }
68
69
        try {
70
            $total = (clone $qb)->select('COUNT(u.id)')->getQuery()->getSingleScalarResult();
71
        } catch (NonUniqueResultException|NoResultException) {
72
            $total = 0;
73
        }
74
75
        $users = $qb
76
            ->setFirstResult($startIndex - 1)
77
            ->setMaxResults($count)
78
            ->getQuery()
79
            ->getResult()
80
        ;
81
82
        $resources = [];
83
84
        foreach ($users as $user) {
85
            $resources[] = $serializer->normalize($user, UserNormalizer::FORMAT);
86
        }
87
88
        $response = [
89
            'schemas' => ['urn:ietf:params:scim:api:messages:2.0:ListResponse'],
90
            'totalResults' => (int) $total,
91
            'itemsPerPage' => \count($resources),
92
            'startIndex' => $startIndex,
93
            'Resources' => $resources,
94
        ];
95
96
        return new JsonResponse($response, Response::HTTP_OK, ['Content-Type' => self::SCIM_CONTENT_TYPE]);
97
    }
98
99
    public function createUser(
100
        Request $request,
101
        EntityManagerInterface $entityManager,
102
        UserRepository $userRepository,
103
        SerializerInterface $serializer,
104
    ): JsonResponse {
105
        $data = $this->getAndValidateJson($request);
106
107
        /** @var User $user */
108
        $user = $serializer->denormalize($data, User::class, UserDenormalizer::FORMAT);
109
110
        if ($userRepository->findOneBy(['username' => $user->getUsername()])) {
111
            throw new ConflictHttpException($this->translator->trans('This login is already in use'));
112
        }
113
114
        $currentAccessUrl = $this->accessUrlHelper->getCurrent();
115
116
        $user
117
            ->setCreator($userRepository->findOnePlatformAdmin())
118
            ->addAuthSourceByAuthentication(UserAuthSource::SCIM, $currentAccessUrl)
119
            ->setPlainPassword('scim')
120
            ->setStatus(STUDENT)
121
            ->setRoleFromStatus(STUDENT)
122
        ;
123
124
        $userRepository->updateUser($user);
125
126
        $currentAccessUrl->addUser($user);
127
128
        $entityManager->flush();
129
130
        if (isset($data['externalId'])) {
131
            $this->scimHelper->saveExternalId($data['externalId'], $user);
132
        }
133
134
        $normalized = $serializer->normalize($user, UserNormalizer::FORMAT);
135
136
        return new JsonResponse(
137
            $normalized,
138
            Response::HTTP_CREATED,
139
            [
140
                'Content-Type' => self::SCIM_CONTENT_TYPE,
141
                'Location' => $normalized['meta']['location'],
142
            ]
143
        );
144
    }
145
}
146