%PDF- %PDF-
Direktori : /www/varak.net/dmarc.varak.net/classes/Users/ |
Current File : //www/varak.net/dmarc.varak.net/classes/Users/DbUser.php |
<?php /** * dmarc-srg - A php parser, viewer and summary report generator for incoming DMARC reports. * Copyright (C) 2023-2024 Aleksey Andreev (liuch) * * Available at: * https://github.com/liuch/dmarc-srg * * 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 the Free * Software Foundation, either version 3 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. * * ========================= * * This file contains the class DbUser * * @category API * @package DmarcSrg * @author Aleksey Andreev (liuch) * @license https://www.gnu.org/licenses/gpl-3.0.html GNU/GPLv3 */ namespace Liuch\DmarcSrg\Users; use Liuch\DmarcSrg\Core; use Liuch\DmarcSrg\Common; use Liuch\DmarcSrg\Exception\SoftException; use Liuch\DmarcSrg\Exception\LogicException; use Liuch\DmarcSrg\Exception\DatabaseNotFoundException; /** * It's a class for accessing to stored user data * * This class is designed for storing and manipulating user data. * All queries to the database are made in lazy mode. */ class DbUser extends User { private $db = null; private $ex_f = null; private $data = [ 'id' => null, 'name' => null, 'enabled' => null, 'password' => null, // If the password exists (boolean) 'level' => null, 'email' => null, 'key' => null, 'session' => null, 'domains' => null, 'created_time' => null, 'updated_time' => null ]; /** * Constructor * * Some examples of use: * (new DbUser('user1'))->verifyPassword($passw) - will verify password $passw for user with name 'user1' * (new DbUser([ 'name' => 'user2', 'level' => 10, 'enabled' => true ]))->save() - will add this user to * the database if it doesn't exist or update it otherwise. * * @param int|string|array $data Some user data to identify it * string value is treated as a name * array value is threated as user data with fields * @param \Liuch\DmarcSrg\Database\DatabaseController $db The database controller * * @return void */ public function __construct($data, $db = null) { $this->db = $db ?? Core::instance()->database(); switch (gettype($data)) { case 'string': $this->data['name'] = strtolower(trim($data)); $this->checkName(); return; case 'integer': if ($data <= 0) { break; } $this->data['id'] = $data; return; case 'array': if (isset($data['id'])) { if (gettype($data['id']) !== 'integer' || $data['id'] <= 0) { break; } $this->data['id'] = $data['id']; } if (isset($data['name'])) { if (gettype($data['name']) !== 'string') { break; } $this->data['name'] = strtolower(trim($data['name'])); $this->checkName(); } if (isset($data['enabled'])) { if (gettype($data['enabled']) !== 'boolean') { break; } $this->data['enabled'] = $data['enabled']; } if (isset($data['level'])) { if (gettype($data['level']) !== 'integer') { break; } $this->data['level'] = $data['level']; } if (isset($data['email'])) { if (gettype($data['email']) !== 'string') { break; } $this->data['email'] = $data['email']; } if (isset($data['key'])) { if (gettype($data['key']) !== 'string') { break; } $this->data['key'] = $data['key']; } if (isset($data['created_time'])) { if (gettype($data['created_time']) !== 'object') { break; } $this->data['created_time'] = $data['created_time']; } if (isset($data['updated_time'])) { if (gettype($data['updated_time']) !== 'object') { break; } $this->data['updated_time'] = $data['updated_time']; } if (isset($data['domains'])) { if (!is_int($data['domains'])) { break; } $this->data['domains'] = $data['domains']; } if (!is_null($this->data['id']) || !is_null($this->data['name'])) { return; } } throw new LogicException('Wrong user data'); } /** * Returns true if the user exists in the database or false otherwise * * @return bool Whether the user exists */ public function exists(): bool { if (is_null($this->ex_f)) { $this->ex_f = $this->db->getMapper('user')->exists($this->data); } return $this->ex_f; } /** * Ensures the user is in the specified state and throws an exception if it is not. * * @param string $state Can be one of these values: 'exist', 'nonexist' * * @throws SoftException * * @return void */ public function ensure(string $state): void { switch ($state) { case 'exist': if (!$this->exists()) { throw new SoftException('The user does not exist'); } break; case 'nonexist': if ($this->exists()) { throw new SoftException('The user already exists'); } break; default: throw new LogicException('Unknown user state'); } } /** * Returns the user id * * @return int */ public function id(): int { if (is_null($this->data['id'])) { $this->fetchData(); } return $this->data['id']; } /** * Returns the user name * * @return string */ public function name(): string { if (is_null($this->data['name'])) { $this->fetchData(); } return $this->data['name']; } /** * Returns the user access level * * @return int */ public function level(): int { if (is_null($this->data['level'])) { $this->fetchData(); } return $this->data['level']; } /** * Checks if the user is enabled * * @return bool */ public function isEnabled(): bool { if (is_null($this->data['enabled'])) { $this->fetchData(); } return $this->data['enabled']; } /** * Sets the list of domains available to the user * * @param array $domains Array of domain names * * @return void */ public function assignDomains(array &$domains): void { $this->db->getMapper('domain')->updateUserDomains($domains, $this->id()); } /** * Returns the sequence number of the session * * It changes when the user credentials or state are changed. * * @return int */ public function session(): int { if (is_null($this->data['session'])) { $this->fetchData(); } return $this->data['session']; } /** * Returns the user's data as an array * * @return array */ public function toArray(): array { foreach ([ 'id', 'name', 'level', 'enabled' ] as $it) { if (is_null($this->data[$it])) { $this->fetchData(); break; } } $res = $this->data; unset($res['id']); unset($res['session']); return $res; } /** * Saves the user's data to the database * * Updates the user's data in the database if the user exists or insert a new record otherwise. * The user id is ignored in the insert mode. * * @return void */ public function save(): void { $this->db->getMapper('user')->save($this->data); $this->ex_f = true; } /** * Deletes the user from the database * * @return void */ public function delete(): void { if (is_null($this->data['id'])) { $this->fetchData(); } $this->db->getMapper('user')->delete($this->data); $this->ex_f = false; } /** * Verifies the passed password with the hash stored in the database * * @param string $password Password to validate * * @return bool */ public function verifyPassword(string $password): bool { if (empty($password)) { return false; } $hash = null; try { $hash = $this->db->getMapper('user')->getPasswordHash($this->data); } catch (DatabaseNotFoundException $e) { $this->ex_f = false; return false; } return password_verify($password, $hash); } /** * Store the passed password to the database as a hash with salt * * @param string $password Password to store * * @return void */ public function setPassword(string $password): void { $hash = password_hash($password, PASSWORD_DEFAULT); $this->db->getMapper('user')->savePasswordHash($this->data, $hash); } /** * Returns a random string bound to the user * * @return string */ public function verificationString(): string { if (is_null($this->data['key'])) { $this->fetchData(); } if (empty($this->data['key'])) { $this->db->getMapper('user')->setUserKey($this->data, Common::randomString(32)); } return $this->data['key']; } /** * Checks if the username value is correct * * @return void */ private function checkName(): void { if (empty($this->data['name'])) { throw new SoftException('The user name must not be an empty string'); } if ($this->data['name'] === 'admin') { throw new SoftException('Incorrect user name'); } } /** * Fetches the user data from the database by its name * * @return void */ private function fetchData(): void { if ($this->ex_f === false) { return; } try { $this->db->getMapper('user')->fetch($this->data); $this->ex_f = true; } catch (DatabaseNotFoundException $e) { $this->ex_f = false; throw new SoftException('User not found'); } } }