* [FIX] Wrong behaviour when requesting user's password change. Thanks to @jorgemfm for the feedback. Closes #1155

* [MOD] Improved events handling by setting fixed events (always triggered)

Signed-off-by: nuxsmin <nuxsmin@syspass.org>
This commit is contained in:
nuxsmin
2018-12-16 12:19:53 +01:00
parent 52d5c7fc97
commit 3cf75fb6ba
10 changed files with 193 additions and 83 deletions

View File

@@ -93,26 +93,41 @@ final class UserPassResetController extends ControllerBase
}
if ($userData->isDisabled() || $userData->isLdap()) {
throw new SPException(__u('Unable to reset the password'), SPException::WARNING, __u('Please contact to the administrator'));
throw new SPException(
__u('Unable to reset the password'),
SPException::WARNING,
__u('Please contact to the administrator')
);
}
$hash = $this->dic->get(UserPassRecoverService::class)->requestForUserId($userData->getId());
$this->eventDispatcher->notifyEvent('request.user.passReset',
$this->eventDispatcher->notifyEvent(
'request.user.passReset',
new Event($this, EventMessage::factory()
->addDescription(__u('Password Recovery'))
->addDetail(__u('Requested for'), sprintf('%s (%s)', $login, $email)))
);
$this->dic->get(MailService::class)->send(__('Password Change'), $email, UserPassRecoverService::getMailMessage($hash));
$this->dic->get(MailService::class)
->send(__('Password Change'),
$email,
UserPassRecoverService::getMailMessage($hash));
return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Request sent'), [__u('You will receive an email to complete the request shortly.')]);
return $this->returnJsonResponse(
JsonResponse::JSON_SUCCESS,
__u('Request sent'),
[__u('You will receive an email to complete the request shortly.')]
);
} catch (\Exception $e) {
processException($e);
$this->addTracking();
$this->eventDispatcher->notifyEvent('exception', new Event($e));
$this->eventDispatcher->notifyEvent(
'exception',
new Event($e)
);
return $this->returnJsonResponseException($e);
}
@@ -146,12 +161,9 @@ final class UserPassResetController extends ControllerBase
*
* @throws \DI\DependencyException
* @throws \DI\NotFoundException
* @throws SPException
*/
public function resetAction($hash = null)
{
$this->checkSecurityToken($this->previousSk, $this->request);
$this->dic->get(LayoutHelper::class)
->getCustomLayout('reset', strtolower($this->controllerName));
@@ -191,15 +203,24 @@ final class UserPassResetController extends ControllerBase
$userId = $userPassRecoverService->getUserIdForHash($hash);
$userPassRecoverService->toggleUsedByHash($hash);
$this->dic->get(UserService::class)->updatePass($userId, $pass);
$userService = $this->dic->get(UserService::class);
$userService->updatePass($userId, $pass);
$this->eventDispatcher->notifyEvent('edit.user.password',
$user = $userService->getById($userId);
$this->eventDispatcher->notifyEvent(
'edit.user.password',
new Event($this, EventMessage::factory()
->addDescription(__u('Password updated'))
->addDetail(__u('User'), $userId))
->addDetail(__u('User'), $user->getLogin())
->addExtra('userId', $userId)
->addExtra('email', $user->getEmail()))
);
return $this->returnJsonResponse(JsonResponse::JSON_SUCCESS, __u('Password updated'));
return $this->returnJsonResponse(
JsonResponse::JSON_SUCCESS,
__u('Password updated')
);
} catch (\Exception $e) {
processException($e);

View File

@@ -6,10 +6,11 @@
<?php echo __('Request Password Change'); ?>
</div>
<div id="box-passreset" class="box-form round">
<form id="frmPassReset" action="" method="post" class="form-action" data-onsubmit="user/passreset"
<form id="frmPassReset" action="" method="post" class="form-action"
data-onsubmit="user/passreset"
data-action-route="userPassReset/saveRequest">
<fieldset id="box-data">
<div>
<div class="form-control">
<i class="material-icons">perm_identity</i>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input id="login" name="login" type="text" required
@@ -19,7 +20,7 @@
for="login"><?php echo __('User'); ?></label>
</div>
</div>
<div>
<div class="form-control">
<i class="material-icons">email</i>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input id="email" name="email" type="email" required
@@ -30,6 +31,7 @@
</div>
</div>
<input type="hidden" name="isAjax" value="1">
<input type="hidden" name="sk" value="<?php echo $sk; ?>">
</fieldset>
<div id="box-buttons">
@@ -40,7 +42,8 @@
<?php echo __('Back'); ?>
</button>
<button id="btnRequest" class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
<button id="btnRequest"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
<?php echo __('Request'); ?>
<i class="material-icons"
title="<?php echo __('Request'); ?>"><?php echo $icons->getIconPlay()->getIcon(); ?></i>

View File

@@ -13,13 +13,15 @@
<?php echo __('Request Password Change'); ?>
</div>
<div id="box-passreset" class="box-form round">
<form id="frmUserPassReset" action="" method="post" class="form-action" data-onsubmit="user/passreset"
<form id="frmUserPassReset" action="" method="post" class="form-action"
data-onsubmit="user/passreset"
data-action-route="userPassReset/saveReset">
<fieldset id="box-data">
<div class="form-control">
<i class="material-icons">vpn_key</i>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input id="password" name="password" type="password" required
<input id="password" name="password" type="password"
required
class="mdl-textfield__input mdl-color-text--indigo-400 passwordfield__input"
value="" maxlength="255"
autocomplete="off">
@@ -30,7 +32,8 @@
<div class="form-control">
<i class="material-icons">vpn_key</i>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input id="password_repeat" name="password_repeat" type="password" required
<input id="password_repeat" name="password_repeat"
type="password" required
class="mdl-textfield__input mdl-color-text--indigo-400"
value="" maxlength="255"
autocomplete="off">
@@ -38,7 +41,9 @@
for="password_repeat"><?php echo __('Password (repeat)'); ?></label>
</div>
</div>
<input type="hidden" name="hash" value="<?php echo $_getvar('hash'); ?>">
<input type="hidden" name="hash"
value="<?php echo $_getvar('hash'); ?>">
<input type="hidden" name="sk" value="<?php echo $sk; ?>">
<input type="hidden" name="isAjax" value="1">
</fieldset>
@@ -50,7 +55,8 @@
<?php echo __('Back'); ?>
</button>
<button id="btnChange" class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
<button id="btnChange"
class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
<?php echo __('Change'); ?>
<i class="material-icons"
title="<?php echo __('Change'); ?>"><?php echo $icons->getIconPlay()->getIcon(); ?></i>

View File

@@ -153,9 +153,9 @@ final class DatabaseLogHandler extends Provider implements EventReceiver
$configEvents = $this->config->getConfigData()->getLogEvents();
if (count($configEvents) === 0) {
$this->events = $this->parseEventsToRegex(LogInterface::EVENTS);
$this->events = $this->parseEventsToRegex(array_merge(LogInterface::EVENTS, LogInterface::EVENTS_FIXED));
} else {
$this->events = $this->parseEventsToRegex($configEvents);
$this->events = $this->parseEventsToRegex(array_merge($configEvents, LogInterface::EVENTS_FIXED));
}
}
}

View File

@@ -121,6 +121,6 @@ final class FileLogHandler extends Provider implements EventReceiver
protected function initialize(Container $dic)
{
$this->language = $dic->get(Language::class);
$this->events = $this->parseEventsToRegex(LogInterface::EVENTS);
$this->events = $this->parseEventsToRegex(array_merge(LogInterface::EVENTS, LogInterface::EVENTS_FIXED));
}
}

View File

@@ -41,23 +41,31 @@ interface LogInterface
'show.account.pass',
'show.account.link',
'copy.account.pass',
'clear.eventlog',
'login.',
'logout',
'track.',
'acl.deny',
'check.tempMasterPassword',
'expire.tempMasterPassword',
'refresh.masterPassword',
'update.',
'import.ldap.',
'run.',
'send.mail',
'unlock.track',
];
const EVENTS_FIXED = [
'upgrade.',
'acl.deny',
'plugin.load.error',
'show.authToken',
'clear.eventlog',
'clear.track',
'unlock.track',
'plugin.load.error',
'upgrade.'
'refresh.masterPassword',
'update.masterPassword.start',
'update.masterPassword.end',
'request.account',
'edit.user.password',
'save.config.',
'create.tempMasterPassword'
];
}

View File

@@ -88,6 +88,7 @@ final class RemoteSyslogHandler extends Provider implements EventReceiver
* </p>
*
* @return void
* @throws \SP\Core\Exceptions\InvalidClassException
* @since 5.1.0
*/
public function update(SplSubject $subject)
@@ -144,9 +145,9 @@ final class RemoteSyslogHandler extends Provider implements EventReceiver
$configEvents = $configData->getLogEvents();
if (count($configEvents) === 0) {
$this->events = $this->parseEventsToRegex(LogInterface::EVENTS);
$this->events = $this->parseEventsToRegex(array_merge(LogInterface::EVENTS, LogInterface::EVENTS_FIXED));
} else {
$this->events = $this->parseEventsToRegex($configEvents);
$this->events = $this->parseEventsToRegex(array_merge($configEvents, LogInterface::EVENTS_FIXED));
}
}
}

View File

@@ -132,9 +132,9 @@ final class SyslogHandler extends Provider implements EventReceiver
$configEvents = $this->config->getConfigData()->getLogEvents();
if (count($configEvents) === 0) {
$this->events = $this->parseEventsToRegex(LogInterface::EVENTS);
$this->events = $this->parseEventsToRegex(array_merge(LogInterface::EVENTS, LogInterface::EVENTS_FIXED));
} else {
$this->events = $this->parseEventsToRegex($configEvents);
$this->events = $this->parseEventsToRegex(array_merge($configEvents, LogInterface::EVENTS_FIXED));
}
}
}

View File

@@ -49,13 +49,20 @@ final class MailHandler extends Provider implements EventReceiver
'delete.',
'edit.',
'save.',
'clear.eventlog',
'refresh.masterPassword',
'update.masterPassword.end',
'import.ldap.end',
'run.backup.end',
'run.import.end',
'request.account'
'run.import.end'
];
const EVENTS_FIXED = [
'clear.eventlog',
'refresh.masterPassword',
'update.masterPassword.start',
'update.masterPassword.end',
'request.account',
'edit.user.password',
'save.config.',
'create.tempMasterPassword'
];
/**
@@ -132,7 +139,13 @@ final class MailHandler extends Provider implements EventReceiver
}
$mailMessage->addDescriptionLine();
$mailMessage->addDescription(sprintf(__('Performed by: %s (%s)'), $userData->getName(), $userData->getLogin()));
if ($userData->getId() !== null) {
$mailMessage->addDescription(sprintf(__('Performed by: %s (%s)'), $userData->getName(), $userData->getLogin()));
} else {
$mailMessage->addDescription(sprintf(__('Performed by: %s (%s)'), 'sysPass', 'APP'));
}
$mailMessage->addDescription(sprintf(__('IP Address: %s'), $this->request->getClientAddress(true)));
$subject = $eventMessage->getDescription(new TextFormatter(), true) ?: $eventType;
@@ -142,6 +155,16 @@ final class MailHandler extends Provider implements EventReceiver
$configData->getMailRecipients(),
$mailMessage
);
$extra = $eventMessage->getExtra();
if (isset($extra['userId'], $extra['email'])) {
$this->mailService->send(
$subject,
$extra['email'],
$mailMessage
);
}
} catch (\Exception $e) {
processException($e);
}
@@ -162,9 +185,9 @@ final class MailHandler extends Provider implements EventReceiver
$configEvents = $this->config->getConfigData()->getMailEvents();
if (count($configEvents) === 0) {
$this->events = $this->parseEventsToRegex(self::EVENTS);
$this->events = $this->parseEventsToRegex(array_merge(self::EVENTS, self::EVENTS_FIXED));
} else {
$this->events = $this->parseEventsToRegex($configEvents);
$this->events = $this->parseEventsToRegex(array_merge($configEvents, self::EVENTS_FIXED));
}
}
}

View File

@@ -36,6 +36,7 @@ use SP\Core\UI\ThemeInterface;
use SP\DataModel\UserLoginData;
use SP\DataModel\UserPreferencesData;
use SP\Http\Request;
use SP\Http\Uri;
use SP\Providers\Auth\AuthProvider;
use SP\Providers\Auth\Browser\BrowserAuthData;
use SP\Providers\Auth\Database\DatabaseAuthData;
@@ -173,9 +174,16 @@ final class LoginService extends Service
$this->loadUserPreferences();
$this->cleanUserData();
$redirect = 'index.php?r=' . ($this->from ? $this->from . '&sk=' . $this->context->getSecurityKey() : 'index');
$uri = new Uri('index.php');
return new LoginResponse(self::STATUS_PASS, $redirect);
if ($this->from) {
$uri->addParam('r', $this->from);
$uri->addParam('sk', $this->context->getSecurityKey());
} else {
$uri->addParam('r', 'index');
}
return new LoginResponse(self::STATUS_PASS, $uri->getUri());
}
/**
@@ -215,11 +223,11 @@ final class LoginService extends Service
if ($userLoginResponse !== null) {
// Comprobar si el usuario está deshabilitado
if ($userLoginResponse->getIsDisabled()) {
$this->eventDispatcher->notifyEvent('login.checkUser.disabled',
new Event($this,
EventMessage::factory()
->addDescription(__u('User disabled'))
->addDetail(__u('User'), $userLoginResponse->getLogin()))
$this->eventDispatcher->notifyEvent(
'login.checkUser.disabled',
new Event($this, EventMessage::factory()
->addDescription(__u('User disabled'))
->addDetail(__u('User'), $userLoginResponse->getLogin()))
);
$this->addTracking();
@@ -232,19 +240,23 @@ final class LoginService extends Service
);
}
// Comprobar si se ha forzado un cambio de clave
// Check whether a user's password change has been requested
if ($userLoginResponse->getIsChangePass()) {
$this->eventDispatcher->notifyEvent('login.checkUser.changePass',
new Event($this,
EventMessage::factory()
->addDetail(__u('User'), $userLoginResponse->getLogin()))
$this->eventDispatcher->notifyEvent(
'login.checkUser.changePass',
new Event($this, EventMessage::factory()
->addDetail(__u('User'), $userLoginResponse->getLogin()))
);
$hash = PasswordUtil::generateRandomBytes(16);
$this->dic->get(UserPassRecoverService::class)->add($userLoginResponse->getId(), $hash);
$this->dic->get(UserPassRecoverService::class)
->add($userLoginResponse->getId(), $hash);
return new LoginResponse(self::STATUS_PASS_RESET, 'index.php?r=userPassReset/change/' . $hash);
$uri = new Uri('index.php');
$uri->addParam('r', 'userPassReset/reset/' . $hash);
return new LoginResponse(self::STATUS_PASS_RESET, $uri->getUri());
}
}
@@ -270,9 +282,10 @@ final class LoginService extends Service
try {
if ($masterPass) {
if ($temporaryMasterPass->checkTempMasterPass($masterPass)) {
$this->eventDispatcher->notifyEvent('login.masterPass.temporary',
new Event($this,
EventMessage::factory()->addDescription(__u('Using temporary password')))
$this->eventDispatcher->notifyEvent(
'login.masterPass.temporary',
new Event($this, EventMessage::factory()
->addDescription(__u('Using temporary password')))
);
$masterPass = $temporaryMasterPass->getUsingKey($masterPass);
@@ -282,9 +295,10 @@ final class LoginService extends Service
$masterPass,
$this->userLoginData)->getStatus() !== UserPassService::MPASS_OK
) {
$this->eventDispatcher->notifyEvent('login.masterPass',
new Event($this,
EventMessage::factory()->addDescription(__u('Wrong master password')))
$this->eventDispatcher->notifyEvent(
'login.masterPass',
new Event($this, EventMessage::factory()
->addDescription(__u('Wrong master password')))
);
$this->addTracking();
@@ -297,18 +311,20 @@ final class LoginService extends Service
);
}
$this->eventDispatcher->notifyEvent('login.masterPass',
new Event($this,
EventMessage::factory()->addDescription(__u('Master password updated')))
$this->eventDispatcher->notifyEvent(
'login.masterPass',
new Event($this, EventMessage::factory()
->addDescription(__u('Master password updated')))
);
} else if ($oldPass) {
if ($userPassService->updateMasterPassFromOldPass(
$oldPass,
$this->userLoginData)->getStatus() !== UserPassService::MPASS_OK
) {
$this->eventDispatcher->notifyEvent('login.masterPass',
new Event($this,
EventMessage::factory()->addDescription(__u('Wrong master password')))
$this->eventDispatcher->notifyEvent(
'login.masterPass',
new Event($this, EventMessage::factory()
->addDescription(__u('Wrong master password')))
);
$this->addTracking();
@@ -321,9 +337,10 @@ final class LoginService extends Service
);
}
$this->eventDispatcher->notifyEvent('login.masterPass',
new Event($this,
EventMessage::factory()->addDescription(__u('Master password updated')))
$this->eventDispatcher->notifyEvent(
'login.masterPass',
new Event($this, EventMessage::factory()
->addDescription(__u('Master password updated')))
);
} else {
switch ($userPassService->loadUserMPass($this->userLoginData)->getStatus()) {
@@ -391,7 +408,8 @@ final class LoginService extends Service
$userLoginResponse->setPreferences(new UserPreferencesData());
}
$this->eventDispatcher->notifyEvent('login.session.load',
$this->eventDispatcher->notifyEvent(
'login.session.load',
new Event($this, EventMessage::factory()
->addDetail(__u('User'), $userLoginResponse->getLogin()))
);
@@ -408,7 +426,10 @@ final class LoginService extends Service
$this->context->setAuthCompleted(true);
$this->eventDispatcher->notifyEvent('login.preferences.load', new Event($this));
$this->eventDispatcher->notifyEvent(
'login.preferences.load',
new Event($this)
);
}
/**
@@ -467,7 +488,10 @@ final class LoginService extends Service
$this->addTracking();
$this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.ldap',
new Event($this, $eventMessage)
);
throw new AuthException(
__u('Wrong login'),
@@ -480,7 +504,10 @@ final class LoginService extends Service
if ($authData->getStatusCode() === LdapAuth::ACCOUNT_EXPIRED) {
$eventMessage->addDescription(__u('Account expired'));
$this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.ldap',
new Event($this, $eventMessage)
);
throw new AuthException(
__u('Account expired'),
@@ -493,7 +520,10 @@ final class LoginService extends Service
if ($authData->getStatusCode() === LdapAuth::ACCOUNT_NO_GROUPS) {
$eventMessage->addDescription(__u('User has no associated groups'));
$this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.ldap',
new Event($this, $eventMessage)
);
throw new AuthException(
__u('User has no associated groups'),
@@ -511,7 +541,10 @@ final class LoginService extends Service
$eventMessage->addDescription(__u('Internal error'));
$this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.ldap',
new Event($this, $eventMessage)
);
throw new AuthException(
__u('Internal error'),
@@ -521,7 +554,8 @@ final class LoginService extends Service
);
}
$this->eventDispatcher->notifyEvent('login.auth.ldap',
$this->eventDispatcher->notifyEvent(
'login.auth.ldap',
new Event($this, EventMessage::factory()
->addDetail(__u('Type'), __FUNCTION__)
->addDetail(__u('LDAP Server'), $authData->getServer())
@@ -582,7 +616,10 @@ final class LoginService extends Service
$eventMessage->addDescription(__u('Wrong login'));
$this->eventDispatcher->notifyEvent('login.auth.database', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.database',
new Event($this, $eventMessage)
);
throw new AuthException(
__u('Wrong login'),
@@ -593,7 +630,10 @@ final class LoginService extends Service
}
if ($authData->getAuthenticated() === true) {
$this->eventDispatcher->notifyEvent('login.auth.database', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.database',
new Event($this, $eventMessage)
);
}
return true;
@@ -626,7 +666,10 @@ final class LoginService extends Service
$eventMessage->addDescription(__u('Wrong login'));
$this->eventDispatcher->notifyEvent('login.auth.browser', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.browser',
new Event($this, $eventMessage)
);
throw new AuthException(
__u('Wrong login'),
@@ -636,7 +679,9 @@ final class LoginService extends Service
);
}
if ($authData->getAuthenticated() === true && $this->configData->isAuthBasicAutoLoginEnabled()) {
if ($authData->getAuthenticated() === true
&& $this->configData->isAuthBasicAutoLoginEnabled()
) {
try {
$userLoginRequest = new UserLoginRequest();
$userLoginRequest->setLogin($this->userLoginData->getLoginUser());
@@ -648,7 +693,10 @@ final class LoginService extends Service
$this->userService->createOnLogin($userLoginRequest);
}
$this->eventDispatcher->notifyEvent('login.auth.browser', new Event($this, $eventMessage));
$this->eventDispatcher->notifyEvent(
'login.auth.browser',
new Event($this, $eventMessage)
);
return true;
} catch (\Exception $e) {