/** * Construct a user API client, accounting for unified api presence, and fall back to system api user if desired. * * @param int $muserid The userid to get the outlook token for. If you want to force a system API user client, use an empty * value here and set $systemfallback to true. * @return \local_o365\rest\o365api|bool A constructed user API client (unified or legacy), or false if error. */ public function construct_user_api($muserid = null, $systemfallback = true) { $unifiedconfigured = \local_o365\rest\unified::is_configured(); if ($unifiedconfigured === true) { $resource = \local_o365\rest\unified::get_resource(); } else { $resource = \local_o365\rest\azuread::get_resource(); } $token = null; if (!empty($muserid)) { $token = \local_o365\oauth2\token::instance($muserid, $resource, $this->clientdata, $this->httpclient); } if (empty($token) && $systemfallback === true) { $token = \local_o365\oauth2\systemtoken::instance(null, $resource, $this->clientdata, $this->httpclient); } if (empty($token)) { throw new \Exception('No token available for user #' . $muserid); } if ($unifiedconfigured === true) { $apiclient = new \local_o365\rest\unified($token, $this->httpclient); } else { $apiclient = new \local_o365\rest\azuread($token, $this->httpclient); } return $apiclient; }
/** * Constructor * * @param int $repositoryid repository instance id * @param int|stdClass $context a context id or context object * @param array $options repository options * @param int $readonly indicate this repo is readonly or not */ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array(), $readonly = 0) { parent::__construct($repositoryid, $context, $options, $readonly); $this->httpclient = new \local_o365\httpclient(); $this->clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $this->onedriveconfigured = \local_o365\rest\onedrive::is_configured(); $this->unifiedconfigured = \local_o365\rest\unified::is_configured(); $this->sharepointconfigured = \local_o365\rest\sharepoint::is_configured(); }
/** * Construct an API client. * * @return \local_o365\rest\o365api|bool A constructed user API client (unified or legacy), or false if error. */ public function get_api() { $unifiedconfigured = \local_o365\rest\unified::is_configured(); if ($unifiedconfigured === true) { $resource = \local_o365\rest\unified::get_resource(); } else { $resource = \local_o365\rest\azuread::get_resource(); } $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $httpclient = new \local_o365\httpclient(); $token = \local_o365\oauth2\systemtoken::instance(null, $resource, $clientdata, $httpclient); if (empty($token)) { throw new \Exception('No token available for system user. Please run local_o365 health check.'); } if ($unifiedconfigured === true) { $apiclient = new \local_o365\rest\unified($token, $httpclient); } else { $apiclient = new \local_o365\rest\azuread($token, $httpclient); } return $apiclient; }
/** * Sync Azure AD Moodle users with the configured Azure AD directory. * * @param array $aadusers Array of Azure AD users from $this->get_users(). * @return bool Success/Failure */ public function sync_users(array $aadusers = array()) { global $DB, $CFG; $aadsync = get_config('local_o365', 'aadsync'); $aadsync = array_flip(explode(',', $aadsync)); $usernames = []; foreach ($aadusers as $i => $user) { $upnlower = \core_text::strtolower($user['userPrincipalName']); $aadusers[$i]['upnlower'] = $upnlower; $usernames[] = $upnlower; $upnsplit = explode('@', $upnlower); if (!empty($upnsplit[0])) { $aadusers[$i]['upnsplit0'] = $upnsplit[0]; $usernames[] = $upnsplit[0]; } } // Retrieve object id for app. if (!PHPUNIT_TEST) { $appinfo = $this->get_application_serviceprincipal_info(); } $objectid = null; if (!empty($appinfo)) { if (\local_o365\rest\unified::is_configured()) { $objectid = $appinfo['value'][0]['id']; } else { $objectid = $appinfo['value'][0]['objectId']; } } list($usernamesql, $usernameparams) = $DB->get_in_or_equal($usernames); $sql = 'SELECT u.username, u.id as muserid, u.auth, tok.id as tokid, conn.id as existingconnectionid, assign.assigned assigned FROM {user} u LEFT JOIN {auth_oidc_token} tok ON tok.username = u.username LEFT JOIN {local_o365_connections} conn ON conn.muserid = u.id LEFT JOIN {local_o365_appassign} assign ON assign.muserid = u.id WHERE u.username ' . $usernamesql . ' AND u.mnethostid = ? AND u.deleted = ? '; $params = array_merge($usernameparams, [$CFG->mnet_localhost_id, '0']); $existingusers = $DB->get_records_sql($sql, $params); foreach ($aadusers as $user) { $this->mtrace(' '); $this->mtrace('Syncing user ' . $user['upnlower']); if (isset($user['aad.isDeleted']) && $user['aad.isDeleted'] == '1') { $this->mtrace('User is deleted. Skipping.'); continue; } if (\local_o365\rest\unified::is_configured()) { $userobjectid = $user['id']; } else { $userobjectid = $user['objectId']; } if (!isset($existingusers[$user['upnlower']]) && !isset($existingusers[$user['upnsplit0']])) { $this->mtrace('User doesn\'t exist in Moodle'); if (!isset($aadsync['create'])) { $this->mtrace('Not creating a Moodle user because that sync option is disabled.'); continue; } try { // Create moodle account, if enabled. $newmuser = $this->create_user_from_aaddata($user); if (!empty($newmuser)) { $this->mtrace('Created user #' . $newmuser->id); } } catch (\Exception $e) { $this->mtrace('Could not create user "' . $user['userPrincipalName'] . '" Reason: ' . $e->getMessage()); } try { if (!PHPUNIT_TEST) { if (!empty($newmuser) && !empty($userobjectid) && !empty($objectid) && isset($aadsync['appassign'])) { $this->assign_user($newmuser->id, $userobjectid, $objectid); } } } catch (\Exception $e) { $this->mtrace('Could not assign user "' . $user['userPrincipalName'] . '" Reason: ' . $e->getMessage()); } } else { $existinguser = null; if (isset($existingusers[$user['upnlower']])) { $existinguser = $existingusers[$user['upnlower']]; } else { if (isset($existingusers[$user['upnsplit0']])) { $existinguser = $existingusers[$user['upnsplit0']]; } } // Assign user to app if not already assigned. if (empty($existinguser->assigned)) { try { if (!PHPUNIT_TEST) { if (!empty($existinguser->muserid) && !empty($userobjectid) && !empty($objectid) && isset($aadsync['appassign'])) { $this->assign_user($existinguser->muserid, $userobjectid, $objectid); } } } catch (\Exception $e) { $this->mtrace('Could not assign user "' . $user['userPrincipalName'] . '" Reason: ' . $e->getMessage()); } } if ($existinguser->auth !== 'oidc' && empty($existinguser->tok)) { $this->mtrace('Found a user in Azure AD that seems to match a user in Moodle'); $this->mtrace(sprintf('moodle username: %s, aad upn: %s', $existinguser->username, $user['upnlower'])); if (!isset($aadsync['match'])) { $this->mtrace('Not matching user because that sync option is disabled.'); continue; } if (!empty($existinguser->existingconnectionid)) { $this->mtrace('User is already matched.'); continue; } // Match to o365 account, if enabled. $matchrec = ['muserid' => $existinguser->muserid, 'aadupn' => $user['upnlower'], 'uselogin' => isset($aadsync['matchswitchauth']) ? 1 : 0]; $DB->insert_record('local_o365_connections', $matchrec); $this->mtrace('Matched user.'); } else { // User already connected. $this->mtrace('User is already synced.'); } } } return true; }