/** * Handle group_member_removed event to remove a user from an o365 group. * * @param \core\event\group_member_removed $event The triggered event. * @return bool Success/Failure. */ public static function handle_group_member_removed(\core\event\group_member_removed $event) { global $DB; $unifiedapiclient = static::get_unified_api('handle_group_member_removed'); if (empty($unifiedapiclient)) { return false; } $azureadapiclient = static::get_azuread_api('handle_group_member_removed'); if (empty($azureadapiclient)) { return false; } $newmemberid = $event->relateduserid; $usergroupid = $event->objectid; // Look up group. $groupobjectrec = static::get_stored_groupdata($usergroupid, 'handle_group_member_removed'); if (empty($groupobjectrec)) { return false; } // Look up user. $userobjectdata = $DB->get_record('local_o365_objects', ['type' => 'user', 'moodleid' => $newmemberid]); if (empty($userobjectdata)) { $msg = 'Not removing user "' . $newmemberid . '" from group "' . $usergroupid . '". No Azure AD data for user found.'; $caller = '\\local_o365\\feature\\usergroups\\observers::handle_group_member_removed'; \local_o365\utils::debug($msg, $caller); return false; } $result = $azureadapiclient->remove_member_from_group($groupobjectrec->objectid, $userobjectdata->objectid); if ($result !== true) { $msg = 'Couldn\'t remove user from group.'; $caller = '\\local_o365\\feature\\usergroups\\observers::handle_group_member_removed'; \local_o365\utils::debug($msg, $caller, $result); return false; } return true; }
/** * Construct a sharepoint API client using the system API user. * * @return \local_o365\rest\sharepoint|bool A constructed sharepoint API client, or false if error. */ public static function construct_sharepoint_api_with_system_user() { try { $spresource = \local_o365\rest\sharepoint::get_resource(); if (!empty($spresource)) { $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (!empty($sptoken)) { $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); return $sharepoint; } } } catch (\Exception $e) { \local_o365\utils::debug($e->getMessage(), get_called_class()); } return false; }
/** * Processes API responses. * * @param string $response The raw response from an API call. * @param array $expectedstructure A structure to validate. * @return array|null Array if successful, null if not. */ public function process_apicall_response($response, array $expectedstructure = array()) { $backtrace = debug_backtrace(0); $callingclass = isset($backtrace[1]['class']) ? $backtrace[1]['class'] : '?'; $callingfunc = isset($backtrace[1]['function']) ? $backtrace[1]['function'] : '?'; $callingline = isset($backtrace[0]['line']) ? $backtrace[0]['line'] : '?'; $caller = $callingclass . '::' . $callingfunc . ':' . $callingline; $result = @json_decode($response, true); if (empty($result) || !is_array($result)) { \local_o365\utils::debug('Bad response received', $caller, $response); throw new \moodle_exception('erroro365apibadcall', 'local_o365'); } if (isset($result['odata.error'])) { $errmsg = 'Error response received.'; \local_o365\utils::debug($errmsg, $caller, $result['odata.error']); if (isset($result['odata.error']['message']) && isset($result['odata.error']['message']['value'])) { $apierrormessage = $result['odata.error']['message']['value']; throw new \moodle_exception('erroro365apibadcall_message', 'local_o365', '', htmlentities($apierrormessage)); } else { throw new \moodle_exception('erroro365apibadcall', 'local_o365'); } } if (isset($result['error'])) { $errmsg = 'Error response received.'; \local_o365\utils::debug($errmsg, $caller, $result['error']); if (isset($result['error']['message'])) { $apierrormessage = 'Unknown error, check logs for more information.'; if (is_string($result['error']['message'])) { $apierrormessage = $result['error']['message']; } else { if (is_array($result['error']['message']) && isset($result['error']['message']['value'])) { $apierrormessage = $result['error']['message']['value']; } } throw new \moodle_exception('erroro365apibadcall_message', 'local_o365', '', htmlentities($apierrormessage)); } else { throw new \moodle_exception('erroro365apibadcall', 'local_o365'); } } foreach ($expectedstructure as $key => $val) { if (!isset($result[$key])) { $errmsg = 'Invalid structure received. No "' . $key . '"'; \local_o365\utils::debug($errmsg, $caller, $result); throw new \moodle_exception('erroro365apibadcall_message', 'local_o365', '', $errmsg); } if ($val !== null && $result[$key] !== $val) { $strreceivedval = \local_o365\utils::tostring($result[$key]); $strval = \local_o365\utils::tostring($val); $errmsg = 'Invalid structure received. Invalid "' . $key . '". Received "' . $strreceivedval . '", expected "' . $strval . '"'; \local_o365\utils::debug($errmsg, $caller, $result); throw new \moodle_exception('erroro365apibadcall_message', 'local_o365', '', $errmsg); } } return $result; }
/** * Get the Azure AD UPN of a connected Moodle user. * * @param \stdClass $user The Moodle user. * @return string|bool The user's Azure AD UPN, or false if failure. */ public static function get_muser_upn($user) { global $DB; $now = time(); if (is_numeric($user)) { $user = $DB->get_record('user', ['id' => $user]); if (empty($user)) { \local_o365\utils::debug('User not found', 'rest\\azuread\\get_muser_upn', $user); return false; } } // Get user UPN. $userobjectdata = $DB->get_record('local_o365_objects', ['type' => 'user', 'moodleid' => $user->id]); if (!empty($userobjectdata)) { return $userobjectdata->o365name; } else { // Get user data. $authoidcuserdata = $DB->get_record('auth_oidc_token', ['username' => $user->username]); if (empty($authoidcuserdata)) { // No data for the user in the OIDC token table. Can't proceed. \local_o365\utils::debug('No oidc token found for user.', 'rest\\azuread\\get_muser_upn', $user->username); return false; } $httpclient = new \local_o365\httpclient(); try { $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); } catch (\Exception $e) { \local_o365\utils::debug($e->getMessage()); return false; } $resource = static::get_resource(); $token = \local_o365\oauth2\systemtoken::instance(null, $resource, $clientdata, $httpclient); $aadapiclient = new \local_o365\rest\azuread($token, $httpclient); $aaduserdata = $aadapiclient->get_user($authoidcuserdata->oidcuniqid); $userobjectdata = (object) ['type' => 'user', 'subtype' => '', 'objectid' => $aaduserdata['objectId'], 'o365name' => $aaduserdata['userPrincipalName'], 'moodleid' => $user->id, 'timecreated' => $now, 'timemodified' => $now]; $userobjectdata->id = $DB->insert_record('local_o365_objects', $userobjectdata); return $userobjectdata->o365name; } }
/** * Looks for links pointing to Office 365 Video content and processes them. * * @param $link HTML tag containing a link * @return string HTML content after processing. */ function filter_oembed_o365videocallback($link) { if (empty($link[3])) { return $link[0]; } $link[3] = preg_replace("/&/", "&", $link[3]); $values = array(); parse_str($link[3], $values); if (empty($values['chid']) || empty($values['vid'])) { return $link[0]; } if (!\local_o365\rest\sharepoint::is_configured()) { \local_o365\utils::debug('filter_oembed share point is not configured', 'filter_oembed_o365videocallback'); return $link[0]; } try { $spresource = \local_o365\rest\sharepoint::get_resource(); if (!empty($spresource)) { $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (!empty($sptoken)) { $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); // Retrieve api url for video service. $url = $sharepoint->videoservice_discover(); if (!empty($url)) { $sharepoint->override_resource($url); $width = 640; if (!empty($values['width'])) { $width = $values['width']; } $height = 360; if (!empty($values['height'])) { $height = $values['height']; } // Retrieve embed code. return $sharepoint->get_video_embed_code($values['chid'], $values['vid'], $width, $height); } } } } catch (\Exception $e) { \local_o365\utils::debug('filter_oembed share point execption: ' . $e->getMessage(), 'filter_oembed_o365videocallback'); } return $link[0]; }
/** * Create a OneNote page inside the given section using the postdata containing the content of the page. * @param string $sectionid Id of OneNote section which the page will be created in. * @param string $postdata String containing the postdata containing the contents of the page. * @param string $boundary Boundary string to be used during the POST request. * @return mixed|null|string The HTTP response object from the POST request. */ protected function create_page_from_postdata($sectionid, $postdata, $boundary) { try { $url = static::API . '/sections/' . $sectionid . '/pages'; $token = $this->get_token(); if (empty($token)) { \local_o365\utils::debug('Could not get user token', 'create_page_from_postdata'); return null; } $ch = curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $headers = ['Content-Type: multipart/form-data; boundary=' . $boundary, 'Authorization: Bearer ' . rawurlencode($token)]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); $rawresponse = curl_exec($ch); // Check if curl call fails. if ($rawresponse === false) { $errorno = curl_errno($ch); curl_close($ch); // If curl call fails and reason is net connectivity return it or return null. return in_array($errorno, ['6', '7', '28']) ? 'connection_error' : null; } $info = curl_getinfo($ch); curl_close($ch); if ($info['http_code'] == 201) { $responsewithoutheader = substr($rawresponse, $info['header_size']); $response = json_decode($responsewithoutheader); return $response; } } catch (\Exception $e) { \local_o365\utils::debug($e->getMessage()); } return null; }
/** * Do the job. */ public function execute() { global $DB, $CFG; require_once $CFG->dirroot . '/calendar/lib.php'; if (\local_o365\utils::is_configured() !== true) { return false; } // Get calendars set to sync in. $starttime = time(); \local_o365\feature\calsync\observers::set_event_import(true); // Using a direct query here so we don't run into static cache issues. $laststarttime = $DB->get_record('config_plugins', ['plugin' => 'local_o365', 'name' => 'calsyncinlastrun']); $laststarttime = !empty($laststarttime) && !empty($laststarttime->value) ? $laststarttime->value : 0; $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $calsubs = $DB->get_recordset_select('local_o365_calsub', 'syncbehav = ? OR syncbehav = ?', ['in', 'both']); $calsync = new \local_o365\feature\calsync\main($clientdata, $httpclient); foreach ($calsubs as $i => $calsub) { try { mtrace('Syncing events for user #' . $calsub->user_id); $events = $calsync->get_events($calsub->user_id, $calsub->o365calid, $laststarttime); if (!empty($events) && is_array($events) && isset($events['value']) && is_array($events['value'])) { if (!empty($events['value'])) { foreach ($events['value'] as $i => $event) { if (!isset($event['Id'])) { $errmsg = 'Skipped an event because of malformed data.'; \local_o365\utils::debug($errmsg, 'importfromoutlook', $event); mtrace($errmsg); continue; } $idmapexists = $DB->record_exists('local_o365_calidmap', ['outlookeventid' => $event['Id']]); if ($idmapexists === false) { // Create Moodle event. $eventparams = ['name' => $event['Subject'], 'description' => $event['Body']['Content'], 'eventtype' => $calsub->caltype, 'repeatid' => 0, 'modulename' => 0, 'instance' => 0, 'timestart' => strtotime($event['Start']), 'visible' => 1, 'uuid' => '', 'sequence' => 1]; $end = strtotime($event['End']); $eventparams['timeduration'] = $end - $eventparams['timestart']; if ($calsub->caltype === 'user') { $eventparams['userid'] = $calsub->caltypeid; } if ($calsub->caltype === 'course') { $eventparams['courseid'] = $calsub->caltypeid; } $moodleevent = \calendar_event::create($eventparams, false); if (!empty($moodleevent) && !empty($moodleevent->id)) { $idmaprec = ['eventid' => $moodleevent->id, 'outlookeventid' => $event['Id'], 'origin' => 'o365', 'userid' => $calsub->user_id]; $DB->insert_record('local_o365_calidmap', (object) $idmaprec); mtrace('Successfully imported event #' . $moodleevent->id); } } } } else { mtrace('No new events to sync in.'); } } else { $errmsg = 'Bad response received when fetching events.'; \local_o365\utils::debug($errmsg, 'importfromoutlook', $events); mtrace($errmsg); } } catch (\Exception $e) { \local_o365\utils::debug('Error syncing events', 'importfromoutlook', $e->getMessage()); mtrace('Error: ' . $e->getMessage()); } } $calsubs->close(); \local_o365\feature\calsync\observers::set_event_import(false); set_config('calsyncinlastrun', $starttime, 'local_o365'); return true; }
/** * Do the job. */ public function execute() { global $DB; // API Setup. try { $spresource = \local_o365\rest\sharepoint::get_resource(); if (empty($spresource)) { throw new \moodle_exception('erroracplocalo365notconfig', 'local_o365'); } $httpclient = new \local_o365\httpclient(); $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc(); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (empty($sptoken)) { throw new \moodle_exception('erroracpnosptoken', 'local_o365'); } $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); } catch (\Exception $e) { $errmsg = 'ERROR: Problem initializing SharePoint API. Reason: ' . $e->getMessage(); mtrace($errmsg); \local_o365\utils::debug($errmsg, 'local_o365\\task\\sharepointinit::execute'); set_config('sharepoint_initialized', 'error', 'local_o365'); return false; } // Create parent site(s). try { mtrace('Creating parent site for Moodle...'); $moodlesiteuri = $sharepoint->get_moodle_parent_site_uri(); $sitelevels = explode('/', $moodlesiteuri); $currentparentsite = ''; foreach ($sitelevels as $partialurl) { $sharepoint->set_site($currentparentsite); if ($sharepoint->site_exists($currentparentsite . '/' . $partialurl) === false) { $moodlesitename = get_string('acp_parentsite_name', 'local_o365'); $moodlesitedesc = get_string('acp_parentsite_desc', 'local_o365'); $frontpagerec = $DB->get_record('course', ['id' => SITEID], 'id,shortname'); if (!empty($frontpagerec) && !empty($frontpagerec->shortname)) { $moodlesitename = $frontpagerec->shortname; } mtrace('Setting parent site to "' . $currentparentsite . '", creating subsite "' . $partialurl . '"'); $result = $sharepoint->create_site($moodlesitename, $partialurl, $moodlesitedesc); $currentparentsite .= '/' . $partialurl; mtrace('Created parent site "' . $currentparentsite . '"'); } else { $currentparentsite .= '/' . $partialurl; mtrace('Parent site "' . $currentparentsite . '" already exists.'); } } mtrace('Finished creating Moodle parent site.'); } catch (\Exception $e) { $errmsg = 'ERROR: Problem creating parent site. Reason: ' . $e->getMessage(); mtrace($errmsg); \local_o365\utils::debug($errmsg, 'local_o365\\task\\sharepointinit::execute'); set_config('sharepoint_initialized', 'error', 'local_o365'); return false; } // Create course sites. mtrace('Creating course subsites in "' . $moodlesiteuri . '"'); $sharepoint->set_site($moodlesiteuri); $courses = $DB->get_recordset('course'); $successes = []; $failures = []; foreach ($courses as $course) { if ($course->id == SITEID) { continue; } try { $sharepoint->create_course_site($course); $successes[] = $course->id; mtrace('Created course subsite for course ' . $course->id); } catch (\Exception $e) { mtrace('Encountered error creating course subsite for course ' . $course->id); $failures[$course->id] = $e->getMessage(); } } if (!empty($failures)) { $errmsg = 'ERROR: Encountered problems creating course sites.'; mtrace($errmsg . ' See logs.'); \local_o365\utils::debug($errmsg, 'local_o365\\task\\sharepointinit::execute', $failures); set_config('sharepoint_initialized', 'error', 'local_o365'); } else { set_config('sharepoint_initialized', '1', 'local_o365'); mtrace('SharePoint successfully initialized.'); return true; } }
/** * 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']); }
/** * Delete a course site and it's associated groups. * @param int $courseid The ID of the course to delete the site for. * @return bool Success/Failure. */ public function delete_course_site($courseid) { global $DB; $spsite = $DB->get_record('local_o365_coursespsite', ['courseid' => $courseid]); if (empty($spsite)) { // No site created (that we know about). $errmsg = 'Did not delete course SharePoint site because no record of a SharePoint site for that course was found.'; \local_o365\utils::debug($errmsg, 'rest\\sharepoint\\delete_course_site', $courseid); return false; } $this->set_site($spsite->siteurl); $spgroupsql = 'SELECT spgroup.* FROM {local_o365_spgroupdata} spgroup JOIN {local_o365_coursespsite} spsite ON spgroup.coursespsiteid = spsite.id WHERE spsite.courseid = ?'; $spgroups = $DB->get_records_sql($sqlgroupsql, [$courseid]); foreach ($spgroups as $spgroup) { try { $this->delete_group_by_id($spgroup->groupid); $DB->delete_records('local_o365_spgroupdata', ['id' => $spgroup->id]); } catch (\Exception $e) { // If the API call failed we can still continue. // Error is logged in API call function if failed. } } $this->delete_site(); $DB->delete_records('local_o365_coursespsite', ['courseid' => $courseid]); return true; }
/** * Do the job. */ public function execute() { $opdata = $this->get_custom_data(); $timecreated = isset($opdata->timecreated) ? $opdata->timecreated : time(); if (\local_o365\utils::is_configured() !== true) { \local_o365\utils::debug(get_string('erroracpauthoidcnotconfig', 'local_o365'), get_called_class()); return false; } // Sync site events. if ($opdata->caltype === 'site') { $this->sync_siteevents($timecreated); } else { if ($opdata->caltype === 'course') { $this->sync_courseevents($opdata->caltypeid, $timecreated); } else { if ($opdata->caltype === 'user') { $this->sync_userevents($opdata->userid, $timecreated); } } } }
/** * Do the job. */ public function execute() { $reqcap = \local_o365\rest\sharepoint::get_course_site_required_capability(); $oidcconfig = get_config('auth_oidc'); if (!empty($oidcconfig)) { $spresource = \local_o365\rest\sharepoint::get_resource(); if (!empty($spresource)) { $httpclient = new \local_o365\httpclient(); $clientdata = new \local_o365\oauth2\clientdata($oidcconfig->clientid, $oidcconfig->clientsecret, $oidcconfig->authendpoint, $oidcconfig->tokenendpoint); $sptoken = \local_o365\oauth2\systemtoken::instance(null, $spresource, $clientdata, $httpclient); if (!empty($sptoken)) { $sharepoint = new \local_o365\rest\sharepoint($sptoken, $httpclient); } else { $errmsg = 'Could not get system API user token for SharePoint'; \local_o365\utils::debug($errmsg, 'local_o365\\task\\sharepointaccesssync::execute'); } } } if (empty($sharepoint)) { throw new \moodle_exception('errorcreatingsharepointclient', 'local_o365'); } $opdata = $this->get_custom_data(); if ($opdata->userid !== '*' && $opdata->roleid !== '*' && !empty($opdata->contextid)) { // Single user role assign/unassign. $this->do_role_assignmentchange($opdata->roleid, $opdata->userid, $opdata->contextid, $reqcap, $sharepoint); } else { if ($opdata->userid === '*' && $opdata->roleid !== '*') { // Capability update. $this->do_role_capabilitychange($opdata->roleid, $reqcap, $sharepoint); } else { if ($opdata->roleid === '*' && $opdata->userid === '*') { // Role deleted. $this->do_role_delete($reqcap, $sharepoint); } } } }
/** * Render OneNote section of the block. * * @return string HTML for the rendered OneNote section of the block. */ protected function render_onenote() { global $USER, $PAGE; $action = optional_param('action', '', PARAM_TEXT); try { $onenoteapi = \local_onenote\api\base::getinstance(); $output = ''; if ($onenoteapi->is_logged_in()) { // Add the "save to onenote" button if we are on an assignment page. $onassignpage = $PAGE->cm && $PAGE->cm->modname == 'assign' && $action == 'editsubmission' ? true : false; if ($onassignpage === true && $onenoteapi->is_student($PAGE->cm->id, $USER->id)) { $workstr = get_string('workonthis', 'block_microsoft'); $output .= $onenoteapi->render_action_button($workstr, $PAGE->cm->id) . '<br /><br />'; } // Find moodle notebook, create if not found. $moodlenotebook = null; $cache = \cache::make('block_microsoft', 'onenotenotebook'); $moodlenotebook = $cache->get($USER->id); if (empty($moodlenotebook)) { $moodlenotebook = $this->get_onenote_notebook($onenoteapi); $result = $cache->set($USER->id, $moodlenotebook); } if (!empty($moodlenotebook)) { $url = new \moodle_url($moodlenotebook['url']); $stropennotebook = get_string('linkonenote', 'block_microsoft'); $linkattrs = ['onclick' => 'window.open(this.href,\'_blank\'); return false;', 'class' => 'servicelink block_microsoft_onenote']; $output .= \html_writer::link($url->out(false), $stropennotebook, $linkattrs); } else { $output .= get_string('error_nomoodlenotebook', 'block_microsoft'); } } else { $output .= $this->render_signin_widget($onenoteapi->get_login_url()); } return $output; } catch (\Exception $e) { if (class_exists('\\local_o365\\utils')) { $debuginfo = !empty($e->debuginfo) ? $e->debuginfo : null; \local_o365\utils::debug($e->getMessage(), 'block_microsoft', $debuginfo); } return '<span class="block_microsoft_onenote servicelink">' . get_string('linkonenote_unavailable', 'block_microsoft') . '<br /><small>' . get_string('contactadmin', 'block_microsoft') . '</small></span>'; } }
/** * Get a token instance for a new resource. * * @param string $resource The new resource. * @param \local_o365\oauth2\clientdata $clientdata Client information. * @param \local_o365\httpclientinterface $httpclient An HTTP client. * @return \local_o365\oauth2\token|bool A constructed token for the new resource, or false if failure. */ public static function get_for_new_resource($userid, $resource, \local_o365\oauth2\clientdata $clientdata, $httpclient) { $aadgraphtoken = static::instance($userid, 'https://graph.windows.net', $clientdata, $httpclient); if (!empty($aadgraphtoken)) { $params = ['client_id' => $clientdata->get_clientid(), 'client_secret' => $clientdata->get_clientsecret(), 'grant_type' => 'refresh_token', 'refresh_token' => $aadgraphtoken->get_refreshtoken(), 'resource' => $resource]; $params = http_build_query($params, '', '&'); $tokenendpoint = $clientdata->get_tokenendpoint(); $header = ['Content-Type: application/x-www-form-urlencoded', 'Content-Length: ' . strlen($params)]; $httpclient->resetHeader(); $httpclient->setHeader($header); $tokenresult = $httpclient->post($tokenendpoint, $params); $tokenresult = @json_decode($tokenresult, true); if (!empty($tokenresult) && isset($tokenresult['token_type']) && $tokenresult['token_type'] === 'Bearer') { static::store_new_token($userid, $tokenresult['access_token'], $tokenresult['expires_on'], $tokenresult['refresh_token'], $tokenresult['scope'], $tokenresult['resource']); $token = static::instance($userid, $resource, $clientdata, $httpclient); return $token; } else { $errmsg = 'Problem encountered getting a new token.'; if (isset($tokenresult['access_token'])) { $tokenresult['access_token'] = '---'; } if (isset($tokenresult['refresh_token'])) { $tokenresult['refresh_token'] = '---'; } $debuginfo = ['tokenresult' => $tokenresult, 'resource' => $resource]; \local_o365\utils::debug($errmsg, 'local_o365\\oauth2\\token::get_for_new_resource', $debuginfo); } } return false; }
/** * Check setup in Azure. */ public function mode_checksetup() { $data = new \stdClass(); $success = false; $enableunifiedapi = optional_param('enableunifiedapi', 0, PARAM_INT); set_config('enableunifiedapi', $enableunifiedapi, 'local_o365'); $chineseapi = optional_param('chineseapi', 0, PARAM_INT); set_config('chineseapi', $chineseapi, 'local_o365'); $aadtenant = required_param('aadtenant', PARAM_TEXT); set_config('aadtenant', $aadtenant, 'local_o365'); $odburl = required_param('odburl', PARAM_TEXT); set_config('odburl', $odburl, 'local_o365'); $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 \moodle_exception('errorchecksystemapiuser', 'local_o365'); } // Legacy API. $legacyapi = new \stdClass(); try { $aadapiclient = new \local_o365\rest\azuread($token, $httpclient); list($missingperms, $haswrite) = $aadapiclient->check_permissions(); $legacyapi->missingperms = $missingperms; $legacyapi->haswrite = $haswrite; } catch (\Exception $e) { \local_o365\utils::debug($e->getMessage(), 'mode_checksetup:legacy'); $legacyapi->error = $e->getMessage(); } $data->legacyapi = $legacyapi; // Unified API. $unifiedapi = new \stdClass(); $unifiedapi->active = false; if (\local_o365\rest\unified::is_enabled() === true) { try { $httpclient = new \local_o365\httpclient(); $unifiedresource = \local_o365\rest\unified::get_resource(); $token = \local_o365\oauth2\systemtoken::instance(null, $unifiedresource, $clientdata, $httpclient); if (empty($token)) { throw new \moodle_exception('errorchecksystemapiuser', 'local_o365'); } $unifiedapiclient = new \local_o365\rest\unified($token, $httpclient); $unifiedpermsresult = $unifiedapiclient->check_permissions(); if ($unifiedpermsresult === null) { $unifiedapi->active = false; } else { $unifiedapi->active = true; $unifiedapi->missingperms = $unifiedpermsresult; } } catch (\Exception $e) { $unifiedapi->active = false; \local_o365\utils::debug($e->getMessage(), 'mode_checksetup:unified'); $unifiedapi->error = $e->getMessage(); } } $data->unifiedapi = $unifiedapi; set_config('unifiedapiactive', (int) $unifiedapi->active, 'local_o365'); set_config('azuresetupresult', serialize($data), 'local_o365'); $success = true; echo $this->ajax_response($data, $success); }