fixed user management

addresses #1
This commit is contained in:
Jan Dittberner 2007-11-22 07:41:30 +00:00
parent 7bffc8bf97
commit ef9a212ece
3 changed files with 173 additions and 123 deletions

View file

@ -79,39 +79,46 @@ function getFullPath($dirname) {
// check configuration // check configuration
$errmsgs = array(); $errmsgs = array();
if (!isset($davconfig['digest.file'])) { if (!isset($davconfig['digest.file'])) {
array_push($errmsgs, 'digest.file not defined'); array_push($errmsgs, 'digest.file is not defined.');
} elseif (!is_readable($davconfig['digest.file']) || } elseif (!is_readable($davconfig['digest.file']) ||
!is_writable($davconfig['digest.file'])) { !is_writable($davconfig['digest.file'])) {
array_push($errmsgs, array_push($errmsgs,
'The specified digest file is not readable and writable.'); 'The specified digest file is not readable and writable.');
} }
if (!isset($davconfig['group.file'])) { if (!isset($davconfig['group.file'])) {
array_push($errmsgs, 'group.file not defined'); array_push($errmsgs, 'group.file is not defined.');
} elseif (!is_readable($davconfig['group.file']) || } elseif (!is_readable($davconfig['group.file']) ||
!is_writable($davconfig['group.file'])) { !is_writable($davconfig['group.file'])) {
array_push($errmsgs, array_push($errmsgs,
'The specified group file is not readable and writable.'); 'The specified group file is not readable and writable.');
} }
if (!isset($davconfig['namemap.file'])) { if (!isset($davconfig['namemap.file'])) {
array_push($errmsgs, 'namemap.file not defined'); array_push($errmsgs, 'namemap.file is not defined.');
} elseif (!is_readable($davconfig['namemap.file']) || } elseif (!is_readable($davconfig['namemap.file']) ||
!is_writable($davconfig['namemap.file'])) { !is_writable($davconfig['namemap.file'])) {
array_push($errmsgs, array_push($errmsgs,
'The specified name mapping file is not readable and writable.'); 'The specified name mapping file is not readable and writable.');
} }
if (!isset($davconfig['dav.dir'])) { if (!isset($davconfig['dav.dir'])) {
array_push($errmsgs, 'dav.dir not defined'); array_push($errmsgs, 'dav.dir is not defined.');
} elseif (!is_dir($davconfig['dav.dir']) || } elseif (!is_dir($davconfig['dav.dir']) ||
!is_readable($davconfig['dav.dir']) || !is_readable($davconfig['dav.dir']) ||
!is_writable($davconfig['dav.dir'])) { !is_writable($davconfig['dav.dir'])) {
array_push($errmsgs, array_push($errmsgs,
'The specified DAV directory is no directory or not accessable.'); 'The specified DAV directory is no directory or not accessable.');
} }
if (empty($davconfig['dav.realm'])) {
array_push($errmsgs, 'dav.realm is not defined.');
}
if (empty($davconfig['dav.uri'])) {
array_push($errmsgs, 'dav.uri is not defined.');
}
if (!empty($errmsgs)) { if (!empty($errmsgs)) {
errorAsHtml(implode("<br />", $errmsgs)); errorAsHtml(implode("<br />", $errmsgs));
} }
$namemap = json_decode(readfile($davconfig['namemap.file']), true); $namemapdata = file_get_contents($davconfig['namemap.file']);
$namemap = json_decode($namemapdata, true);
if ($namemap === NULL) { if ($namemap === NULL) {
$namemap = array(); $namemap = array();
} }

View file

@ -27,8 +27,17 @@
* 02110-1301 USA. * 02110-1301 USA.
*/ */
if (!isset($_SERVER['DavAdminConfDir'])) {
header('HTTP/1.0 500 Internal Server Error');
header('Status: 500 Internal Server Error');
header('Content-Type: text/plain;charset=utf8');
print("The Server is not configured correctly. " .
"Please tell your Administrator to set the " .
"DavAdminConfDir environment variable.");
exit();
}
/** Include configuration information. */ /** Include configuration information. */
require_once('config.inc.php'); require_once($_SERVER['DavAdminConfDir'] . '/config.inc.php');
// output is plain text (JSON or an error message) // output is plain text (JSON or an error message)
header("Content-Type: text/plain; charset=UTF-8"); header("Content-Type: text/plain; charset=UTF-8");
@ -45,19 +54,15 @@ function getGroups($part) {
preg_match_all($regexp, $part, $matches); preg_match_all($regexp, $part, $matches);
$array = $matches[1]; $array = $matches[1];
$last_string = trim(array_pop($array)); $last_string = trim(array_pop($array));
if ($last_string != '') {
try {
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']);
$sth = $dbh->prepare("SELECT DISTINCT groupname FROM dav_group WHERE LOWER(groupname) LIKE LOWER(?) ORDER BY groupname");
$sth->execute(array("%" . $last_string . "%"));
$prefix = count($array) ? implode(",", $array) . ", " : '';
$retval = array(); $retval = array();
foreach ($sth->fetchAll(PDO::FETCH_ASSOC) as $row) { if ($last_string != '') {
$retval[$prefix . $row['groupname']] = $row['groupname']; $groups = file($GLOBALS['davconfig']['group.file']);
foreach ($groups as $line) {
list($group, $users) = explode(":", $line);
$group = trim($group);
if (stripos($group, $last_string) === 0) {
array_push($retval, $group);
} }
$dbh = null;
} catch (PDOException $e) {
return $e->getMessage();
} }
} }
return json_encode($retval); return json_encode($retval);

View file

@ -34,14 +34,12 @@ function getGroups($username) {
$groupdata = file($GLOBALS['davconfig']['group.file']); $groupdata = file($GLOBALS['davconfig']['group.file']);
$retval = array(); $retval = array();
foreach ($groupdata as $line) { foreach ($groupdata as $line) {
$colonpos = strpos($line, ":"); list($group, $users) = explode(":", $line);
if ($colonpos > 0) { $group = trim($group);
$groupname = trim(substr($line, 0, $colonpos - 1)); $users = explode(" ", $users);
$users = explode(" ", substr($line, $colonpos + 1));
foreach ($users as $user) { foreach ($users as $user) {
if (trim($user) == $username) { if (trim($user) == $username) {
array_push($retval, $groupname); array_push($retval, $group);
}
} }
} }
} }
@ -122,11 +120,85 @@ function validateUserData(&$userdata, $forinsert) {
return $errormsgs; return $errormsgs;
} }
/**
* Creates an entry for a digest authentication file.
*
* @param string $username user name
* @param string $realm realm name
* @param string $password password
* @return string digest entry
*/
function createDigest($username, $realm, $password) { function createDigest($username, $realm, $password) {
return sprintf("%s:%s:%s", $username, $realm, return sprintf("%s:%s:%s", $username, $realm,
md5(sprintf("%s:%s:%s", $username, $realm, $password))); md5(sprintf("%s:%s:%s", $username, $realm, $password)));
} }
function updateNameMap() {
$fh = fopen($GLOBALS['davconfig']['namemap.file'], 'w');
fwrite($fh, json_encode($GLOBALS['namemap']));
fclose($fh);
}
function updateDigest(&$userdata) {
if ($userdata['password']) {
$digests = file($GLOBALS['davconfig']['digest.file']);
$written = false;
$fh = fopen($GLOBALS['davconfig']['digest.file'], 'w');
foreach ($digests as $digest) {
list($username, $realm, $data) = explode(":", $digest);
if ($username == $userdata['username']
&& $realm == $GLOBALS['davconfig']['dav.realm']) {
fwrite($fh, createDigest($userdata['username'],
$GLOBALS['davconfig']['dav.realm'],
$userdata['password']) . "\n");
$written = true;
} else {
fwrite($fh, $digest);
}
}
if (!$written) {
fwrite($fh, createDigest($userdata['username'],
$GLOBALS['davconfig']['dav.realm'],
$userdata['password']) . "\n");
}
fclose($fh);
}
}
function updateGroups(&$userdata) {
if ($userdata['groups']) {
$written = array();
foreach (explode(",", $userdata['groups']) as $group) {
$written[trim($group)] = false;
}
$groupdata = file($GLOBALS['davconfig']['group.file']);
$fh = fopen($GLOBALS['davconfig']['group.file'], 'w');
foreach ($groupdata as $groupline) {
list ($group, $users) = explode(":", $groupline);
$group = trim($group);
$users = explode(" ", trim($users));
foreach ($users as $key => $user) {
$users[$key] = trim($user);
}
if (array_key_exists($group, $written)) {
if (!in_array($userdata['username'], $users)) {
array_push($users, $userdata['username']);
}
fprintf($fh, "%s: %s\n", $group, implode(" ", $users));
$written[$group] = true;
} else {
fwrite($fh, $groupline);
}
}
foreach ($written as $group => $done) {
if (!$done) {
fprintf($fh, "%s: %s\n", $group, $userdata['username']);
}
}
fclose($fh);
}
}
/** /**
* Updates the data of a user in the database. * Updates the data of a user in the database.
* *
@ -137,53 +209,17 @@ function updateUser(&$userdata) {
if (!empty($validation)) { if (!empty($validation)) {
errorAsXml(implode("\n", $validation)); errorAsXml(implode("\n", $validation));
} }
try { $GLOBALS['namemap'][$userdata['uid']] =
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']); array('uid' => $userdata['uid'],
$dbh->beginTransaction(); 'username' => $userdata['username'],
if ($userdata['password']) { 'firstname' => $userdata['firstname'],
$sth = $dbh->prepare("UPDATE dav_password SET firstname=:firstname, lastname=:lastname, password=md5(:password) WHERE uid=:uid"); 'lastname' => $userdata['lastname']);
if (!$sth->execute(array(':firstname' => $userdata['firstname'], // write name mapping data
':lastname' => $userdata['lastname'], updateNameMap();
':password' => $userdata['password'], // write digest data
':uid' => $userdata['uid']))) { updateDigest($userdata);
$dbh->rollback(); // update group file
statementErrorAsXml($sth); updateGroups($userdata);
}
} else {
$sth = $dbh->prepare("UPDATE dav_password SET firstname=:firstname, lastname=:lastname WHERE uid=:uid");
if (!$sth->execute(array(':firstname' => $userdata['firstname'],
':lastname' => $userdata['lastname'],
':uid' => $userdata['uid']))) {
$dbh->rollback();
statementErrorAsXml($sth);
}
}
if ($userdata['groups']) {
$groups = array();
$sth = $dbh->prepare("DELETE FROM dav_group WHERE username=:username");
if (!$sth->execute(array(':username' => $userdata['username']))) {
$dbh->rollback();
statementErrorAsXml($sth);
}
$sth = $dbh->prepare("INSERT INTO dav_group (username, groupname) VALUES (:username, :groupname)");
foreach (explode(",", $userdata['groups']) as $group) {
$group = trim($group);
if (!in_array($group, $groups)) {
array_push($groups, $group);
if (!$sth->execute(array(':username' => $userdata['username'],
':groupname' => $group))) {
$dbh->rollback();
statementErrorAsXml($sth);
}
$sth->closeCursor();
}
}
}
$dbh->commit();
$dbh = null;
} catch (PDOException $e) {
errorAsXml($e->getMessage());
}
} }
/** /**
@ -196,40 +232,58 @@ function insertUser(&$userdata) {
if (!empty($validation)) { if (!empty($validation)) {
errorAsXml(implode("\n", $validation)); errorAsXml(implode("\n", $validation));
} }
try { $uids = array_keys($GLOBALS['namemap']);
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']); if (empty($uids)) {
$dbh->beginTransaction(); $uid = 1;
$sth = $dbh->prepare("INSERT INTO dav_password (username, firstname, lastname, password) VALUES (:username, :firstname, :lastname, md5(:password))"); } else {
if (!$sth->execute(array(':username' => $userdata['username'], arsort($uids);
':firstname' => $userdata['firstname'], $uid = $uids[0] + 1;
':lastname' => $userdata['lastname'],
':password' => $userdata['password']))) {
$dbh->rollback();
statementErrorAsXml($sth);
}
$uid = $dbh->lastInsertId('dav_password_uid_seq');
$groups = array();
$sth = $dbh->prepare("INSERT INTO dav_group (username, groupname) VALUES (:username, :groupname)");
foreach (split(",", $userdata['groups']) as $group) {
$group = trim($group);
if (!in_array($group, $groups)) {
array_push($groups, $group);
if (!$sth->execute(array(':username' => $userdata['username'],
':groupname' => $group))) {
$dbh->rollback();
statementErrorAsXml($sth);
}
$sth->closeCursor();
}
}
$dbh->commit();
$dbh = null;
} catch (PDOException $e) {
errorAsXml($e->getMessage);
} }
$GLOBALS['namemap'][$uid] =
array('uid' => $uid,
'username' => $userdata['username'],
'firstname' => $userdata['firstname'],
'lastname' => $userdata['lastname']);
// write name mapping data
updateNameMap();
// write digest data
updateDigest($userdata);
// update group file
updateGroups($userdata);
return $uid; return $uid;
} }
function removeDigest($username) {
$digests = file($GLOBALS['davconfig']['digest.file']);
$fh = fopen($GLOBALS['davconfig']['digest.file'], 'w');
foreach ($digests as $digest) {
list($username, $realm, $data) = explode(":", $digest);
if (!($username == $userdata['username']
&& $realm == $GLOBALS['davconfig']['dav.realm'])) {
fwrite($fh, $digest);
}
}
fclose($fh);
}
function removeFromGroups($username) {
$groupdata = file($GLOBALS['davconfig']['group.file']);
$fh = fopen($GLOBALS['davconfig']['group.file'], 'w');
foreach ($groupdata as $groupline) {
list ($group, $users) = explode(":", $groupline);
$group = trim($group);
$users = explode(" ", trim($users));
foreach ($users as $key => $user) {
$users[$key] = trim($user);
}
if (in_array($username, $users)) {
$users = array_splice($users, array_search($username, $users));
}
fprintf($fh, "%s: %s\n", $group, implode(" ", $users));
}
fclose($fh);
}
/** /**
* Delete the user with the given user id and its group assignments * Delete the user with the given user id and its group assignments
* from the database. * from the database.
@ -237,27 +291,13 @@ function insertUser(&$userdata) {
* @param int $uid user id * @param int $uid user id
*/ */
function deleteUser($uid) { function deleteUser($uid) {
if (!is_numeric($uid)) { if (!(is_numeric($uid) && array_key_exists($uid, $GLOBALS['namemap']))) {
errorAsXml(sprintf(_("Invalid user id %s"), $uid)); errorAsXml(sprintf(_("Invalid user id %s"), $uid));
} }
try { removeDigest($GLOBALS['namemap'][$uid]['username']);
$dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']); removeFromGroups($GLOBALS['namemap'][$uid]['username']);
$dbh->beginTransaction(); unset($GLOBALS['namemap'][$uid]);
$query = $dbh->prepare("DELETE FROM dav_group WHERE username IN (SELECT username FROM dav_password WHERE uid=:uid)"); updateNameMap();
if (!$query->execute(array(':uid' => $uid))) {
$dbh->rollback();
statementErrorAsXml($query);
}
$query = $dbh->prepare("DELETE FROM dav_password WHERE uid=:uid");
if (!$query->execute(array(':uid' => $uid))) {
$dbh->rollback();
statementErrorAsXml($query);
}
$dbh->commit();
$dbh = null;
} catch (PDOException $e) {
errorAsXml($e->getMessage());
}
} }
if ($_GET) { if ($_GET) {
@ -300,8 +340,6 @@ if ($_GET) {
invalidCall(); invalidCall();
} }
} else { } else {
$currentuser = $_SERVER['PHP_AUTH_USER'];
header("Content-Type: text/html; charset=UTF-8"); header("Content-Type: text/html; charset=UTF-8");
$smarty->assign("users", $namemap); $smarty->assign("users", $namemap);
$smarty->display("users.html"); $smarty->display("users.html");