Merge pull request #65 from LDAPAccountManager/feature/parallelEditing
Feature/parallel editing
This commit is contained in:
commit
2993588a2a
|
@ -1,6 +1,7 @@
|
|||
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
|
||||
- Windows: added home drive and force password change to profile editor
|
||||
- LAM Pro:
|
||||
-> Bind DLZ: entry table can show record data (use special attribute "#records" in server profile)
|
||||
- Fixed bugs:
|
||||
|
|
|
@ -745,9 +745,8 @@ class accountContainer {
|
|||
*
|
||||
* @param ConfiguredType $type account type
|
||||
* @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)) {
|
||||
trigger_error('Argument of accountContainer must be ConfiguredType.', E_USER_ERROR);
|
||||
}
|
||||
|
@ -760,7 +759,6 @@ class accountContainer {
|
|||
$this->current_page=0;
|
||||
$this->subpage='attributes';
|
||||
$this->isNewAccount = false;
|
||||
$this->randomID = $randomID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -824,8 +822,6 @@ class accountContainer {
|
|||
/** send password via mail to this alternate address */
|
||||
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
|
||||
|
@ -865,10 +861,6 @@ class accountContainer {
|
|||
* It prints the HTML code of each account page.
|
||||
*/
|
||||
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;
|
||||
$oldSubpage = $this->subpage;
|
||||
$result = array();
|
||||
|
@ -1322,7 +1314,7 @@ class accountContainer {
|
|||
$passwordButton = new htmlButton('accountContainerPassword', _('Set password'));
|
||||
$passwordButton->setIconClass('passwordButton');
|
||||
$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() . '\');');
|
||||
$leftButtonGroup->addElement($passwordButton);
|
||||
}
|
||||
|
@ -1377,8 +1369,7 @@ class accountContainer {
|
|||
jQuery("#inputForm").validationEngine();
|
||||
});
|
||||
</script>';
|
||||
echo "<form id=\"inputForm\" enctype=\"multipart/form-data\" action=\"edit.php\" method=\"post\" onSubmit=\"saveScrollPosition('inputForm')\" autocomplete=\"off\">\n";
|
||||
echo '<input type="hidden" name="account_randomID" value="' . $this->randomID . '">';
|
||||
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="' . getSecurityTokenName() . '" value="' . getSecurityTokenValue() . '">';
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,9 @@ use \LAMException;
|
|||
use \phpseclib\Net\SSH2;
|
||||
use \phpseclib\Crypt\RSA;
|
||||
/*
|
||||
$Id$
|
||||
|
||||
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
|
||||
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);
|
||||
if ($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)) {
|
||||
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/)
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -57,6 +57,31 @@ if (!isLoggedIn()) {
|
|||
// Set correct language, codepages, ....
|
||||
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();
|
||||
//load account
|
||||
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);
|
||||
die();
|
||||
}
|
||||
$_SESSION['account'] = new accountContainer($type, 'account', getRandomNumber());
|
||||
$result = $_SESSION['account']->load_account($DN);
|
||||
$_SESSION[$sessionKey] = new accountContainer($type, $sessionKey);
|
||||
$result = $_SESSION[$sessionKey]->load_account($DN);
|
||||
if (sizeof($result) > 0) {
|
||||
include __DIR__ . '/../../lib/adminHeader.inc';
|
||||
foreach ($result as $message) {
|
||||
|
@ -92,7 +117,7 @@ if (isset($_GET['DN'])) {
|
|||
}
|
||||
}
|
||||
// new account
|
||||
else if (count($_POST) == 0) {
|
||||
elseif (empty($_POST)) {
|
||||
$type = $typeManager->getConfiguredType($_GET['type']);
|
||||
if ($type->isHidden()) {
|
||||
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());
|
||||
die();
|
||||
}
|
||||
$_SESSION['account'] = new accountContainer($type, 'account', getRandomNumber());
|
||||
$_SESSION['account']->new_account();
|
||||
$_SESSION[$sessionKey] = new accountContainer($type, $sessionKey);
|
||||
$_SESSION[$sessionKey]->new_account();
|
||||
}
|
||||
|
||||
// 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/)
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -74,6 +74,14 @@ if (!empty($_POST)) {
|
|||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
$sessionKey = $sessionAccountPrefix . (new \DateTime(null, getTimeZone()))->getTimestamp() . getRandomNumber();
|
||||
//load account
|
||||
$_SESSION['account'] = new \accountContainer($type, 'account');
|
||||
$_SESSION[$sessionKey] = new \accountContainer($type, $sessionKey);
|
||||
// Show HTML Page
|
||||
include '../lib/adminHeader.inc';
|
||||
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->addLabel(new htmlOutputText(_('DN') . ':'));
|
||||
$container->addField(new htmlOutputText($_SESSION['delete_dn'][$i]));
|
||||
$_SESSION['account']->load_account($_SESSION['delete_dn'][$i]);
|
||||
if (!$_SESSION['account']->hasOnlyVirtualChildren()) {
|
||||
$_SESSION[$sessionKey]->load_account($_SESSION['delete_dn'][$i]);
|
||||
if (!$_SESSION[$sessionKey]->hasOnlyVirtualChildren()) {
|
||||
$childCount = getChildCount($_SESSION['delete_dn'][$i]);
|
||||
if ($childCount > 0) {
|
||||
$container->addLabel(new htmlOutputText(_('Number of child entries') . ':'));
|
||||
|
@ -182,6 +191,8 @@ if (isset($_POST['delete'])) {
|
|||
addSecurityTokenToMetaHTML($container);
|
||||
$container->add(new htmlHiddenInput('type', $type->getId()), 12);
|
||||
|
||||
$sessionKey = $sessionAccountPrefix . (new \DateTime(null, getTimeZone()))->getTimestamp() . getRandomNumber();
|
||||
$_SESSION[$sessionKey] = new \accountContainer($type, $sessionKey);
|
||||
// Delete dns
|
||||
$allOk = true;
|
||||
$allErrors = array();
|
||||
|
@ -189,10 +200,10 @@ if (isset($_POST['delete'])) {
|
|||
// Set to true if an real error has happened
|
||||
$stopprocessing = false;
|
||||
// First load DN.
|
||||
$_SESSION['account']->load_account($deleteDN);
|
||||
$_SESSION[$sessionKey]->load_account($deleteDN);
|
||||
// get commands and changes of each attribute
|
||||
$moduleNames = array_keys($_SESSION['account']->getAccountModules());
|
||||
$modules = $_SESSION['account']->getAccountModules();
|
||||
$moduleNames = array_keys($_SESSION[$sessionKey]->getAccountModules());
|
||||
$modules = $_SESSION[$sessionKey]->getAccountModules();
|
||||
$attributes = array();
|
||||
$errors = array();
|
||||
// predelete actions
|
||||
|
@ -279,7 +290,7 @@ if (isset($_POST['delete'])) {
|
|||
}
|
||||
}
|
||||
if (!$stopprocessing) {
|
||||
$recursive = !$_SESSION['account']->hasOnlyVirtualChildren();
|
||||
$recursive = !$_SESSION[$sessionKey]->hasOnlyVirtualChildren();
|
||||
$messages = deleteDN($deleteDN, $recursive);
|
||||
$errors = array_merge($errors, $messages);
|
||||
if (sizeof($errors) > 0) {
|
||||
|
|
|
@ -75,8 +75,12 @@ class Ajax {
|
|||
if (isset($_GET['module']) && isset($_GET['scope']) && in_array($_GET['module'], getAvailableModules($_GET['scope']))) {
|
||||
enforceUserIsLoggedIn();
|
||||
if (isset($_GET['useContainer']) && ($_GET['useContainer'] == '1')) {
|
||||
if (!isset($_SESSION['account'])) die();
|
||||
$module = $_SESSION['account']->getAccountModule($_GET['module']);
|
||||
$sessionKey = htmlspecialchars($_GET['editKey']);
|
||||
if (!isset($_SESSION[$sessionKey])) {
|
||||
logNewMessage(LOG_ERR, 'Unable to find account container');
|
||||
die();
|
||||
}
|
||||
$module = $_SESSION[$sessionKey]->getAccountModule($_GET['module']);
|
||||
$module->handleAjaxRequest();
|
||||
}
|
||||
else {
|
||||
|
@ -157,7 +161,8 @@ class Ajax {
|
|||
* @param array $input input parameters
|
||||
*/
|
||||
private static function managePasswordChange($input) {
|
||||
$return = $_SESSION['account']->setNewPassword($input);
|
||||
$sessionKey = htmlspecialchars($_GET['editKey']);
|
||||
$return = $_SESSION[$sessionKey]->setNewPassword($input);
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue