From 6944993ceca3c18867c71d76041a8f5503fc8457 Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Tue, 29 Oct 2024 13:27:03 +0100 Subject: [PATCH 1/8] implement LDAP for club1 server only see #237 + Config param to enable club1 local LDAP auth + if user exist in database, will try to auth using LDAP --- app/class/Config.php | 13 ++++ app/class/Controllerconnect.php | 122 ++++++++++++++++++-------------- app/class/Modelclub1ldap.php | 62 ++++++++++++++++ 3 files changed, 143 insertions(+), 54 deletions(-) create mode 100644 app/class/Modelclub1ldap.php diff --git a/app/class/Config.php b/app/class/Config.php index 08ddaec8..015abe24 100644 --- a/app/class/Config.php +++ b/app/class/Config.php @@ -59,6 +59,9 @@ abstract class Config /** Indicate if img should have loading="lazy" attribute */ protected static bool $lazyloadimg = true; + /** Use club1 LDAP auth */ + protected static bool $club1ldap = false; + public const LANG_MIN = 2; public const LANG_MAX = 16; @@ -349,6 +352,11 @@ public static function lazyloadimg(): bool return self::$lazyloadimg; } + public static function club1ldap(): bool + { + return self::$club1ldap; + } + // __________________________________________ S E T ______________________________________ @@ -592,4 +600,9 @@ public static function setlazyloadimg($lazyloadimg): bool { return self::$lazyloadimg = boolval($lazyloadimg); } + + public static function setclub1ldap($club1ldap): void + { + self::$club1ldap = boolval($club1ldap); + } } diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php index f2bed795..ba1fd219 100644 --- a/app/class/Controllerconnect.php +++ b/app/class/Controllerconnect.php @@ -3,7 +3,6 @@ namespace Wcms; use RuntimeException; -use Wcms\Exception\Database\Notfoundexception; class Controllerconnect extends Controller { @@ -16,9 +15,14 @@ public function log(): void $id = $_POST['id'] ?? null; $route = $_POST['route'] ?? 'home'; if ($_POST['log'] === 'login') { - $this->login($route, $id); + $this->login(); } elseif ($_POST['log'] === 'logout') { - $this->logout($route, $id); + $this->logout(); + } + if (is_string($id)) { + $this->routedirect($route, ['page' => $id]); + } else { + $this->routedirect($route); } } } @@ -39,74 +43,84 @@ public function connect(): void /** - * Will login an user using POST datas and redirect - * - * @param string $route For redirection - * @param ?string $paramid For redirection (optionnal, can be used for pages redirection) + * Will try to login an user using POST datas */ - protected function login(string $route, ?string $paramid = null): void + protected function login(): void { if (!empty($_POST['pass']) && !empty($_POST['user'])) { + $this->modelconnect = new Modelconnect(); $userid = $_POST['user']; + $pass = false; + try { $this->user = $this->usermanager->get($userid); // May throw DatabaseException - if (!$this->usermanager->passwordcheck($this->user, $_POST['pass'])) { - $userid = $this->user->id(); - $this->sendflashmessage("Wrong credentials", self::FLASH_ERROR); - Logger::error("wrong credential for user : '$userid' when attempting to loggin"); - } elseif ( - $this->user->expiredate() !== false && - $this->user->expiredate('date') < $this->now && - $this->user->level() < 10 - ) { - $this->sendflashmessage("Account expired", self::FLASH_ERROR); - } else { - $this->user->connectcounter(); - $this->usermanager->add($this->user); - $this->servicesession->setuser($this->user->id()); - $this->sendflashmessage("Successfully logged in as " . $this->user->id(), self::FLASH_SUCCESS); - - if (!empty($_POST['rememberme'])) { - if ($this->user->cookie() > 0) { - $this->modelconnect = new Modelconnect(); - $wsessionid = $this->user->newsession(); - $this->modelconnect->createauthcookie( - $this->user->id(), - $wsessionid, - $this->user->cookie() - ); - $this->usermanager->add($this->user); - $this->servicesession->setwsessionid($wsessionid); - } else { - $message = "Can't remember you beccause user cookie conservation time is set to 0 days"; - $this->sendflashmessage($message, self::FLASH_WARNING); - } - } + } catch (RuntimeException $e) { + $this->sendflashmessage('Wrong credentials', self::FLASH_ERROR); + Logger::errorex($e); + return; + } + + if (Config::club1ldap()) { + // use ldap for password + try { + $ldap = new Modelclub1ldap(); + $pass = $ldap->auth($userid, $_POST['pass']); + $ldap->disconnect(); + } catch (RuntimeException $e) { + $this->sendflashmessage('Error with LDAP connection', self::FLASH_ERROR); + Logger::errorex($e); + return; } - } catch (Notfoundexception $e) { + } else { + // compare password + $pass = $this->usermanager->passwordcheck($this->user, $_POST['pass']); + } + + if (!$pass) { $this->sendflashmessage("Wrong credentials", self::FLASH_ERROR); - Logger::errorex($e); + return; + } + + if ( + $this->user->expiredate() !== false && + $this->user->expiredate('date') < $this->now && + $this->user->level() < 10 + ) { + $this->sendflashmessage("Account expired", self::FLASH_ERROR); + return; + } + + try { + $this->user->connectcounter(); + $this->usermanager->add($this->user); + $this->servicesession->setuser($this->user->id()); + $this->sendflashmessage("Successfully logged in as " . $this->user->id(), self::FLASH_SUCCESS); + + if (!empty($_POST['rememberme'])) { + if ($this->user->cookie() > 0) { + $wsessionid = $this->user->newsession(); + $this->modelconnect->createauthcookie( + $this->user->id(), + $wsessionid, + $this->user->cookie() + ); + $this->usermanager->add($this->user); + $this->servicesession->setwsessionid($wsessionid); + } else { + $message = "Can't remember you beccause user cookie conservation time is set to 0 days"; + $this->sendflashmessage($message, self::FLASH_WARNING); + } + } } catch (RuntimeException $e) { $message = "Can't create authentification cookie : $e"; $this->sendflashmessage($message, self::FLASH_WARNING); Logger::error($message); } } - if (is_string($paramid)) { - $this->routedirect($route, ['page' => $paramid]); - } else { - $this->routedirect($route); - } } - public function logout($route, $id = null): void + protected function logout(): void { $this->disconnect(); - - if ($id !== null && $route !== 'home') { - $this->routedirect($route, ['page' => $id]); - } else { - $this->routedirect($route); - } } } diff --git a/app/class/Modelclub1ldap.php b/app/class/Modelclub1ldap.php new file mode 100644 index 00000000..92b6257b --- /dev/null +++ b/app/class/Modelclub1ldap.php @@ -0,0 +1,62 @@ +connection = @ldap_connect($this->ldapserver); + if ($this->connection === false) { + throw new RuntimeException('bad LDAP server syntax'); + } + ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, 3); + } + + /** + * Try to authenticate user against CLUB1 local LDAP server + * + * @param string $username + * @param string $password + * + * @return bool indicating if auth is a success + * + * @throws RuntimeException If LDAP connection failed + */ + public function auth(string $username, string $password): bool + { + $binddn = "$this->u=$username,$this->d"; + + $ldapbind = @ldap_bind($this->connection, $binddn, $password); + if ($ldapbind === false) { + $errno = ldap_errno($this->connection); + switch ($errno) { + case self::LDAP_INVALID_CREDENTIALS: + return false; + } + throw new RuntimeException(ldap_err2str($errno)); + } + return true; + } + + public function disconnect(): void + { + ldap_close($this->connection); + } +} From 26af2ef652407e0e695ca13dce0b395b3f78601a Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Tue, 29 Oct 2024 19:45:50 +0100 Subject: [PATCH 2/8] remove hardcoded club1 LDAP server use Config param to setup LDAP auth --- app/class/Config.php | 46 ++++++++++++++++--- app/class/Controllerconnect.php | 6 +-- .../{Modelclub1ldap.php => Modelldap.php} | 23 ++++++---- 3 files changed, 58 insertions(+), 17 deletions(-) rename app/class/{Modelclub1ldap.php => Modelldap.php} (63%) diff --git a/app/class/Config.php b/app/class/Config.php index 015abe24..d570096d 100644 --- a/app/class/Config.php +++ b/app/class/Config.php @@ -59,8 +59,10 @@ abstract class Config /** Indicate if img should have loading="lazy" attribute */ protected static bool $lazyloadimg = true; - /** Use club1 LDAP auth */ - protected static bool $club1ldap = false; + /** LDAP auth */ + protected static string $ldapserver = ''; + protected static string $ldaptree = ''; + protected static string $ldapu = ''; public const LANG_MIN = 2; public const LANG_MAX = 16; @@ -159,6 +161,18 @@ public static function url($endslash = true): string return self::$domain . (!empty(self::$basepath) ? '/' . self::$basepath : "") . ($endslash ? '/' : ''); } + /** + * @return bool Indicate if ldap is configured. (all 3 params are not empty) + */ + public static function isldap(): bool + { + return ( + !empty(self::$ldapserver) + && !empty(self::$ldaptree) + && !empty(self::$ldapu) + ); + } + // ________________________________________ G E T _______________________________________ public static function pagetable() @@ -352,9 +366,19 @@ public static function lazyloadimg(): bool return self::$lazyloadimg; } - public static function club1ldap(): bool + public static function ldapserver(): string { - return self::$club1ldap; + return self::$ldapserver; + } + + public static function ldaptree(): string + { + return self::$ldaptree; + } + + public static function ldapu(): string + { + return self::$ldapu; } @@ -601,8 +625,18 @@ public static function setlazyloadimg($lazyloadimg): bool return self::$lazyloadimg = boolval($lazyloadimg); } - public static function setclub1ldap($club1ldap): void + public static function setldapserver($ldapserver): void + { + self::$ldapserver = $ldapserver; + } + + public static function setldaptree($ldaptree): void + { + self::$ldaptree = $ldaptree; + } + + public static function setldapu($ldapu): void { - self::$club1ldap = boolval($club1ldap); + self::$ldapu = $ldapu; } } diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php index ba1fd219..ea068b28 100644 --- a/app/class/Controllerconnect.php +++ b/app/class/Controllerconnect.php @@ -60,10 +60,10 @@ protected function login(): void return; } - if (Config::club1ldap()) { + if (Config::isldap()) { // use ldap for password try { - $ldap = new Modelclub1ldap(); + $ldap = new Modelldap(Config::ldapserver(), Config::ldaptree(), Config::ldapu()); $pass = $ldap->auth($userid, $_POST['pass']); $ldap->disconnect(); } catch (RuntimeException $e) { @@ -72,7 +72,7 @@ protected function login(): void return; } } else { - // compare password + // compare password using database password $pass = $this->usermanager->passwordcheck($this->user, $_POST['pass']); } diff --git a/app/class/Modelclub1ldap.php b/app/class/Modelldap.php similarity index 63% rename from app/class/Modelclub1ldap.php rename to app/class/Modelldap.php index 92b6257b..7d2ad109 100644 --- a/app/class/Modelclub1ldap.php +++ b/app/class/Modelldap.php @@ -4,28 +4,35 @@ use RuntimeException; -class Modelclub1ldap extends Model +class Modelldap extends Model { - protected string $ldapserver = 'ldap://localhost:389'; - - protected string $d = 'ou=People,dc=club1,dc=fr'; - protected string $u = 'uid'; + protected string $ldapserver; + protected string $tree; + protected string $u; /** @var mixed $connection resource (PHP 7) or LDAPConnection (PHP 8)*/ protected $connection; - private const LDAP_INVALID_CREDENTIALS = 0x31; + protected const LDAP_INVALID_CREDENTIALS = 0x31; /** + * @param string $ldapserver LDAP server, like `ldap://server.tld:port` or just `ldap://localhost` + * @param string $tree LDAP structure tree without the username part. + * Like `ou=people,dc=server,dc=tld` + * @param string $u Username storing name, something like `uid`. + * * @throws RuntimeException */ - public function __construct() + public function __construct(string $ldapserver, string $tree, string $u) { + $this->ldapserver = $ldapserver; $this->connection = @ldap_connect($this->ldapserver); if ($this->connection === false) { throw new RuntimeException('bad LDAP server syntax'); } + $this->tree = $tree; + $this->u = $u; ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, 3); } @@ -41,7 +48,7 @@ public function __construct() */ public function auth(string $username, string $password): bool { - $binddn = "$this->u=$username,$this->d"; + $binddn = "$this->u=$username,$this->tree"; $ldapbind = @ldap_bind($this->connection, $binddn, $password); if ($ldapbind === false) { From bad28556e3e324fb100417fe9a62c0f91f90851a Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Tue, 29 Oct 2024 21:25:49 +0100 Subject: [PATCH 3/8] Users with password set to null need LDAP auth --- app/class/Controllerconnect.php | 2 +- app/class/User.php | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php index ea068b28..311e2766 100644 --- a/app/class/Controllerconnect.php +++ b/app/class/Controllerconnect.php @@ -60,7 +60,7 @@ protected function login(): void return; } - if (Config::isldap()) { + if ($this->user->isldap()) { // use ldap for password try { $ldap = new Modelldap(Config::ldapserver(), Config::ldaptree(), Config::ldapu()); diff --git a/app/class/User.php b/app/class/User.php index 92d77419..a77b9502 100644 --- a/app/class/User.php +++ b/app/class/User.php @@ -11,7 +11,7 @@ class User extends Item protected string $id = ''; protected int $level = 0; protected string $signature = ''; - protected ?string $password; + protected ?string $password = null; protected bool $passwordhashed = false; /** @var string $name Displayed name */ @@ -60,6 +60,15 @@ public function __construct($datas = []) $this->hydrate($datas); } + /** + * Indicate if User is authenticated using LDAP. + * It is if password is set to null. + */ + public function isldap(): bool + { + return (is_null($this->password)); + } + // _________________________ G E T _______________________ public function id() From 267fd0754aa12e113f5a154d34fb068d2fe5aa29 Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Wed, 30 Oct 2024 01:26:11 +0100 Subject: [PATCH 4/8] users can be created if LDAP auth is ok see #237 + Config param to define user level --- app/class/Config.php | 13 +++++++++++++ app/class/Controllerconnect.php | 12 +++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/app/class/Config.php b/app/class/Config.php index d570096d..10041bfa 100644 --- a/app/class/Config.php +++ b/app/class/Config.php @@ -63,6 +63,7 @@ abstract class Config protected static string $ldapserver = ''; protected static string $ldaptree = ''; protected static string $ldapu = ''; + protected static int $ldapuserlevel = 0; public const LANG_MIN = 2; public const LANG_MAX = 16; @@ -381,6 +382,11 @@ public static function ldapu(): string return self::$ldapu; } + public static function ldapuserlevel(): int + { + return self::$ldapuserlevel; + } + // __________________________________________ S E T ______________________________________ @@ -639,4 +645,11 @@ public static function setldapu($ldapu): void { self::$ldapu = $ldapu; } + + public static function setldapuserlevel($ldapuserlevel): void + { + if (is_int($ldapuserlevel) && $ldapuserlevel >= 0 && $ldapuserlevel <= 10) { + self::$ldapuserlevel = $ldapuserlevel; + } + } } diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php index 311e2766..feb7a502 100644 --- a/app/class/Controllerconnect.php +++ b/app/class/Controllerconnect.php @@ -55,13 +55,16 @@ protected function login(): void try { $this->user = $this->usermanager->get($userid); // May throw DatabaseException } catch (RuntimeException $e) { - $this->sendflashmessage('Wrong credentials', self::FLASH_ERROR); - Logger::errorex($e); - return; + if (Config::ldapuserlevel() > 0) { + $this->user = new User(['password' => null, 'level' => Config::ldapuserlevel(), 'id' => $userid]); + } else { + $this->sendflashmessage('Wrong credentials', self::FLASH_ERROR); + Logger::errorex($e); + return; + } } if ($this->user->isldap()) { - // use ldap for password try { $ldap = new Modelldap(Config::ldapserver(), Config::ldaptree(), Config::ldapu()); $pass = $ldap->auth($userid, $_POST['pass']); @@ -72,7 +75,6 @@ protected function login(): void return; } } else { - // compare password using database password $pass = $this->usermanager->passwordcheck($this->user, $_POST['pass']); } From 2077fb183dacfa56331f4ebf15b7b5e8e0284ba9 Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Thu, 31 Oct 2024 13:14:13 +0100 Subject: [PATCH 5/8] new user from ldap have their author personnal bookmark created --- app/class/Controllerconnect.php | 34 +++++++++++++++++++++++---- app/class/Controlleruser.php | 41 +++++++++------------------------ app/class/Modelbookmark.php | 22 ++++++++++++++++++ 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php index feb7a502..de4b8c4c 100644 --- a/app/class/Controllerconnect.php +++ b/app/class/Controllerconnect.php @@ -54,7 +54,9 @@ protected function login(): void try { $this->user = $this->usermanager->get($userid); // May throw DatabaseException + $userisindb = true; } catch (RuntimeException $e) { + $userisindb = false; if (Config::ldapuserlevel() > 0) { $this->user = new User(['password' => null, 'level' => Config::ldapuserlevel(), 'id' => $userid]); } else { @@ -97,8 +99,16 @@ protected function login(): void $this->usermanager->add($this->user); $this->servicesession->setuser($this->user->id()); $this->sendflashmessage("Successfully logged in as " . $this->user->id(), self::FLASH_SUCCESS); + } catch (RuntimeException $e) { + $this->sendflashmessage('Error while trying to persist user in database', self::FLASH_ERROR); + Logger::errorex($e); + if (! $userisindb) { // if user was'nt in database, this mean creation failed. In this case, abort. + return; + } + } - if (!empty($_POST['rememberme'])) { + if (!empty($_POST['rememberme'])) { + try { if ($this->user->cookie() > 0) { $wsessionid = $this->user->newsession(); $this->modelconnect->createauthcookie( @@ -112,11 +122,25 @@ protected function login(): void $message = "Can't remember you beccause user cookie conservation time is set to 0 days"; $this->sendflashmessage($message, self::FLASH_WARNING); } + } catch (RuntimeException $e) { + $message = "Can't create authentification cookie : $e"; + $this->sendflashmessage($message, self::FLASH_WARNING); + Logger::error($message); + } + } + + // if user was not in database before, we can creat it's author personnal bookmark + if (!$userisindb) { + try { + $bookmarkmanager = new Modelbookmark(); + $bookmarkmanager->addauthorbookmark($this->user); + } catch (RuntimeException $e) { + $this->sendflashmessage( + 'error while creating user\'s personnal author bookmark', + self::FLASH_WARNING + ); + Logger::errorex($e); } - } catch (RuntimeException $e) { - $message = "Can't create authentification cookie : $e"; - $this->sendflashmessage($message, self::FLASH_WARNING); - Logger::error($message); } } } diff --git a/app/class/Controlleruser.php b/app/class/Controlleruser.php index 98090a46..dca08e9c 100644 --- a/app/class/Controlleruser.php +++ b/app/class/Controlleruser.php @@ -50,8 +50,18 @@ public function add() $this->sendflashmessage('User successfully added', self::FLASH_SUCCESS); } catch (Databaseexception $e) { $this->sendflashmessage($e->getMessage(), self::FLASH_ERROR); + Logger::errorex($e); + } + try { + $bookmarkmanager = new Modelbookmark(); + $bookmarkmanager->addauthorbookmark($user); + } catch (RuntimeException $e) { + $this->sendflashmessage( + 'error while creating user\'s personnal author bookmark', + self::FLASH_WARNING + ); + Logger::errorex($e); } - $this->addauthorbookmark($user); $this->routedirect('user'); } } @@ -137,33 +147,4 @@ protected function update(array $datas): void $this->usermanager->update($userupdate); } } - - /** - * Create a bookmark that filter pages where the user is an author. - * Send a flash message in case of error. - * - * @param User $user The concerned user (need to be already added in database) - */ - protected function addauthorbookmark(User $user): void - { - try { - $bookmarkmanager = new Modelbookmark(); - $userbookmark = new Bookmark(); - $uid = $user->id(); - $userbookmark->init( - "$uid-is-author", - "?authorfilter[0]=$uid&submit=filter", - '👤', - "$uid's pages", - "Pages where $uid is listed as an author", - ); - $userbookmark->setuser($user->id()); - $bookmarkmanager->add($userbookmark); - } catch (RuntimeException $e) { - $this->sendflashmessage( - 'Could not create personnal user author bookmark: ' . $e->getMessage(), - self::FLASH_ERROR - ); - } - } } diff --git a/app/class/Modelbookmark.php b/app/class/Modelbookmark.php index 96946455..3975316a 100644 --- a/app/class/Modelbookmark.php +++ b/app/class/Modelbookmark.php @@ -192,6 +192,28 @@ public function update(Bookmark $bookmark): Bookmark return $bookmark; } + /** + * Create a bookmark that filter pages where the given user is an author. + * + * @param User $user The concerned user (need to be already added in database) + * + * @throws RuntimeException If the process failed + */ + public function addauthorbookmark(User $user): void + { + $userbookmark = new Bookmark(); + $uid = $user->id(); + $userbookmark->init( + "$uid-is-author", + "?authorfilter[0]=$uid&submit=filter", + '👤', + "$uid's pages", + "Pages where $uid is listed as an author", + ); + $userbookmark->setuser($user->id()); + $this->add($userbookmark); + } + /** * @param Bookmark|string $id string ID or bookmark * From 54b96d1ee239d3aa2274b3635072142761cdfabe Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Sat, 2 Nov 2024 19:24:48 +0100 Subject: [PATCH 6/8] prevent LDAP auth user to edit their database password see #237 + allow forbidden view to link to any given route --- app/class/Controllerprofile.php | 6 +++++ app/view/templates/forbidden.php | 2 +- app/view/templates/profile.php | 44 +++++++++++++++++--------------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/app/class/Controllerprofile.php b/app/class/Controllerprofile.php index cca48b09..3238bcf5 100644 --- a/app/class/Controllerprofile.php +++ b/app/class/Controllerprofile.php @@ -53,6 +53,12 @@ public function update() */ public function password() { + if ($this->user->isldap()) { + http_response_code(403); + $this->showtemplate('forbidden', ['route' => 'profile']); + exit; + } + if ( !isset($_POST['currentpassword']) || !$this->usermanager->passwordcheck($this->user, $_POST['currentpassword']) diff --git a/app/view/templates/forbidden.php b/app/view/templates/forbidden.php index e8297439..4995874f 100644 --- a/app/view/templates/forbidden.php +++ b/app/view/templates/forbidden.php @@ -23,7 +23,7 @@

back to page read view

-

Go back to home +

Go back stop() ?> diff --git a/app/view/templates/profile.php b/app/view/templates/profile.php index 86515006..676e332e 100644 --- a/app/view/templates/profile.php +++ b/app/view/templates/profile.php @@ -62,35 +62,37 @@ -

-

Password

+ isldap()) : ?> +
+

Password

-
+ -

Password have to be between and characters long.

+

Password have to be between and characters long.

-

- - -

+

+ + +

-

- - -

+

+ + +

-

- - -

+

+ + +

-

- -

+

+ +

-
+ -
+
+ From 9ff02bfea061c5aafbd001af9b048899d0ca13f2 Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Sat, 2 Nov 2024 19:46:33 +0100 Subject: [PATCH 7/8] indicate which users use LDAP auth in user management view see #237 + prevent local password from being edited by admins --- app/class/Controlleruser.php | 22 ++++++++++++++-------- app/class/User.php | 8 ++++++++ app/view/templates/user.php | 10 ++++++++-- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/class/Controlleruser.php b/app/class/Controlleruser.php index dca08e9c..7965a47e 100644 --- a/app/class/Controlleruser.php +++ b/app/class/Controlleruser.php @@ -117,6 +117,8 @@ protected function delete(array $datas): void * @throws Notfoundexception If User is not found in the database * @throws Databaseexception If an error occured with database * @throws Runtimeexception In case of other various problems + * + * @todo move this to Modeluser */ protected function update(array $datas): void { @@ -137,14 +139,18 @@ protected function update(array $datas): void && $this->user->id() === $user->id() ) { throw new RuntimeException('You cannot quit administration job'); - } else { - if ($userupdate->password() !== $user->password() && $user->passwordhashed()) { - $userupdate->setpasswordhashed(false); - } - if ($userupdate->passwordhashed() && !$user->passwordhashed()) { - $userupdate->hashpassword(); - } - $this->usermanager->update($userupdate); } + + if ($userupdate->password() !== $user->password() && $user->passwordhashed()) { + $userupdate->setpasswordhashed(false); + } + if ($userupdate->passwordhashed() && !$user->passwordhashed()) { + $userupdate->hashpassword(); + } + if ($user->isldap()) { + $userupdate->removepassword(); + $userupdate->setpasswordhashed(false); + } + $this->usermanager->update($userupdate); } } diff --git a/app/class/User.php b/app/class/User.php index a77b9502..dea7d1d1 100644 --- a/app/class/User.php +++ b/app/class/User.php @@ -309,6 +309,14 @@ public function validpassword() return false; } + /** + * Set password to null value. This mean authentication depends on LDAP. + */ + public function removepassword(): void + { + $this->password = null; + } + /** * Generate new unique session ID and store it * @param string $info session info to store diff --git a/app/view/templates/user.php b/app/view/templates/user.php index 20b8dcb4..72ec40ad 100644 --- a/app/view/templates/user.php +++ b/app/view/templates/user.php @@ -68,11 +68,17 @@ - + isldap()) : ?> + LDAP auth + + + - passwordhashed() ? '' : '' ?> + isldap()) : ?> + passwordhashed() ? '' : '' ?> + From 1c63f0dbad91de6ca1c68384b6ee433f874cfe04 Mon Sep 17 00:00:00 2001 From: vincent-peugnet Date: Sat, 2 Nov 2024 21:06:58 +0100 Subject: [PATCH 8/8] new LDAP fields in admin view see #237 --- app/class/Config.php | 10 ++--- app/class/Controllerconnect.php | 5 +++ app/class/Modelldap.php | 7 +++- app/view/templates/admin.php | 65 +++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/app/class/Config.php b/app/class/Config.php index 10041bfa..ce71abb9 100644 --- a/app/class/Config.php +++ b/app/class/Config.php @@ -631,24 +631,24 @@ public static function setlazyloadimg($lazyloadimg): bool return self::$lazyloadimg = boolval($lazyloadimg); } - public static function setldapserver($ldapserver): void + public static function setldapserver(string $ldapserver): void { self::$ldapserver = $ldapserver; } - public static function setldaptree($ldaptree): void + public static function setldaptree(string $ldaptree): void { self::$ldaptree = $ldaptree; } - public static function setldapu($ldapu): void + public static function setldapu(string $ldapu): void { self::$ldapu = $ldapu; } - public static function setldapuserlevel($ldapuserlevel): void + public static function setldapuserlevel(int $ldapuserlevel): void { - if (is_int($ldapuserlevel) && $ldapuserlevel >= 0 && $ldapuserlevel <= 10) { + if ($ldapuserlevel >= 0 && $ldapuserlevel <= 10) { self::$ldapuserlevel = $ldapuserlevel; } } diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php index de4b8c4c..9713234c 100644 --- a/app/class/Controllerconnect.php +++ b/app/class/Controllerconnect.php @@ -67,6 +67,11 @@ protected function login(): void } if ($this->user->isldap()) { + if (!Config::isldap()) { + $this->sendflashmessage('Error with LDAP connection', self::FLASH_ERROR); + Logger::error("User $userid tried to authenticate against LDAP, but LDAP is not configured"); + return; + } try { $ldap = new Modelldap(Config::ldapserver(), Config::ldaptree(), Config::ldapu()); $pass = $ldap->auth($userid, $_POST['pass']); diff --git a/app/class/Modelldap.php b/app/class/Modelldap.php index 7d2ad109..310421a1 100644 --- a/app/class/Modelldap.php +++ b/app/class/Modelldap.php @@ -3,6 +3,7 @@ namespace Wcms; use RuntimeException; +use Wcms\Exception\Missingextensionexception; class Modelldap extends Model { @@ -22,10 +23,14 @@ class Modelldap extends Model * Like `ou=people,dc=server,dc=tld` * @param string $u Username storing name, something like `uid`. * - * @throws RuntimeException + * @throws RuntimeException if LDAP server syntax did pass the sanity test + * @throws Missingextensionexception if LDAP extension is not installed */ public function __construct(string $ldapserver, string $tree, string $u) { + if (!extension_loaded('ldap')) { + throw new Missingextensionexception('PHP LDAP extension is not installed'); + } $this->ldapserver = $ldapserver; $this->connection = @ldap_connect($this->ldapserver); if ($this->connection === false) { diff --git a/app/view/templates/admin.php b/app/view/templates/admin.php index be51b99c..3affe764 100644 --- a/app/view/templates/admin.php +++ b/app/view/templates/admin.php @@ -362,6 +362,71 @@

+
+

LDAP auth

+ +

+ W authenticates users with a password linked to their account, stored in your instance database. + If you have an LDAP server, you can choose to authenticate your users with this server instead, + rather than using W's database to store their password. + In this case, W will no longer allow user's passwords to be changed. +

+ +

LDAP connection infos

+ +

+ Address of the LDAP server. Should start with: + ldap:// or ldaps://. + Followed by the server address. + For a local server, put localhost. + A port can be specified by adding :port at the end. +

+ +

+ + +

+ +

+ The LDAP tree structure, but without the part containing user identifier. +

+ +

+ + +

+ +

+ The name of the user field in the LDAP database. +

+ +

+ + +

+ + + +

New account creation

+ +

+ Users can be registered in LDAP but not have an account in W. + In this case, you can choose to have accounts created by defining the level of these new users. +

+ +

+ + +

+
+ stop('page') ?>