mirror of
https://github.com/moodle/moodle.git
synced 2025-03-17 14:10:08 +01:00
MDL-15098 dml auth conversion
This commit is contained in:
parent
21a7e260fc
commit
df884cd852
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @author Martin Dougiamas
|
||||
* @authro Jerome GUTIERREZ
|
||||
@ -43,7 +44,7 @@ class auth_plugin_cas extends auth_plugin_base {
|
||||
//hack prefix to objectclass
|
||||
if (empty($this->config->objectclass)) { // Can't send empty filter
|
||||
$this->config->objectclass='objectClass=*';
|
||||
} else if (strpos($this->config->objectclass, 'objectClass=') !== 0) {
|
||||
} else if (stripos($this->config->objectclass, 'objectClass=') !== 0) {
|
||||
$this->config->objectclass = 'objectClass='.$this->config->objectclass;
|
||||
}
|
||||
}
|
||||
@ -361,10 +362,13 @@ if ( !is_object($PHPCAS_CLIENT) ) {
|
||||
function get_userinfo($username) {
|
||||
$textlib = textlib_get_instance();
|
||||
$extusername = $textlib->convert($username, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
$ldapconnection = $this->ldap_connect();
|
||||
$attrmap = $this->ldap_attributes();
|
||||
|
||||
$result = array();
|
||||
$search_attribs = array();
|
||||
|
||||
foreach ($attrmap as $key=>$values) {
|
||||
if (!is_array($values)) {
|
||||
$values = array($values);
|
||||
@ -388,7 +392,7 @@ if ( !is_object($PHPCAS_CLIENT) ) {
|
||||
$values = array($values);
|
||||
}
|
||||
$ldapval = NULL;
|
||||
foreach ($values as $value) {
|
||||
foreach ($values as $value) {
|
||||
if ($value == 'dn') {
|
||||
$result[$key] = $user_dn;
|
||||
}
|
||||
@ -562,11 +566,11 @@ if ( !is_object($PHPCAS_CLIENT) ) {
|
||||
/**
|
||||
* checks if user exists on external db
|
||||
*
|
||||
* @param string $username (with system magic quotes)
|
||||
* @param string $username
|
||||
*/
|
||||
function user_exists($username) {
|
||||
$textlib = textlib_get_instance();
|
||||
$extusername = $textlib->convert(stripslashes($username), 'utf-8', $this->config->ldapencoding);
|
||||
$extusername = $textlib->convert($username, 'utf-8', $this->config->ldapencoding);
|
||||
//returns true if given username exist on ldap
|
||||
$users = $this->ldap_get_userlist("({$this->config->user_attribute}=".$this->filter_addslashes($extusername).")");
|
||||
return count($users);
|
||||
@ -579,81 +583,55 @@ if ( !is_object($PHPCAS_CLIENT) ) {
|
||||
* Syncing users removes or suspends users that dont exists anymore in external db.
|
||||
* Creates new users and updates coursecreator status of users.
|
||||
*
|
||||
* @param int $bulk_insert_records will insert $bulkinsert_records per insert statement
|
||||
* valid only with $unsafe. increase to a couple thousand for
|
||||
* blinding fast inserts -- but test it: you may hit mysqld's
|
||||
* max_allowed_packet limit.
|
||||
* @param bool $do_updates will do pull in data updates from ldap if relevant
|
||||
*/
|
||||
function sync_users ($bulk_insert_records = 1000, $do_updates = true) {
|
||||
global $CFG;
|
||||
function sync_users ($do_updates = true) {
|
||||
|
||||
global $CFG, $DB;
|
||||
|
||||
$textlib = textlib_get_instance();
|
||||
$droptablesql = array(); /// sql commands to drop the table (because session scope could be a problem for
|
||||
/// some persistent drivers like ODBTP (mssql) or if this function is invoked
|
||||
/// from within a PHP application using persistent connections
|
||||
// configure a temp table
|
||||
$dbman = $DB->get_manager();
|
||||
|
||||
/// TODO: move this to sql generators
|
||||
error('fix temporary table code in CAS');
|
||||
/// Define table user to be created
|
||||
$table = new xmldb_table('tmp_extuser');
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
|
||||
$table->add_field('username', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, null, null);
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_index('username', XMLDB_INDEX_UNIQUE, array('mnethostid', 'username'));
|
||||
|
||||
print "Configuring temp table\n";
|
||||
switch (strtolower($CFG->dbfamily)) {
|
||||
case 'mysql':
|
||||
$temptable = $CFG->prefix . 'extuser';
|
||||
$droptablesql[] = 'DROP TEMPORARY TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later
|
||||
echo "Creating temp table $temptable\n";
|
||||
execute_sql('CREATE TEMPORARY TABLE ' . $temptable . ' (username VARCHAR(64), PRIMARY KEY (username)) TYPE=MyISAM', false);
|
||||
break;
|
||||
case 'postgres':
|
||||
$temptable = $CFG->prefix . 'extuser';
|
||||
$droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later
|
||||
echo "Creating temp table $temptable\n";
|
||||
$bulk_insert_records = 1; // no support for multiple sets of values
|
||||
execute_sql('CREATE TEMPORARY TABLE '. $temptable . ' (username VARCHAR(64), PRIMARY KEY (username))', false);
|
||||
break;
|
||||
case 'mssql':
|
||||
$temptable = '#'.$CFG->prefix . 'extuser'; /// MSSQL temp tables begin with #
|
||||
$droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later
|
||||
echo "Creating temp table $temptable\n";
|
||||
$bulk_insert_records = 1; // no support for multiple sets of values
|
||||
execute_sql('CREATE TABLE ' . $temptable . ' (username VARCHAR(64), PRIMARY KEY (username))', false);
|
||||
break;
|
||||
case 'oracle':
|
||||
$temptable = $CFG->prefix . 'extuser';
|
||||
$droptablesql[] = 'TRUNCATE TABLE ' . $temptable; // oracle requires truncate before being able to drop a temp table
|
||||
$droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later
|
||||
echo "Creating temp table $temptable\n";
|
||||
$bulk_insert_records = 1; // no support for multiple sets of values
|
||||
execute_sql('CREATE GLOBAL TEMPORARY TABLE '.$temptable.' (username VARCHAR(64), PRIMARY KEY (username)) ON COMMIT PRESERVE ROWS', false);
|
||||
break;
|
||||
echo "Creating temp table $temptable\n";
|
||||
if (!$dbman->create_temp_table($table)) {
|
||||
print "Failed to create temporary users table - aborting\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
print "Connecting to ldap...\n";
|
||||
$ldapconnection = $this->ldap_connect();
|
||||
|
||||
if (!$ldapconnection) {
|
||||
@ldap_close($ldapconnection);
|
||||
print get_string('auth_ldap_noconnect','auth',$this->config->host_url);
|
||||
exit;
|
||||
}
|
||||
|
||||
////
|
||||
//// get user's list from ldap to sql in a scalable fashion
|
||||
////
|
||||
// prepare some data we'll need
|
||||
$filter = "(&(".$this->config->user_attribute."=*)(".$this->config->objectclass."))";
|
||||
|
||||
$contexts = explode(";",$this->config->contexts);
|
||||
|
||||
if (!empty($this->config->create_context)) {
|
||||
array_push($contexts, $this->config->create_context);
|
||||
}
|
||||
|
||||
$fresult = array();
|
||||
foreach ($contexts as $context) {
|
||||
$context = trim($context);
|
||||
if (empty($context)) {
|
||||
continue;
|
||||
}
|
||||
begin_sql();
|
||||
if ($this->config->search_sub) {
|
||||
//use ldap_search to find first user from subtree
|
||||
$ldap_result = ldap_search($ldapconnection, $context,
|
||||
@ -665,49 +643,44 @@ error('fix temporary table code in CAS');
|
||||
$filter,
|
||||
array($this->config->user_attribute));
|
||||
}
|
||||
|
||||
if ($entry = ldap_first_entry($ldapconnection, $ldap_result)) {
|
||||
do {
|
||||
$value = ldap_get_values_len($ldapconnection, $entry, $this->config->user_attribute);
|
||||
$value = $textlib->convert($value[0], $this->config->ldapencoding, 'utf-8');
|
||||
array_push($fresult, $value);
|
||||
if (count($fresult) >= $bulk_insert_records) {
|
||||
$this->ldap_bulk_insert($fresult, $temptable);
|
||||
$fresult = array();
|
||||
}
|
||||
$this->ldap_bulk_insert($value);
|
||||
} while ($entry = ldap_next_entry($ldapconnection, $entry));
|
||||
}
|
||||
unset($ldap_result); // free mem
|
||||
// insert any remaining users and release mem
|
||||
if (count($fresult)) {
|
||||
$this->ldap_bulk_insert($fresult, $temptable);
|
||||
$fresult = array();
|
||||
}
|
||||
commit_sql();
|
||||
}
|
||||
|
||||
/// preserve our user database
|
||||
/// if the temp table is empty, it probably means that something went wrong, exit
|
||||
/// so as to avoid mass deletion of users; which is hard to undo
|
||||
$count = get_record_sql('SELECT COUNT(username) AS count, 1 FROM ' . $temptable);
|
||||
$count = $count->{'count'};
|
||||
$count = $DB->count_records_sql('SELECT COUNT(username) AS count, 1 FROM {tmp_extuser}');
|
||||
if ($count < 1) {
|
||||
print "Did not get any users from LDAP -- error? -- exiting\n";
|
||||
exit;
|
||||
} else {
|
||||
print "Got $count records from LDAP\n\n";
|
||||
}
|
||||
|
||||
|
||||
/// User removal
|
||||
// find users in DB that aren't in ldap -- to be removed!
|
||||
// this is still not as scalable (but how often do we mass delete?)
|
||||
if (!empty($this->config->removeuser)) {
|
||||
$sql = "SELECT u.id, u.username, u.email, u.auth
|
||||
FROM {$CFG->prefix}user u
|
||||
LEFT JOIN $temptable e ON u.username = e.username
|
||||
WHERE u.auth='cas'
|
||||
AND u.deleted=0
|
||||
AND e.username IS NULL";
|
||||
$remove_users = get_records_sql($sql);
|
||||
$sql = "SELECT u.id, u.username, u.email, u.auth
|
||||
FROM {user} u
|
||||
LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = ?)
|
||||
WHERE u.auth='cas'
|
||||
AND u.deleted=0
|
||||
AND e.username IS NULL";
|
||||
$remove_users = $DB->get_records_sql($sql, array($CFG->mnet_localhost_id));
|
||||
|
||||
if (!empty($remove_users)) {
|
||||
print "User entries to remove: ". count($remove_users) . "\n";
|
||||
|
||||
foreach ($remove_users as $user) {
|
||||
if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) {
|
||||
if (delete_user($user)) {
|
||||
@ -719,7 +692,7 @@ error('fix temporary table code in CAS');
|
||||
$updateuser = new object();
|
||||
$updateuser->id = $user->id;
|
||||
$updateuser->auth = 'nologin';
|
||||
if (update_record('user', $updateuser)) {
|
||||
if ($DB->update_record('user', $updateuser)) {
|
||||
echo "\t"; print_string('auth_dbsuspenduser', 'auth', array($user->username, $user->id)); echo "\n";
|
||||
} else {
|
||||
echo "\t"; print_string('auth_dbsuspendusererror', 'auth', $user->username); echo "\n";
|
||||
@ -731,32 +704,36 @@ error('fix temporary table code in CAS');
|
||||
}
|
||||
unset($remove_users); // free mem!
|
||||
}
|
||||
|
||||
/// Revive suspended users
|
||||
if (!empty($this->config->removeuser) and $this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
|
||||
$sql = "SELECT u.id, u.username
|
||||
FROM $temptable e, {$CFG->prefix}user u
|
||||
WHERE e.username=u.username
|
||||
AND u.auth='nologin'";
|
||||
$revive_users = get_records_sql($sql);
|
||||
FROM {user} u
|
||||
JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = ?)
|
||||
WHERE u.auth='nologin' AND u.deleted=0";
|
||||
$revive_users = $DB->get_records_sql($sql, array($CFG->mnet_localhost_id));
|
||||
|
||||
if (!empty($revive_users)) {
|
||||
print "User entries to be revived: ". count($revive_users) . "\n";
|
||||
begin_sql();
|
||||
|
||||
foreach ($revive_users as $user) {
|
||||
$updateuser = new object();
|
||||
$updateuser->id = $user->id;
|
||||
$updateuser->auth = 'cas';
|
||||
if (update_record('user', $updateuser)) {
|
||||
$updateuser->auth = 'ldap';
|
||||
if ($DB->pdate_record('user', $updateuser)) {
|
||||
echo "\t"; print_string('auth_dbreviveser', 'auth', array($user->username, $user->id)); echo "\n";
|
||||
} else {
|
||||
echo "\t"; print_string('auth_dbreviveusererror', 'auth', $user->username); echo "\n";
|
||||
}
|
||||
}
|
||||
commit_sql();
|
||||
} else {
|
||||
print "No user entries to be revived\n";
|
||||
}
|
||||
|
||||
unset($revive_users);
|
||||
}
|
||||
|
||||
|
||||
/// User Updates - time-consuming (optional)
|
||||
if ($do_updates) {
|
||||
// narrow down what fields we need to update
|
||||
@ -775,15 +752,17 @@ error('fix temporary table code in CAS');
|
||||
}
|
||||
// print_r($all_keys); print_r($updatekeys);
|
||||
unset($all_keys); unset($key);
|
||||
|
||||
} else {
|
||||
print "No updates to be done\n";
|
||||
}
|
||||
if ( $do_updates and !empty($updatekeys) ) { // run updates only if relevant
|
||||
$users = get_records_sql("SELECT u.username, u.id
|
||||
FROM {$CFG->prefix}user u
|
||||
WHERE u.deleted=0 AND u.auth='cas'");
|
||||
$users = $DB->get_records_sql("SELECT u.username, u.id
|
||||
FROM {user} u
|
||||
WHERE u.deleted=0 AND u.auth='cas' AND u.mnethostid = ?", array($CFG->mnet_localhost_id));
|
||||
if (!empty($users)) {
|
||||
print "User entries to update: ". count($users). "\n";
|
||||
|
||||
$sitecontext = get_context_instance(CONTEXT_SYSTEM);
|
||||
if (!empty($this->config->creators) and !empty($this->config->memberattribute)
|
||||
and $roles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) {
|
||||
@ -791,9 +770,11 @@ error('fix temporary table code in CAS');
|
||||
} else {
|
||||
$creatorrole = false;
|
||||
}
|
||||
begin_sql();
|
||||
|
||||
$DB->begin_sql();
|
||||
$xcount = 0;
|
||||
$maxxcount = 100;
|
||||
|
||||
foreach ($users as $user) {
|
||||
echo "\t"; print_string('auth_dbupdatinguser', 'auth', array($user->username, $user->id));
|
||||
if (!$this->update_user_record($user->username, $updatekeys)) {
|
||||
@ -801,6 +782,7 @@ error('fix temporary table code in CAS');
|
||||
}
|
||||
echo "\n";
|
||||
$xcount++;
|
||||
|
||||
// update course creators if needed
|
||||
if ($creatorrole !== false) {
|
||||
if ($this->iscreator($user->username)) {
|
||||
@ -809,13 +791,14 @@ error('fix temporary table code in CAS');
|
||||
role_unassign($creatorrole->id, $user->id, 0, $sitecontext->id, 'cas');
|
||||
}
|
||||
}
|
||||
|
||||
if ($xcount++ > $maxxcount) {
|
||||
commit_sql();
|
||||
begin_sql();
|
||||
$DB->commit_sql();
|
||||
$DB->begin_sql();
|
||||
$xcount = 0;
|
||||
}
|
||||
}
|
||||
commit_sql();
|
||||
$DB->commit_sql();
|
||||
unset($users); // free mem
|
||||
}
|
||||
} else { // end do updates
|
||||
@ -823,15 +806,18 @@ error('fix temporary table code in CAS');
|
||||
}
|
||||
/// User Additions
|
||||
// find users missing in DB that are in LDAP
|
||||
// note that get_records_sql wants at least 2 fields returned,
|
||||
// and gives me a nifty object I don't want.
|
||||
// note: we do not care about deleted accounts anymore, this feature was replaced by suspending to nologin auth plugin
|
||||
$sql = "SELECT e.username, e.username
|
||||
FROM $temptable e LEFT JOIN {$CFG->prefix}user u ON e.username = u.username
|
||||
WHERE u.id IS NULL";
|
||||
$add_users = get_records_sql($sql); // get rid of the fat
|
||||
// mnetid not used here in join because we can not add users with the same username
|
||||
$sql = "SELECT e.id, e.username
|
||||
FROM {user} u
|
||||
LEFT JOIN {tmp_extuser} e ON u.username = e.username
|
||||
WHERE u.id IS NULL";
|
||||
$add_users = $DB->get_records_sql($sql); // get rid of the fat
|
||||
|
||||
if (!empty($add_users)) {
|
||||
print "User entries to add: ". count($add_users). "\n";
|
||||
|
||||
$sitecontext = get_context_instance(CONTEXT_SYSTEM);
|
||||
if (!empty($this->config->creators) and !empty($this->config->memberattribute)
|
||||
and $roles = get_roles_with_capability('moodle/legacy:coursecreator', CAP_ALLOW)) {
|
||||
@ -839,9 +825,11 @@ error('fix temporary table code in CAS');
|
||||
} else {
|
||||
$creatorrole = false;
|
||||
}
|
||||
begin_sql();
|
||||
|
||||
$DB->begin_sql();
|
||||
foreach ($add_users as $user) {
|
||||
$user = $this->get_userinfo_asobj(addslashes($user->username));
|
||||
$user = $this->get_userinfo_asobj($user->username);
|
||||
|
||||
// prep a few params
|
||||
$user->modified = time();
|
||||
$user->confirmed = 1;
|
||||
@ -850,9 +838,9 @@ error('fix temporary table code in CAS');
|
||||
if (empty($user->lang)) {
|
||||
$user->lang = $CFG->lang;
|
||||
}
|
||||
$user = addslashes_recursive($user);
|
||||
if ($id = insert_record('user',$user)) {
|
||||
echo "\t"; print_string('auth_dbinsertuser', 'auth', array(stripslashes($user->username), $id)); echo "\n";
|
||||
|
||||
if ($id = $DB->insert_record('user', $user)) {
|
||||
echo "\t"; print_string('auth_dbinsertuser', 'auth', array($user->username, $id)); echo "\n";
|
||||
$userobj = $this->update_user_record($user->username);
|
||||
if (!empty($this->config->forcechangepassword)) {
|
||||
set_user_preference('auth_forcepasswordchange', 1, $userobj->id);
|
||||
@ -860,18 +848,23 @@ error('fix temporary table code in CAS');
|
||||
} else {
|
||||
echo "\t"; print_string('auth_dbinsertusererror', 'auth', $user->username); echo "\n";
|
||||
}
|
||||
|
||||
// add course creators if needed
|
||||
if ($creatorrole !== false and $this->iscreator(stripslashes($user->username))) {
|
||||
if ($creatorrole !== false and $this->iscreator($user->username)) {
|
||||
role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'cas');
|
||||
}
|
||||
}
|
||||
commit_sql();
|
||||
$DB->commit_sql();
|
||||
unset($add_users); // free mem
|
||||
} else {
|
||||
print "No users to be added\n";
|
||||
}
|
||||
|
||||
$dbman->drop_temp_table($table);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a local user record from an external source.
|
||||
* This is a lighter version of the one in moodlelib -- won't do
|
||||
@ -883,30 +876,36 @@ error('fix temporary table code in CAS');
|
||||
* @param string $username username
|
||||
*/
|
||||
function update_user_record($username, $updatekeys = false) {
|
||||
global $CFG, $DB;
|
||||
global $CFG;
|
||||
|
||||
//just in case check text case
|
||||
$username = trim(moodle_strtolower($username));
|
||||
|
||||
// get the current user record
|
||||
$user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id));
|
||||
if (empty($user)) { // trouble
|
||||
error_log("Cannot update non-existent user: ".stripslashes($username));
|
||||
print_error('auth_dbusernotexist','auth',$username);
|
||||
error_log("Cannot update non-existent user: ".$username);
|
||||
print_error('auth_dbusernotexist','auth','',$username);
|
||||
die;
|
||||
}
|
||||
|
||||
// Protect the userid from being overwritten
|
||||
$userid = $user->id;
|
||||
|
||||
if ($newinfo = $this->get_userinfo($username)) {
|
||||
$newinfo = truncate_userinfo($newinfo);
|
||||
|
||||
if (empty($updatekeys)) { // all keys? this does not support removing values
|
||||
$updatekeys = array_keys($newinfo);
|
||||
}
|
||||
|
||||
foreach ($updatekeys as $key) {
|
||||
if (isset($newinfo[$key])) {
|
||||
$value = $newinfo[$key];
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
if (!empty($this->config->{'field_updatelocal_' . $key})) {
|
||||
if ($user->{$key} != $value) { // only update if it's changed
|
||||
$DB->set_field('user', $key, $value, array('id'=>$userid));
|
||||
@ -920,17 +919,13 @@ error('fix temporary table code in CAS');
|
||||
}
|
||||
/**
|
||||
* Bulk insert in SQL's temp table
|
||||
* @param array $users is an array of usernames
|
||||
*/
|
||||
function ldap_bulk_insert($users, $temptable) {
|
||||
// bulk insert -- superfast with $bulk_insert_records
|
||||
$sql = 'INSERT INTO ' . $temptable . ' (username) VALUES ';
|
||||
// make those values safe
|
||||
$users = addslashes_recursive($users);
|
||||
// join and quote the whole lot
|
||||
$sql = $sql . "('" . implode("'),('", $users) . "')";
|
||||
print "\t+ " . count($users) . " users\n";
|
||||
execute_sql($sql, false);
|
||||
function ldap_bulk_insert($username) {
|
||||
global $DB;
|
||||
|
||||
$username = moodle_strtolower($username); // usernames are __always__ lowercase.
|
||||
$DB->insert_record_raw('tmp_extuser', array('username'=>$username), false, true);
|
||||
print ".";
|
||||
}
|
||||
/**
|
||||
* Returns true if user should be coursecreator.
|
||||
|
@ -43,6 +43,6 @@ if (!is_enabled_auth('cas')) {
|
||||
}
|
||||
|
||||
$casauth = get_auth_plugin('cas');
|
||||
$casauth->sync_users(1000, true);
|
||||
$casauth->sync_users(true);
|
||||
|
||||
?>
|
@ -342,7 +342,7 @@ class auth_plugin_db extends auth_plugin_base {
|
||||
|
||||
if (!empty($add_users)) {
|
||||
print_string('auth_dbuserstoadd','auth',count($add_users)); echo "\n";
|
||||
begin_sql();
|
||||
$DB->begin_sql();
|
||||
foreach($add_users as $user) {
|
||||
$username = $user;
|
||||
$user = $this->get_userinfo_asobj($user);
|
||||
@ -357,7 +357,6 @@ class auth_plugin_db extends auth_plugin_base {
|
||||
$user->lang = $CFG->lang;
|
||||
}
|
||||
|
||||
$user = addslashes_object($user);
|
||||
// maybe the user has been deleted before
|
||||
if ($old_user = $DB->get_record('user', array('username'=>$user->username, 'deleted'=>1, 'mnethostid'=>$user->mnethostid))) {
|
||||
$user->id = $old_user->id;
|
||||
@ -374,7 +373,7 @@ class auth_plugin_db extends auth_plugin_base {
|
||||
echo "\t"; print_string('auth_dbinsertusererror', 'auth', $user->username); echo "\n";
|
||||
}
|
||||
}
|
||||
commit_sql();
|
||||
$DB->commit_sql();
|
||||
unset($add_users); // free mem
|
||||
}
|
||||
return true;
|
||||
|
@ -254,12 +254,12 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
/**
|
||||
* checks if user exists on external db
|
||||
*
|
||||
* @param string $username (with system magic quotes)
|
||||
* @param string $username
|
||||
*/
|
||||
function user_exists($username) {
|
||||
|
||||
$textlib = textlib_get_instance();
|
||||
$extusername = $textlib->convert(stripslashes($username), 'utf-8', $this->config->ldapencoding);
|
||||
$extusername = $textlib->convert($username, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
//returns true if given username exist on ldap
|
||||
$users = $this->ldap_get_userlist("({$this->config->user_attribute}=".$this->filter_addslashes($extusername).")");
|
||||
@ -271,13 +271,13 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
* By using information in userobject
|
||||
* Use user_exists to prevent dublicate usernames
|
||||
*
|
||||
* @param mixed $userobject Moodle userobject (with system magic quotes)
|
||||
* @param mixed $plainpass Plaintext password (with system magic quotes)
|
||||
* @param mixed $userobject Moodle userobject
|
||||
* @param mixed $plainpass Plaintext password
|
||||
*/
|
||||
function user_create($userobject, $plainpass) {
|
||||
$textlib = textlib_get_instance();
|
||||
$extusername = $textlib->convert(stripslashes($userobject->username), 'utf-8', $this->config->ldapencoding);
|
||||
$extpassword = $textlib->convert(stripslashes($plainpass), 'utf-8', $this->config->ldapencoding);
|
||||
$extusername = $textlib->convert($userobject->username, 'utf-8', $this->config->ldapencoding);
|
||||
$extpassword = $textlib->convert($plainpass, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
switch ($this->config->passtype) {
|
||||
case 'md5':
|
||||
@ -302,7 +302,7 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
}
|
||||
foreach ($values as $value) {
|
||||
if (!empty($userobject->$key) ) {
|
||||
$newuser[$value] = $textlib->convert(stripslashes($userobject->$key), 'utf-8', $this->config->ldapencoding);
|
||||
$newuser[$value] = $textlib->convert($userobject->$key, 'utf-8', $this->config->ldapencoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,6 +437,8 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
* @param string $confirmsecret
|
||||
*/
|
||||
function user_confirm($username, $confirmsecret) {
|
||||
global $DB;
|
||||
|
||||
$user = get_complete_user_data('username', $username);
|
||||
|
||||
if (!empty($user)) {
|
||||
@ -450,10 +452,10 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
if (!$this->user_activate($username)) {
|
||||
return AUTH_CONFIRM_FAIL;
|
||||
}
|
||||
if (!set_field("user", "confirmed", 1, "id", $user->id)) {
|
||||
if (!$DB->set_field("user", "confirmed", 1, array("id"=>$user->id))) {
|
||||
return AUTH_CONFIRM_FAIL;
|
||||
}
|
||||
if (!set_field("user", "firstaccess", time(), "id", $user->id)) {
|
||||
if (!$DB->set_field("user", "firstaccess", time(), array("id"=>$user->id))) {
|
||||
return AUTH_CONFIRM_FAIL;
|
||||
}
|
||||
return AUTH_CONFIRM_OK;
|
||||
@ -469,14 +471,14 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
* If userpassword does not expire it should return 0. If password is already expired
|
||||
* it should return negative value.
|
||||
*
|
||||
* @param mixed $username username (with system magic quotes)
|
||||
* @param mixed $username username
|
||||
* @return integer
|
||||
*/
|
||||
function password_expire($username) {
|
||||
$result = 0;
|
||||
|
||||
$textlib = textlib_get_instance();
|
||||
$extusername = $textlib->convert(stripslashes($username), 'utf-8', $this->config->ldapencoding);
|
||||
$extusername = $textlib->convert($username, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
$ldapconnection = $this->ldap_connect();
|
||||
$user_dn = $this->ldap_find_userdn($ldapconnection, $extusername);
|
||||
@ -512,57 +514,23 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
* Syncing users removes or suspends users that dont exists anymore in external db.
|
||||
* Creates new users and updates coursecreator status of users.
|
||||
*
|
||||
* @param int $bulk_insert_records will insert $bulkinsert_records per insert statement
|
||||
* valid only with $unsafe. increase to a couple thousand for
|
||||
* blinding fast inserts -- but test it: you may hit mysqld's
|
||||
* max_allowed_packet limit.
|
||||
* @param bool $do_updates will do pull in data updates from ldap if relevant
|
||||
*/
|
||||
function sync_users ($bulk_insert_records = 1000, $do_updates = true) {
|
||||
|
||||
global $CFG;
|
||||
function sync_users($do_updates=true) {
|
||||
global $CFG, $DB;
|
||||
|
||||
$textlib = textlib_get_instance();
|
||||
$dbman = $DB->get_manager();
|
||||
|
||||
$droptablesql = array(); /// sql commands to drop the table (because session scope could be a problem for
|
||||
/// some persistent drivers like ODBTP (mssql) or if this function is invoked
|
||||
/// from within a PHP application using persistent connections
|
||||
$temptable = $CFG->prefix . 'extuser';
|
||||
$createtemptablesql = '';
|
||||
/// Define table user to be created
|
||||
$table = new xmldb_table('tmp_extuser');
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
|
||||
$table->add_field('username', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, null, null);
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_index('username', XMLDB_INDEX_UNIQUE, array('mnethostid', 'username'));
|
||||
|
||||
// configure a temp table
|
||||
print "Configuring temp table\n";
|
||||
error('fix temporary table code in CAS'); // use sql generator
|
||||
switch (strtolower($CFG->dbfamily)) {
|
||||
case 'mysql':
|
||||
$droptablesql[] = 'DROP TEMPORARY TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
$createtemptablesql = 'CREATE TEMPORARY TABLE ' . $temptable . ' (username VARCHAR(64), PRIMARY KEY (username)) TYPE=MyISAM';
|
||||
break;
|
||||
case 'postgres':
|
||||
$droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
$bulk_insert_records = 1; // no support for multiple sets of values
|
||||
$createtemptablesql = 'CREATE TEMPORARY TABLE '. $temptable . ' (username VARCHAR(64), PRIMARY KEY (username))';
|
||||
break;
|
||||
case 'mssql':
|
||||
$temptable = '#'. $temptable; /// MSSQL temp tables begin with #
|
||||
$droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
$bulk_insert_records = 1; // no support for multiple sets of values
|
||||
$createtemptablesql = 'CREATE TABLE ' . $temptable . ' (username VARCHAR(64), PRIMARY KEY (username))';
|
||||
break;
|
||||
case 'oracle':
|
||||
$droptablesql[] = 'TRUNCATE TABLE ' . $temptable; // oracle requires truncate before being able to drop a temp table
|
||||
$droptablesql[] = 'DROP TABLE ' . $temptable; // sql command to drop the table (because session scope could be a problem)
|
||||
$bulk_insert_records = 1; // no support for multiple sets of values
|
||||
$createtemptablesql = 'CREATE GLOBAL TEMPORARY TABLE '.$temptable.' (username VARCHAR(64), PRIMARY KEY (username)) ON COMMIT PRESERVE ROWS';
|
||||
break;
|
||||
}
|
||||
|
||||
/// TODO: remove these ugly hacks
|
||||
error('fix temporary table code in CAS');
|
||||
|
||||
execute_sql_arr($droptablesql, true, false); /// Drop temp table to avoid persistence problems later
|
||||
echo "Creating temp table $temptable\n";
|
||||
if(! execute_sql($createtemptablesql, false) ){
|
||||
if (!$dbman->create_temp_table($table)) {
|
||||
print "Failed to create temporary users table - aborting\n";
|
||||
exit;
|
||||
}
|
||||
@ -594,7 +562,6 @@ error('fix temporary table code in CAS');
|
||||
if (empty($context)) {
|
||||
continue;
|
||||
}
|
||||
begin_sql();
|
||||
if ($this->config->search_sub) {
|
||||
//use ldap_search to find first user from subtree
|
||||
$ldap_result = ldap_search($ldapconnection, $context,
|
||||
@ -611,29 +578,16 @@ error('fix temporary table code in CAS');
|
||||
do {
|
||||
$value = ldap_get_values_len($ldapconnection, $entry, $this->config->user_attribute);
|
||||
$value = $textlib->convert($value[0], $this->config->ldapencoding, 'utf-8');
|
||||
// usernames are __always__ lowercase.
|
||||
array_push($fresult, moodle_strtolower($value));
|
||||
if (count($fresult) >= $bulk_insert_records) {
|
||||
$this->ldap_bulk_insert($fresult, $temptable);
|
||||
$fresult = array();
|
||||
}
|
||||
$this->ldap_bulk_insert($value);
|
||||
} while ($entry = ldap_next_entry($ldapconnection, $entry));
|
||||
}
|
||||
unset($ldap_result); // free mem
|
||||
|
||||
// insert any remaining users and release mem
|
||||
if (count($fresult)) {
|
||||
$this->ldap_bulk_insert($fresult, $temptable);
|
||||
$fresult = array();
|
||||
}
|
||||
commit_sql();
|
||||
}
|
||||
|
||||
/// preserve our user database
|
||||
/// if the temp table is empty, it probably means that something went wrong, exit
|
||||
/// so as to avoid mass deletion of users; which is hard to undo
|
||||
$count = get_record_sql('SELECT COUNT(username) AS count, 1 FROM ' . $temptable);
|
||||
$count = $count->{'count'};
|
||||
$count = $DB->count_records_sql('SELECT COUNT(username) AS count, 1 FROM {tmp_extuser}');
|
||||
if ($count < 1) {
|
||||
print "Did not get any users from LDAP -- error? -- exiting\n";
|
||||
exit;
|
||||
@ -647,12 +601,12 @@ error('fix temporary table code in CAS');
|
||||
// this is still not as scalable (but how often do we mass delete?)
|
||||
if (!empty($this->config->removeuser)) {
|
||||
$sql = "SELECT u.id, u.username, u.email, u.auth
|
||||
FROM {$CFG->prefix}user u
|
||||
LEFT JOIN $temptable e ON u.username = e.username
|
||||
WHERE u.auth='ldap'
|
||||
AND u.deleted=0
|
||||
AND e.username IS NULL";
|
||||
$remove_users = get_records_sql($sql);
|
||||
FROM {user} u
|
||||
LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = ?)
|
||||
WHERE u.auth='ldap'
|
||||
AND u.deleted=0
|
||||
AND e.username IS NULL";
|
||||
$remove_users = $DB->get_records_sql($sql, array($CFG->mnet_localhost_id));
|
||||
|
||||
if (!empty($remove_users)) {
|
||||
print "User entries to remove: ". count($remove_users) . "\n";
|
||||
@ -668,7 +622,7 @@ error('fix temporary table code in CAS');
|
||||
$updateuser = new object();
|
||||
$updateuser->id = $user->id;
|
||||
$updateuser->auth = 'nologin';
|
||||
if (update_record('user', $updateuser)) {
|
||||
if ($DB->update_record('user', $updateuser)) {
|
||||
echo "\t"; print_string('auth_dbsuspenduser', 'auth', array($user->username, $user->id)); echo "\n";
|
||||
} else {
|
||||
echo "\t"; print_string('auth_dbsuspendusererror', 'auth', $user->username); echo "\n";
|
||||
@ -684,26 +638,24 @@ error('fix temporary table code in CAS');
|
||||
/// Revive suspended users
|
||||
if (!empty($this->config->removeuser) and $this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
|
||||
$sql = "SELECT u.id, u.username
|
||||
FROM $temptable e, {$CFG->prefix}user u
|
||||
WHERE e.username=u.username
|
||||
AND u.auth='nologin'";
|
||||
$revive_users = get_records_sql($sql);
|
||||
FROM {user} u
|
||||
JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = ?)
|
||||
WHERE u.auth='nologin' AND u.deleted=0";
|
||||
$revive_users = $DB->get_records_sql($sql, array($CFG->mnet_localhost_id));
|
||||
|
||||
if (!empty($revive_users)) {
|
||||
print "User entries to be revived: ". count($revive_users) . "\n";
|
||||
|
||||
begin_sql();
|
||||
foreach ($revive_users as $user) {
|
||||
$updateuser = new object();
|
||||
$updateuser->id = $user->id;
|
||||
$updateuser->auth = 'ldap';
|
||||
if (update_record('user', $updateuser)) {
|
||||
if ($DB->pdate_record('user', $updateuser)) {
|
||||
echo "\t"; print_string('auth_dbreviveser', 'auth', array($user->username, $user->id)); echo "\n";
|
||||
} else {
|
||||
echo "\t"; print_string('auth_dbreviveusererror', 'auth', $user->username); echo "\n";
|
||||
}
|
||||
}
|
||||
commit_sql();
|
||||
} else {
|
||||
print "No user entries to be revived\n";
|
||||
}
|
||||
@ -735,9 +687,9 @@ error('fix temporary table code in CAS');
|
||||
print "No updates to be done\n";
|
||||
}
|
||||
if ( $do_updates and !empty($updatekeys) ) { // run updates only if relevant
|
||||
$users = get_records_sql("SELECT u.username, u.id
|
||||
FROM {$CFG->prefix}user u
|
||||
WHERE u.deleted=0 AND u.auth='ldap'");
|
||||
$users = $DB->get_records_sql("SELECT u.username, u.id
|
||||
FROM {user} u
|
||||
WHERE u.deleted=0 AND u.auth='ldap' AND u.mnethostid = ?", array($CFG->mnet_localhost_id));
|
||||
if (!empty($users)) {
|
||||
print "User entries to update: ". count($users). "\n";
|
||||
|
||||
@ -749,7 +701,7 @@ error('fix temporary table code in CAS');
|
||||
$creatorrole = false;
|
||||
}
|
||||
|
||||
begin_sql();
|
||||
$DB->begin_sql();
|
||||
$xcount = 0;
|
||||
$maxxcount = 100;
|
||||
|
||||
@ -771,12 +723,12 @@ error('fix temporary table code in CAS');
|
||||
}
|
||||
|
||||
if ($xcount++ > $maxxcount) {
|
||||
commit_sql();
|
||||
begin_sql();
|
||||
$DB->commit_sql();
|
||||
$DB->begin_sql();
|
||||
$xcount = 0;
|
||||
}
|
||||
}
|
||||
commit_sql();
|
||||
$DB->commit_sql();
|
||||
unset($users); // free mem
|
||||
}
|
||||
} else { // end do updates
|
||||
@ -785,13 +737,14 @@ error('fix temporary table code in CAS');
|
||||
|
||||
/// User Additions
|
||||
// find users missing in DB that are in LDAP
|
||||
// note that get_records_sql wants at least 2 fields returned,
|
||||
// and gives me a nifty object I don't want.
|
||||
// note: we do not care about deleted accounts anymore, this feature was replaced by suspending to nologin auth plugin
|
||||
$sql = "SELECT e.username, e.username
|
||||
FROM $temptable e LEFT JOIN {$CFG->prefix}user u ON e.username = u.username
|
||||
WHERE u.id IS NULL";
|
||||
$add_users = get_records_sql($sql); // get rid of the fat
|
||||
// mnetid not used here in join because we can not add users with the same username
|
||||
$sql = "SELECT e.id, e.username
|
||||
FROM {user} u
|
||||
LEFT JOIN {tmp_extuser} e ON u.username = e.username
|
||||
WHERE u.id IS NULL";
|
||||
$add_users = $DB->get_records_sql($sql); // get rid of the fat
|
||||
|
||||
if (!empty($add_users)) {
|
||||
print "User entries to add: ". count($add_users). "\n";
|
||||
@ -804,9 +757,9 @@ error('fix temporary table code in CAS');
|
||||
$creatorrole = false;
|
||||
}
|
||||
|
||||
begin_sql();
|
||||
$DB->begin_sql();
|
||||
foreach ($add_users as $user) {
|
||||
$user = $this->get_userinfo_asobj(addslashes($user->username));
|
||||
$user = $this->get_userinfo_asobj($user->username);
|
||||
|
||||
// prep a few params
|
||||
$user->modified = time();
|
||||
@ -817,10 +770,8 @@ error('fix temporary table code in CAS');
|
||||
$user->lang = $CFG->lang;
|
||||
}
|
||||
|
||||
$user = addslashes_recursive($user);
|
||||
|
||||
if ($id = insert_record('user',$user)) {
|
||||
echo "\t"; print_string('auth_dbinsertuser', 'auth', array(stripslashes($user->username), $id)); echo "\n";
|
||||
if ($id = $DB->insert_record('user', $user)) {
|
||||
echo "\t"; print_string('auth_dbinsertuser', 'auth', array($user->username, $id)); echo "\n";
|
||||
$userobj = $this->update_user_record($user->username);
|
||||
if (!empty($this->config->forcechangepassword)) {
|
||||
set_user_preference('auth_forcepasswordchange', 1, $userobj->id);
|
||||
@ -830,15 +781,18 @@ error('fix temporary table code in CAS');
|
||||
}
|
||||
|
||||
// add course creators if needed
|
||||
if ($creatorrole !== false and $this->iscreator(stripslashes($user->username))) {
|
||||
if ($creatorrole !== false and $this->iscreator($user->username)) {
|
||||
role_assign($creatorrole->id, $user->id, 0, $sitecontext->id, 0, 0, 0, 'ldap');
|
||||
}
|
||||
}
|
||||
commit_sql();
|
||||
$DB->commit_sql();
|
||||
unset($add_users); // free mem
|
||||
} else {
|
||||
print "No users to be added\n";
|
||||
}
|
||||
|
||||
$dbman->drop_temp_table($table);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -897,30 +851,25 @@ error('fix temporary table code in CAS');
|
||||
|
||||
/**
|
||||
* Bulk insert in SQL's temp table
|
||||
* @param array $users is an array of usernames
|
||||
*/
|
||||
function ldap_bulk_insert($users, $temptable) {
|
||||
function ldap_bulk_insert($username) {
|
||||
global $DB;
|
||||
|
||||
// bulk insert -- superfast with $bulk_insert_records
|
||||
$sql = 'INSERT INTO ' . $temptable . ' (username) VALUES ';
|
||||
// make those values safe
|
||||
$users = addslashes_recursive($users);
|
||||
// join and quote the whole lot
|
||||
$sql = $sql . "('" . implode("'),('", $users) . "')";
|
||||
print "\t+ " . count($users) . " users\n";
|
||||
execute_sql($sql, false);
|
||||
$username = moodle_strtolower($username); // usernames are __always__ lowercase.
|
||||
$DB->insert_record_raw('tmp_extuser', array('username'=>$username), false, true);
|
||||
print ".";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Activates (enables) user in external db so user can login to external db
|
||||
*
|
||||
* @param mixed $username username (with system magic quotes)
|
||||
* @param mixed $username
|
||||
* @return boolen result
|
||||
*/
|
||||
function user_activate($username) {
|
||||
$textlib = textlib_get_instance();
|
||||
$extusername = $textlib->convert(stripslashes($username), 'utf-8', $this->config->ldapencoding);
|
||||
$extusername = $textlib->convert($username, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
$ldapconnection = $this->ldap_connect();
|
||||
|
||||
@ -955,7 +904,7 @@ error('fix temporary table code in CAS');
|
||||
*/
|
||||
/* function user_disable($username) {
|
||||
$textlib = textlib_get_instance();
|
||||
$extusername = $textlib->convert(stripslashes($username), 'utf-8', $this->config->ldapencoding);
|
||||
$extusername = $textlib->convert($username, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
$ldapconnection = $this->ldap_connect();
|
||||
|
||||
|
@ -41,6 +41,6 @@ if (!is_enabled_auth('ldap')) {
|
||||
}
|
||||
|
||||
$ldapauth = get_auth_plugin('ldap');
|
||||
$ldapauth->sync_users(1000, true);
|
||||
$ldapauth->sync_users(true);
|
||||
|
||||
?>
|
||||
|
Loading…
x
Reference in New Issue
Block a user