Merge pull request #65 from LDAPAccountManager/feature/parallelEditing
Feature/parallel editing
This commit is contained in:
commit
2993588a2a
|
@ -1,6 +1,7 @@
|
||||||
6.8
|
6.8
|
||||||
- Windows: added home drive and force password change to profile editor
|
- Parallel editing of multiple entries in different browser tabs supported
|
||||||
- LAM supports the progressive web app standard which allows to install LAM as an icon on home screen
|
- LAM supports the progressive web app standard which allows to install LAM as an icon on home screen
|
||||||
|
- Windows: added home drive and force password change to profile editor
|
||||||
- LAM Pro:
|
- LAM Pro:
|
||||||
-> Bind DLZ: entry table can show record data (use special attribute "#records" in server profile)
|
-> Bind DLZ: entry table can show record data (use special attribute "#records" in server profile)
|
||||||
- Fixed bugs:
|
- Fixed bugs:
|
||||||
|
|
|
@ -745,9 +745,8 @@ class accountContainer {
|
||||||
*
|
*
|
||||||
* @param ConfiguredType $type account type
|
* @param ConfiguredType $type account type
|
||||||
* @param string $base key in $_SESSION where this object is saved
|
* @param string $base key in $_SESSION where this object is saved
|
||||||
* @param integer $randomID random ID to avoid parallel editing (default: null)
|
|
||||||
*/
|
*/
|
||||||
function __construct($type, $base, $randomID = null) {
|
function __construct($type, $base) {
|
||||||
if (!($type instanceof ConfiguredType)) {
|
if (!($type instanceof ConfiguredType)) {
|
||||||
trigger_error('Argument of accountContainer must be ConfiguredType.', E_USER_ERROR);
|
trigger_error('Argument of accountContainer must be ConfiguredType.', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -760,7 +759,6 @@ class accountContainer {
|
||||||
$this->current_page=0;
|
$this->current_page=0;
|
||||||
$this->subpage='attributes';
|
$this->subpage='attributes';
|
||||||
$this->isNewAccount = false;
|
$this->isNewAccount = false;
|
||||||
$this->randomID = $randomID;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,8 +822,6 @@ class accountContainer {
|
||||||
/** send password via mail to this alternate address */
|
/** send password via mail to this alternate address */
|
||||||
private $sendPasswordViaMailAlternateAddress = null;
|
private $sendPasswordViaMailAlternateAddress = null;
|
||||||
|
|
||||||
/** random ID number to avoid parallel editing of accounts in multiple browser tabs */
|
|
||||||
private $randomID = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the account module with the given class name
|
* Returns the account module with the given class name
|
||||||
|
@ -865,10 +861,6 @@ class accountContainer {
|
||||||
* It prints the HTML code of each account page.
|
* It prints the HTML code of each account page.
|
||||||
*/
|
*/
|
||||||
function continue_main() {
|
function continue_main() {
|
||||||
if (!empty($_POST['account_randomID']) && ($this->randomID != $_POST['account_randomID'])) {
|
|
||||||
metaRefresh("../lists/list.php?type=" . $this->type->getId() . '&accountEditInvalidID=true');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
$oldPage = $this->current_page;
|
$oldPage = $this->current_page;
|
||||||
$oldSubpage = $this->subpage;
|
$oldSubpage = $this->subpage;
|
||||||
$result = array();
|
$result = array();
|
||||||
|
@ -1322,7 +1314,7 @@ class accountContainer {
|
||||||
$passwordButton = new htmlButton('accountContainerPassword', _('Set password'));
|
$passwordButton = new htmlButton('accountContainerPassword', _('Set password'));
|
||||||
$passwordButton->setIconClass('passwordButton');
|
$passwordButton->setIconClass('passwordButton');
|
||||||
$passwordButton->setOnClick('passwordShowChangeDialog(\'' . _('Set password') . '\', \'' . _('Ok') . '\', \''
|
$passwordButton->setOnClick('passwordShowChangeDialog(\'' . _('Set password') . '\', \'' . _('Ok') . '\', \''
|
||||||
. _('Cancel') . '\', \'' . _('Set random password') . '\', \'../misc/ajax.php?function=passwordChange\',\''
|
. _('Cancel') . '\', \'' . _('Set random password') . '\', \'../misc/ajax.php?function=passwordChange&editKey=' . htmlspecialchars($this->base) . '\',\''
|
||||||
. getSecurityTokenName() . '\',\'' . getSecurityTokenValue() . '\');');
|
. getSecurityTokenName() . '\',\'' . getSecurityTokenValue() . '\');');
|
||||||
$leftButtonGroup->addElement($passwordButton);
|
$leftButtonGroup->addElement($passwordButton);
|
||||||
}
|
}
|
||||||
|
@ -1377,8 +1369,7 @@ class accountContainer {
|
||||||
jQuery("#inputForm").validationEngine();
|
jQuery("#inputForm").validationEngine();
|
||||||
});
|
});
|
||||||
</script>';
|
</script>';
|
||||||
echo "<form id=\"inputForm\" enctype=\"multipart/form-data\" action=\"edit.php\" method=\"post\" onSubmit=\"saveScrollPosition('inputForm')\" autocomplete=\"off\">\n";
|
echo "<form id=\"inputForm\" enctype=\"multipart/form-data\" action=\"edit.php?editKey=" . htmlspecialchars($this->base) . "\" method=\"post\" onSubmit=\"saveScrollPosition('inputForm')\" autocomplete=\"off\">\n";
|
||||||
echo '<input type="hidden" name="account_randomID" value="' . $this->randomID . '">';
|
|
||||||
echo '<input type="hidden" name="' . getSecurityTokenName() . '" value="' . getSecurityTokenValue() . '">';
|
echo '<input type="hidden" name="' . getSecurityTokenName() . '" value="' . getSecurityTokenValue() . '">';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,9 @@ use \LAMException;
|
||||||
use \phpseclib\Net\SSH2;
|
use \phpseclib\Net\SSH2;
|
||||||
use \phpseclib\Crypt\RSA;
|
use \phpseclib\Crypt\RSA;
|
||||||
/*
|
/*
|
||||||
$Id$
|
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2017 Roland Gruber
|
Copyright (C) 2017 - 2019 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -108,7 +107,9 @@ class Remote {
|
||||||
$sr = @ldap_read($_SESSION['ldap']->server(), $credentials[0], "objectClass=posixAccount", array('uid'), 0, 0, 0, LDAP_DEREF_NEVER);
|
$sr = @ldap_read($_SESSION['ldap']->server(), $credentials[0], "objectClass=posixAccount", array('uid'), 0, 0, 0, LDAP_DEREF_NEVER);
|
||||||
if ($sr) {
|
if ($sr) {
|
||||||
$entry = @ldap_get_entries($_SESSION['ldap']->server(), $sr);
|
$entry = @ldap_get_entries($_SESSION['ldap']->server(), $sr);
|
||||||
$username = $entry[0]['uid'][0];
|
if (!empty($entry[0]['uid'])) {
|
||||||
|
$username = $entry[0]['uid'][0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (empty($username)) {
|
if (empty($username)) {
|
||||||
throw new LAMException(sprintf(_("Your LAM admin user (%s) must be a valid Unix account to work with lamdaemon!"), getAbstractDN($credentials[0])));
|
throw new LAMException(sprintf(_("Your LAM admin user (%s) must be a valid Unix account to work with lamdaemon!"), getAbstractDN($credentials[0])));
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2003 - 2006 Tilo Lutz
|
Copyright (C) 2003 - 2006 Tilo Lutz
|
||||||
2005 - 2018 Roland Gruber
|
2005 - 2019 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -57,6 +57,31 @@ if (!isLoggedIn()) {
|
||||||
// Set correct language, codepages, ....
|
// Set correct language, codepages, ....
|
||||||
setlanguage();
|
setlanguage();
|
||||||
|
|
||||||
|
$sessionAccountPrefix = 'editContainer';
|
||||||
|
if (isset($_GET['editKey'])) {
|
||||||
|
$sessionKey = htmlspecialchars($_GET['editKey']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$sessionKey = $sessionAccountPrefix . (new \DateTime(null, getTimeZone()))->getTimestamp() . getRandomNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup account containers in session
|
||||||
|
$cleanupCandidates = array();
|
||||||
|
foreach ($_SESSION as $key => $value) {
|
||||||
|
if (strpos($key, $sessionAccountPrefix) === 0) {
|
||||||
|
$cleanupCandidates[] = $key;
|
||||||
|
}
|
||||||
|
$candidateCount = sizeof($cleanupCandidates);
|
||||||
|
if ($candidateCount > 100) {
|
||||||
|
$numToDelete = $candidateCount - 100;
|
||||||
|
natsort($cleanupCandidates);
|
||||||
|
for ($i = 0; $i < $numToDelete; $i++) {
|
||||||
|
$toDelete = array_shift($cleanupCandidates);
|
||||||
|
unset($_SESSION[$toDelete]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$typeManager = new LAM\TYPES\TypeManager();
|
$typeManager = new LAM\TYPES\TypeManager();
|
||||||
//load account
|
//load account
|
||||||
if (isset($_GET['DN'])) {
|
if (isset($_GET['DN'])) {
|
||||||
|
@ -80,8 +105,8 @@ if (isset($_GET['DN'])) {
|
||||||
logNewMessage(LOG_ERR, 'User tried to access entry of type ' . $type->getId() . ' outside suffix ' . $suffix);
|
logNewMessage(LOG_ERR, 'User tried to access entry of type ' . $type->getId() . ' outside suffix ' . $suffix);
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
$_SESSION['account'] = new accountContainer($type, 'account', getRandomNumber());
|
$_SESSION[$sessionKey] = new accountContainer($type, $sessionKey);
|
||||||
$result = $_SESSION['account']->load_account($DN);
|
$result = $_SESSION[$sessionKey]->load_account($DN);
|
||||||
if (sizeof($result) > 0) {
|
if (sizeof($result) > 0) {
|
||||||
include __DIR__ . '/../../lib/adminHeader.inc';
|
include __DIR__ . '/../../lib/adminHeader.inc';
|
||||||
foreach ($result as $message) {
|
foreach ($result as $message) {
|
||||||
|
@ -92,7 +117,7 @@ if (isset($_GET['DN'])) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// new account
|
// new account
|
||||||
else if (count($_POST) == 0) {
|
elseif (empty($_POST)) {
|
||||||
$type = $typeManager->getConfiguredType($_GET['type']);
|
$type = $typeManager->getConfiguredType($_GET['type']);
|
||||||
if ($type->isHidden()) {
|
if ($type->isHidden()) {
|
||||||
logNewMessage(LOG_ERR, 'User tried to access hidden account type: ' . $type->getId());
|
logNewMessage(LOG_ERR, 'User tried to access hidden account type: ' . $type->getId());
|
||||||
|
@ -102,11 +127,11 @@ else if (count($_POST) == 0) {
|
||||||
logNewMessage(LOG_ERR, 'User tried to create entry of forbidden account type: ' . $type->getId());
|
logNewMessage(LOG_ERR, 'User tried to create entry of forbidden account type: ' . $type->getId());
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
$_SESSION['account'] = new accountContainer($type, 'account', getRandomNumber());
|
$_SESSION[$sessionKey] = new accountContainer($type, $sessionKey);
|
||||||
$_SESSION['account']->new_account();
|
$_SESSION[$sessionKey]->new_account();
|
||||||
}
|
}
|
||||||
|
|
||||||
// show account page
|
// show account page
|
||||||
$_SESSION['account']->continue_main();
|
$_SESSION[$sessionKey]->continue_main();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -11,7 +11,7 @@ use \htmlStatusMessage;
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2003 - 2006 Tilo Lutz
|
Copyright (C) 2003 - 2006 Tilo Lutz
|
||||||
Copyright (C) 2007 - 2018 Roland Gruber
|
Copyright (C) 2007 - 2019 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -74,6 +74,14 @@ if (!empty($_POST)) {
|
||||||
validateSecurityToken();
|
validateSecurityToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sessionAccountPrefix = 'deleteContainer';
|
||||||
|
foreach ($_SESSION as $key => $value) {
|
||||||
|
if (strpos($key, $sessionAccountPrefix) === 0) {
|
||||||
|
unset($_SESSION[$key]);
|
||||||
|
logNewMessage(LOG_NOTICE, "del " . $key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$typeManager = new \LAM\TYPES\TypeManager();
|
$typeManager = new \LAM\TYPES\TypeManager();
|
||||||
|
|
||||||
if (isset($_POST['type']) && ($typeManager->getConfiguredType($_POST['type']) === null)) {
|
if (isset($_POST['type']) && ($typeManager->getConfiguredType($_POST['type']) === null)) {
|
||||||
|
@ -99,8 +107,9 @@ if (isset($_GET['type']) && isset($_SESSION['delete_dn'])) {
|
||||||
$users[] = substr($dn, $start, $end-$start);
|
$users[] = substr($dn, $start, $end-$start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sessionKey = $sessionAccountPrefix . (new \DateTime(null, getTimeZone()))->getTimestamp() . getRandomNumber();
|
||||||
//load account
|
//load account
|
||||||
$_SESSION['account'] = new \accountContainer($type, 'account');
|
$_SESSION[$sessionKey] = new \accountContainer($type, $sessionKey);
|
||||||
// Show HTML Page
|
// Show HTML Page
|
||||||
include '../lib/adminHeader.inc';
|
include '../lib/adminHeader.inc';
|
||||||
echo "<div class=\"" . $type->getScope() . "-bright smallPaddingContent\">";
|
echo "<div class=\"" . $type->getScope() . "-bright smallPaddingContent\">";
|
||||||
|
@ -116,8 +125,8 @@ if (isset($_GET['type']) && isset($_SESSION['delete_dn'])) {
|
||||||
$container->addField(new htmlOutputText($users[$i]));
|
$container->addField(new htmlOutputText($users[$i]));
|
||||||
$container->addLabel(new htmlOutputText(_('DN') . ':'));
|
$container->addLabel(new htmlOutputText(_('DN') . ':'));
|
||||||
$container->addField(new htmlOutputText($_SESSION['delete_dn'][$i]));
|
$container->addField(new htmlOutputText($_SESSION['delete_dn'][$i]));
|
||||||
$_SESSION['account']->load_account($_SESSION['delete_dn'][$i]);
|
$_SESSION[$sessionKey]->load_account($_SESSION['delete_dn'][$i]);
|
||||||
if (!$_SESSION['account']->hasOnlyVirtualChildren()) {
|
if (!$_SESSION[$sessionKey]->hasOnlyVirtualChildren()) {
|
||||||
$childCount = getChildCount($_SESSION['delete_dn'][$i]);
|
$childCount = getChildCount($_SESSION['delete_dn'][$i]);
|
||||||
if ($childCount > 0) {
|
if ($childCount > 0) {
|
||||||
$container->addLabel(new htmlOutputText(_('Number of child entries') . ':'));
|
$container->addLabel(new htmlOutputText(_('Number of child entries') . ':'));
|
||||||
|
@ -182,6 +191,8 @@ if (isset($_POST['delete'])) {
|
||||||
addSecurityTokenToMetaHTML($container);
|
addSecurityTokenToMetaHTML($container);
|
||||||
$container->add(new htmlHiddenInput('type', $type->getId()), 12);
|
$container->add(new htmlHiddenInput('type', $type->getId()), 12);
|
||||||
|
|
||||||
|
$sessionKey = $sessionAccountPrefix . (new \DateTime(null, getTimeZone()))->getTimestamp() . getRandomNumber();
|
||||||
|
$_SESSION[$sessionKey] = new \accountContainer($type, $sessionKey);
|
||||||
// Delete dns
|
// Delete dns
|
||||||
$allOk = true;
|
$allOk = true;
|
||||||
$allErrors = array();
|
$allErrors = array();
|
||||||
|
@ -189,10 +200,10 @@ if (isset($_POST['delete'])) {
|
||||||
// Set to true if an real error has happened
|
// Set to true if an real error has happened
|
||||||
$stopprocessing = false;
|
$stopprocessing = false;
|
||||||
// First load DN.
|
// First load DN.
|
||||||
$_SESSION['account']->load_account($deleteDN);
|
$_SESSION[$sessionKey]->load_account($deleteDN);
|
||||||
// get commands and changes of each attribute
|
// get commands and changes of each attribute
|
||||||
$moduleNames = array_keys($_SESSION['account']->getAccountModules());
|
$moduleNames = array_keys($_SESSION[$sessionKey]->getAccountModules());
|
||||||
$modules = $_SESSION['account']->getAccountModules();
|
$modules = $_SESSION[$sessionKey]->getAccountModules();
|
||||||
$attributes = array();
|
$attributes = array();
|
||||||
$errors = array();
|
$errors = array();
|
||||||
// predelete actions
|
// predelete actions
|
||||||
|
@ -279,7 +290,7 @@ if (isset($_POST['delete'])) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$stopprocessing) {
|
if (!$stopprocessing) {
|
||||||
$recursive = !$_SESSION['account']->hasOnlyVirtualChildren();
|
$recursive = !$_SESSION[$sessionKey]->hasOnlyVirtualChildren();
|
||||||
$messages = deleteDN($deleteDN, $recursive);
|
$messages = deleteDN($deleteDN, $recursive);
|
||||||
$errors = array_merge($errors, $messages);
|
$errors = array_merge($errors, $messages);
|
||||||
if (sizeof($errors) > 0) {
|
if (sizeof($errors) > 0) {
|
||||||
|
|
|
@ -75,8 +75,12 @@ class Ajax {
|
||||||
if (isset($_GET['module']) && isset($_GET['scope']) && in_array($_GET['module'], getAvailableModules($_GET['scope']))) {
|
if (isset($_GET['module']) && isset($_GET['scope']) && in_array($_GET['module'], getAvailableModules($_GET['scope']))) {
|
||||||
enforceUserIsLoggedIn();
|
enforceUserIsLoggedIn();
|
||||||
if (isset($_GET['useContainer']) && ($_GET['useContainer'] == '1')) {
|
if (isset($_GET['useContainer']) && ($_GET['useContainer'] == '1')) {
|
||||||
if (!isset($_SESSION['account'])) die();
|
$sessionKey = htmlspecialchars($_GET['editKey']);
|
||||||
$module = $_SESSION['account']->getAccountModule($_GET['module']);
|
if (!isset($_SESSION[$sessionKey])) {
|
||||||
|
logNewMessage(LOG_ERR, 'Unable to find account container');
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
$module = $_SESSION[$sessionKey]->getAccountModule($_GET['module']);
|
||||||
$module->handleAjaxRequest();
|
$module->handleAjaxRequest();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -157,7 +161,8 @@ class Ajax {
|
||||||
* @param array $input input parameters
|
* @param array $input input parameters
|
||||||
*/
|
*/
|
||||||
private static function managePasswordChange($input) {
|
private static function managePasswordChange($input) {
|
||||||
$return = $_SESSION['account']->setNewPassword($input);
|
$sessionKey = htmlspecialchars($_GET['editKey']);
|
||||||
|
$return = $_SESSION[$sessionKey]->setNewPassword($input);
|
||||||
echo json_encode($return);
|
echo json_encode($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue