/** * Get the content of the block. * * @return stdObject */ public function get_content() { global $USER, $DB; if (!isloggedin()) { return null; } if ($this->content !== null) { return $this->content; } $this->content = new \stdClass(); $this->content->text = ''; $this->content->footer = ''; try { $o365connected = \local_o365\utils::is_o365_connected($USER->id); if ($o365connected === true) { $this->content->text .= $this->get_content_connected(); } else { $connection = $DB->get_record('local_o365_connections', ['muserid' => $USER->id]); if (!empty($connection)) { $uselogin = !empty($connection->uselogin) ? true : false; $this->content->text .= $this->get_content_matched($connection->aadupn, $uselogin); } else { $this->content->text .= $this->get_content_notconnected(); } } } catch (\Exception $e) { $this->content->text = $e->getMessage(); } return $this->content; }
/** * Run before the main page mode - determines connection status. * * @return bool Success/Failure. */ public function header() { global $USER, $DB; $this->o365loginconnected = $USER->auth === 'oidc' ? true : false; $this->o365connected = \local_o365\utils::is_o365_connected($USER->id); return true; }
/** * Sync sharepoint access for a list of courses and users. * * @param array $courses The courses to sync. * @param array $users The users to sync. * @param string $requiredcap The required capability. * @param \local\o365\rest\sharepoint $sharepoint Constructed sharepoint API client. * @return bool Success/Failure. */ protected function sync_spsiteaccess_for_courses_and_users(array $courses, array $users, $requiredcap, \local_o365\rest\sharepoint $sharepoint) { global $DB; foreach ($courses as $course) { $courseid = is_numeric($course) ? $course : $course->id; $context = \context_course::instance($courseid); $spgroupsql = 'SELECT * FROM {local_o365_coursespsite} site JOIN {local_o365_spgroupdata} grp ON grp.coursespsiteid = site.id WHERE site.courseid = ? AND grp.permtype = ?'; $spgrouprec = $DB->get_record_sql($spgroupsql, [$courseid, 'contribute']); if (!empty($spgrouprec)) { foreach ($users as $user) { $userid = is_numeric($user) ? $user : $user->id; if (!\local_o365\utils::is_o365_connected($userid)) { continue; } $userupn = \local_o365\rest\azuread::get_muser_upn($user); $hascap = has_capability($requiredcap, $context, $user); if ($hascap === true) { // Add to group. try { mtrace('Adding user #' . $userid . ' to group id ' . $spgrouprec->groupid . '...'); $sharepoint->add_user_to_group($userupn, $spgrouprec->groupid, $userid); } catch (\Exception $e) { mtrace('Error: ' . $e->getMessage()); } } else { // Remove from group. try { mtrace('Removing user #' . $userid . ' from group id ' . $spgrouprec->groupid . '...'); $sharepoint->remove_user_from_group($userupn, $spgrouprec->groupid, $userid); } catch (\Exception $e) { mtrace('Error: ' . $e->getMessage()); } } } } } return true; }
/** * Determines whether the given Azure AD UPN is already matched to a Moodle user (and has not been completed). * * @return false|stdClass Either the matched Moodle user record, or false if not matched. */ protected function check_for_matched($aadupn) { global $DB; $dbman = $DB->get_manager(); if ($dbman->table_exists('local_o365_connections')) { $match = $DB->get_record('local_o365_connections', ['aadupn' => $aadupn]); if (!empty($match) && \local_o365\utils::is_o365_connected($match->muserid) !== true) { return $DB->get_record('user', ['id' => $match->muserid]); } } return false; }
/** * Gets the instance of the correct api class. Use this method to get an instance of the api class. * * @return \local_onenote\api\base An implementation of the OneNote API. */ public static function getinstance() { global $USER, $SESSION, $CFG; $msaccountclass = '\\local_onenote\\api\\msaccount'; $o365class = '\\local_onenote\\api\\o365'; $class = ''; $iso365user = \local_o365\utils::is_o365_connected($USER->id) === true && class_exists('\\local_o365\\rest\\onenote') ? true : false; if ($iso365user === true) { $sesskey = class_exists('\\local_msaccount\\client') ? 'msaccount_client-' . md5(\local_msaccount\client::SCOPE) : null; $disableo365onenote = get_user_preferences('local_o365_disableo365onenote', 0); // If the user is logged in to msaccount OneNote, or has o365 OneNote disabled. $iso365user = !empty($sesskey) && !empty($SESSION->{$sesskey}) || !empty($disableo365onenote) ? false : $iso365user; if ($iso365user === true) { try { $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $onenoteresource = \local_o365\rest\onenote::get_resource(); $token = \local_o365\oauth2\token::instance($USER->id, $onenoteresource, $clientdata, $httpclient); if (empty($token)) { $iso365user = false; } } catch (\Exception $e) { $iso365user = false; } } if ($iso365user === true) { $class = $o365class; } else { $class = class_exists('\\local_msaccount\\client') ? $msaccountclass : null; } } else { $class = class_exists('\\local_msaccount\\client') ? $msaccountclass : null; } if (empty($class)) { throw new \moodle_exception('error_noapiavailable', 'local_onenote'); } if (empty(self::$instance)) { self::$instance = new $class(); } return self::$instance; }
/** * Initiate an OIDC authorization request. * * @param bool $uselogin Whether to switch the user's Moodle login method to OpenID Connect upon successful authorization. */ protected function doauthrequest($uselogin) { global $CFG, $SESSION, $DB, $USER; require_once $CFG->dirroot . '/auth/oidc/auth.php'; $stateparams = ['redirect' => '/local/o365/ucp.php']; $extraparams = []; $promptlogin = false; $o365connected = \local_o365\utils::is_o365_connected($USER->id); if ($o365connected === true) { // User is already connected. redirect('/local/o365/ucp.php'); } $connection = $DB->get_record('local_o365_connections', ['muserid' => $USER->id]); if (!empty($connection)) { // Matched user. $extraparams['login_hint'] = $connection->aadupn; $promptlogin = true; } $auth = new \auth_oidc\loginflow\authcode(); $auth->set_httpclient(new \auth_oidc\httpclient()); if ($uselogin !== true) { $SESSION->auth_oidc_connectiononly = true; $stateparams['connectiononly'] = true; } $auth->initiateauthrequest($promptlogin, $stateparams, $extraparams); }
/** * Add users with a given capability in a given context to a Sharepoint group. * * @param \context $context The context to check for the capability. * @param string $capability The capability to check for. * @param int $spgroupid The sharepoint group ID to add users to. */ public function add_users_with_capability_to_group($context, $capability, $spgroupid) { $now = time(); $users = get_users_by_capability($context, $capability); $results = []; // Assign users to group. foreach ($users as $user) { // Only Azure AD users can be added to sharepoint. if (\local_o365\utils::is_o365_connected($user->id) !== true) { continue; } try { $userupn = \local_o365\rest\azuread::get_muser_upn($user); } catch (\Exception $e) { continue; } if (!empty($userupn)) { $results[$user->id] = $this->add_user_to_group($userupn, $spgroupid, $user->id); } } return $results; }
/** * Repository method to serve the referenced file * * @see send_stored_file * * @param stored_file $storedfile the file that contains the reference * @param int $lifetime Number of seconds before the file should expire from caches (null means $CFG->filelifetime) * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin * @param array $options additional options affecting the file serving */ public function send_file($storedfile, $lifetime = null, $filter = 0, $forcedownload = false, array $options = null) { global $USER; $caller = '\\repository_office365::send_file'; $reference = $this->unpack_reference($storedfile->get_reference()); $fileuserid = $storedfile->get_userid(); $sourceclient = $this->get_onedrive_apiclient(false, $fileuserid); if (empty($sourceclient)) { \local_o365\utils::debug('Could not construct api client for user', 'send_file', $fileuserid); send_file_not_found(); die; } $fileinfo = $sourceclient->get_file_metadata($reference['id']); // Do embedding if relevant. $doembed = $this->do_embedding($reference, $forcedownload); if ($doembed === true) { if (\local_o365\utils::is_o365_connected($USER->id) !== true) { // Embedding currently only supported for logged-in Office 365 users. echo get_string('erroro365required', 'repository_office365'); die; } if (!empty($sourceclient)) { if (isset($fileinfo['webUrl'])) { $fileurl = $fileinfo['webUrl']; } else { $fileurl = isset($reference['url']) ? $reference['url'] : ''; } if (empty($fileurl)) { $errstr = 'Embed was requested, but could not get file info to complete request.'; \local_o365\utils::debug($errstr, 'send_file', ['reference' => $reference, 'fileinfo' => $fileinfo]); } else { try { $embedurl = $sourceclient->get_embed_url($reference['id'], $fileurl); $embedurl = isset($embedurl['value']) ? $embedurl['value'] : ''; } catch (\Exception $e) { // Note: exceptions will already be logged in get_embed_url. $embedurl = ''; } if (!empty($embedurl)) { redirect($embedurl); } else { if (!empty($fileurl)) { redirect($fileurl); } else { $errstr = 'Embed was requested, but could not complete.'; \local_o365\utils::debug($errstr, 'send_file', $reference); } } } } else { \local_o365\utils::debug('Could not construct OneDrive client for system api user.', 'send_file'); } } redirect($fileinfo['webUrl']); }
/** * Gets the instance of the correct api class. Use this method to get an instance of the api class. * * @return \local_onenote\api\base An implementation of the OneNote API. */ public static function getinstance() { global $USER, $SESSION, $CFG; $msaccountclass = '\\local_onenote\\api\\msaccount'; $o365class = '\\local_onenote\\api\\o365'; $iso365user = \local_o365\utils::is_o365_connected($USER->id) === true && class_exists('\\local_o365\\rest\\onenote') ? true : false; if ($iso365user === true) { require_once $CFG->dirroot . '/local/msaccount/msaccount_client.php'; $sesskey = 'msaccount_client-' . md5(\msaccount_client::SCOPE); $disableo365onenote = get_user_preferences('local_o365_disableo365onenote', 0); $iso365user = !empty($SESSION->{$sesskey}) || !empty($disableo365onenote) ? false : $iso365user; if ($iso365user === true) { try { $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $onenoteresource = \local_o365\rest\onenote::get_resource(); $token = \local_o365\oauth2\token::instance($USER->id, $onenoteresource, $clientdata, $httpclient); if (empty($token)) { $iso365user = false; } } catch (\Exception $e) { $iso365user = false; } } $class = $iso365user === true ? $o365class : $msaccountclass; } else { $class = $msaccountclass; } if (empty(self::$instance)) { self::$instance = new $class(); } return self::$instance; }
/** * Do the job. */ public function execute() { global $DB; $sql = 'SELECT mq.*, u.id as muserid, muserconn.id as muserexistingconnectionid, officeconn.id as officeuserexistingconnectionid, oidctok.id as officeuserexistingoidctoken FROM {local_o365_matchqueue} mq LEFT JOIN {user} u ON mq.musername = u.username LEFT JOIN {local_o365_connections} muserconn ON muserconn.muserid = u.id LEFT JOIN {local_o365_connections} officeconn ON officeconn.aadupn = mq.o365username LEFT JOIN {auth_oidc_token} oidctok ON oidctok.oidcusername = mq.o365username WHERE mq.completed = ? AND mq.errormessage = "" ORDER BY mq.id ASC LIMIT 0, 100'; $params = ['0']; $matchqueue = $DB->get_recordset_sql($sql, $params); $apiclient = $this->get_api(); foreach ($matchqueue as $matchrec) { mtrace('Processing ' . $matchrec->musername . '/' . $matchrec->o365username); try { // Check for matching Moodle user. if (empty($matchrec->muserid)) { $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->errormessage = get_string('task_processmatchqueue_err_nomuser', 'local_o365'); $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace($updatedrec->errormessage); continue; } // Check whether Moodle user is already o365 connected. if (\local_o365\utils::is_o365_connected($matchrec->muserid)) { $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->errormessage = get_string('task_processmatchqueue_err_museralreadyo365', 'local_o365'); $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace($updatedrec->errormessage); continue; } // Check existing matches for Moodle user. if (!empty($matchrec->muserexistingconnectionid)) { $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->errormessage = get_string('task_processmatchqueue_err_museralreadymatched', 'local_o365'); $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace($updatedrec->errormessage); continue; } // Check existing matches for Office user. if (!empty($matchrec->officeuserexistingconnectionid)) { $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->errormessage = get_string('task_processmatchqueue_err_o365useralreadymatched', 'local_o365'); $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace($updatedrec->errormessage); continue; } // Check existing tokens for Office 365 user (indicates o365 user is already connected to someone). if (!empty($matchrec->officeuserexistingoidctoken)) { $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->errormessage = get_string('task_processmatchqueue_err_o365useralreadyconnected', 'local_o365'); $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace($updatedrec->errormessage); continue; } // Check o365 username. $userfound = false; try { $o365user = $apiclient->get_user_by_upn($matchrec->o365username); $userfound = true; } catch (\Exception $e) { $userfound = false; } if ($userfound !== true) { $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->errormessage = get_string('task_processmatchqueue_err_noo365user', 'local_o365'); $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace($updatedrec->errormessage); continue; } // Match validated. $connectionrec = new \stdClass(); $connectionrec->muserid = $matchrec->muserid; $connectionrec->aadupn = \core_text::strtolower($o365user['userPrincipalName']); $connectionrec->uselogin = 0; $DB->insert_record('local_o365_connections', $connectionrec); $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace('Match record created for userid #' . $matchrec->muserid . ' and o365 user ' . $connectionrec->aadupn); } catch (\Exception $e) { $exceptionstring = $e->getMessage() . ': ' . $e->debuginfo; $updatedrec = new \stdClass(); $updatedrec->id = $matchrec->id; $updatedrec->errormessage = $exceptionstring; $updatedrec->completed = 1; $DB->update_record('local_o365_matchqueue', $updatedrec); mtrace($exceptionstring); } } $matchqueue->close(); return true; }