Auth: Add update_user() method on backends and save() method on user

This commit is contained in:
Benjamin Renard 2024-06-04 11:36:16 +02:00
parent f7de9b9648
commit 89e29b8add
Signed by: bn8
GPG key ID: 3E2E1CE1907115BC
3 changed files with 114 additions and 0 deletions

View file

@ -21,6 +21,18 @@ class Backend {
return null;
}
/**
* Update a user
* @param \EesyPHP\Auth\User $user The user object
* @param array<string,mixed> $changes Array of changes
* @param boolean $no_change_as_success Consider no change provided as success
* (optional, default: false)
* @return boolean True if user was updated, false otherwise
*/
public static function update_user($user, $changes, $no_change_as_success=False) {
return false;
}
/**
* Check a user password
* @param \EesyPHP\Auth\User $user The user object

View file

@ -263,6 +263,69 @@ class Ldap extends Backend {
return new User($username, '\\EesyPHP\\Auth\\Ldap', $info);
}
/**
* Update a user
* @param \EesyPHP\Auth\User $user The user object
* @param array<string,mixed> $changes Array of changes
* @param boolean $no_change_as_success Consider no change provided as success
* (optional, default: false)
* @return boolean True if user was updated, false otherwise
*/
public static function update_user($user, $changes, $no_change_as_success=False) {
Log::debug("Ldap::update_user(%s): changes=%s", $user->dn, vardump($changes));
if (!$user->dn) {
Log::error("Ldap::update_user(): Invalid user provided (no DN)");
return false;
}
if (!is_array($changes)) {
Log::error("Ldap::update_user(%s): Invalid changes provided (not an array)", $user->dn);
return false;
}
$attrs = App::get('auth.ldap.user_attributes', null, 'array');
$updated_attrs = [];
$deleted_attrs = [];
foreach($changes as $attr => $value) {
if ($attr == "dn") continue;
if (!array_key_exists($attr, $attrs)) {
Log::error(
"Ldap::update_user(%s): Changes on unknown attribute %s provided",
$user->dn, $attr
);
return false;
}
$ldap_name = Config::get("$attr.ldap_name", $attr, 'string', false, $attrs);
if ($value)
$updated_attrs[$ldap_name] = ensure_is_array($value);
else
$deleted_attrs[] = $ldap_name;
}
if (empty($updated_attrs) && empty($deleted_attrs)) {
Log::debug("Ldap::update_user(%s): no change provided", $user->dn);
return $no_change_as_success;
}
if (!self :: connect()) return false;
// @phpstan-ignore-next-line
$entry = self :: $connection -> getEntry($user->dn);
// @phpstan-ignore-next-line
if (Net_LDAP2::isError($entry)) {
Log::warning('User "%s" (%s) not found', $user->username, $user->dn);
return false;
}
if ($updated_attrs) $entry->replace($updated_attrs);
if ($deleted_attrs) $entry->delete($deleted_attrs);
$result = $entry -> update();
// @phpstan-ignore-next-line
if (Net_LDAP2::isError($result)) {
Log::error(
'Fail to update user "%s" (%s): %s',
$user->username, $user->dn, $result->getMessage()
);
return false;
}
Log::info('User "%s" (%s) updated', $user->username, $user->dn);
return true;
}
/**
* Check a user password
* @param \EesyPHP\Auth\User $user The user object

View file

@ -2,8 +2,10 @@
namespace EesyPHP\Auth;
use EesyPHP\Hook;
use EesyPHP\Log;
use function EesyPHP\ensure_is_array;
use function EesyPHP\vardump;
class User {
@ -25,6 +27,12 @@ class User {
*/
private $info;
/**
* Original user object (set on change and keep to handle update)
* @var User|null
*/
private $original_user;
/**
* Constructor
* @param string $username The username
@ -66,6 +74,7 @@ class User {
* @return void
*/
public function __set($key, $value) {
Log::trace("%s->__set(%s): new value=%s", $this, $key, vardump($value));
switch ($key) {
case 'username':
$this -> username = strval($value);
@ -77,6 +86,8 @@ class User {
$this -> info = ensure_is_array($value);
break;
default:
if (!isset($this ->original_user))
$this -> original_user = new User($this->username, $this->backend, $this->info);
$this -> info[$key] = $value;
}
}
@ -119,4 +130,32 @@ class User {
return $this -> namename;
}
/**
* Update user
* @return bool
*/
public function save() {
if (!isset($this -> original_user)) {
Log::debug("%s->save(): original_user not set, no change to save.", $this);
return true;
}
$changes = [];
foreach ($this->info as $attr => $value)
if ($this->original_user->$attr != $value)
$changes[$attr] = $value;
if (!$changes) {
Log::debug("%s->save(): no info updated, no change to save", $this);
return true;
}
$result = call_user_func(
array($this -> backend, 'update_user'),
$this -> original_user, $changes, true
);
if ($result) {
unset($this -> original_user);
Hook::trigger("user_updated", ["user" => $this, "changes" => $changes]);
}
return $result;
}
}