new api 2.0

This commit is contained in:
daniel 2024-01-16 08:05:45 +01:00
parent b2a5472be3
commit bdc500c1b0
13 changed files with 282 additions and 36 deletions

View File

@ -49,6 +49,7 @@ return function (App $app, ContainerInterface $container) {
}
}
// TODO: XXX.
$user = 'admin';
$_SESSION['id_usuario'] = $user;
$config['id_user'] = $user;

View File

@ -2775,11 +2775,12 @@ function get_os_name($id_os)
/**
* Get user's dashboards
*
* @param int user id.
* @param integer $id_user User id.
* @param integer $id_dashboard Dashboard id.
*
* @return array Dashboard name of the given user.
*/
function get_user_dashboards($id_user)
function get_user_dashboards($id_user, $id_dashboard=null)
{
if (users_is_admin($id_user)) {
$sql = "SELECT id, name
@ -2806,6 +2807,10 @@ function get_user_dashboards($id_user)
}
}
if ($id_dashboard !== null) {
$sql .= sprintf(' AND id = %d', $id_dashboard);
}
return db_get_all_rows_sql($sql);
}

View File

@ -73,6 +73,10 @@ function io_safe_input($value)
{
// Stop!! Are you sure to modify this critical code? Because the older
// versions are serius headache in many places of Pandora.
if (empty($value) === true) {
return $value;
}
if (is_numeric($value)) {
return $value;
}

View File

@ -56,12 +56,15 @@ abstract class Controller
{
$queryParams = ($request->getQueryParams() ?? []);
$parsedBody = ($request->getParsedBody() ?? []);
// if (JSON_ERROR_NONE !== json_last_error()) {
// throw new \UnexpectedValueException(sprintf(
// 'Cannot decoded body JSON, error: %s',
// json_last_error_msg()
// ));
// }
if (JSON_ERROR_NONE !== json_last_error()) {
throw new \UnexpectedValueException(
sprintf(
'Cannot decoded body JSON, error: %s',
json_last_error_msg()
)
);
}
$params = array_merge($queryParams, $parsedBody);
return $params;

View File

@ -618,23 +618,23 @@ final class User extends Entity
'email' => $this->getEmail(),
'phone' => $this->getPhone(),
'isAdmin' => $this->getIsAdmin(),
'language' => $this->getLanguage()->name,
'language' => $this->getLanguage()?->name,
'timezone' => $this->getTimezone(),
'blockSize' => $this->getBlockSize(),
'idSkin' => $this->getIdSkin(),
'disabled' => $this->getDisabled(),
'shortcut' => $this->getShortcut(),
'shortcutData' => $this->getShortcutData(),
'section' => $this->getSection()->name,
'section' => $this->getSection()?->name,
'dataSection' => $this->getDataSection(),
'metaconsoleSection' => $this->getMetaconsoleSection()->name,
'metaconsoleSection' => $this->getMetaconsoleSection()?->name,
'metaconsoleDataSection' => $this->getMetaconsoleDataSection(),
'forceChangePass' => $this->getForceChangePass(),
'lastPassChange' => $this->getLastPassChange(),
'lastFailedLogin' => $this->getLastFailedLogin(),
'failedAttempt' => $this->getFailedAttempt(),
'loginBlocked' => $this->getLoginBlocked(),
'metaconsoleAccess' => $this->getMetaconsoleAccess()->name,
'metaconsoleAccess' => $this->getMetaconsoleAccess()?->name,
'notLogin' => $this->getNotLogin(),
'localUser' => $this->getLocalUser(),
'metaconsoleAgentsManager' => $this->getMetaconsoleAgentsManager(),

View File

@ -128,7 +128,7 @@ final class UserDataMapper extends DataMapperAbstract
'defaultEventFilter' => $data[self::DEFAULT_EVENT_FILTER],
'metaconsoleDefaultEventFilter' => $data[self::METACONSOLE_DEFAULT_EVENT_FILTER],
'showTipsStartup' => $data[self::SHOW_TIPS_STARTUP],
'autorefreshWhiteList' => json_decode($this->repository->safeOutput($data[self::AUTOREFRESH_WHITE_LIST])),
'autorefreshWhiteList' => ($data[self::AUTOREFRESH_WHITE_LIST] !== null) ? json_decode($this->repository->safeOutput($data[self::AUTOREFRESH_WHITE_LIST])) : null,
'timeAutorefresh' => $data[self::TIME_AUTOREFRESH],
'defaultCustomView' => $data[self::DEFAULT_CUSTOM_VIEW],
'ehorusUserLevelUser' => $this->repository->safeOutput($data[self::EHORUS_USER_LEVEL_USER]),
@ -191,7 +191,7 @@ final class UserDataMapper extends DataMapperAbstract
self::DEFAULT_EVENT_FILTER => $data->getDefaultEventFilter(),
self::METACONSOLE_DEFAULT_EVENT_FILTER => $data->getMetaconsoleDefaultEventFilter(),
self::SHOW_TIPS_STARTUP => $data->getShowTipsStartup(),
self::AUTOREFRESH_WHITE_LIST => $this->repository->safeInput(json_encode($data->getAutorefreshWhiteList())),
self::AUTOREFRESH_WHITE_LIST => ($data->getAutorefreshWhiteList() !== null) ? $this->repository->safeInput(json_encode($data->getAutorefreshWhiteList())) : null,
self::TIME_AUTOREFRESH => $data->getTimeAutorefresh(),
self::DEFAULT_CUSTOM_VIEW => $data->getDefaultCustomView(),
self::EHORUS_USER_LEVEL_USER => $this->repository->safeInput($data->getEhorusUserLevelUser()),

View File

@ -0,0 +1,26 @@
<?php
namespace PandoraFMS\Modules\Users\Enums;
use PandoraFMS\Modules\Shared\Traits\EnumTrait;
enum UserAutoRefreshPagesEnum: string
{
use EnumTrait;
case AGENT_DETAIL = 'operation/agentes/estado_agente';
case ALERT_DETAIL = 'operation/agentes/alerts_status';
case CLUSTER_VIEW = 'enterprise/operation/cluster/cluster';
case GIS_MAP = 'operation/gis_maps/render_view';
case GRAPH_VIEWER = 'operation/reporting/graph_viewer';
case SNMP_CONSOLE = 'operation/snmpconsole/snmp_view';
case SAP_VIEW = 'general/sap_view';
case TACTICAL_VIEW = 'operation/agentes/tactical';
case GROUP_VIEW = 'operation/agentes/group_view';
case MONITOR_DETAIL = 'operation/agentes/status_monitor';
case SERVICES = 'enterprise/operation/services/services';
case DASHBOARD = 'operation/dashboard/dashboard';
case VISUAL_CONSOLE = 'operation/visual_console/render_view';
case EVENTS = 'operation/events/events';
}

View File

@ -17,4 +17,5 @@ case ALERT_DETAIL = 'alert_detail';
case EXTERNAL_LINK = 'external_link';
case OTHER = 'other';
case DASHBOARD = 'dashboard';
}

View File

@ -57,7 +57,6 @@ class UserRepositoryMySQL extends RepositoryMySQL implements UserRepository
{
$sql = $this->getUsersQuery($userFilter, $this->userDataMapper, true);
try {
hd($sql, true);
$count = $this->dbGetValueSql($sql);
} catch (\Throwable $th) {
// Capture errors mysql.

View File

@ -25,12 +25,15 @@ final class CreateUserService
$user = $this->userRepository->create($user);
// TODO: Save pass.
\save_pass_history($user->getIdUser(), $user->getPasswordValidate());
$this->audit->write(
'User Management',
' Create user #'.$user->getIdUser()
AUDIT_LOG_USER_MANAGEMENT,
' Create user '.$user->getIdUser(),
json_encode($user->toArray())
);
// TODO: Campos personalizados.
return $user;
}

View File

@ -25,9 +25,15 @@ final class UpdateUserService
$user = $this->userRepository->update($user);
// TODO: Save pass.
if (empty($user->getPasswordValidate()) === false) {
\save_pass_history($user->getIdUser(), $user->getPasswordValidate());
}
$this->audit->write(
'User Management',
' Update user #'.$user->getIdUser()
' Update user '.$user->getIdUser(),
json_encode($user->toArray())
);
return $user;

View File

@ -0,0 +1,114 @@
<?php
namespace PandoraFMS\Modules\Users\Services;
use PandoraFMS\Modules\Shared\Exceptions\BadRequestException;
use PandoraFMS\Modules\Shared\Services\Config;
use PandoraFMS\Modules\Users\Entities\User;
final class ValidatePasswordUserService
{
public function __construct(
private Config $config,
) {
}
public function __invoke(User $user, ?User $oldUser): void
{
// Excluyes palabras.
$excludePassword = $this->checkExcludePassword($user->getPassword());
if ($excludePassword === true) {
throw new BadRequestException(
__('The password provided is not valid. Please set another one.')
);
}
// Si es una actualizacion, revisas el o los antiguos paswords,
// que no se pueda repetir.
if ($oldUser !== null) {
$newPass = password_hash($user->getPassword(), PASSWORD_BCRYPT);
if ((bool) $this->config->get('enable_pass_history') === true) {
$oldPasswords = $this->getOldPasswords($user->getIdUser());
foreach ($oldPasswords as $oldPass) {
if ($oldPass['password'] === $newPass) {
throw new BadRequestException(
__(
'Password must be different from the %s previous changes',
$this->config->get('compare_pass')
)
);
}
}
} else {
if ($oldUser->getPassword() === $newPass) {
throw new BadRequestException(__('Password must be different'));
}
}
}
// Tamaño del Password.
if ((strlen($user->getPassword())) < $this->config->get('pass_size')) {
throw new BadRequestException(__('Password too short'));
}
// Numeros includos.
if ($this->config->get('pass_needs_numbers')
&& preg_match('/([[:alpha:]])*(\d)+(\w)*/', $user->getPassword()) == 0
) {
throw new BadRequestException(__('Password must contain numbers'));
}
// Simbolos incluidos.
if ($this->config->get('pass_needs_symbols')
&& preg_match('/(\w)*(\W)+(\w)*/', $user->getPassword()) == 0
) {
throw new BadRequestException(__('Password must contain symbols'));
}
}
private function checkExcludePassword(string $newPassword): bool
{
if ((bool) $this->config->get('enable_pass_policy') === true
&& empty($this->config->get('exclusion_word_list')) === false
) {
$wordList = explode(',', $this->config->get('exclusion_word_list'));
if (is_array($wordList) === true) {
foreach ($wordList as $word) {
if ($newPassword === trim(io_safe_output($word))) {
return true;
}
}
}
}
return false;
}
private function getOldPasswords(string $idUser): array
{
// TODO: create new service for this.
$sql = sprintf(
'SELECT `password`
FROM tpassword_history
WHERE id_user="%s"
ORDER BY date_begin
DESC LIMIT %d',
$idUser,
$this->config->get('compare_pass')
);
$oldPasswords = db_get_all_rows_sql($sql);
if ((bool) $oldPasswords === false) {
$oldPasswords = [];
}
return $oldPasswords;
}
}

View File

@ -12,6 +12,9 @@ use PandoraFMS\Modules\Users\Enums\UserHomeScreenEnum;
use PandoraFMS\Modules\Users\Services\CheckOldPasswordUserService;
use PandoraFMS\Modules\Users\Services\GetUserService;
use Models\VisualConsole\Container as VisualConsole;
use PandoraFMS\Modules\Users\Services\ValidatePasswordUserService;
final class UserValidation
{
@ -21,6 +24,7 @@ final class UserValidation
private Timestamp $timestamp,
private GetUserService $getUserService,
private CheckOldPasswordUserService $checkOldPasswordUserService,
private ValidatePasswordUserService $validatePasswordUserService
) {
}
@ -55,6 +59,18 @@ final class UserValidation
$user->setApiToken($this->generateApiToken());
}
if ($user->getFirstName() === null) {
$user->setFirstName('');
}
if ($user->getLastName() === null) {
$user->setLastName('');
}
if ($user->getMiddleName() === null) {
$user->setMiddleName('');
}
if ($user->getIdSkin() === null) {
$user->setIdSkin(0);
}
@ -107,10 +123,22 @@ final class UserValidation
$user->setDisabled(false);
}
if ($user->getSection() === null) {
$user->setSection(UserHomeScreenEnum::DEFAULT);
}
if ($user->getDataSection() === null) {
$user->setDataSection('');
}
if ($user->getMetaconsoleSection() === null) {
$user->setMetaconsoleSection(UserHomeScreenEnum::DEFAULT);
}
if ($user->getMetaconsoleDataSection() === null) {
$user->setMetaconsoleDataSection('');
}
if ($user->getForceChangePass() === null) {
$user->setForceChangePass(false);
}
@ -145,12 +173,7 @@ final class UserValidation
}
if (\enterprise_installed() === true) {
$excludePassword = $this->checkExcludePassword($user->getPassword());
if ($excludePassword === true) {
throw new BadRequestException(
__('The password provided is not valid. Please set another one.')
);
}
$this->validatePasswordUserService->__invoke($user, $oldUser);
}
// Only administrator users will not have to confirm the old password.
@ -162,9 +185,6 @@ final class UserValidation
$this->checkOldPasswordUserService->__invoke($user);
}
// TODO: check validate pass.
// if ((!is_user_admin($config['id_user']) || $config['enable_pass_policy_admin']) && $config['enable_pass_policy']) {
// login_validate_pass
$user->setPassword(password_hash($user->getPassword(), PASSWORD_BCRYPT));
if ($oldUser !== null) {
$user->setLastPassChange($this->getCurrentTimestamp());
@ -186,6 +206,58 @@ final class UserValidation
if (empty($user->getDefaultCustomView()) === false) {
$this->validateCustomView($user->getDefaultCustomView());
}
if ($user->getSection() === UserHomeScreenEnum::DEFAULT
|| $user->getSection() === UserHomeScreenEnum::EVENT_LIST
|| $user->getSection() === UserHomeScreenEnum::TACTICAL_VIEW
|| $user->getSection() === UserHomeScreenEnum::ALERT_DETAIL
|| $user->getSection() === UserHomeScreenEnum::GROUP_VIEW
) {
$user->setDataSection('');
} else {
if (empty($user->getDataSection()) === true) {
throw new BadRequestException(
__(
'Section data of type %s, cannot be empty',
$user->getSection()->name
)
);
}
if ($user->getSection() === UserHomeScreenEnum::VISUAL_CONSOLE) {
$this->validateVisualConsole((int) $user->getDataSection());
}
if ($user->getSection() === UserHomeScreenEnum::DASHBOARD) {
$this->validateDashboard($this->config->get('id_user'), $user->getDataSection());
}
}
if ($user->getMetaconsoleSection() === UserHomeScreenEnum::DEFAULT
|| $user->getMetaconsoleSection() === UserHomeScreenEnum::EVENT_LIST
|| $user->getMetaconsoleSection() === UserHomeScreenEnum::TACTICAL_VIEW
|| $user->getMetaconsoleSection() === UserHomeScreenEnum::ALERT_DETAIL
|| $user->getMetaconsoleSection() === UserHomeScreenEnum::GROUP_VIEW
) {
$user->setMetaconsoleDataSection('');
} else {
if (empty($user->getMetaconsoleDataSection()) === true) {
throw new BadRequestException(
__(
'Metaconsole section data of type %s, cannot be empty',
$user->getMetaconsoleSection()->name
)
);
}
if ($user->getMetaconsoleSection() === UserHomeScreenEnum::VISUAL_CONSOLE) {
$this->validateVisualConsole((int) $user->getMetaconsoleDataSection());
}
if ($user->getMetaconsoleSection() === UserHomeScreenEnum::DASHBOARD) {
$this->validateDashboard($this->config->get('id_user'), $user->getMetaconsoleDataSection());
}
}
}
@ -238,14 +310,6 @@ final class UserValidation
}
private function checkExcludePassword(string $newPassword): bool
{
// TODO: create new service for this.
$return = \enterprise_hook('excludedPassword', [$newPassword]);
return $return;
}
private function isAdmin(string $idUser): bool
{
// TODO: create new service for this.
@ -280,4 +344,24 @@ final class UserValidation
}
protected function validateDashboard(string $idUser, int $idDashboard): void
{
// TODO: create new service for this.
if (! (bool) \get_user_dashboards($idUser, $idDashboard)) {
throw new BadRequestException(__('Invalid id Dashboard'));
}
}
protected function validateVisualConsole(int $visualConsoleId): void
{
// TODO: create new service for this.
try {
VisualConsole::fromDB(['id' => $visualConsoleId]);
} catch (\Throwable $e) {
throw new BadRequestException(__('Invalid visual console id'));
}
}
}