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'; $user = 'admin';
$_SESSION['id_usuario'] = $user; $_SESSION['id_usuario'] = $user;
$config['id_user'] = $user; $config['id_user'] = $user;

View File

@ -2775,11 +2775,12 @@ function get_os_name($id_os)
/** /**
* Get user's dashboards * 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. * @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)) { if (users_is_admin($id_user)) {
$sql = "SELECT id, name $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); 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 // Stop!! Are you sure to modify this critical code? Because the older
// versions are serius headache in many places of Pandora. // versions are serius headache in many places of Pandora.
if (empty($value) === true) {
return $value;
}
if (is_numeric($value)) { if (is_numeric($value)) {
return $value; return $value;
} }

View File

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

View File

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

View File

@ -128,7 +128,7 @@ final class UserDataMapper extends DataMapperAbstract
'defaultEventFilter' => $data[self::DEFAULT_EVENT_FILTER], 'defaultEventFilter' => $data[self::DEFAULT_EVENT_FILTER],
'metaconsoleDefaultEventFilter' => $data[self::METACONSOLE_DEFAULT_EVENT_FILTER], 'metaconsoleDefaultEventFilter' => $data[self::METACONSOLE_DEFAULT_EVENT_FILTER],
'showTipsStartup' => $data[self::SHOW_TIPS_STARTUP], '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], 'timeAutorefresh' => $data[self::TIME_AUTOREFRESH],
'defaultCustomView' => $data[self::DEFAULT_CUSTOM_VIEW], 'defaultCustomView' => $data[self::DEFAULT_CUSTOM_VIEW],
'ehorusUserLevelUser' => $this->repository->safeOutput($data[self::EHORUS_USER_LEVEL_USER]), '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::DEFAULT_EVENT_FILTER => $data->getDefaultEventFilter(),
self::METACONSOLE_DEFAULT_EVENT_FILTER => $data->getMetaconsoleDefaultEventFilter(), self::METACONSOLE_DEFAULT_EVENT_FILTER => $data->getMetaconsoleDefaultEventFilter(),
self::SHOW_TIPS_STARTUP => $data->getShowTipsStartup(), 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::TIME_AUTOREFRESH => $data->getTimeAutorefresh(),
self::DEFAULT_CUSTOM_VIEW => $data->getDefaultCustomView(), self::DEFAULT_CUSTOM_VIEW => $data->getDefaultCustomView(),
self::EHORUS_USER_LEVEL_USER => $this->repository->safeInput($data->getEhorusUserLevelUser()), 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 EXTERNAL_LINK = 'external_link';
case OTHER = 'other'; case OTHER = 'other';
case DASHBOARD = 'dashboard'; case DASHBOARD = 'dashboard';
} }

View File

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

View File

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

View File

@ -25,9 +25,15 @@ final class UpdateUserService
$user = $this->userRepository->update($user); $user = $this->userRepository->update($user);
// TODO: Save pass.
if (empty($user->getPasswordValidate()) === false) {
\save_pass_history($user->getIdUser(), $user->getPasswordValidate());
}
$this->audit->write( $this->audit->write(
'User Management', 'User Management',
' Update user #'.$user->getIdUser() ' Update user '.$user->getIdUser(),
json_encode($user->toArray())
); );
return $user; 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\CheckOldPasswordUserService;
use PandoraFMS\Modules\Users\Services\GetUserService; use PandoraFMS\Modules\Users\Services\GetUserService;
use Models\VisualConsole\Container as VisualConsole;
use PandoraFMS\Modules\Users\Services\ValidatePasswordUserService;
final class UserValidation final class UserValidation
{ {
@ -21,6 +24,7 @@ final class UserValidation
private Timestamp $timestamp, private Timestamp $timestamp,
private GetUserService $getUserService, private GetUserService $getUserService,
private CheckOldPasswordUserService $checkOldPasswordUserService, private CheckOldPasswordUserService $checkOldPasswordUserService,
private ValidatePasswordUserService $validatePasswordUserService
) { ) {
} }
@ -55,6 +59,18 @@ final class UserValidation
$user->setApiToken($this->generateApiToken()); $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) { if ($user->getIdSkin() === null) {
$user->setIdSkin(0); $user->setIdSkin(0);
} }
@ -107,10 +123,22 @@ final class UserValidation
$user->setDisabled(false); $user->setDisabled(false);
} }
if ($user->getSection() === null) {
$user->setSection(UserHomeScreenEnum::DEFAULT);
}
if ($user->getDataSection() === null) {
$user->setDataSection('');
}
if ($user->getMetaconsoleSection() === null) { if ($user->getMetaconsoleSection() === null) {
$user->setMetaconsoleSection(UserHomeScreenEnum::DEFAULT); $user->setMetaconsoleSection(UserHomeScreenEnum::DEFAULT);
} }
if ($user->getMetaconsoleDataSection() === null) {
$user->setMetaconsoleDataSection('');
}
if ($user->getForceChangePass() === null) { if ($user->getForceChangePass() === null) {
$user->setForceChangePass(false); $user->setForceChangePass(false);
} }
@ -145,12 +173,7 @@ final class UserValidation
} }
if (\enterprise_installed() === true) { if (\enterprise_installed() === true) {
$excludePassword = $this->checkExcludePassword($user->getPassword()); $this->validatePasswordUserService->__invoke($user, $oldUser);
if ($excludePassword === true) {
throw new BadRequestException(
__('The password provided is not valid. Please set another one.')
);
}
} }
// Only administrator users will not have to confirm the old password. // Only administrator users will not have to confirm the old password.
@ -162,9 +185,6 @@ final class UserValidation
$this->checkOldPasswordUserService->__invoke($user); $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)); $user->setPassword(password_hash($user->getPassword(), PASSWORD_BCRYPT));
if ($oldUser !== null) { if ($oldUser !== null) {
$user->setLastPassChange($this->getCurrentTimestamp()); $user->setLastPassChange($this->getCurrentTimestamp());
@ -186,6 +206,58 @@ final class UserValidation
if (empty($user->getDefaultCustomView()) === false) { if (empty($user->getDefaultCustomView()) === false) {
$this->validateCustomView($user->getDefaultCustomView()); $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 private function isAdmin(string $idUser): bool
{ {
// TODO: create new service for this. // 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'));
}
}
} }