/**
  * Do the job.
  */
 public function execute()
 {
     if (\local_o365\utils::is_configured() !== true) {
         return false;
     }
     $aadsyncenabled = get_config('local_o365', 'aadsync');
     if (empty($aadsyncenabled) || $aadsyncenabled === 'photosynconlogin') {
         mtrace('Azure AD cron sync disabled. Nothing to do.');
         return true;
     }
     $httpclient = new \local_o365\httpclient();
     $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc();
     $usersync = new \local_o365\feature\usersync\main($clientdata, $httpclient);
     $skiptoken = get_config('local_o365', 'task_usersync_lastskiptoken');
     if (empty($skiptoken)) {
         $skiptoken = '';
     }
     for ($i = 0; $i < 5; $i++) {
         $users = $usersync->get_users('default', $skiptoken);
         if (!empty($users) && is_array($users) && !empty($users['value']) && is_array($users['value'])) {
             $usersync->sync_users($users['value']);
         } else {
             // No users returned, we're likely past the last page of results. Erase deltalink state and exit loop.
             mtrace('No more users to sync.');
             set_config('task_usersync_lastskiptoken', '', 'local_o365');
             break;
         }
         $nextlink = '';
         if (isset($users['odata.nextLink'])) {
             $nextlink = $users['odata.nextLink'];
         } else {
             if (isset($users['@odata.nextLink'])) {
                 $nextlink = $users['@odata.nextLink'];
             }
         }
         // If we have an odata.nextLink, extract deltalink value and store in $deltalink for the next loop. Otherwise break.
         if (!empty($nextlink)) {
             $skiptoken = $this->extract_skiptoken($nextlink);
             if (empty($skiptoken)) {
                 $skiptoken = '';
                 mtrace('Bad odata.nextLink received.');
                 break;
             }
         } else {
             $skiptoken = '';
             mtrace('No odata.nextLink received.');
             break;
         }
     }
     if (!empty($skiptoken)) {
         mtrace('Partial user sync completed. Saving place for next run.');
     } else {
         mtrace('Full user sync completed. Resetting saved state for new run.');
     }
     set_config('task_usersync_lastskiptoken', $skiptoken, 'local_o365');
     return true;
 }
 /**
  * Handle role_deleted event
  *
  * Does the following:
  *     - Unfortunately the role has already been deleted when we hear about it here, and have no way to determine the affected
  *     users. Therefore, we have to do a global sync.
  *
  * @param \core\event\role_deleted $event The triggered event.
  * @return bool Success/Failure.
  */
 public static function handle_role_deleted(\core\event\role_deleted $event)
 {
     if (\local_o365\utils::is_configured() !== true) {
         return false;
     }
     $roleid = $event->objectid;
     // Role deletions can be heavy - run in cron.
     $spaccesssync = new \local_o365\task\sharepointaccesssync();
     $spaccesssync->set_custom_data(['roleid' => '*', 'userid' => '*', 'contextid' => null]);
     \core\task\manager::queue_adhoc_task($spaccesssync);
     return true;
 }
Exemple #3
0
 /**
  * Setup repistory form.
  *
  * @param moodleform $mform Moodle form (passed by reference)
  * @param string $classname repository class name
  */
 public static function type_config_form($mform, $classname = 'repository')
 {
     global $CFG;
     $a = new stdClass();
     if (\local_o365\utils::is_configured() !== true) {
         $mform->addElement('static', null, '', get_string('notconfigured', 'repository_onenote', $CFG->wwwroot));
     }
     parent::type_config_form($mform);
 }
 /**
  * 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;
     if (\local_o365\utils::is_configured() !== true) {
         return false;
     }
     $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;
 }
 /**
  * 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;
 }
 /**
  * Handle calendar_unsubscribed event - queue calendar sync jobs for cron.
  *
  * @param \local_o365\event\calendar_unsubscribed $event The triggered event.
  * @return bool Success/Failure.
  */
 public static function handle_calendar_unsubscribed(\local_o365\event\calendar_unsubscribed $event)
 {
     if (\local_o365\utils::is_configured() !== true) {
         return false;
     }
     $eventdata = $event->get_data();
     $calunsubscribe = new \local_o365\feature\calsync\task\syncoldevents();
     $calunsubscribe->set_custom_data(['caltype' => $eventdata['other']['caltype'], 'caltypeid' => isset($eventdata['other']['caltypeid']) ? $eventdata['other']['caltypeid'] : 0, 'userid' => $eventdata['userid'], 'timecreated' => time()]);
     \core\task\manager::queue_adhoc_task($calunsubscribe);
     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()
 {
     global $DB;
     if (\local_o365\utils::is_configured() !== true) {
         return false;
     }
     $configsetting = get_config('local_o365', 'creategroups');
     if (empty($configsetting)) {
         mtrace('Groups not enabled, skipping...');
         return true;
     }
     $now = time();
     $httpclient = new \local_o365\httpclient();
     $clientdata = \local_o365\oauth2\clientdata::instance_from_oidc();
     $unifiedresource = \local_o365\rest\unified::get_resource();
     $unifiedtoken = \local_o365\oauth2\systemtoken::instance(null, $unifiedresource, $clientdata, $httpclient);
     if (empty($unifiedtoken)) {
         mtrace('Could not get unified API token.');
         return true;
     }
     $unifiedclient = new \local_o365\rest\unified($unifiedtoken, $httpclient);
     $aadresource = \local_o365\rest\azuread::get_resource();
     $aadtoken = \local_o365\oauth2\systemtoken::instance(null, $aadresource, $clientdata, $httpclient);
     if (empty($aadtoken)) {
         mtrace('Could not get Azure AD token.');
         return true;
     }
     $aadclient = new \local_o365\rest\azuread($aadtoken, $httpclient);
     $siterec = $DB->get_record('course', ['id' => SITEID]);
     $siteshortname = strtolower(preg_replace('/[^a-z0-9]+/iu', '', $siterec->shortname));
     $sql = 'SELECT crs.*
               FROM {course} crs
          LEFT JOIN {local_o365_objects} obj ON obj.type = ? AND obj.subtype = ? AND obj.moodleid = crs.id
              WHERE obj.id IS NULL AND crs.id != ?
              LIMIT 0, 5';
     $params = ['group', 'course', SITEID];
     $courses = $DB->get_recordset_sql($sql, $params);
     foreach ($courses as $course) {
         // Create group.
         $groupname = $siterec->shortname . ': ' . $course->fullname;
         $groupshortname = $siteshortname . '_' . $course->shortname;
         $response = $unifiedclient->create_group($groupname, $groupshortname);
         if (empty($response) || !is_array($response) || empty($response['id'])) {
             mtrace('Could not create group for course #' . $course->id);
             var_dump($response);
             continue;
         }
         mtrace('Created group ' . $response['id'] . ' for course #' . $course->id);
         $objectrec = ['type' => 'group', 'subtype' => 'course', 'objectid' => $response['id'], 'moodleid' => $course->id, 'o365name' => $groupname, 'timecreated' => $now, 'timemodified' => $now];
         $objectrec['id'] = $DB->insert_record('local_o365_objects', (object) $objectrec);
         mtrace('Recorded group object (' . $objectrec['objectid'] . ') into object table with record id ' . $objectrec['id']);
         // It takes a little while for the group object to register.
         mtrace('Waiting 10 seconds for group to register...');
         sleep(10);
         // Add enrolled users to group.
         mtrace('Adding users to group (' . $objectrec['objectid'] . ')');
         $coursecontext = \context_course::instance($course->id);
         list($esql, $params) = get_enrolled_sql($coursecontext);
         $sql = "SELECT u.*,\n                           tok.oidcuniqid as userobjectid\n                      FROM {user} u\n                      JOIN ({$esql}) je ON je.id = u.id\n                      JOIN {auth_oidc_token} tok ON tok.username = u.username AND tok.resource = :tokresource\n                     WHERE u.deleted = 0";
         $params['tokresource'] = 'https://graph.windows.net';
         $enrolled = $DB->get_recordset_sql($sql, $params);
         foreach ($enrolled as $user) {
             $response = $aadclient->add_member_to_group($objectrec['objectid'], $user->userobjectid);
             if ($response === true) {
                 mtrace('Added user #' . $user->id . ' (' . $user->userobjectid . ')');
             } else {
                 mtrace('Could not add user #' . $user->id . ' (' . $user->userobjectid . ')');
                 mtrace('Received: ' . $response);
             }
         }
         $enrolled->close();
     }
     $courses->close();
 }