shared frontend, UserAPI invalidate sessions, bugfixes, stuff
This commit is contained in:
@@ -76,13 +76,9 @@ namespace Core\API\Permission {
|
||||
}
|
||||
|
||||
// user would have required groups, check for 2fa-state
|
||||
if ($currentUser) {
|
||||
$tfaToken = $currentUser->getTwoFactorToken();
|
||||
if ($tfaToken && $tfaToken->isConfirmed() && !$tfaToken->isAuthenticated()) {
|
||||
$this->lastError = '2FA-Authorization is required';
|
||||
http_response_code(401);
|
||||
return false;
|
||||
}
|
||||
if ($currentUser && !$this->check2FA()) {
|
||||
http_response_code(401);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace Core\API;
|
||||
use Core\Driver\Logger\Logger;
|
||||
use Core\Driver\SQL\Query\Insert;
|
||||
use Core\Objects\Context;
|
||||
use Core\Objects\DatabaseEntity\TwoFactorToken;
|
||||
use Core\Objects\TwoFactor\KeyBasedTwoFactorToken;
|
||||
use PhpMqtt\Client\MqttClient;
|
||||
|
||||
abstract class Request {
|
||||
@@ -126,6 +128,33 @@ abstract class Request {
|
||||
protected abstract function _execute(): bool;
|
||||
public static function getDefaultACL(Insert $insert): void { }
|
||||
|
||||
protected function check2FA(?TwoFactorToken $tfaToken = null): bool {
|
||||
|
||||
// do not require 2FA for verifying endpoints
|
||||
if ($this instanceof \Core\API\Tfa\VerifyTotp || $this instanceof \Core\API\Tfa\VerifyKey) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($tfaToken === null) {
|
||||
$tfaToken = $this->context->getUser()?->getTwoFactorToken();
|
||||
}
|
||||
|
||||
if ($tfaToken && $tfaToken->isConfirmed() && !$tfaToken->isAuthenticated()) {
|
||||
|
||||
if ($tfaToken instanceof KeyBasedTwoFactorToken && !$tfaToken->hasChallenge()) {
|
||||
$tfaToken->generateChallenge();
|
||||
}
|
||||
|
||||
$this->lastError = '2FA-Authorization is required';
|
||||
$this->result["twoFactorToken"] = $tfaToken->jsonSerialize([
|
||||
"type", "challenge", "authenticated", "confirmed", "credentialID"
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public final function execute($values = array()): bool {
|
||||
|
||||
$this->params = array_merge([], $this->defaultParams);
|
||||
@@ -196,15 +225,9 @@ abstract class Request {
|
||||
$this->lastError = 'You are not logged in.';
|
||||
http_response_code(401);
|
||||
return false;
|
||||
} else if ($session) {
|
||||
$tfaToken = $session->getUser()->getTwoFactorToken();
|
||||
if ($tfaToken && $tfaToken->isConfirmed() && !$tfaToken->isAuthenticated()) {
|
||||
if (!($this instanceof \Core\API\Tfa\VerifyTotp) && !($this instanceof \Core\API\Tfa\VerifyKey)) {
|
||||
$this->lastError = '2FA-Authorization is required';
|
||||
http_response_code(401);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if ($session && !$this->check2FA()) {
|
||||
http_response_code(401);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ use Core\Driver\SQL\Expression\Count;
|
||||
use Core\Driver\SQL\Expression\Distinct;
|
||||
use Core\Driver\SQL\Query\Insert;
|
||||
use Core\Objects\DatabaseEntity\Group;
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
use Core\Objects\DatabaseEntity\User;
|
||||
use DateTime;
|
||||
use Core\Driver\SQL\Condition\Compare;
|
||||
use Core\Driver\SQL\Condition\CondBool;
|
||||
@@ -20,26 +22,6 @@ class Stats extends Request {
|
||||
parent::__construct($context, $externalCall, array());
|
||||
}
|
||||
|
||||
private function getUserCount(): int {
|
||||
$sql = $this->context->getSQL();
|
||||
$res = $sql->select(new Count())->from("User")->execute();
|
||||
$this->success = $this->success && ($res !== FALSE);
|
||||
$this->lastError = $sql->getLastError();
|
||||
|
||||
return ($this->success ? intval($res[0]["count"]) : 0);
|
||||
}
|
||||
|
||||
private function getPageCount(): int {
|
||||
$sql = $this->context->getSQL();
|
||||
$res = $sql->select(new Count())->from("Route")
|
||||
->where(new CondBool("active"))
|
||||
->execute();
|
||||
$this->success = $this->success && ($res !== FALSE);
|
||||
$this->lastError = $sql->getLastError();
|
||||
|
||||
return ($this->success ? intval($res[0]["count"]) : 0);
|
||||
}
|
||||
|
||||
private function checkSettings(): bool {
|
||||
$req = new \Core\API\Settings\Get($this->context);
|
||||
$this->success = $req->execute(array("key" => "^(mail_enabled|recaptcha_enabled)$"));
|
||||
@@ -72,8 +54,9 @@ class Stats extends Request {
|
||||
}
|
||||
|
||||
public function _execute(): bool {
|
||||
$userCount = $this->getUserCount();
|
||||
$pageCount = $this->getPageCount();
|
||||
$sql = $this->context->getSQL();
|
||||
$userCount = User::count($sql);
|
||||
$pageCount = Route::count($sql, new CondBool("active"));
|
||||
$req = new \Core\API\Visitors\Stats($this->context);
|
||||
$this->success = $req->execute(array("type"=>"monthly"));
|
||||
$this->lastError = $req->getLastError();
|
||||
|
||||
@@ -189,6 +189,11 @@ namespace Core\API\TFA {
|
||||
$sql = $this->context->getSQL();
|
||||
$this->success = $twoFactorToken->confirm($sql) !== false;
|
||||
$this->lastError = $sql->getLastError();
|
||||
|
||||
if ($this->success) {
|
||||
$this->context->invalidateSessions(true);
|
||||
}
|
||||
|
||||
return $this->success;
|
||||
}
|
||||
}
|
||||
@@ -315,6 +320,7 @@ namespace Core\API\TFA {
|
||||
|
||||
if ($this->success) {
|
||||
$this->result["twoFactorToken"] = $twoFactorToken->jsonSerialize();
|
||||
$this->context->invalidateSessions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -222,7 +222,8 @@ namespace Core\API\User {
|
||||
|
||||
public function __construct(Context $context, $externalCall = false) {
|
||||
parent::__construct($context, $externalCall,
|
||||
self::getPaginationParameters(['id', 'name', 'email', 'groups', 'registeredAt'])
|
||||
self::getPaginationParameters(['id', 'name', 'email', 'groups', 'registeredAt'],
|
||||
'id', 'asc')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -253,8 +254,8 @@ namespace Core\API\User {
|
||||
|
||||
$groupNames = new Alias(
|
||||
$sql->select(new JsonArrayAgg("name"))->from("Group")
|
||||
->leftJoin("NM_Group_User", "NM_Group_User.group_id", "Group.id")
|
||||
->whereEq("NM_Group_User.user_id", new Column("User.id")),
|
||||
->leftJoin("NM_User_groups", "NM_User_groups.group_id", "Group.id")
|
||||
->whereEq("NM_User_groups.user_id", new Column("User.id")),
|
||||
"groups"
|
||||
);
|
||||
|
||||
@@ -588,15 +589,7 @@ namespace Core\API\User {
|
||||
$this->result["user"] = $user->jsonSerialize();
|
||||
$this->result["session"] = $session->jsonSerialize();
|
||||
$this->result["logoutIn"] = $session->getExpiresSeconds();
|
||||
if ($tfaToken && $tfaToken->isConfirmed()) {
|
||||
if ($tfaToken instanceof KeyBasedTwoFactorToken) {
|
||||
$tfaToken->generateChallenge();
|
||||
}
|
||||
|
||||
$this->result["twoFactorToken"] = $tfaToken->jsonSerialize([
|
||||
"type", "challenge", "authenticated", "confirmed", "credentialID"
|
||||
]);
|
||||
}
|
||||
$this->check2FA($tfaToken);
|
||||
$this->success = true;
|
||||
}
|
||||
} else {
|
||||
@@ -1116,6 +1109,7 @@ namespace Core\API\User {
|
||||
if ($user->save($sql)) {
|
||||
$this->logger->info("Issued password reset for user id=" . $user->getId());
|
||||
$userToken->invalidate($sql);
|
||||
$this->context->invalidateSessions(false);
|
||||
return true;
|
||||
} else {
|
||||
return $this->createError("Error updating user details: " . $sql->getLastError());
|
||||
@@ -1152,6 +1146,7 @@ namespace Core\API\User {
|
||||
}
|
||||
|
||||
$sql = $this->context->getSQL();
|
||||
$updateFields = [];
|
||||
|
||||
$currentUser = $this->context->getUser();
|
||||
if ($newUsername !== null) {
|
||||
@@ -1159,11 +1154,13 @@ namespace Core\API\User {
|
||||
return false;
|
||||
} else {
|
||||
$currentUser->name = $newUsername;
|
||||
$updateFields[] = "name";
|
||||
}
|
||||
}
|
||||
|
||||
if ($newFullName !== null) {
|
||||
$currentUser->fullName = $newFullName;
|
||||
$updateFields[] = "fullName";
|
||||
}
|
||||
|
||||
if ($newPassword !== null || $newPasswordConfirm !== null) {
|
||||
@@ -1175,11 +1172,17 @@ namespace Core\API\User {
|
||||
}
|
||||
|
||||
$currentUser->password = $this->hashPassword($newPassword);
|
||||
$updateFields[] = "password";
|
||||
}
|
||||
}
|
||||
|
||||
$this->success = $currentUser->save($sql) !== false;
|
||||
$this->lastError = $sql->getLastError();
|
||||
if (!empty($updateFields)) {
|
||||
$this->success = $currentUser->save($sql, $updateFields) !== false;
|
||||
$this->lastError = $sql->getLastError();
|
||||
if ($this->success && in_array("password", $updateFields)) {
|
||||
$this->context->invalidateSessions(true);
|
||||
}
|
||||
}
|
||||
return $this->success;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user