Total Complexity | 87 |
Total Lines | 645 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like UserManagement often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use UserManagement, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
49 | class UserManagement extends \core\common\Entity |
||
50 | { |
||
51 | |||
52 | /** |
||
53 | * our handle to the INST database |
||
54 | * |
||
55 | * @var DBConnection |
||
56 | */ |
||
57 | private $databaseHandle; |
||
58 | public $currentInstitutions; |
||
59 | public $newUser = false; |
||
60 | public $hasPotenialNewInst = false; |
||
61 | |||
62 | /** |
||
63 | * Class constructor. Nothing special to be done when constructing. |
||
64 | * |
||
65 | * @throws Exception |
||
66 | */ |
||
67 | public function __construct() |
||
68 | { |
||
69 | parent::__construct(); |
||
70 | $handle = DBConnection::handle(self::$databaseType); |
||
71 | if ($handle instanceof DBConnection) { |
||
72 | $this->databaseHandle = $handle; |
||
73 | } else { |
||
74 | throw new Exception("This database type is never an array!"); |
||
75 | } |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * database which this class queries by default |
||
80 | * |
||
81 | * @var string |
||
82 | */ |
||
83 | private static $databaseType = "INST"; |
||
84 | |||
85 | const TOKENSTATUS_OK_NEW = 1; |
||
86 | const TOKENSTATUS_OK_EXISTING = 2; |
||
87 | const TOKENSTATUS_FAIL_ALREADYCONSUMED = -1; |
||
88 | const TOKENSTATUS_FAIL_EXPIRED = -2; |
||
89 | const TOKENSTATUS_FAIL_NONEXISTING = -3; |
||
90 | |||
91 | /** |
||
92 | * Checks if a given invitation token exists and is valid in the invitations database |
||
93 | * returns a string with the following values: |
||
94 | * |
||
95 | * OK-NEW valid token exists, and is not attached to an existing institution. When consuming the token, a new inst will be created |
||
96 | * OK-EXISTING valid token exists, and is attached to an existing institution. When consuming the token, user will be added as an admin |
||
97 | * FAIL-NONEXISTINGTOKEN this token does not exist at all in the database |
||
98 | * FAIL-ALREADYCONSUMED the token exists, but has been used before |
||
99 | * FAIL-EXPIRED the token exists, but has expired |
||
100 | * |
||
101 | * @param string $token the invitation token |
||
102 | * @return int |
||
103 | */ |
||
104 | public function checkTokenValidity($token) |
||
105 | { |
||
106 | $check = $this->databaseHandle->exec("SELECT invite_token, cat_institution_id |
||
107 | FROM invitations |
||
108 | WHERE invite_token = ? AND invite_created >= TIMESTAMPADD(DAY, -1, NOW()) AND used = 0", "s", $token); |
||
109 | // SELECT -> resource, not boolean |
||
110 | if ($tokenCheck = mysqli_fetch_object(/** @scrutinizer ignore-type */ $check)) { |
||
111 | if ($tokenCheck->cat_institution_id === NULL) { |
||
112 | return self::TOKENSTATUS_OK_NEW; |
||
113 | } |
||
114 | return self::TOKENSTATUS_OK_EXISTING; |
||
115 | } |
||
116 | // if we haven't returned from the function yet, it is an invalid token... |
||
117 | // be a little verbose what's wrong with it |
||
118 | $checkReason = $this->databaseHandle->exec("SELECT invite_token, used FROM invitations WHERE invite_token = ?", "s", $token); |
||
119 | // SELECT -> resource, not boolean |
||
120 | if ($invalidTokenCheck = mysqli_fetch_object(/** @scrutinizer ignore-type */ $checkReason)) { |
||
121 | if ($invalidTokenCheck->used == 1) { |
||
122 | return self::TOKENSTATUS_FAIL_ALREADYCONSUMED; |
||
123 | } |
||
124 | return self::TOKENSTATUS_FAIL_EXPIRED; |
||
125 | } |
||
126 | return self::TOKENSTATUS_FAIL_NONEXISTING; |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * This function creates a new IdP in the database based on a valid invitation token - or adds a new administrator |
||
131 | * to an existing one. The institution is created for the logged-in user (second argument) who presents the token (first |
||
132 | * argument). The tokens are created via createToken(). |
||
133 | * |
||
134 | * @param string $token The invitation token (must exist in the database and be valid). |
||
135 | * @param string $owner Persistent User ID who becomes the administrator of the institution |
||
136 | * @return IdP |
||
137 | */ |
||
138 | public function createIdPFromToken(string $token, string $owner) |
||
139 | { |
||
140 | new CAT(); // be sure that Entity's static members are initialised |
||
141 | common\Entity::intoThePotatoes(); |
||
142 | // the token either has cat_institution_id set -> new admin for existing inst |
||
143 | // or contains a number of parameters from external DB -> set up new inst |
||
144 | $instinfo = $this->databaseHandle->exec("SELECT cat_institution_id, country, name, invite_issuer_level, invite_dest_mail, external_db_uniquehandle, invite_fortype |
||
145 | FROM invitations |
||
146 | WHERE invite_token = ? AND invite_created >= TIMESTAMPADD(DAY, -1, NOW()) AND used = 0", "s", $token); |
||
147 | // SELECT -> resource, no boolean |
||
148 | if ($invitationDetails = mysqli_fetch_assoc(/** @scrutinizer ignore-type */ $instinfo)) { |
||
149 | if ($invitationDetails['cat_institution_id'] !== NULL) { // add new admin to existing IdP |
||
150 | // we can't rely on a unique key on this table (user IDs |
||
151 | // possibly too long), so run a query to find there's an |
||
152 | // tuple already; and act accordingly |
||
153 | $catId = $invitationDetails['cat_institution_id']; |
||
154 | $level = $invitationDetails['invite_issuer_level']; |
||
155 | $destMail = $invitationDetails['invite_dest_mail']; |
||
156 | $existing = $this->databaseHandle->exec("SELECT user_id FROM ownership WHERE user_id = ? AND institution_id = ?", "si", $owner, $catId); |
||
157 | // SELECT -> resource, not boolean |
||
158 | if (mysqli_num_rows(/** @scrutinizer ignore-type */ $existing) > 0) { |
||
159 | $this->databaseHandle->exec("UPDATE ownership SET blesslevel = ?, orig_mail = ? WHERE user_id = ? AND institution_id = ?", "sssi", $level, $destMail, $owner, $catId); |
||
160 | } else { |
||
161 | $this->databaseHandle->exec("INSERT INTO ownership (user_id, institution_id, blesslevel, orig_mail) VALUES(?, ?, ?, ?)", "siss", $owner, $catId, $level, $destMail); |
||
162 | } |
||
163 | common\Logging::writeAudit_s((string) $owner, "OWN", "IdP " . $invitationDetails['cat_institution_id'] . " - added user as owner"); |
||
164 | common\Entity::outOfThePotatoes(); |
||
165 | return new IdP($invitationDetails['cat_institution_id']); |
||
166 | } |
||
167 | // create new IdP |
||
168 | $fed = new Federation($invitationDetails['country']); |
||
169 | // find the best name for the entity: C if specified, otherwise English, otherwise whatever |
||
170 | if ($invitationDetails['external_db_uniquehandle'] != NULL) { |
||
171 | $idp = $this->newIdPFromExternal($invitationDetails['external_db_uniquehandle'], $fed, $invitationDetails, $owner); |
||
172 | } else { |
||
173 | $bestnameguess = $invitationDetails['name']; |
||
174 | $idp = new IdP($fed->newIdP('TOKEN', $invitationDetails['invite_fortype'], $owner, $invitationDetails['invite_issuer_level'], $invitationDetails['invite_dest_mail'], $bestnameguess)); |
||
175 | $idp->addAttribute("general:instname", 'C', $bestnameguess); |
||
176 | } |
||
177 | common\Logging::writeAudit_s($owner, "NEW", "IdP " . $idp->identifier . " - created from invitation"); |
||
178 | |||
179 | // in case we have more admins in the queue which were invited to |
||
180 | // administer the same inst but haven't redeemed their invitations |
||
181 | // yet, then we will have to rewrite the invitations to point to the |
||
182 | // newly created actual IdP rather than the placeholder entry in the |
||
183 | // invitations table |
||
184 | // which other pending invites do we have? |
||
185 | |||
186 | $otherPending = $this->databaseHandle->exec("SELECT id |
||
187 | FROM invitations |
||
188 | WHERE invite_created >= TIMESTAMPADD(DAY, -1, NOW()) AND used = 0 AND name = ? AND country = ? AND ( cat_institution_id IS NULL OR external_db_uniquehandle IS NULL ) ", "ss", $invitationDetails['name'], $invitationDetails['country']); |
||
189 | // SELECT -> resource, no boolean |
||
190 | while ($pendingDetail = mysqli_fetch_object(/** @scrutinizer ignore-type */ $otherPending)) { |
||
191 | $this->databaseHandle->exec("UPDATE invitations SET cat_institution_id = " . $idp->identifier . " WHERE id = " . $pendingDetail->id); |
||
192 | } |
||
193 | common\Entity::outOfThePotatoes(); |
||
194 | return $idp; |
||
195 | } |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * create new institution based on the edxternalDB data |
||
200 | * @param string $extId - the eduroam database identifier |
||
201 | * @param object $fed - the CAT federation object where the institution should be created |
||
202 | * @param string $owner |
||
203 | * @return type |
||
204 | */ |
||
205 | public function createIdPFromExternal($extId, $fed, $owner) |
||
218 | } |
||
219 | |||
220 | /* |
||
221 | * This is the common part of the code for createIdPFromToken and createIdPFromExternal |
||
222 | */ |
||
223 | private function newIdPFromExternal($extId, $fed, $invitationDetails, $owner, $externalinfo = []) |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * Adds a new administrator to an existing IdP |
||
243 | * @param IdP $idp institution to which the admin is to be added. |
||
244 | * @param string $user persistent user ID that is to be added as an admin. |
||
245 | * @return boolean This function always returns TRUE. |
||
246 | */ |
||
247 | public function addAdminToIdp($idp, $user) |
||
248 | { |
||
249 | $existing = $this->databaseHandle->exec("SELECT user_id FROM ownership WHERE user_id = ? AND institution_id = ?", "si", $user, $idp->identifier); |
||
250 | // SELECT -> resource, not boolean |
||
251 | if (mysqli_num_rows(/** @scrutinizer ignore-type */ $existing) == 0) { |
||
252 | $this->databaseHandle->exec("INSERT INTO ownership (institution_id,user_id,blesslevel,orig_mail) VALUES(?, ?, 'FED', 'SELF-APPOINTED')", "is", $idp->identifier, $user); |
||
253 | } |
||
254 | return TRUE; |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Deletes an administrator from the IdP. If the IdP and user combination doesn't match, nothing happens. |
||
259 | * @param IdP $idp institution from which the admin is to be deleted. |
||
260 | * @param string $user persistent user ID that is to be deleted as an admin. |
||
261 | * @return boolean This function always returns TRUE. |
||
262 | */ |
||
263 | public function removeAdminFromIdP($idp, $user) |
||
264 | { |
||
265 | $this->databaseHandle->exec("DELETE from ownership WHERE institution_id = $idp->identifier AND user_id = ?", "s", $user); |
||
266 | return TRUE; |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Invalidates a token so that it can't be used any more. Tokens automatically expire after 24h, but can be invalidated |
||
271 | * earlier, e.g. after having been used to create an institution. If the token doesn't exist in the DB or is already invalidated, |
||
272 | * nothing happens. |
||
273 | * |
||
274 | * @param string $token the token to invalidate |
||
275 | * @return boolean This function always returns TRUE. |
||
276 | */ |
||
277 | public function invalidateToken($token) |
||
281 | } |
||
282 | |||
283 | /** |
||
284 | * Creates a new invitation token. The token's main purpose is to be sent out by mail. The function either can generate a token for a new |
||
285 | * administrator of an existing institution, or for a new institution. In the latter case, the institution only actually gets |
||
286 | * created in the DB if the token is actually consumed via createIdPFromToken(). |
||
287 | * |
||
288 | * @param boolean $isByFedadmin is the invitation token created for a federation admin (TRUE) or from an existing inst admin (FALSE) |
||
289 | * @param array $for identifiers (typically email addresses) for which the invitation is created |
||
290 | * @param mixed $instIdentifier either an instance of the IdP class (for existing institutions to invite new admins) or a string (new institution - this is the inst name then) |
||
291 | * @param string $externalId if the IdP to be created is related to an external DB entity, this parameter contains that ID |
||
292 | * @param string $country if the institution is new (i.e. $inst is a string) this parameter needs to specify the federation of the new inst |
||
293 | * @param string $partType the type of participant |
||
294 | * @return mixed The function returns either the token (as string) or FALSE if something went wrong |
||
295 | * @throws Exception |
||
296 | */ |
||
297 | public function createTokens($isByFedadmin, $for, $instIdentifier, $externalId = 0, $country = 0, $partType = 0) |
||
298 | { |
||
299 | $level = ($isByFedadmin ? "FED" : "INST"); |
||
300 | $tokenList = []; |
||
301 | foreach ($for as $oneDest) { |
||
302 | $token = bin2hex(random_bytes(40)); |
||
303 | if ($instIdentifier instanceof IdP) { |
||
304 | $this->databaseHandle->exec("INSERT INTO invitations (invite_fortype, invite_issuer_level, invite_dest_mail, invite_token,cat_institution_id) VALUES(?, ?, ?, ?, ?)", "ssssi", $instIdentifier->type, $level, $oneDest, $token, $instIdentifier->identifier); |
||
305 | $tokenList[$token] = $oneDest; |
||
306 | } else if (func_num_args() == 5) { |
||
307 | $ROid = strtoupper($country).'01'; |
||
308 | $cat = new CAT(); |
||
309 | $extinfo = $cat->getExternalDBEntityDetails($externalId, $ROid); |
||
310 | $extCountry = $extinfo['country']; |
||
311 | $extType = $extinfo['type']; |
||
312 | if(\config\Master::FUNCTIONALITY_FLAGS['SINGLE_SERVICE'] === 'MSP') { |
||
313 | $extType = \core\IdP::TYPE_SP; |
||
314 | } |
||
315 | $this->databaseHandle->exec("INSERT INTO invitations (invite_fortype, invite_issuer_level, invite_dest_mail, invite_token,name,country, external_db_uniquehandle) VALUES(?, ?, ?, ?, ?, ?, ?)", "sssssss", $extType, $level, $oneDest, $token, $instIdentifier, $extCountry, $externalId); |
||
316 | $tokenList[$token] = $oneDest; |
||
317 | } else if (func_num_args() == 6) { // string name, and country set - whole new IdP |
||
318 | $this->databaseHandle->exec("INSERT INTO invitations (invite_fortype, invite_issuer_level, invite_dest_mail, invite_token,name,country) VALUES(?, ?, ?, ?, ?, ?)", "ssssss", $partType, $level, $oneDest, $token, $instIdentifier, $country); |
||
319 | $tokenList[$token] = $oneDest; |
||
320 | } else { |
||
321 | throw new Exception("The invitation is somehow ... wrong."); |
||
322 | } |
||
323 | } |
||
324 | if (count($for) != count($tokenList)) { |
||
325 | throw new Exception("Creation of a new token failed!"); |
||
326 | } |
||
327 | return $tokenList; |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * Retrieves all pending invitations for an institution or for a federation. |
||
332 | * |
||
333 | * @param int $idpIdentifier the identifier of the institution. If not set, returns invitations for not-yet-created insts |
||
334 | * @return array if idp_identifier is set: an array of strings (mail addresses); otherwise an array of tuples (country;name;mail) |
||
335 | */ |
||
336 | public function listPendingInvitations($idpIdentifier = 0) |
||
337 | { |
||
338 | $retval = []; |
||
339 | $invitations = $this->databaseHandle->exec("SELECT cat_institution_id, country, name, invite_issuer_level, invite_dest_mail, invite_token , TIMESTAMPADD(DAY, 1, invite_created) as expiry |
||
340 | FROM invitations |
||
341 | WHERE cat_institution_id " . ( $idpIdentifier != 0 ? "= $idpIdentifier" : "IS NULL") . " AND invite_created >= TIMESTAMPADD(DAY, -1, NOW()) AND used = 0"); |
||
342 | // SELECT -> resource, not boolean |
||
343 | common\Logging::debug_s(4, "Retrieving pending invitations for " . ($idpIdentifier != 0 ? "IdP $idpIdentifier" : "IdPs awaiting initial creation" ) . ".\n"); |
||
344 | while ($invitationQuery = mysqli_fetch_object(/** @scrutinizer ignore-type */ $invitations)) { |
||
345 | $retval[] = ["country" => $invitationQuery->country, "name" => $invitationQuery->name, "mail" => $invitationQuery->invite_dest_mail, "token" => $invitationQuery->invite_token, "expiry" => $invitationQuery->expiry]; |
||
346 | } |
||
347 | return $retval; |
||
348 | } |
||
349 | |||
350 | /** Retrieves all invitations which have expired in the last hour. |
||
351 | * |
||
352 | * @return array of expired invitations |
||
353 | */ |
||
354 | public function listRecentlyExpiredInvitations() |
||
355 | { |
||
356 | $retval = []; |
||
357 | $invitations = $this->databaseHandle->exec("SELECT cat_institution_id, country, name, invite_issuer_level, invite_dest_mail, invite_token |
||
358 | FROM invitations |
||
359 | WHERE invite_created >= TIMESTAMPADD(HOUR, -25, NOW()) AND invite_created < TIMESTAMPADD(HOUR, -24, NOW()) AND used = 0"); |
||
360 | // SELECT -> resource, not boolean |
||
361 | while ($expInvitationQuery = mysqli_fetch_object(/** @scrutinizer ignore-type */ $invitations)) { |
||
362 | common\Logging::debug_s(4, "Retrieving recently expired invitations (expired in last hour)\n"); |
||
363 | if ($expInvitationQuery->cat_institution_id == NULL) { |
||
364 | $retval[] = ["country" => $expInvitationQuery->country, "level" => $expInvitationQuery->invite_issuer_level, "name" => $expInvitationQuery->name, "mail" => $expInvitationQuery->invite_dest_mail]; |
||
365 | } else { |
||
366 | $retval[] = ["country" => $expInvitationQuery->country, "level" => $expInvitationQuery->invite_issuer_level, "name" => "Existing IdP", "mail" => $expInvitationQuery->invite_dest_mail]; |
||
367 | } |
||
368 | } |
||
369 | return $retval; |
||
370 | } |
||
371 | |||
372 | /** |
||
373 | * For a given persistent user identifier, returns an array of institution identifiers (not the actual objects!) for which this |
||
374 | * user is the/a administrator and also do comparisons to the eduroam DB results. |
||
375 | * If the federation autoregister-synced flag is set if it turns out that the eduroam DB |
||
376 | * lists the email of the current logged-in admin as an admin of an existing CAT institution |
||
377 | * and this institution is synced to the matching external institutuin then this admin |
||
378 | * will be automatically added tho the institution and the 'existing' part of $this->currentInstitutions |
||
379 | * will be updated. This identifier will also be listed to $this->currentInstitutions['resynced'] |
||
380 | * |
||
381 | * If the federation autoregister-new-inst flag is set and there are exeternal institututions which could be |
||
382 | * candidated for creating them in CAT - add the identifiers of these institutuins to this->currentInstitutions[new'] |
||
383 | * |
||
384 | * @param boolean $applyAutoSync controls if automatic additions if the user to the admins should be performed |
||
385 | * @return array array of institution IDs |
||
386 | */ |
||
387 | public function listInstitutionsByAdmin($applyAutoSync = false) |
||
388 | { |
||
389 | $edugain = $_SESSION['eduGAIN']; |
||
390 | // get the list of local identifers of institutions managed by this user |
||
391 | // it will be returned as $this->currentInstitutions |
||
392 | $this->getCurrentInstitutionsByAdmin(); |
||
393 | if (count($this->currentInstitutions) == 0) { |
||
394 | $this->newUser = true; |
||
395 | } |
||
396 | // check if selfservice_registration is set to eduGAIN - if not then return with the durrent list |
||
397 | if (\config\ConfAssistant::CONSORTIUM['selfservice_registration'] !== 'eduGAIN') { |
||
398 | common\Logging::debug_s(4, "selfservice_registration not set to eduGAIN\n"); |
||
399 | return $this->currentInstitutions; |
||
400 | } |
||
401 | // now add additional institutions based on the external DB |
||
402 | // proceed only if user has been authenticated fron an eduGAIN IdP |
||
403 | if ($edugain == false) { |
||
404 | return $this->currentInstitutions; |
||
405 | } |
||
406 | $email = $_SESSION['auth_email']; |
||
407 | $externalDB = CAT::determineExternalConnection(); |
||
408 | // get the list of identifiers in the external DB with this user listed as the admin and linked to CAT institutions |
||
409 | $extInstList = $externalDB->listExternalEntitiesByUserEmail($email); |
||
410 | $extInstListTmp = $extInstList; |
||
411 | // we begin by removing entites in $extInstList which are already managed by this user and synced - |
||
412 | // these require no further checking |
||
413 | foreach ($extInstListTmp as $country => $extInstCountryList) { |
||
414 | $len = count($extInstCountryList); |
||
415 | for($i = 0; $i < $len; ++$i) { |
||
416 | $extInst = $extInstCountryList[$i]; |
||
417 | if ($extInst['inst_id'] != NULL && in_array($extInst['inst_id'], $this->currentInstitutions['existing'])) { |
||
418 | unset($extInstList[$country][$i]); |
||
419 | } |
||
420 | } |
||
421 | if (count($extInstList[$country]) == 0) { |
||
422 | unset($extInstList[$country]); |
||
423 | } |
||
424 | } |
||
425 | // now verify the $extInstList separately for each federation making sure |
||
426 | // that the federation allows autoregistration |
||
427 | foreach ($extInstList as $country => $extInstCountryList) { |
||
428 | $fed = new Federation($country); |
||
429 | $this->doExternalDBAutoregister($extInstCountryList, $fed, $applyAutoSync); |
||
430 | $this->doExternalDBAutoregisterNew($extInstCountryList, $fed); |
||
431 | } |
||
432 | // now we run tests for adding admins based on pairwise-id and entitlement |
||
433 | $entitledCountries = $this->getUserEntitledFed(); |
||
434 | $entitlementInst = $this->listCatInstitutionsByPairwiseId(); |
||
435 | common\Logging::debug_s(4, $entitlementInst, "entitlementInst\n", "\n"); |
||
436 | foreach ($entitlementInst as $country => $instList) { |
||
437 | if (!in_array($country, $entitledCountries)) { |
||
438 | continue; |
||
439 | } |
||
440 | $fed = new Federation($country); |
||
441 | $this->doEntitlementAutoregister($instList, $fed); |
||
442 | } |
||
443 | $_SESSION['entitledIdPs'] = array_column($this->currentInstitutions['entitlement'], 0); |
||
444 | common\Logging::debug_s(4, $this->currentInstitutions, "currentInstitutions\n", "\n"); |
||
445 | return $this->currentInstitutions; |
||
446 | } |
||
447 | |||
448 | /** |
||
449 | * Handle auto-registration of admin for CAT institutions which are synced to |
||
450 | * eduroam DB institutions which have the current admin listed |
||
451 | * The method verifies that the federation allows auto-registration |
||
452 | * |
||
453 | * @param array $extInstCountryList - list of eduroam DB candidate institutions |
||
454 | * @param object $fed - the Federation object |
||
455 | * @param boolean $applyAutoSync - do we write updated to the databaes? |
||
456 | */ |
||
457 | private function doExternalDBAutoregister($extInstCountryList, $fed, $applyAutoSync = false) { |
||
478 | } |
||
479 | } |
||
480 | } |
||
481 | |||
482 | /** |
||
483 | * Handle auto-creation of new CAT institutions which match |
||
484 | * eduroam DB institutions which have the current admin listed |
||
485 | * The method verifies that the federation allows auto-cereation |
||
486 | * |
||
487 | * @param array $extInstCountryList - list of eduroam DB candidate institutions |
||
488 | * @param object $fed - the Federation object |
||
489 | */ |
||
490 | private function doExternalDBAutoregisterNew($extInstCountryList, $fed) { |
||
491 | $newInstFlag = $fed->getAttributes('fed:autoregister-new-inst'); |
||
492 | if ($newInstFlag == []) { |
||
493 | return; |
||
494 | } |
||
495 | foreach ($extInstCountryList as $extInst) { |
||
496 | common\Logging::debug_s(4, "Testing ".$extInst['external_db_id']." for potential new inst\n"); |
||
497 | if ($extInst['inst_id'] != null) { // there alreay exeists a CAT institution synced to this one |
||
498 | continue; |
||
499 | } |
||
500 | $country = $fed->tld; |
||
501 | // now run checks against creating dupplicates in CAT DB |
||
502 | $disectedNames = ExternalEduroamDBData::dissectCollapsedInstitutionNames($extInst['name']); |
||
503 | $names = $disectedNames['joint']; |
||
504 | $realms = ExternalEduroamDBData::dissectCollapsedInstitutionRealms($extInst['realm']); |
||
505 | $foundMatch = $this->checkForSimilarInstitutions($names, $realms); |
||
506 | common\Logging::debug_s(4, $foundMatch, "checkForSimilarInstitutions returned: ","\n"); |
||
507 | if ($foundMatch == 0) { |
||
508 | $this->currentInstitutions['new'][] = [$extInst['external_db_id'], $disectedNames['perlang'], $country]; |
||
509 | } |
||
510 | } |
||
511 | } |
||
512 | |||
513 | /** |
||
514 | * Handle auto-registration of admin for CAT institutions |
||
515 | * based on data from eduGAIN login |
||
516 | * The method verifies that the federation allows this type of auto-registration |
||
517 | * |
||
518 | * @param boolean $applyAutoSync - do we write updated to the databaes? |
||
519 | * @param object $fed - the Federation object |
||
520 | */ |
||
521 | private function doEntitlementAutoregister($instList, $fed) { |
||
530 | } |
||
531 | } |
||
532 | |||
533 | } |
||
534 | |||
535 | /** |
||
536 | * Generate a list of externalDB institutions for which the admin is entitled |
||
537 | * based on the eduPersonEntitlement setting and scope from pairwise-id |
||
538 | * The |
||
539 | * @return array indexed by countries |
||
540 | */ |
||
541 | private function listCatInstitutionsByPairwiseId() { |
||
542 | if (!isset(\config\ConfAssistant::CONSORTIUM['entitlement'])) { |
||
543 | return []; |
||
544 | } |
||
545 | // first check if pairwise-id is set |
||
546 | $userId = $_SESSION['user']; |
||
547 | if (substr($userId, 0, 12) !== 'pairwise-id:') { |
||
548 | return []; |
||
549 | } |
||
550 | |||
551 | // next check if entitlement is setand matches our expectations |
||
552 | if (!isset($_SESSION['entitlement'])) { |
||
553 | return []; |
||
554 | } |
||
555 | |||
556 | // get realm from pariwise-id |
||
557 | if (preg_match('/^pairwise-id:[^@]+@([^!]+)!/', $userId, $matches) == 0) { |
||
558 | return []; |
||
559 | } |
||
560 | |||
561 | $userRealm = $matches[1]; |
||
562 | common\Logging::debug_s(4, $userRealm, "userRealm:", "\n"); |
||
563 | // list CAT inst_id and country from the profile |
||
564 | $query = "SELECT DISTINCT profile.inst_id,country FROM profile JOIN institution on profile.inst_id = institution.inst_id WHERE realm LIKE '%@$userRealm' OR realm LIKE '%@%.$userRealm'"; |
||
565 | $institutions = $this->databaseHandle->exec($query); |
||
566 | $catInstList = $institutions->fetch_all(); |
||
567 | $returnarray = []; |
||
568 | foreach ($catInstList as $inst) { |
||
569 | $country = $inst[1]; |
||
570 | if (!isset($returnarray[$country])) { |
||
571 | $returnarray[$country] = []; |
||
572 | } |
||
573 | $returnarray[$country][] = $inst[0]; |
||
574 | } |
||
575 | return $returnarray; |
||
576 | } |
||
577 | |||
578 | /** |
||
579 | * Get the list of eduroam countries that the user could potentially auto-register |
||
580 | * based on eduPersonEntitlement. The list of countries is based on matching between |
||
581 | * the eduGAIN federation where the eduGAIN IdP is registered and the counters that this federation serves |
||
582 | * Before passing on the list it is checked if particular countries allow entitlement-based |
||
583 | * autoregistration |
||
584 | * |
||
585 | * @return array indexed by countries |
||
586 | */ |
||
587 | private function getUserEntitledFed() { |
||
588 | if (!isset($_SESSION['entitlement'])) { |
||
589 | return []; |
||
590 | } |
||
591 | $entitledCountries = []; |
||
592 | $countries = $this->databaseHandle->exec("SELECT country FROM edugain WHERE reg_auth = ?", 's', $_SESSION['eduGAIN']); |
||
593 | $countryList = $countries->fetch_all(); |
||
594 | $countriesTmp = []; |
||
595 | foreach ($countryList as $country) { |
||
596 | $requiredEntitlement = NULL; |
||
597 | $countryCode = $country[0]; |
||
598 | $fed = new Federation($countryCode); |
||
599 | $autoreg = $fed->getAttributes('fed:autoregister-entitlement'); |
||
600 | $entitlementVal = $fed->getAttributes('fed:entitlement-attr'); |
||
601 | if (isset($autoreg[0]['value']) && $autoreg[0]['value'] == 'on') { |
||
602 | $requiredEntitlement = isset($entitlementVal[0]['value']) ? $entitlementVal[0]['value'] : \config\ConfAssistant::CONSORTIUM['entitlement']; |
||
603 | } |
||
604 | common\Logging::debug_s(4, $requiredEntitlement, "$countryCode requiredEntitlement\n", "\n"); |
||
605 | if (in_array($requiredEntitlement, $_SESSION['entitlement'])) { |
||
606 | $entitledCountries[] = $countryCode; |
||
607 | } |
||
608 | } |
||
609 | common\Logging::debug_s(4, $entitledCountries, "entitledCountries:\n", "\n"); |
||
610 | return $entitledCountries; |
||
611 | } |
||
612 | |||
613 | /** |
||
614 | * Tests if the institution with these identifier does not yet exist in CAT. |
||
615 | * This is done by testing the admins "new" institutions, this way we also make sure |
||
616 | * that this admin is actually also allowed to create the new one |
||
617 | * |
||
618 | * @return int 1 or 0. 1 means we are free to create the inst. |
||
619 | */ |
||
620 | |||
621 | public function checkForCatMatch($extId, $ROid) { |
||
622 | $this->listInstitutionsByAdmin(); |
||
623 | foreach ($this->currentInstitutions['new'] as $newInst) { |
||
624 | if ($extId == $newInst[0] && $ROid == strtoupper($newInst[2]).'01') { |
||
625 | return 0; |
||
626 | } |
||
627 | } |
||
628 | return 1; |
||
629 | } |
||
630 | |||
631 | /** |
||
632 | * get the list of current institutions of the given admin |
||
633 | * |
||
634 | * This method does not rerurn anything but sets $this->currentInstitutions |
||
635 | * it only fillsh the 'existing' block, leaving the other two for other methods |
||
636 | * to deal with |
||
637 | */ |
||
638 | private function getCurrentInstitutionsByAdmin() { |
||
654 | } |
||
655 | |||
656 | /** |
||
657 | * given arrays of realms and names check if there already are institutions in CAT that |
||
658 | * could be a match - this is for ellimination and against creating duplicates |
||
659 | * still this is not perfect, no realms given and institutions with a slightly different |
||
660 | * name will return no-match and thus open possibility for dupplicates |
||
661 | * |
||
662 | * @param array $namesToTest |
||
663 | * @param array $realmsToTest |
||
664 | * @return int - 1 - a match was found, 0 - no match found |
||
665 | */ |
||
666 | private function checkForSimilarInstitutions($namesToTest, $realmsToTest) { |
||
694 | } |
||
695 | } |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths