/** * Add the users to the system. Make sure that they have to change their * password on next login also. */ function uploadcsv_submit(Pieform $form, $values) { global $SESSION, $CSVDATA, $FORMAT, $UPDATES, $USER, $MEMBERS, $GROUPS; $formatkeylookup = array_flip($FORMAT); $institution = $values['institution']; db_begin(); $lines_done = 0; $num_lines = count($CSVDATA); foreach ($MEMBERS as $gid => $members) { $updates = group_update_members($gid, $members, $lines_done, $num_lines); $lines_done += sizeof($members); if (empty($updates)) { unset($UPDATES[$GROUPS[$gid]]); } else { $UPDATES[$GROUPS[$gid]] = $updates; log_debug('updated group members ' . $GROUPS[$gid] . ' (' . implode(', ', array_keys((array) $updates)) . ')'); } } db_commit(); // TODO: Fix this to show correct info $SESSION->add_ok_msg(get_string('csvfileprocessedsuccessfully', 'admin')); if ($UPDATES) { $updatemsg = smarty_core(); $updatemsg->assign('updates', $UPDATES); $SESSION->add_info_msg($updatemsg->fetch('admin/groups/memberscsvupdatemessage.tpl'), false); } else { $SESSION->add_ok_msg(get_string('numbergroupsupdated', 'admin', 0)); } set_progress_done('uploadgroupmemberscsv'); redirect('/admin/groups/uploadmemberscsv.php'); }
/** * update one or more sets of group membership * * @param array $groups */ public static function update_group_members($groups) { global $USER, $WEBSERVICE_INSTITUTION; // Do basic automatic PARAM checks on incoming data, using params description $params = self::validate_parameters(self::update_group_members_parameters(), array('groups' => $groups)); db_begin(); $groupids = array(); foreach ($params['groups'] as $group) { // Make sure that the group doesn't already exist if (!empty($group['id'])) { if (!($dbgroup = get_record('group', 'id', $group['id'], 'deleted', 0))) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('groupnotexist', 'auth.webservice', $group['id'])); } } else { if (!empty($group['name'])) { if (!($dbgroup = get_record('group', 'name', $group['name'], 'deleted', 0))) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('groupnotexist', 'auth.webservice', $group['name'])); } } else { if (!empty($group['shortname'])) { if (empty($group['institution'])) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('instmustset', 'auth.webservice', $group['shortname'])); } if (!($dbgroup = get_record('group', 'shortname', $group['shortname'], 'institution', $group['institution'], 'deleted', 0))) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('groupnotexist', 'auth.webservice', $group['shortname'] . '/' . $group['institution'])); } } else { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('nogroup', 'auth.webservice')); } } } // are we allowed to administer this group if (!empty($dbgroup->institution) && $WEBSERVICE_INSTITUTION != $dbgroup->institution) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('accessdeniedforinstgroup', 'auth.webservice', $group['institution'], $group['name'])); } if (!empty($dbgroup->institution) && !$USER->can_edit_institution($dbgroup->institution)) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('accessdeniedforinstgroup', 'auth.webservice', $group['institution'], $group['shortname'])); } // get old members $oldmembers = get_records_array('group_member', 'group', $dbgroup->id, '', 'member,role'); $existingmembers = array(); if (!empty($oldmembers)) { foreach ($oldmembers as $member) { $existingmembers[$member->member] = $member->role; } } // check that the members exist and we are allowed to administer them foreach ($group['members'] as $member) { if (!empty($member['id'])) { $dbuser = get_record('usr', 'id', $member['id'], 'deleted', 0); } else { if (!empty($member['username'])) { $dbuser = get_record('usr', 'username', $member['username'], 'deleted', 0); } else { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('nousernameoridgroup', 'auth.webservice', $group['name'])); } } if (empty($dbuser)) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('invalidusergroup', 'auth.webservice', $member['id'] . '/' . $member['username'], $group['name'])); } // check user is in this institution if this is an institution controlled group if (!empty($dbgroup->shortname) && !empty($dbgroup->institution)) { if (!mahara_external_in_institution($dbuser, $WEBSERVICE_INSTITUTION)) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('notauthforuseridinstitutiongroup', 'auth.webservice', $dbuser->id, $WEBSERVICE_INSTITUTION, $group['shortname'])); } } else { // Make sure auth is valid if (!($authinstance = get_record('auth_instance', 'id', $dbuser->authinstance))) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('invalidauthtype', 'auth.webservice', $dbuser->authinstance)); } // check the institution is allowed // basic check authorisation to edit for the current institution of the user if (!$USER->can_edit_institution($authinstance->institution)) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('accessdeniedforinstuser', 'auth.webservice', $authinstance->institution, $dbuser->username)); } } // determine the changes to the group membership if ($member['action'] == 'remove') { if (isset($existingmembers[$dbuser->id])) { unset($existingmembers[$dbuser->id]); } // silently fail } else { if ($member['action'] == 'add') { // check the specified role if (!in_array($member['role'], self::$member_roles)) { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('invalidmemroles', 'auth.webservice', $member['role'], $dbuser->username)); } $existingmembers[$dbuser->id] = $member['role']; // silently fail } else { throw new WebserviceInvalidParameterException('update_group_members | ' . get_string('membersinvalidaction', 'auth.webservice', $member['action'], $dbuser->id . '/' . $dbuser->username, $group['name'])); } } } // now update the group membership group_update_members($dbgroup->id, $existingmembers); } db_commit(); return null; }
/** * Update details of an existing group. * * @param array $new New values for the group table. * @param bool $create Create the group if it doesn't exist yet */ function group_update($new, $create = false) { if (!empty($new->id)) { $old = get_record_select('group', 'id = ? AND deleted = 0', array($new->id)); } else { if (!empty($new->institution) && isset($new->shortname) && strlen($new->shortname)) { $old = get_record_select('group', 'shortname = ? AND institution = ? AND deleted = 0', array($new->shortname, $new->institution)); if (!$old && $create) { return group_create((array) $new); } } } if (!$old) { throw new NotFoundException("group_update: group not found"); } if (!empty($old->institution) && $old->institution != 'mahara') { // Api-controlled group; check permissions. global $USER; if (!$USER->can_edit_institution($old->institution)) { throw new AccessDeniedException("group_update: cannot update a group in this institution"); } } if (isset($new->submittableto) && empty($new->submittableto) || !isset($new->submittableto) && empty($old->submittableto)) { $new->allowarchives = 0; } // Institution and shortname cannot be updated (yet) unset($new->institution); unset($new->shortname); foreach (array('id', 'grouptype', 'public', 'request', 'submittableto', 'allowarchives', 'editroles', 'hidden', 'hidemembers', 'hidemembersfrommembers', 'groupparticipationreports') as $f) { if (!isset($new->{$f})) { $new->{$f} = $old->{$f}; } } if (isset($new->jointype)) { log_warn("group_update: ignoring supplied jointype"); unset($new->jointype); } // If the caller isn't trying to enable open/controlled, use the old values if (!isset($new->open)) { $new->open = empty($new->controlled) && $old->jointype == 'open'; } if (!isset($new->controlled)) { $new->controlled = empty($new->open) && $old->jointype == 'controlled'; } if ($new->open) { if ($new->controlled) { throw new InvalidArgumentException("group_update: a group cannot have both open and controlled membership"); } $new->request = 0; $new->jointype = 'open'; } else { if ($new->controlled) { $new->jointype = 'controlled'; } else { $new->jointype = 'approve'; } } unset($new->open); unset($new->controlled); // Ensure only one of invitefriends,suggestfriends gets enabled. if (!empty($new->invitefriends)) { $new->suggestfriends = 0; } else { if (!isset($new->invitefriends)) { $new->invitefriends = (int) ($old->invitefriends && empty($new->suggestfriends)); } } if (!isset($new->suggestfriends)) { $new->suggestfriends = $old->suggestfriends; } $diff = array_diff_assoc((array) $new, (array) $old); if (empty($diff)) { return null; } db_begin(); if (isset($new->members)) { group_update_members($new->id, $new->members); unset($new->members); } update_record('group', $new, 'id'); // Add users who have requested membership of a group that's becoming // open if ($old->jointype != 'open' && $new->jointype == 'open') { $userids = get_column_sql(' SELECT u.id FROM {usr} u JOIN {group_member_request} r ON u.id = r.member WHERE r.group = ? AND u.deleted = 0', array($new->id)); if ($userids) { foreach ($userids as $uid) { group_add_user($new->id, $uid); } } } // Invitations to controlled groups are allowed, but if the admin is // changing a group to controlled membership, we'll assume they want // want to revoke all the existing invitations. if ($old->jointype != 'controlled' && $new->jointype == 'controlled') { delete_records('group_member_invite', 'group', $new->id); } // Remove requests if ($old->request && !$new->request) { delete_records('group_member_request', 'group', $new->id); } // When the group type changes, make sure everyone has a valid role. safe_require('grouptype', $new->grouptype); $allowedroles = call_static_method('GroupType' . ucfirst($new->grouptype), 'get_roles'); set_field_select('group_member', 'role', 'member', '"group" = ? AND NOT role IN (' . join(',', array_fill(0, count($allowedroles), '?')) . ')', array_merge(array($new->id), $allowedroles)); // When a group changes from public -> private or vice versa, set the // appropriate access permissions on the group homepage view. if ($old->public != $new->public) { $homepageid = get_field('view', 'id', 'type', 'grouphomepage', 'group', $new->id); if ($old->public && !$new->public) { delete_records('view_access', 'view', $homepageid, 'accesstype', 'public'); insert_record('view_access', (object) array('view' => $homepageid, 'accesstype' => 'loggedin', 'ctime' => db_format_timestamp(time()))); } else { if (!$old->public && $new->public) { delete_records('view_access', 'view', $homepageid, 'accesstype', 'loggedin'); insert_record('view_access', (object) array('view' => $homepageid, 'accesstype' => 'public', 'ctime' => db_format_timestamp(time()))); } } } db_commit(); return $diff; }
/** * synchronize Mahara's groups with groups defined on a LDAP server * * @param boolean $dryrun dummy execution. Do not perform any database operations * @return boolean */ function sync_groups($dryrun = false) { global $USER; log_info('---------- started groupsync auth instance ' . $this->instanceid . ' at ' . date('r', time()) . ' ----------'); if (!$this->get_config('syncgroupscron')) { log_info('Not set to sync groups, so exiting'); return true; } // We need to tell the session that we are the admin user, so that we have permission to manipulate groups $USER->reanimate(1, 1); $syncbyattribute = $this->get_config('syncgroupsbyuserfield') && $this->get_config('syncgroupsgroupattribute'); $syncbyclass = $this->get_config('syncgroupsbyclass') && $this->get_config('syncgroupsgroupclass') && $this->get_config('syncgroupsgroupattribute') && $this->get_config('syncgroupsmemberattribute'); $excludelist = $this->get_config('syncgroupsexcludelist'); $includelist = $this->get_config('syncgroupsincludelist'); $searchsub = $this->get_config('syncgroupssearchsub'); $grouptype = $this->get_config('syncgroupsgrouptype'); $groupattribute = $this->get_config('syncgroupsgroupattribute'); $docreate = $this->get_config('syncgroupsautocreate'); // If neither one is set, return if (!$syncbyattribute && !$syncbyclass) { log_info('not set to sync by user attribute or by group objects, so exiting'); return true; } if (get_config('auth_ldap_debug_sync_cron')) { log_debug("exclusion list : "); var_dump($excludelist); log_debug("inclusion list : "); var_dump($includelist); } // fetch userids of current members of that institution if ($this->institution == 'mahara') { $currentmembers = get_records_sql_assoc('select u.username as username, u.id as id from {usr} u where u.deleted=0 and not exists (select 1 from {usr_institution} ui where ui.usr=u.id)', array()); } else { $currentmembers = get_records_sql_assoc('select u.username as username, u.id as id from {usr} u inner join {usr_institution} ui on u.id=ui.usr where u.deleted=0 and ui.institution=?', array($this->institution)); } if (get_config('auth_ldap_debug_sync_cron')) { log_debug("current members : " . count($currentmembers)); var_dump($currentmembers); } if (get_config('auth_ldap_debug_sync_cron')) { log_debug("config. LDAP : "); var_dump($this->get_config()); } $groups = array(); if ($syncbyattribute) { // get the distinct values of the used attribute by a LDAP search // that may be restricted by flags -c or -o $groups = array_merge($groups, $this->get_attribute_distinct_values($searchsub)); } if ($syncbyclass) { $groups = array_merge($groups, $this->ldap_get_grouplist('*', $searchsub)); } if (get_config('auth_ldap_debug_sync_cron')) { log_debug("Found LDAP groups : "); var_dump($groups); } $nbadded = 0; foreach ($groups as $group) { $nomatch = false; log_debug("Processing group '{$group}'"); if (!ldap_sync_filter_name($group, $includelist, $excludelist)) { continue; } if (get_config('auth_ldap_debug_sync_cron')) { log_debug("processing group : "); var_dump($group); } $ldapusers = array(); if ($syncbyattribute) { $ldapusers = array_merge($ldapusers, $this->get_users_having_attribute_value($group)); } if ($syncbyclass) { $ldapusers = array_merge($ldapusers, $this->ldap_get_group_members($group)); } // test whether this group exists within the institution // group.shortname is limited to 255 characters. Unlikely anyone will hit this, but why not? $shortname = substr($group, 0, 255); if (!($dbgroup = get_record('group', 'shortname', $shortname, 'institution', $this->institution))) { if (!$docreate) { log_debug('autocreation is off so skipping Mahara not existing group ' . $group); continue; } if (count($ldapusers) == 0) { log_debug('will not autocreate an empty Mahara group ' . $group); continue; } try { log_info('creating group ' . $group); // Make sure the name is unique (across all institutions) // group.name only allows 128 characters. In the event of // really long group names, we'll arbitrarily truncate them $basename = $this->institution . ' : ' . $group; $name = substr($basename, 0, 128); $n = 0; while (record_exists('group', 'name', $name)) { $n++; $tail = " {$n}"; $name .= substr($basename, 0, 128 - strlen($tail)) . $tail; } $dbgroup = array(); $dbgroup['name'] = $name; $dbgroup['institution'] = $this->institution; $dbgroup['shortname'] = $shortname; $dbgroup['grouptype'] = $grouptype; // default standard (change to course) $dbgroup['controlled'] = 1; //definitively $nbadded++; if (!$dryrun) { $groupid = group_create($dbgroup); } } catch (Exception $ex) { log_warn($ex->getMessage()); continue; } } else { $groupid = $dbgroup->id; log_debug('group exists ' . $group); } // now it does exist see what members should be added/removed if (get_config('auth_ldap_debug_sync_cron')) { log_debug($group . ' : '); var_dump($ldapusers); } // Puts the site's "admin" user into the group as a group admin $members = array('1' => 'admin'); //must be set otherwise fatal error group_update_members: no group admins listed for group foreach ($ldapusers as $username) { if (isset($currentmembers[$username])) { $id = $currentmembers[$username]->id; $members[$id] = 'member'; } } if (get_config('auth_ldap_debug_sync_cron')) { log_debug('new members list : ' . count($members)); var_dump($members); } unset($ldapusers); //try to save memory before memory consuming call to API $result = $dryrun ? false : group_update_members($groupid, $members); if ($result) { log_info(" -> added : {$result['added']} removed : {$result['removed']} updated : {$result['updated']}"); } else { log_debug('-> no change for ' . $group); } unset($members); //break; } log_info('---------- finished groupsync auth instance ' . $this->instanceid . ' at ' . date('r', time()) . ' ----------'); return true; }
$groupid = $dbgroup->id; $cli->cli_print('group exists ' . $group); $ldapusers = $instance->get_users_having_attribute_value($group); } // now it does exist see what members should be added/removed $members = array('1' => 'admin'); //must be set otherwise fatal error group_update_members: no group admins listed for group foreach ($ldapusers as $username) { if (isset($currentmembers[$username])) { $id = $currentmembers[$username]; $members[$id] = 'member'; } } if ($CFG->debug_ldap_groupes) { moodle_print_object('new members list : ' . count($members) . ' ', $members); } unset($ldapusers); //try to save memory before memory consuming call to API $result = $dryrun ? false : group_update_members($groupid, $members); if ($result) { $cli->cli_print(" -> added : {$result['added']} removed : {$result['removed']} updated : {$result['updated']}"); } else { $cli->cli_print('-> no change for ' . $group); } unset($members); //break; } } $USER->logout(); // important cli::cli_exit('---------- ended at ' . date('r', time()) . ' ----------', true);