Passed
Pull Request — 1.11.x (#5763)
by Angel Fernando Quiroz
08:39
created

AzureSyncUsersCommand::getAzureUsers()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 48
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 32
c 2
b 0
f 0
dl 0
loc 48
rs 9.0968
cc 5
nc 5
nop 0
1
<?php
2
3
/* For license terms, see /license.txt */
4
5
use Chamilo\UserBundle\Entity\User;
6
7
class AzureSyncUsersCommand extends AzureCommand
8
{
9
    /**
10
     * @throws Exception
11
     *
12
     * @return Generator<int, string>
13
     */
14
    public function __invoke(): Generator
15
    {
16
        yield 'Synchronizing users from Azure.';
17
18
        /** @var array<string, int> $existingUsers */
19
        $existingUsers = [];
20
21
        foreach ($this->getAzureUsers() as $azureUserInfo) {
22
            try {
23
                $userId = $this->plugin->registerUser($azureUserInfo, 'id');
24
            } catch (Exception $e) {
25
                yield $e->getMessage();
26
27
                continue;
28
            }
29
30
            $existingUsers[$azureUserInfo['id']] = $userId;
31
32
            yield sprintf('User (ID %d) with received info: %s ', $userId, serialize($azureUserInfo));
33
        }
34
35
        yield '----------------';
36
        yield 'Updating users status';
37
38
        $roleGroups = $this->plugin->getGroupUidPerRole();
39
        $roleActions = $this->plugin->getActionPerRole();
40
41
        $userManager = UserManager::getManager();
42
        $em = Database::getManager();
43
44
        foreach ($roleGroups as $userRole => $groupUid) {
45
            $azureGroupMembersInfo = iterator_to_array($this->getAzureGroupMembers($groupUid));
46
            $azureGroupMembersUids = array_column($azureGroupMembersInfo, 'id');
47
48
            foreach ($azureGroupMembersUids as $azureGroupMembersUid) {
49
                $userId = $existingUsers[$azureGroupMembersUid] ?? null;
50
51
                if (!$userId) {
52
                    continue;
53
                }
54
55
                if (isset($roleActions[$userRole])) {
56
                    /** @var User $user */
57
                    $user = $userManager->find($userId);
58
59
                    $roleActions[$userRole]($user);
60
61
                    yield sprintf('User (ID %d) status %s', $userId, $userRole);
62
                }
63
            }
64
65
            $em->flush();
66
        }
67
68
        if ('true' === $this->plugin->get(AzureActiveDirectory::SETTING_DEACTIVATE_NONEXISTING_USERS)) {
69
            yield '----------------';
70
71
            yield 'Trying deactivate non-existing users in Azure';
72
73
            $users = UserManager::getRepository()->findByAuthSource('azure');
74
            $userIdList = array_map(
75
                function ($user) {
76
                    return $user->getId();
77
                },
78
                $users
79
            );
80
81
            $nonExistingUsers = array_diff($userIdList, $existingUsers);
82
83
            UserManager::deactivate_users($nonExistingUsers);
84
85
            yield sprintf(
86
                'Deactivated users IDs: %s',
87
                implode(', ', $nonExistingUsers)
88
            );
89
        }
90
    }
91
92
    /**
93
     * @throws Exception
94
     *
95
     * @return Generator<int, array<string, string>>
96
     */
97
    private function getAzureUsers(): Generator
98
    {
99
        $userFields = [
100
            'givenName',
101
            'surname',
102
            'mail',
103
            'userPrincipalName',
104
            'businessPhones',
105
            'mobilePhone',
106
            'accountEnabled',
107
            'mailNickname',
108
            'id',
109
        ];
110
111
        $query = sprintf(
112
            '$top=%d&$select=%s',
113
            AzureActiveDirectory::API_PAGE_SIZE,
114
            implode(',', $userFields)
115
        );
116
117
        $token = null;
118
119
        do {
120
            $this->generateOrRefreshToken($token);
121
122
            try {
123
                $azureUsersRequest = $this->provider->request(
124
                    'get',
125
                    "users?$query",
126
                    $token
127
                );
128
            } catch (Exception $e) {
129
                throw new Exception('Exception when requesting users from Azure: '.$e->getMessage());
130
            }
131
132
            $azureUsersInfo = $azureUsersRequest['value'] ?? [];
133
134
            foreach ($azureUsersInfo as $azureUserInfo) {
135
                yield $azureUserInfo;
136
            }
137
138
            $hasNextLink = false;
139
140
            if (!empty($azureUsersRequest['@odata.nextLink'])) {
141
                $hasNextLink = true;
142
                $query = parse_url($azureUsersRequest['@odata.nextLink'], PHP_URL_QUERY);
143
            }
144
        } while ($hasNextLink);
145
    }
146
147
    /**
148
     * @throws Exception
149
     */
150
    public function getAzureGroupMembers(string $groupUid): Generator
151
    {
152
        $userFields = [
153
            'id',
154
        ];
155
156
        $query = sprintf(
157
            '$top=%d&$select=%s',
158
            AzureActiveDirectory::API_PAGE_SIZE,
159
            implode(',', $userFields)
160
        );
161
162
        $token = null;
163
164
        do {
165
            $this->generateOrRefreshToken($token);
166
167
            try {
168
                $azureGroupMembersRequest = $this->provider->request(
169
                    'get',
170
                    "groups/$groupUid/members?$query",
171
                    $token
172
                );
173
            } catch (Exception $e) {
174
                throw new Exception('Exception when requesting group members from Azure: '.$e->getMessage());
175
            }
176
177
            $azureGroupMembers = $azureGroupMembersRequest['value'] ?? [];
178
179
            foreach ($azureGroupMembers as $azureGroupMember) {
180
                yield $azureGroupMember;
181
            }
182
183
            $hasNextLink = false;
184
185
            if (!empty($azureGroupMembersRequest['@odata.nextLink'])) {
186
                $hasNextLink = true;
187
                $query = parse_url($azureGroupMembersRequest['@odata.nextLink'], PHP_URL_QUERY);
188
            }
189
        } while ($hasNextLink);
190
    }
191
}
192