Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ldap auth feature #484

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
60 changes: 60 additions & 0 deletions app/class/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ abstract class Config
/** Indicate if img should have loading="lazy" attribute */
protected static bool $lazyloadimg = true;

/** LDAP auth */
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;

Expand Down Expand Up @@ -156,6 +162,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()
Expand Down Expand Up @@ -349,6 +367,26 @@ public static function lazyloadimg(): bool
return self::$lazyloadimg;
}

public static function ldapserver(): string
{
return self::$ldapserver;
}

public static function ldaptree(): string
{
return self::$ldaptree;
}

public static function ldapu(): string
{
return self::$ldapu;
}

public static function ldapuserlevel(): int
{
return self::$ldapuserlevel;
}


// __________________________________________ S E T ______________________________________

Expand Down Expand Up @@ -592,4 +630,26 @@ public static function setlazyloadimg($lazyloadimg): bool
{
return self::$lazyloadimg = boolval($lazyloadimg);
}

public static function setldapserver(string $ldapserver): void
{
self::$ldapserver = $ldapserver;
}

public static function setldaptree(string $ldaptree): void
{
self::$ldaptree = $ldaptree;
}

public static function setldapu(string $ldapu): void
{
self::$ldapu = $ldapu;
}

public static function setldapuserlevel(int $ldapuserlevel): void
{
if ($ldapuserlevel >= 0 && $ldapuserlevel <= 10) {
self::$ldapuserlevel = $ldapuserlevel;
}
}
}
157 changes: 101 additions & 56 deletions app/class/Controllerconnect.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Wcms;

use RuntimeException;
use Wcms\Exception\Database\Notfoundexception;

class Controllerconnect extends Controller
{
Expand All @@ -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);
}
}
}
Expand All @@ -39,74 +43,115 @@ 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);
$userisindb = true;
} catch (RuntimeException $e) {
$userisindb = false;
if (Config::ldapuserlevel() > 0) {
$this->user = new User(['password' => null, 'level' => Config::ldapuserlevel(), 'id' => $userid]);
} 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);
}
}
$this->sendflashmessage('Wrong credentials', self::FLASH_ERROR);
Logger::errorex($e);
return;
}
}

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']);
$ldap->disconnect();
} catch (RuntimeException $e) {
$this->sendflashmessage('Error with LDAP connection', self::FLASH_ERROR);
Logger::errorex($e);
return;
}
} catch (Notfoundexception $e) {
} else {
$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);
} catch (RuntimeException $e) {
$message = "Can't create authentification cookie : $e";
$this->sendflashmessage($message, self::FLASH_WARNING);
Logger::error($message);
$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'])) {
try {
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 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);
}
}
}
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);
}
}
}
6 changes: 6 additions & 0 deletions app/class/Controllerprofile.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'])
Expand Down
59 changes: 23 additions & 36 deletions app/class/Controlleruser.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
}
Expand Down Expand Up @@ -107,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
{
Expand All @@ -127,43 +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);
}
}

/**
* 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
);
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);
}
}
Loading
Loading