primo commit
This commit is contained in:
26
components/com_users/src/Controller/CallbackController.php
Normal file
26
components/com_users/src/Controller/CallbackController.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\Component\Users\Administrator\Controller\CallbackController as AdminCallbackController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication plugins' AJAX callback controller
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class CallbackController extends AdminCallbackController
|
||||
{
|
||||
}
|
||||
55
components/com_users/src/Controller/CaptiveController.php
Normal file
55
components/com_users/src/Controller/CaptiveController.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Users\Administrator\Controller\CaptiveController as AdminCaptiveController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Captive Multi-factor Authentication page controller
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class CaptiveController extends AdminCaptiveController
|
||||
{
|
||||
/**
|
||||
* Execute a task by triggering a Method in the derived class.
|
||||
*
|
||||
* @param string $task The task to perform.
|
||||
*
|
||||
* @return mixed The value returned by the called Method.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function execute($task)
|
||||
{
|
||||
try {
|
||||
return parent::execute($task);
|
||||
} catch (\Exception $e) {
|
||||
if ($e->getCode() !== 403) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($this->app->getIdentity()->guest) {
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
139
components/com_users/src/Controller/DisplayController.php
Normal file
139
components/com_users/src/Controller/DisplayController.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Base controller class for Users.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to display a view.
|
||||
*
|
||||
* @param boolean $cachable If true, the view output will be cached
|
||||
* @param array|boolean $urlparams An array of safe URL parameters and their variable types.
|
||||
* @see \Joomla\CMS\Filter\InputFilter::clean() for valid values.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.5
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function display($cachable = false, $urlparams = false)
|
||||
{
|
||||
// Get the document object.
|
||||
$document = $this->app->getDocument();
|
||||
|
||||
// Set the default view name and format from the Request.
|
||||
$vName = $this->input->getCmd('view', 'login');
|
||||
$vFormat = $document->getType();
|
||||
$lName = $this->input->getCmd('layout', 'default');
|
||||
|
||||
if ($view = $this->getView($vName, $vFormat)) {
|
||||
// Do any specific processing by view.
|
||||
switch ($vName) {
|
||||
case 'registration':
|
||||
// If the user is already logged in, redirect to the profile page.
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
if ($user->guest != 1) {
|
||||
// Redirect to profile page.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=profile', false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user registration is enabled
|
||||
if (ComponentHelper::getParams('com_users')->get('allowUserRegistration') == 0) {
|
||||
// Registration is disabled - Redirect to login page.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The user is a guest, load the registration model and show the registration page.
|
||||
$model = $this->getModel('Registration');
|
||||
break;
|
||||
|
||||
case 'profile':
|
||||
// Handle view specific models.
|
||||
// If the user is a guest, redirect to the login page.
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
if ($user->guest == 1) {
|
||||
// Redirect to login page.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$model = $this->getModel($vName);
|
||||
break;
|
||||
|
||||
case 'login':
|
||||
// Handle the default views.
|
||||
$model = $this->getModel($vName);
|
||||
break;
|
||||
|
||||
case 'remind':
|
||||
case 'reset':
|
||||
// If the user is already logged in, redirect to the profile page.
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
if ($user->guest != 1) {
|
||||
// Redirect to profile page.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=profile', false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$model = $this->getModel($vName);
|
||||
break;
|
||||
|
||||
case 'captive':
|
||||
case 'methods':
|
||||
case 'method':
|
||||
$controller = $this->factory->createController($vName, 'Site', [], $this->app, $this->input);
|
||||
$task = $this->input->get('task', '');
|
||||
|
||||
return $controller->execute($task);
|
||||
|
||||
default:
|
||||
$model = $this->getModel('Login');
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we don't send a referer
|
||||
if (\in_array($vName, ['remind', 'reset'])) {
|
||||
$this->app->setHeader('Referrer-Policy', 'no-referrer', true);
|
||||
}
|
||||
|
||||
// Push the model into the view (as default).
|
||||
$view->setModel($model, true);
|
||||
$view->setLayout($lName);
|
||||
|
||||
// Push document object into the view.
|
||||
$view->document = $document;
|
||||
|
||||
$view->display();
|
||||
}
|
||||
}
|
||||
}
|
||||
55
components/com_users/src/Controller/MethodController.php
Normal file
55
components/com_users/src/Controller/MethodController.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Users\Administrator\Controller\MethodController as AdminMethodController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication method controller
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class MethodController extends AdminMethodController
|
||||
{
|
||||
/**
|
||||
* Execute a task by triggering a Method in the derived class.
|
||||
*
|
||||
* @param string $task The task to perform.
|
||||
*
|
||||
* @return mixed The value returned by the called Method.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function execute($task)
|
||||
{
|
||||
try {
|
||||
return parent::execute($task);
|
||||
} catch (\Exception $e) {
|
||||
if ($e->getCode() !== 403) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($this->app->getIdentity()->guest) {
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
55
components/com_users/src/Controller/MethodsController.php
Normal file
55
components/com_users/src/Controller/MethodsController.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Users\Administrator\Controller\MethodsController as AdminMethodsController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication methods selection and management controller
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class MethodsController extends AdminMethodsController
|
||||
{
|
||||
/**
|
||||
* Execute a task by triggering a Method in the derived class.
|
||||
*
|
||||
* @param string $task The task to perform.
|
||||
*
|
||||
* @return mixed The value returned by the called Method.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function execute($task)
|
||||
{
|
||||
try {
|
||||
return parent::execute($task);
|
||||
} catch (\Exception $e) {
|
||||
if ($e->getCode() !== 403) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($this->app->getIdentity()->guest) {
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
232
components/com_users/src/Controller/ProfileController.php
Normal file
232
components/com_users/src/Controller/ProfileController.php
Normal file
@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSWebApplicationInterface;
|
||||
use Joomla\CMS\Event\Model;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Profile controller class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class ProfileController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to check out a user for editing and redirect to the edit form.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$app = $this->app;
|
||||
$user = $this->app->getIdentity();
|
||||
$loginUserId = (int) $user->id;
|
||||
|
||||
// Get the current user id.
|
||||
$userId = $this->input->getInt('user_id');
|
||||
|
||||
// Check if the user is trying to edit another users profile.
|
||||
if ($userId != $loginUserId) {
|
||||
$app->enqueueMessage(Text::_('JERROR_ALERTNOAUTHOR'), 'error');
|
||||
$app->setHeader('status', 403, true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$cookieLogin = $user->get('cookieLogin');
|
||||
|
||||
// Check if the user logged in with a cookie
|
||||
if (!empty($cookieLogin)) {
|
||||
// If so, the user must login to edit the password and other data.
|
||||
$app->enqueueMessage(Text::_('JGLOBAL_REMEMBER_MUST_LOGIN'), 'message');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the user id for the user to edit in the session.
|
||||
$app->setUserState('com_users.edit.profile.id', $userId);
|
||||
|
||||
// Redirect to the edit screen.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=profile&layout=edit', false));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save a user's profile data.
|
||||
*
|
||||
* @return void|boolean
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
$app = $this->app;
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\ProfileModel $model */
|
||||
$model = $this->getModel('Profile', 'Site');
|
||||
$user = $this->app->getIdentity();
|
||||
$userId = (int) $user->id;
|
||||
|
||||
// Get the user data.
|
||||
$requestData = $app->getInput()->post->get('jform', [], 'array');
|
||||
|
||||
// Force the ID to this user.
|
||||
$requestData['id'] = $userId;
|
||||
|
||||
// Validate the posted data.
|
||||
$form = $model->getForm();
|
||||
|
||||
if (!$form) {
|
||||
throw new \Exception($model->getError(), 500);
|
||||
}
|
||||
|
||||
// Send an object which can be modified through the plugin event
|
||||
$objData = (object) $requestData;
|
||||
$this->getDispatcher()->dispatch(
|
||||
'onContentNormaliseRequestData',
|
||||
new Model\NormaliseRequestDataEvent('onContentNormaliseRequestData', [
|
||||
'context' => 'com_users.user',
|
||||
'data' => $objData,
|
||||
'subject' => $form,
|
||||
])
|
||||
);
|
||||
$requestData = (array) $objData;
|
||||
|
||||
// Validate the posted data.
|
||||
$data = $model->validate($form, $requestData);
|
||||
|
||||
// Check for errors.
|
||||
if ($data === false) {
|
||||
// Get the validation messages.
|
||||
$errors = $model->getErrors();
|
||||
|
||||
// Push up to three validation messages out to the user.
|
||||
for ($i = 0, $n = \count($errors); $i < $n && $i < 3; $i++) {
|
||||
if ($errors[$i] instanceof \Exception) {
|
||||
$app->enqueueMessage($errors[$i]->getMessage(), CMSWebApplicationInterface::MSG_ERROR);
|
||||
} else {
|
||||
$app->enqueueMessage($errors[$i], CMSWebApplicationInterface::MSG_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// Unset the passwords.
|
||||
unset($requestData['password1'], $requestData['password2']);
|
||||
|
||||
// Save the data in the session.
|
||||
$app->setUserState('com_users.edit.profile.data', $requestData);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$userId = (int) $app->getUserState('com_users.edit.profile.id');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=profile&layout=edit&user_id=' . $userId, false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to save the data.
|
||||
$return = $model->save($data);
|
||||
|
||||
// Check for errors.
|
||||
if ($return === false) {
|
||||
// Save the data in the session.
|
||||
$app->setUserState('com_users.edit.profile.data', $data);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$userId = (int) $app->getUserState('com_users.edit.profile.id');
|
||||
$this->setMessage(Text::sprintf('COM_USERS_PROFILE_SAVE_FAILED', $model->getError()), 'warning');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=profile&layout=edit&user_id=' . $userId, false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Redirect the user and adjust session state based on the chosen task.
|
||||
switch ($this->getTask()) {
|
||||
case 'apply':
|
||||
// Check out the profile.
|
||||
$app->setUserState('com_users.edit.profile.id', $return);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$this->setMessage(Text::_('COM_USERS_PROFILE_SAVE_SUCCESS'));
|
||||
|
||||
$redirect = $app->getUserState('com_users.edit.profile.redirect', '');
|
||||
|
||||
// Don't redirect to an external URL.
|
||||
if (!Uri::isInternal($redirect)) {
|
||||
$redirect = null;
|
||||
}
|
||||
|
||||
if (!$redirect) {
|
||||
$redirect = 'index.php?option=com_users&view=profile&layout=edit&hidemainmenu=1';
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_($redirect, false));
|
||||
break;
|
||||
|
||||
default:
|
||||
// Clear the profile id from the session.
|
||||
$app->setUserState('com_users.edit.profile.id', null);
|
||||
|
||||
$redirect = $app->getUserState('com_users.edit.profile.redirect', '');
|
||||
|
||||
// Don't redirect to an external URL.
|
||||
if (!Uri::isInternal($redirect)) {
|
||||
$redirect = null;
|
||||
}
|
||||
|
||||
if (!$redirect) {
|
||||
$redirect = 'index.php?option=com_users&view=profile&user_id=' . $return;
|
||||
}
|
||||
|
||||
// Redirect to the list screen.
|
||||
$this->setMessage(Text::_('COM_USERS_PROFILE_SAVE_SUCCESS'));
|
||||
$this->setRedirect(Route::_($redirect, false));
|
||||
break;
|
||||
}
|
||||
|
||||
// Flush the data from the session.
|
||||
$app->setUserState('com_users.edit.profile.data', null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to cancel an edit.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function cancel()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
// Flush the data from the session.
|
||||
$this->app->setUserState('com_users.edit.profile', null);
|
||||
|
||||
// Redirect to user profile.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=profile', false));
|
||||
}
|
||||
}
|
||||
251
components/com_users/src/Controller/RegistrationController.php
Normal file
251
components/com_users/src/Controller/RegistrationController.php
Normal file
@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSWebApplicationInterface;
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\User\UserFactoryAwareInterface;
|
||||
use Joomla\CMS\User\UserFactoryAwareTrait;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Registration controller class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class RegistrationController extends BaseController implements UserFactoryAwareInterface
|
||||
{
|
||||
use UserFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* Method to activate a user.
|
||||
*
|
||||
* @return boolean True on success, false on failure.
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function activate()
|
||||
{
|
||||
$user = $this->app->getIdentity();
|
||||
$input = $this->input;
|
||||
$uParams = ComponentHelper::getParams('com_users');
|
||||
|
||||
// Check for admin activation. Don't allow non-super-admin to delete a super admin
|
||||
if ($uParams->get('useractivation') != 2 && $user->id) {
|
||||
$this->setRedirect('index.php');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If user registration or account activation is disabled, throw a 403.
|
||||
if ($uParams->get('useractivation') == 0 || $uParams->get('allowUserRegistration') == 0) {
|
||||
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
|
||||
}
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\RegistrationModel $model */
|
||||
$model = $this->getModel('Registration', 'Site');
|
||||
$token = $input->getAlnum('token');
|
||||
|
||||
// Check that the token is in a valid format.
|
||||
if ($token === null || \strlen($token) !== 32) {
|
||||
throw new \Exception(Text::_('JINVALID_TOKEN'), 403);
|
||||
}
|
||||
|
||||
// Get the User ID
|
||||
$userIdToActivate = $model->getUserIdFromToken($token);
|
||||
|
||||
if (!$userIdToActivate) {
|
||||
$this->setMessage(Text::_('COM_USERS_ACTIVATION_TOKEN_NOT_FOUND'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the user we want to activate
|
||||
$userToActivate = $this->getUserFactory()->loadUserById($userIdToActivate);
|
||||
|
||||
// Admin activation is on and admin is activating the account
|
||||
if (($uParams->get('useractivation') == 2) && $userToActivate->getParam('activate', 0)) {
|
||||
// If a user admin is not logged in, redirect them to the login page with an error message
|
||||
if (!$user->authorise('core.create', 'com_users') || !$user->authorise('core.manage', 'com_users')) {
|
||||
$activationUrl = 'index.php?option=com_users&task=registration.activate&token=' . $token;
|
||||
$loginUrl = 'index.php?option=com_users&view=login&return=' . base64_encode($activationUrl);
|
||||
|
||||
// In case we still run into this in the second step the user does not have the right permissions
|
||||
$message = Text::_('COM_USERS_REGISTRATION_ACL_ADMIN_ACTIVATION_PERMISSIONS');
|
||||
|
||||
// When we are not logged in we should login
|
||||
if ($user->guest) {
|
||||
$message = Text::_('COM_USERS_REGISTRATION_ACL_ADMIN_ACTIVATION');
|
||||
}
|
||||
|
||||
$this->setMessage($message);
|
||||
$this->setRedirect(Route::_($loginUrl, false));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to activate the user.
|
||||
$return = $model->activate($token);
|
||||
|
||||
// Check for errors.
|
||||
if ($return === false) {
|
||||
// Redirect back to the home page.
|
||||
$this->setMessage(Text::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $model->getError()), 'error');
|
||||
$this->setRedirect('index.php');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$useractivation = $uParams->get('useractivation');
|
||||
|
||||
// Redirect to the login screen.
|
||||
if ($useractivation == 0) {
|
||||
$this->setMessage(Text::_('COM_USERS_REGISTRATION_SAVE_SUCCESS'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
} elseif ($useractivation == 1) {
|
||||
$this->setMessage(Text::_('COM_USERS_REGISTRATION_ACTIVATE_SUCCESS'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
} elseif ($return->getParam('activate')) {
|
||||
$this->setMessage(Text::_('COM_USERS_REGISTRATION_VERIFY_SUCCESS'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=registration&layout=complete', false));
|
||||
} else {
|
||||
$this->setMessage(Text::_('COM_USERS_REGISTRATION_ADMINACTIVATE_SUCCESS'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=registration&layout=complete', false));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to register a user.
|
||||
*
|
||||
* @return boolean True on success, false on failure.
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
// If registration is disabled - Redirect to login page.
|
||||
if (ComponentHelper::getParams('com_users')->get('allowUserRegistration') == 0) {
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$app = $this->app;
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\RegistrationModel $model */
|
||||
$model = $this->getModel('Registration', 'Site');
|
||||
|
||||
// Get the user data.
|
||||
$requestData = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
// Validate the posted data.
|
||||
$form = $model->getForm();
|
||||
|
||||
if (!$form) {
|
||||
throw new \Exception($model->getError(), 500);
|
||||
}
|
||||
|
||||
$data = $model->validate($form, $requestData);
|
||||
|
||||
// Check for validation errors.
|
||||
if ($data === false) {
|
||||
// Get the validation messages.
|
||||
$errors = $model->getErrors();
|
||||
|
||||
// Push up to three validation messages out to the user.
|
||||
for ($i = 0, $n = \count($errors); $i < $n && $i < 3; $i++) {
|
||||
if ($errors[$i] instanceof \Exception) {
|
||||
$app->enqueueMessage($errors[$i]->getMessage(), CMSWebApplicationInterface::MSG_ERROR);
|
||||
} else {
|
||||
$app->enqueueMessage($errors[$i], CMSWebApplicationInterface::MSG_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We need the filtered value of calendar fields because the UTC normalisation is
|
||||
* done in the filter and on output. This would apply the Timezone offset on
|
||||
* reload. We set the calendar values we save to the processed date.
|
||||
*/
|
||||
$filteredData = $form->filter($requestData);
|
||||
|
||||
foreach ($form->getFieldset() as $field) {
|
||||
if ($field->type === 'Calendar') {
|
||||
$fieldName = $field->fieldname;
|
||||
|
||||
if ($field->group) {
|
||||
if (isset($filteredData[$field->group][$fieldName])) {
|
||||
$requestData[$field->group][$fieldName] = $filteredData[$field->group][$fieldName];
|
||||
}
|
||||
} else {
|
||||
if (isset($filteredData[$fieldName])) {
|
||||
$requestData[$fieldName] = $filteredData[$fieldName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save the data in the session.
|
||||
$app->setUserState('com_users.registration.data', $requestData);
|
||||
|
||||
// Redirect back to the registration screen.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=registration', false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to save the data.
|
||||
$return = $model->register($data);
|
||||
|
||||
// Check for errors.
|
||||
if ($return === false) {
|
||||
// Save the data in the session.
|
||||
$app->setUserState('com_users.registration.data', $data);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$this->setMessage($model->getError(), 'error');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=registration', false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flush the data from the session.
|
||||
$app->setUserState('com_users.registration.data', null);
|
||||
|
||||
// Redirect to the profile screen.
|
||||
if ($return === 'adminactivate') {
|
||||
$this->setMessage(Text::_('COM_USERS_REGISTRATION_COMPLETE_VERIFY'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=registration&layout=complete', false));
|
||||
} elseif ($return === 'useractivate') {
|
||||
$this->setMessage(Text::_('COM_USERS_REGISTRATION_COMPLETE_ACTIVATE'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=registration&layout=complete', false));
|
||||
} else {
|
||||
$this->setMessage(Text::_('COM_USERS_REGISTRATION_SAVE_SUCCESS'));
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
63
components/com_users/src/Controller/RemindController.php
Normal file
63
components/com_users/src/Controller/RemindController.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Reset controller class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class RemindController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to request a username reminder.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function remind()
|
||||
{
|
||||
// Check the request token.
|
||||
$this->checkToken('post');
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\RemindModel $model */
|
||||
$model = $this->getModel('Remind', 'Site');
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
// Submit the password reset request.
|
||||
$return = $model->processRemindRequest($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return == false && JDEBUG) {
|
||||
// The request failed.
|
||||
// Go back to the request form.
|
||||
$message = Text::sprintf('COM_USERS_REMIND_REQUEST_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=remind', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// To not expose if the user exists or not we send a generic message.
|
||||
$message = Text::_('COM_USERS_REMIND_REQUEST');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false), $message, 'notice');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
185
components/com_users/src/Controller/ResetController.php
Normal file
185
components/com_users/src/Controller/ResetController.php
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Reset controller class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class ResetController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to request a password reset.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function request()
|
||||
{
|
||||
// Check the request token.
|
||||
$this->checkToken('post');
|
||||
|
||||
$app = $this->app;
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\ResetModel $model */
|
||||
$model = $this->getModel('Reset', 'Site');
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
// Submit the password reset request.
|
||||
$return = $model->processResetRequest($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return instanceof \Exception && JDEBUG) {
|
||||
// Get the error message to display.
|
||||
if ($app->get('error_reporting')) {
|
||||
$message = $return->getMessage();
|
||||
} else {
|
||||
$message = Text::_('COM_USERS_RESET_REQUEST_ERROR');
|
||||
}
|
||||
|
||||
// Go back to the request form.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset', false), $message, 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($return === false && JDEBUG) {
|
||||
// The request failed.
|
||||
// Go back to the request form.
|
||||
$message = Text::sprintf('COM_USERS_RESET_REQUEST_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// To not expose if the user exists or not we send a generic message.
|
||||
$message = Text::_('COM_USERS_RESET_REQUEST');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset&layout=confirm', false), $message, 'notice');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to confirm the password request.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @access public
|
||||
* @since 1.6
|
||||
*/
|
||||
public function confirm()
|
||||
{
|
||||
// Check the request token.
|
||||
$this->checkToken('request');
|
||||
|
||||
$app = $this->app;
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\ResetModel $model */
|
||||
$model = $this->getModel('Reset', 'Site');
|
||||
$data = $this->input->get('jform', [], 'array');
|
||||
|
||||
// Confirm the password reset request.
|
||||
$return = $model->processResetConfirm($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return instanceof \Exception) {
|
||||
// Get the error message to display.
|
||||
if ($app->get('error_reporting')) {
|
||||
$message = $return->getMessage();
|
||||
} else {
|
||||
$message = Text::_('COM_USERS_RESET_CONFIRM_ERROR');
|
||||
}
|
||||
|
||||
// Go back to the confirm form.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset&layout=confirm', false), $message, 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($return === false) {
|
||||
// Confirm failed.
|
||||
// Go back to the confirm form.
|
||||
$message = Text::sprintf('COM_USERS_RESET_CONFIRM_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset&layout=confirm', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirm succeeded.
|
||||
// Proceed to step three.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset&layout=complete', false));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to complete the password reset process.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function complete()
|
||||
{
|
||||
// Check for request forgeries
|
||||
$this->checkToken('post');
|
||||
|
||||
$app = $this->app;
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\ResetModel $model */
|
||||
$model = $this->getModel('Reset', 'Site');
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
// Complete the password reset request.
|
||||
$return = $model->processResetComplete($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return instanceof \Exception) {
|
||||
// Get the error message to display.
|
||||
if ($app->get('error_reporting')) {
|
||||
$message = $return->getMessage();
|
||||
} else {
|
||||
$message = Text::_('COM_USERS_RESET_COMPLETE_ERROR');
|
||||
}
|
||||
|
||||
// Go back to the complete form.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset&layout=complete', false), $message, 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($return === false) {
|
||||
// Complete failed.
|
||||
// Go back to the complete form.
|
||||
$message = Text::sprintf('COM_USERS_RESET_COMPLETE_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=reset&layout=complete', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Complete succeeded.
|
||||
// Proceed to the login form.
|
||||
$message = Text::_('COM_USERS_RESET_COMPLETE_SUCCESS');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false), $message);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
270
components/com_users/src/Controller/UserController.php
Normal file
270
components/com_users/src/Controller/UserController.php
Normal file
@ -0,0 +1,270 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Application\ApplicationHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Registration controller class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class UserController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to log in a user.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
$this->checkToken('post');
|
||||
|
||||
$input = $this->input->getInputForRequestMethod();
|
||||
|
||||
// Populate the data array:
|
||||
$data = [];
|
||||
|
||||
$data['return'] = base64_decode($input->get('return', '', 'BASE64'));
|
||||
$data['username'] = $input->get('username', '', 'USERNAME');
|
||||
$data['password'] = $input->get('password', '', 'RAW');
|
||||
$data['secretkey'] = $input->get('secretkey', '', 'RAW');
|
||||
|
||||
// Check for a simple menu item id
|
||||
if (is_numeric($data['return'])) {
|
||||
$itemId = (int) $data['return'];
|
||||
$data['return'] = 'index.php?Itemid=' . $itemId;
|
||||
|
||||
if (Multilanguage::isEnabled()) {
|
||||
$language = $this->getModel('Login', 'Site')->getMenuLanguage($itemId);
|
||||
|
||||
if ($language !== '*') {
|
||||
$data['return'] .= '&lang=' . $language;
|
||||
}
|
||||
}
|
||||
} elseif (!Uri::isInternal($data['return'])) {
|
||||
// Don't redirect to an external URL.
|
||||
$data['return'] = '';
|
||||
}
|
||||
|
||||
// Set the return URL if empty.
|
||||
if (empty($data['return'])) {
|
||||
$data['return'] = 'index.php?option=com_users&view=profile';
|
||||
}
|
||||
|
||||
// Set the return URL in the user state to allow modification by plugins
|
||||
$this->app->setUserState('users.login.form.return', $data['return']);
|
||||
|
||||
// Get the log in options.
|
||||
$options = [];
|
||||
$options['remember'] = $this->input->getBool('remember', false);
|
||||
$options['return'] = $data['return'];
|
||||
|
||||
// Get the log in credentials.
|
||||
$credentials = [];
|
||||
$credentials['username'] = $data['username'];
|
||||
$credentials['password'] = $data['password'];
|
||||
$credentials['secretkey'] = $data['secretkey'];
|
||||
|
||||
// Perform the log in.
|
||||
if (true !== $this->app->login($credentials, $options)) {
|
||||
// Login failed !
|
||||
// Clear user name, password and secret key before sending the login form back to the user.
|
||||
$data['remember'] = (int) $options['remember'];
|
||||
$data['username'] = '';
|
||||
$data['password'] = '';
|
||||
$data['secretkey'] = '';
|
||||
$this->app->setUserState('users.login.form.data', $data);
|
||||
$this->app->redirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
}
|
||||
|
||||
// Success
|
||||
if ($options['remember'] == true) {
|
||||
$this->app->setUserState('rememberLogin', true);
|
||||
}
|
||||
|
||||
$this->app->setUserState('users.login.form.data', []);
|
||||
|
||||
$this->app->redirect(Route::_($this->app->getUserState('users.login.form.return'), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to log out a user.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
$this->checkToken('request');
|
||||
|
||||
$app = $this->app;
|
||||
|
||||
// Prepare the logout options.
|
||||
$options = [
|
||||
'clientid' => $app->get('shared_session', '0') ? null : 0,
|
||||
];
|
||||
|
||||
// Perform the log out.
|
||||
$error = $app->logout(null, $options);
|
||||
$input = $app->getInput()->getInputForRequestMethod();
|
||||
|
||||
// Check if the log out succeeded.
|
||||
if ($error instanceof \Exception) {
|
||||
$app->redirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
}
|
||||
|
||||
// Get the return URL from the request and validate that it is internal.
|
||||
$return = $input->get('return', '', 'BASE64');
|
||||
$return = base64_decode($return);
|
||||
|
||||
// Check for a simple menu item id
|
||||
if (is_numeric($return)) {
|
||||
$itemId = (int) $return;
|
||||
$return = 'index.php?Itemid=' . $itemId;
|
||||
|
||||
if (Multilanguage::isEnabled()) {
|
||||
$language = $this->getModel('Login', 'Site')->getMenuLanguage($itemId);
|
||||
|
||||
if ($language !== '*') {
|
||||
$return .= '&lang=' . $language;
|
||||
}
|
||||
}
|
||||
} elseif (!Uri::isInternal($return)) {
|
||||
$return = '';
|
||||
}
|
||||
|
||||
// In case redirect url is not set, redirect user to homepage
|
||||
if (empty($return)) {
|
||||
$return = Uri::root();
|
||||
}
|
||||
|
||||
// Show a message when a user is logged out.
|
||||
$app->enqueueMessage(Text::_('COM_USERS_FRONTEND_LOGOUT_SUCCESS'), 'message');
|
||||
|
||||
// Redirect the user.
|
||||
$app->redirect(Route::_($return, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to logout directly and redirect to page.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function menulogout()
|
||||
{
|
||||
// Get the ItemID of the page to redirect after logout
|
||||
$app = $this->app;
|
||||
$active = $app->getMenu()->getActive();
|
||||
$itemid = $active ? $active->getParams()->get('logout') : 0;
|
||||
|
||||
// Get the language of the page when multilang is on
|
||||
if (Multilanguage::isEnabled()) {
|
||||
if ($itemid) {
|
||||
$language = $this->getModel('Login', 'Site')->getMenuLanguage($itemid);
|
||||
|
||||
// URL to redirect after logout
|
||||
$url = 'index.php?Itemid=' . $itemid . ($language !== '*' ? '&lang=' . $language : '');
|
||||
} else {
|
||||
// Logout is set to default. Get the home page ItemID
|
||||
$lang_code = $app->getInput()->cookie->getString(ApplicationHelper::getHash('language'));
|
||||
$item = $app->getMenu()->getDefault($lang_code);
|
||||
$itemid = $item->id;
|
||||
|
||||
// Redirect to Home page after logout
|
||||
$url = 'index.php?Itemid=' . $itemid;
|
||||
}
|
||||
} else {
|
||||
// URL to redirect after logout, default page if no ItemID is set
|
||||
$url = $itemid ? 'index.php?Itemid=' . $itemid : Uri::root();
|
||||
}
|
||||
|
||||
// Logout and redirect
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&task=user.logout&' . Session::getFormToken() . '=1&return=' . base64_encode($url), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to request a username reminder.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function remind()
|
||||
{
|
||||
// Check the request token.
|
||||
$this->checkToken('post');
|
||||
|
||||
$app = $this->app;
|
||||
|
||||
/** @var \Joomla\Component\Users\Site\Model\RemindModel $model */
|
||||
$model = $this->getModel('Remind', 'Site');
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
// Submit the username remind request.
|
||||
$return = $model->processRemindRequest($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return instanceof \Exception) {
|
||||
// Get the error message to display.
|
||||
$message = $app->get('error_reporting')
|
||||
? $return->getMessage()
|
||||
: Text::_('COM_USERS_REMIND_REQUEST_ERROR');
|
||||
|
||||
// Go back to the complete form.
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=remind', false), $message, 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($return === false) {
|
||||
// Go back to the complete form.
|
||||
$message = Text::sprintf('COM_USERS_REMIND_REQUEST_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=remind', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Proceed to the login form.
|
||||
$message = Text::_('COM_USERS_REMIND_REQUEST_SUCCESS');
|
||||
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false), $message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to resend a user.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function resend()
|
||||
{
|
||||
// Check for request forgeries
|
||||
// $this->checkToken('post');
|
||||
}
|
||||
}
|
||||
24
components/com_users/src/Model/BackupcodesModel.php
Normal file
24
components/com_users/src/Model/BackupcodesModel.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Model for managing backup codes
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class BackupcodesModel extends \Joomla\Component\Users\Administrator\Model\BackupcodesModel
|
||||
{
|
||||
}
|
||||
24
components/com_users/src/Model/CaptiveModel.php
Normal file
24
components/com_users/src/Model/CaptiveModel.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Captive Multi-factor Authentication page's model
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class CaptiveModel extends \Joomla\Component\Users\Administrator\Model\CaptiveModel
|
||||
{
|
||||
}
|
||||
155
components/com_users/src/Model/LoginModel.php
Normal file
155
components/com_users/src/Model/LoginModel.php
Normal file
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\MVC\Model\FormModel;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Login model class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class LoginModel extends FormModel
|
||||
{
|
||||
/**
|
||||
* Method to get the login form.
|
||||
*
|
||||
* The base form is loaded from XML and then an event is fired
|
||||
* for users plugins to extend the form with extra fields.
|
||||
*
|
||||
* @param array $data An optional array of data for the form to interrogate.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form A Form object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_users.login', 'login', ['load_data' => $loadData]);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return array The default data is an empty array.
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered login form data.
|
||||
$app = Factory::getApplication();
|
||||
$data = $app->getUserState('users.login.form.data', []);
|
||||
|
||||
$input = $app->getInput()->getInputForRequestMethod();
|
||||
|
||||
// Check for return URL from the request first
|
||||
if ($return = $input->get('return', '', 'BASE64')) {
|
||||
$data['return'] = base64_decode($return);
|
||||
|
||||
if (!Uri::isInternal($data['return'])) {
|
||||
$data['return'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$app->setUserState('users.login.form.data', $data);
|
||||
|
||||
$this->preprocessData('com_users.login', $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function populateState()
|
||||
{
|
||||
// Get the application object.
|
||||
$params = Factory::getApplication()->getParams('com_users');
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override Joomla\CMS\MVC\Model\AdminModel::preprocessForm to ensure the correct plugin group is loaded.
|
||||
*
|
||||
* @param Form $form A Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception if there is an error in the form event.
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'user')
|
||||
{
|
||||
parent::preprocessForm($form, $data, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the language for the given menu id.
|
||||
*
|
||||
* @param int $id The menu id
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function getMenuLanguage(int $id): string
|
||||
{
|
||||
if (!Multilanguage::isEnabled()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('language'))
|
||||
->from($db->quoteName('#__menu'))
|
||||
->where($db->quoteName('client_id') . ' = 0')
|
||||
->where($db->quoteName('id') . ' = :id')
|
||||
->bind(':id', $id, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
return $db->loadResult();
|
||||
} catch (\RuntimeException $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
24
components/com_users/src/Model/MethodModel.php
Normal file
24
components/com_users/src/Model/MethodModel.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication Method management model
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class MethodModel extends \Joomla\Component\Users\Administrator\Model\MethodModel
|
||||
{
|
||||
}
|
||||
24
components/com_users/src/Model/MethodsModel.php
Normal file
24
components/com_users/src/Model/MethodsModel.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication Methods list page's model
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class MethodsModel extends \Joomla\Component\Users\Administrator\Model\MethodsModel
|
||||
{
|
||||
}
|
||||
337
components/com_users/src/Model/ProfileModel.php
Normal file
337
components/com_users/src/Model/ProfileModel.php
Normal file
@ -0,0 +1,337 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
use Joomla\CMS\Access\Access;
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Form\FormFactoryInterface;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\FormModel;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\String\PunycodeHelper;
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\CMS\User\UserHelper;
|
||||
use Joomla\Component\Users\Administrator\Model\UserModel;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Profile model class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class ProfileModel extends FormModel
|
||||
{
|
||||
/**
|
||||
* @var object The user profile data.
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request).
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
* @param ?FormFactoryInterface $formFactory The form factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\BaseDatabaseModel
|
||||
* @since 3.2
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null, ?FormFactoryInterface $formFactory = null)
|
||||
{
|
||||
$config = array_merge(
|
||||
[
|
||||
'events_map' => ['validate' => 'user'],
|
||||
],
|
||||
$config
|
||||
);
|
||||
|
||||
parent::__construct($config, $factory, $formFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the profile form data.
|
||||
*
|
||||
* The base form data is loaded and then an event is fired
|
||||
* for users plugins to extend the data.
|
||||
*
|
||||
* @return User
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
if ($this->data === null) {
|
||||
$userId = $this->getState('user.id');
|
||||
|
||||
// Initialise the table with Joomla\CMS\User\User.
|
||||
$this->data = new User($userId);
|
||||
|
||||
// Set the base user data.
|
||||
$this->data->email1 = $this->data->email;
|
||||
|
||||
// Override the base user data with any data in the session.
|
||||
$temp = (array) Factory::getApplication()->getUserState('com_users.edit.profile.data', []);
|
||||
|
||||
foreach ($temp as $k => $v) {
|
||||
$this->data->$k = $v;
|
||||
}
|
||||
|
||||
// Unset the passwords.
|
||||
unset($this->data->password1, $this->data->password2);
|
||||
|
||||
$registry = new Registry($this->data->params);
|
||||
$this->data->params = $registry->toArray();
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the profile form.
|
||||
*
|
||||
* The base form is loaded from XML and then an event is fired
|
||||
* for users plugins to extend the form with extra fields.
|
||||
*
|
||||
* @param array $data An optional array of data for the form to interrogate.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form|bool A Form object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_users.profile', 'profile', ['control' => 'jform', 'load_data' => $loadData]);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for username compliance and parameter set
|
||||
$isUsernameCompliant = true;
|
||||
$username = $loadData ? $form->getValue('username') : $this->loadFormData()->username;
|
||||
|
||||
if ($username) {
|
||||
$isUsernameCompliant = !(preg_match('#[<>"\'%;()&\\\\]|\\.\\./#', $username)
|
||||
|| \strlen(mb_convert_encoding($username, 'ISO-8859-1', 'UTF-8')) < 2
|
||||
|| trim($username) !== $username);
|
||||
}
|
||||
|
||||
$this->setState('user.username.compliant', $isUsernameCompliant);
|
||||
|
||||
if ($isUsernameCompliant && !ComponentHelper::getParams('com_users')->get('change_login_name')) {
|
||||
$form->setFieldAttribute('username', 'class', '');
|
||||
$form->setFieldAttribute('username', 'filter', '');
|
||||
$form->setFieldAttribute('username', 'description', 'COM_USERS_PROFILE_NOCHANGE_USERNAME_DESC');
|
||||
$form->setFieldAttribute('username', 'validate', '');
|
||||
$form->setFieldAttribute('username', 'message', '');
|
||||
$form->setFieldAttribute('username', 'readonly', 'true');
|
||||
$form->setFieldAttribute('username', 'required', 'false');
|
||||
}
|
||||
|
||||
// When multilanguage is set, a user's default site language should also be a Content Language
|
||||
if (Multilanguage::isEnabled()) {
|
||||
$form->setFieldAttribute('language', 'type', 'frontendlanguage', 'params');
|
||||
}
|
||||
|
||||
// If the user needs to change their password, mark the password fields as required
|
||||
if ($this->getCurrentUser()->requireReset) {
|
||||
$form->setFieldAttribute('password1', 'required', 'true');
|
||||
$form->setFieldAttribute('password2', 'required', 'true');
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
$data = $this->getData();
|
||||
|
||||
$this->preprocessData('com_users.profile', $data, 'user');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override preprocessForm to load the user plugin group instead of content.
|
||||
*
|
||||
* @param Form $form A Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception if there is an error in the form event.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'user')
|
||||
{
|
||||
if (ComponentHelper::getParams('com_users')->get('frontend_userparams')) {
|
||||
$form->loadFile('frontend', false);
|
||||
|
||||
if ($this->getCurrentUser()->authorise('core.login.admin')) {
|
||||
$form->loadFile('frontend_admin', false);
|
||||
}
|
||||
}
|
||||
|
||||
parent::preprocessForm($form, $data, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function populateState()
|
||||
{
|
||||
// Get the application object.
|
||||
$params = Factory::getApplication()->getParams('com_users');
|
||||
|
||||
// Get the user id.
|
||||
$userId = Factory::getApplication()->getUserState('com_users.edit.profile.id');
|
||||
$userId = !empty($userId) ? $userId : (int) $this->getCurrentUser()->id;
|
||||
|
||||
// Set the user id.
|
||||
$this->setState('user.id', $userId);
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array $data The form data.
|
||||
*
|
||||
* @return mixed The user id on success, false on failure.
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
$userId = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('user.id');
|
||||
|
||||
$user = new User($userId);
|
||||
|
||||
// Prepare the data for the user object.
|
||||
$data['email'] = PunycodeHelper::emailToPunycode($data['email1']);
|
||||
$data['password'] = $data['password1'];
|
||||
|
||||
// Unset the username if it should not be overwritten
|
||||
$isUsernameCompliant = $this->getState('user.username.compliant');
|
||||
|
||||
if ($isUsernameCompliant && !ComponentHelper::getParams('com_users')->get('change_login_name')) {
|
||||
unset($data['username']);
|
||||
}
|
||||
|
||||
// Unset block and sendEmail so they do not get overwritten
|
||||
unset($data['block'], $data['sendEmail']);
|
||||
|
||||
// Bind the data.
|
||||
if (!$user->bind($data)) {
|
||||
$this->setError($user->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the users plugin group.
|
||||
PluginHelper::importPlugin('user');
|
||||
|
||||
// Retrieve the user groups so they don't get overwritten
|
||||
unset($user->groups);
|
||||
$user->groups = Access::getGroupsByUser($user->id, false);
|
||||
|
||||
// Store the data.
|
||||
if (!$user->save()) {
|
||||
$this->setError($user->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destroy all active sessions for the user after changing the password
|
||||
if ($data['password1']) {
|
||||
UserHelper::destroyUserSessions($user->id, true);
|
||||
}
|
||||
|
||||
return $user->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuration forms for all two-factor authentication methods
|
||||
* in an array.
|
||||
*
|
||||
* @param integer $userId The user ID to load the forms for (optional)
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.2
|
||||
*
|
||||
* @deprecated 4.2 will be removed in 6.0.
|
||||
* Will be removed without replacement
|
||||
*/
|
||||
public function getTwofactorform($userId = null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* No longer used
|
||||
*
|
||||
* @param integer $userId Ignored
|
||||
*
|
||||
* @return \stdClass
|
||||
*
|
||||
* @since 3.2
|
||||
*
|
||||
* @deprecated 4.2 will be removed in 6.0.
|
||||
* Will be removed without replacement
|
||||
*/
|
||||
public function getOtpConfig($userId = null)
|
||||
{
|
||||
@trigger_error(
|
||||
\sprintf(
|
||||
'%s() is deprecated. Use \Joomla\Component\Users\Administrator\Helper\Mfa::getUserMfaRecords() instead.',
|
||||
__METHOD__
|
||||
),
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
/** @var UserModel $model */
|
||||
$model = $this->bootComponent('com_users')
|
||||
->getMVCFactory()->createModel('User', 'Administrator');
|
||||
|
||||
return $model->getOtpConfig();
|
||||
}
|
||||
}
|
||||
656
components/com_users/src/Model/RegistrationModel.php
Normal file
656
components/com_users/src/Model/RegistrationModel.php
Normal file
@ -0,0 +1,656 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
use Joomla\CMS\Application\ApplicationHelper;
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Date\Date;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Form\FormFactoryInterface;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\Mail\MailTemplate;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\FormModel;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\String\PunycodeHelper;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\CMS\User\UserFactoryAwareInterface;
|
||||
use Joomla\CMS\User\UserFactoryAwareTrait;
|
||||
use Joomla\CMS\User\UserHelper;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Registration model class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class RegistrationModel extends FormModel implements UserFactoryAwareInterface
|
||||
{
|
||||
use UserFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* @var object The user registration data.
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request).
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
* @param ?FormFactoryInterface $formFactory The form factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\BaseDatabaseModel
|
||||
* @since 3.2
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null, ?FormFactoryInterface $formFactory = null)
|
||||
{
|
||||
$config = array_merge(
|
||||
[
|
||||
'events_map' => ['validate' => 'user'],
|
||||
],
|
||||
$config
|
||||
);
|
||||
|
||||
parent::__construct($config, $factory, $formFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the user ID from the given token
|
||||
*
|
||||
* @param string $token The activation token.
|
||||
*
|
||||
* @return mixed False on failure, id of the user on success
|
||||
*
|
||||
* @since 3.8.13
|
||||
*/
|
||||
public function getUserIdFromToken($token)
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
// Get the user id based on the token.
|
||||
$query = $db->getQuery(true);
|
||||
$query->select($db->quoteName('id'))
|
||||
->from($db->quoteName('#__users'))
|
||||
->where($db->quoteName('activation') . ' = :activation')
|
||||
->where($db->quoteName('block') . ' = 1')
|
||||
->where($db->quoteName('lastvisitDate') . ' IS NULL')
|
||||
->bind(':activation', $token);
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
return (int) $db->loadResult();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to activate a user account.
|
||||
*
|
||||
* @param string $token The activation token.
|
||||
*
|
||||
* @return mixed False on failure, user object on success.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function activate($token)
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
$userParams = ComponentHelper::getParams('com_users');
|
||||
$userId = $this->getUserIdFromToken($token);
|
||||
|
||||
// Check for a valid user id.
|
||||
if (!$userId) {
|
||||
$this->setError(Text::_('COM_USERS_ACTIVATION_TOKEN_NOT_FOUND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the users plugin group.
|
||||
PluginHelper::importPlugin('user');
|
||||
|
||||
// Activate the user.
|
||||
$user = $this->getUserFactory()->loadUserById($userId);
|
||||
|
||||
// Admin activation is on and user is verifying their email
|
||||
if (($userParams->get('useractivation') == 2) && !$user->getParam('activate', 0)) {
|
||||
$linkMode = $app->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;
|
||||
|
||||
// Compile the admin notification mail values.
|
||||
$data = $user->getProperties();
|
||||
$data['activation'] = ApplicationHelper::getHash(UserHelper::genRandomPassword());
|
||||
$user->set('activation', $data['activation']);
|
||||
$data['siteurl'] = Uri::base();
|
||||
$data['activate'] = Route::link(
|
||||
'site',
|
||||
'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
|
||||
false,
|
||||
$linkMode,
|
||||
true
|
||||
);
|
||||
|
||||
$data['fromname'] = $app->get('fromname');
|
||||
$data['mailfrom'] = $app->get('mailfrom');
|
||||
$data['sitename'] = $app->get('sitename');
|
||||
$user->setParam('activate', 1);
|
||||
|
||||
// Get all admin users
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName(['name', 'email', 'sendEmail', 'id']))
|
||||
->from($db->quoteName('#__users'))
|
||||
->where($db->quoteName('sendEmail') . ' = 1')
|
||||
->where($db->quoteName('block') . ' = 0');
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$rows = $db->loadObjectList();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send mail to all users with users creating permissions and receiving system emails
|
||||
foreach ($rows as $row) {
|
||||
$usercreator = $this->getUserFactory()->loadUserById($row->id);
|
||||
|
||||
if ($usercreator->authorise('core.create', 'com_users') && $usercreator->authorise('core.manage', 'com_users')) {
|
||||
try {
|
||||
$mailer = new MailTemplate('com_users.registration.admin.verification_request', $app->getLanguage()->getTag());
|
||||
$mailer->addTemplateData($data);
|
||||
$mailer->addRecipient($row->email);
|
||||
$return = $mailer->send();
|
||||
} catch (\Exception $exception) {
|
||||
try {
|
||||
Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror');
|
||||
|
||||
$return = false;
|
||||
} catch (\RuntimeException $exception) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_($exception->errorMessage()), 'warning');
|
||||
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an error.
|
||||
if ($return !== true) {
|
||||
$this->setError(Text::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (($userParams->get('useractivation') == 2) && $user->getParam('activate', 0)) {
|
||||
// Admin activation is on and admin is activating the account
|
||||
$user->set('activation', '');
|
||||
$user->set('block', '0');
|
||||
|
||||
// Compile the user activated notification mail values.
|
||||
$data = $user->getProperties();
|
||||
$user->setParam('activate', 0);
|
||||
$data['fromname'] = $app->get('fromname');
|
||||
$data['mailfrom'] = $app->get('mailfrom');
|
||||
$data['sitename'] = $app->get('sitename');
|
||||
$data['siteurl'] = Uri::base();
|
||||
$mailer = new MailTemplate('com_users.registration.user.admin_activated', $app->getLanguage()->getTag());
|
||||
$mailer->addTemplateData($data);
|
||||
$mailer->addRecipient($data['email']);
|
||||
|
||||
try {
|
||||
$return = $mailer->send();
|
||||
} catch (\Exception $exception) {
|
||||
try {
|
||||
Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror');
|
||||
|
||||
$return = false;
|
||||
} catch (\RuntimeException $exception) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_($exception->errorMessage()), 'warning');
|
||||
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an error.
|
||||
if ($return !== true) {
|
||||
$this->setError(Text::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$user->set('activation', '');
|
||||
$user->set('block', '0');
|
||||
}
|
||||
|
||||
// Store the user object.
|
||||
if (!$user->save()) {
|
||||
$this->setError(Text::sprintf('COM_USERS_REGISTRATION_ACTIVATION_SAVE_FAILED', $user->getError()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the registration form data.
|
||||
*
|
||||
* The base form data is loaded and then an event is fired
|
||||
* for users plugins to extend the data.
|
||||
*
|
||||
* @return mixed Data object on success, false on failure.
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
if ($this->data === null) {
|
||||
$this->data = new \stdClass();
|
||||
$app = Factory::getApplication();
|
||||
$params = ComponentHelper::getParams('com_users');
|
||||
|
||||
// Override the base user data with any data in the session.
|
||||
$temp = (array) $app->getUserState('com_users.registration.data', []);
|
||||
|
||||
// Don't load the data in this getForm call, or we'll call ourself
|
||||
$form = $this->getForm([], false);
|
||||
|
||||
foreach ($temp as $k => $v) {
|
||||
// Here we could have a grouped field, let's check it
|
||||
if (\is_array($v)) {
|
||||
$this->data->$k = new \stdClass();
|
||||
|
||||
foreach ($v as $key => $val) {
|
||||
if ($form->getField($key, $k) !== false) {
|
||||
$this->data->$k->$key = $val;
|
||||
}
|
||||
}
|
||||
} elseif ($form->getField($k) !== false) {
|
||||
// Only merge the field if it exists in the form.
|
||||
$this->data->$k = $v;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the groups the user should be added to after registration.
|
||||
$this->data->groups = [];
|
||||
|
||||
// Get the default new user group, guest or public group if not specified.
|
||||
$system = $params->get('new_usertype', $params->get('guest_usergroup', 1));
|
||||
|
||||
$this->data->groups[] = $system;
|
||||
|
||||
// Unset the passwords.
|
||||
unset($this->data->password1, $this->data->password2);
|
||||
|
||||
// Get the dispatcher and load the users plugins.
|
||||
PluginHelper::importPlugin('user');
|
||||
|
||||
// Trigger the data preparation event.
|
||||
Factory::getApplication()->triggerEvent('onContentPrepareData', ['com_users.registration', $this->data]);
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the registration form.
|
||||
*
|
||||
* The base form is loaded from XML and then an event is fired
|
||||
* for users plugins to extend the form with extra fields.
|
||||
*
|
||||
* @param array $data An optional array of data for the form to interrogate.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form A Form object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_users.registration', 'registration', ['control' => 'jform', 'load_data' => $loadData]);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// When multilanguage is set, a user's default site language should also be a Content Language
|
||||
if (Multilanguage::isEnabled()) {
|
||||
$form->setFieldAttribute('language', 'type', 'frontendlanguage', 'params');
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
$data = $this->getData();
|
||||
|
||||
if (Multilanguage::isEnabled() && empty($data->language)) {
|
||||
$data->language = Factory::getLanguage()->getTag();
|
||||
}
|
||||
|
||||
$this->preprocessData('com_users.registration', $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override preprocessForm to load the user plugin group instead of content.
|
||||
*
|
||||
* @param Form $form A Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception if there is an error in the form event.
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'user')
|
||||
{
|
||||
$userParams = ComponentHelper::getParams('com_users');
|
||||
|
||||
// Add the choice for site language at registration time
|
||||
if ($userParams->get('site_language') == 1 && $userParams->get('frontend_userparams') == 1) {
|
||||
$form->loadFile('sitelang', false);
|
||||
}
|
||||
|
||||
parent::preprocessForm($form, $data, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function populateState()
|
||||
{
|
||||
// Get the application object.
|
||||
$app = Factory::getApplication();
|
||||
$params = $app->getParams('com_users');
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array $temp The form data.
|
||||
*
|
||||
* @return mixed The user id on success, false on failure.
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function register($temp)
|
||||
{
|
||||
$params = ComponentHelper::getParams('com_users');
|
||||
|
||||
// Initialise the table with Joomla\CMS\User\User.
|
||||
$user = new User();
|
||||
$data = (array) $this->getData();
|
||||
|
||||
// Merge in the registration data.
|
||||
foreach ($temp as $k => $v) {
|
||||
$data[$k] = $v;
|
||||
}
|
||||
|
||||
// Prepare the data for the user object.
|
||||
$data['email'] = PunycodeHelper::emailToPunycode($data['email1']);
|
||||
$data['password'] = $data['password1'];
|
||||
$useractivation = $params->get('useractivation');
|
||||
$sendpassword = $params->get('sendpassword', 1);
|
||||
|
||||
// Check if the user needs to activate their account.
|
||||
if (($useractivation == 1) || ($useractivation == 2)) {
|
||||
$data['activation'] = ApplicationHelper::getHash(UserHelper::genRandomPassword());
|
||||
$data['block'] = 1;
|
||||
}
|
||||
|
||||
// Bind the data.
|
||||
if (!$user->bind($data)) {
|
||||
$this->setError($user->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the users plugin group.
|
||||
PluginHelper::importPlugin('user');
|
||||
|
||||
// Store the data.
|
||||
if (!$user->save()) {
|
||||
$this->setError(Text::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $user->getError()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
// Compile the notification mail values.
|
||||
$data = $user->getProperties();
|
||||
$data['fromname'] = $app->get('fromname');
|
||||
$data['mailfrom'] = $app->get('mailfrom');
|
||||
$data['sitename'] = $app->get('sitename');
|
||||
$data['siteurl'] = Uri::root();
|
||||
|
||||
// Handle account activation/confirmation emails.
|
||||
if ($useractivation == 2) {
|
||||
// Set the link to confirm the user email.
|
||||
$linkMode = $app->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;
|
||||
|
||||
$data['activate'] = Route::link(
|
||||
'site',
|
||||
'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
|
||||
false,
|
||||
$linkMode,
|
||||
true
|
||||
);
|
||||
|
||||
$mailtemplate = 'com_users.registration.user.admin_activation';
|
||||
} elseif ($useractivation == 1) {
|
||||
// Set the link to activate the user account.
|
||||
$linkMode = $app->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;
|
||||
|
||||
$data['activate'] = Route::link(
|
||||
'site',
|
||||
'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
|
||||
false,
|
||||
$linkMode,
|
||||
true
|
||||
);
|
||||
|
||||
$mailtemplate = 'com_users.registration.user.self_activation';
|
||||
} else {
|
||||
$mailtemplate = 'com_users.registration.user.registration_mail';
|
||||
}
|
||||
|
||||
if ($sendpassword) {
|
||||
$mailtemplate .= '_w_pw';
|
||||
}
|
||||
|
||||
// Try to send the registration email.
|
||||
try {
|
||||
$mailer = new MailTemplate($mailtemplate, $app->getLanguage()->getTag());
|
||||
$mailer->addTemplateData($data);
|
||||
$mailer->addRecipient($data['email']);
|
||||
$mailer->addUnsafeTags(['username', 'password_clear', 'name']);
|
||||
$return = $mailer->send();
|
||||
} catch (\Exception $exception) {
|
||||
try {
|
||||
Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror');
|
||||
|
||||
$return = false;
|
||||
} catch (\RuntimeException $exception) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_($exception->errorMessage()), 'warning');
|
||||
|
||||
$this->setError(Text::_('COM_MESSAGES_ERROR_MAIL_FAILED'));
|
||||
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Send mail to all users with user creating permissions and receiving system emails
|
||||
if (($params->get('useractivation') < 2) && ($params->get('mail_to_admin') == 1)) {
|
||||
// Get all admin users
|
||||
$query->clear()
|
||||
->select($db->quoteName(['name', 'email', 'sendEmail', 'id']))
|
||||
->from($db->quoteName('#__users'))
|
||||
->where($db->quoteName('sendEmail') . ' = 1')
|
||||
->where($db->quoteName('block') . ' = 0');
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$rows = $db->loadObjectList();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send mail to all superadministrators id
|
||||
foreach ($rows as $row) {
|
||||
$usercreator = $this->getUserFactory()->loadUserById($row->id);
|
||||
|
||||
if (!$usercreator->authorise('core.create', 'com_users') || !$usercreator->authorise('core.manage', 'com_users')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$mailer = new MailTemplate('com_users.registration.admin.new_notification', $app->getLanguage()->getTag());
|
||||
$mailer->addTemplateData($data);
|
||||
$mailer->addRecipient($row->email);
|
||||
$mailer->addUnsafeTags(['username', 'name']);
|
||||
$return = $mailer->send();
|
||||
} catch (\Exception $exception) {
|
||||
try {
|
||||
Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror');
|
||||
|
||||
$return = false;
|
||||
} catch (\RuntimeException $exception) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_($exception->errorMessage()), 'warning');
|
||||
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an error.
|
||||
if ($return !== true) {
|
||||
$this->setError(Text::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an error.
|
||||
if ($return !== true) {
|
||||
$this->setError(Text::_('COM_USERS_REGISTRATION_SEND_MAIL_FAILED'));
|
||||
|
||||
// Send a system message to administrators receiving system mails
|
||||
$db = $this->getDatabase();
|
||||
$query->clear()
|
||||
->select($db->quoteName('id'))
|
||||
->from($db->quoteName('#__users'))
|
||||
->where($db->quoteName('block') . ' = 0')
|
||||
->where($db->quoteName('sendEmail') . ' = 1');
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$userids = $db->loadColumn();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (\count($userids) > 0) {
|
||||
$jdate = new Date();
|
||||
$dateToSql = $jdate->toSql();
|
||||
$subject = Text::_('COM_USERS_MAIL_SEND_FAILURE_SUBJECT');
|
||||
$message = Text::sprintf('COM_USERS_MAIL_SEND_FAILURE_BODY', $data['username']);
|
||||
|
||||
// Build the query to add the messages
|
||||
foreach ($userids as $userid) {
|
||||
$values = [
|
||||
':user_id_from',
|
||||
':user_id_to',
|
||||
':date_time',
|
||||
':subject',
|
||||
':message',
|
||||
];
|
||||
$query->clear()
|
||||
->insert($db->quoteName('#__messages'))
|
||||
->columns($db->quoteName(['user_id_from', 'user_id_to', 'date_time', 'subject', 'message']))
|
||||
->values(implode(',', $values));
|
||||
$query->bind(':user_id_from', $userid, ParameterType::INTEGER)
|
||||
->bind(':user_id_to', $userid, ParameterType::INTEGER)
|
||||
->bind(':date_time', $dateToSql)
|
||||
->bind(':subject', $subject)
|
||||
->bind(':message', $message);
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$db->execute();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($useractivation == 1) {
|
||||
return 'useractivate';
|
||||
}
|
||||
|
||||
if ($useractivation == 2) {
|
||||
return 'adminactivate';
|
||||
}
|
||||
|
||||
return $user->id;
|
||||
}
|
||||
}
|
||||
211
components/com_users/src/Model/RemindModel.php
Normal file
211
components/com_users/src/Model/RemindModel.php
Normal file
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
use Joomla\CMS\Event\User\AfterRemindEvent;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\Mail\MailTemplate;
|
||||
use Joomla\CMS\MVC\Model\FormModel;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\String\PunycodeHelper;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Remind model class for Users.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class RemindModel extends FormModel
|
||||
{
|
||||
/**
|
||||
* Method to get the username remind request form.
|
||||
*
|
||||
* @param array $data An optional array of data for the form to interrogate.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form|bool A Form object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_users.remind', 'remind', ['control' => 'jform', 'load_data' => $loadData]);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override preprocessForm to load the user plugin group instead of content.
|
||||
*
|
||||
* @param Form $form A Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception if there is an error in the form event.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'user')
|
||||
{
|
||||
parent::preprocessForm($form, $data, 'user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function populateState()
|
||||
{
|
||||
// Get the application object.
|
||||
$app = Factory::getApplication();
|
||||
$params = $app->getParams('com_users');
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the remind username email
|
||||
*
|
||||
* @param array $data Array with the data received from the form
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function processRemindRequest($data)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->getForm();
|
||||
$data['email'] = PunycodeHelper::emailToPunycode($data['email']);
|
||||
|
||||
// Check for an error.
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the data.
|
||||
$data = $this->validate($form, $data);
|
||||
|
||||
// Check for an error.
|
||||
if ($data instanceof \Exception) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the validation results.
|
||||
if ($data === false) {
|
||||
// Get the validation messages from the form.
|
||||
foreach ($form->getErrors() as $formError) {
|
||||
$this->setError($formError->getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the user id for the given email address.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__users'))
|
||||
->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)')
|
||||
->bind(':email', $data['email']);
|
||||
|
||||
// Get the user id.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$user = $db->loadObject();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a user.
|
||||
if (empty($user)) {
|
||||
$this->setError(Text::_('COM_USERS_USER_NOT_FOUND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the user isn't blocked.
|
||||
if ($user->block) {
|
||||
$this->setError(Text::_('COM_USERS_USER_BLOCKED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Assemble the login link.
|
||||
$link = 'index.php?option=com_users&view=login';
|
||||
$mode = $app->get('force_ssl', 0) == 2 ? 1 : (-1);
|
||||
|
||||
// Put together the email template data.
|
||||
$data = ArrayHelper::fromObject($user);
|
||||
$data['sitename'] = $app->get('sitename');
|
||||
$data['link_text'] = Route::_($link, false, $mode);
|
||||
$data['link_html'] = Route::_($link, true, $mode);
|
||||
|
||||
$mailer = new MailTemplate('com_users.reminder', $app->getLanguage()->getTag());
|
||||
$mailer->addTemplateData($data);
|
||||
$mailer->addRecipient($user->email, $user->name);
|
||||
|
||||
// Try to send the password reset request email.
|
||||
try {
|
||||
$return = $mailer->send();
|
||||
} catch (\Exception $exception) {
|
||||
try {
|
||||
Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror');
|
||||
|
||||
$return = false;
|
||||
} catch (\RuntimeException $exception) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_($exception->errorMessage()), 'warning');
|
||||
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an error.
|
||||
if ($return !== true) {
|
||||
$this->setError(Text::_('COM_USERS_MAIL_FAILED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getDispatcher()->dispatch('onUserAfterRemind', new AfterRemindEvent('onUserAfterRemind', [
|
||||
'subject' => $user,
|
||||
]));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
547
components/com_users/src/Model/ResetModel.php
Normal file
547
components/com_users/src/Model/ResetModel.php
Normal file
@ -0,0 +1,547 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Model;
|
||||
|
||||
use Joomla\CMS\Application\ApplicationHelper;
|
||||
use Joomla\CMS\Event\AbstractEvent;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\Mail\MailTemplate;
|
||||
use Joomla\CMS\MVC\Model\FormModel;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\String\PunycodeHelper;
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\CMS\User\UserFactoryAwareInterface;
|
||||
use Joomla\CMS\User\UserFactoryAwareTrait;
|
||||
use Joomla\CMS\User\UserHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Reset model class for Users.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class ResetModel extends FormModel implements UserFactoryAwareInterface
|
||||
{
|
||||
use UserFactoryAwareTrait;
|
||||
|
||||
/**
|
||||
* Method to get the password reset request form.
|
||||
*
|
||||
* The base form is loaded from XML and then an event is fired
|
||||
* for users plugins to extend the form with extra fields.
|
||||
*
|
||||
* @param array $data An optional array of data for the form to interrogate.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form A Form object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_users.reset_request', 'reset_request', ['control' => 'jform', 'load_data' => $loadData]);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the password reset complete form.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form A Form object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getResetCompleteForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_users.reset_complete', 'reset_complete', $options = ['control' => 'jform']);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the password reset confirm form.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form A Form object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getResetConfirmForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_users.reset_confirm', 'reset_confirm', $options = ['control' => 'jform']);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$form->setValue('token', '', Factory::getApplication()->getInput()->get('token'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override preprocessForm to load the user plugin group instead of content.
|
||||
*
|
||||
* @param Form $form A Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception if there is an error in the form event.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'user')
|
||||
{
|
||||
parent::preprocessForm($form, $data, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function populateState()
|
||||
{
|
||||
// Get the application object.
|
||||
$params = Factory::getApplication()->getParams('com_users');
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the new password after reset is done
|
||||
*
|
||||
* @param array $data The data expected for the form.
|
||||
*
|
||||
* @return mixed \Exception | boolean
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function processResetComplete($data)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->getResetCompleteForm();
|
||||
|
||||
// Check for an error.
|
||||
if ($form instanceof \Exception) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
// Filter and validate the form data.
|
||||
$data = $form->filter($data);
|
||||
$return = $form->validate($data);
|
||||
|
||||
// Check for an error.
|
||||
if ($return instanceof \Exception) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Check the validation results.
|
||||
if ($return === false) {
|
||||
// Get the validation messages from the form.
|
||||
foreach ($form->getErrors() as $formError) {
|
||||
$this->setError($formError->getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the token and user id from the confirmation process.
|
||||
$app = Factory::getApplication();
|
||||
$token = $app->getUserState('com_users.reset.token', null);
|
||||
$userId = $app->getUserState('com_users.reset.user', null);
|
||||
|
||||
// Check the token and user id.
|
||||
if (empty($token) || empty($userId)) {
|
||||
return new \Exception(Text::_('COM_USERS_RESET_COMPLETE_TOKENS_MISSING'), 403);
|
||||
}
|
||||
|
||||
// Get the user object.
|
||||
$user = $this->getUserFactory()->loadUserById($userId);
|
||||
|
||||
$event = AbstractEvent::create(
|
||||
'onUserBeforeResetComplete',
|
||||
[
|
||||
'subject' => $user,
|
||||
]
|
||||
);
|
||||
$app->getDispatcher()->dispatch($event->getName(), $event);
|
||||
|
||||
// Check for a user and that the tokens match.
|
||||
if (empty($user) || $user->activation !== $token) {
|
||||
$this->setError(Text::_('COM_USERS_USER_NOT_FOUND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the user isn't blocked.
|
||||
if ($user->block) {
|
||||
$this->setError(Text::_('COM_USERS_USER_BLOCKED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the user is reusing the current password if required to reset their password
|
||||
if ($user->requireReset == 1 && UserHelper::verifyPassword($data['password1'], $user->password)) {
|
||||
$this->setError(Text::_('JLIB_USER_ERROR_CANNOT_REUSE_PASSWORD'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prepare user data.
|
||||
$data['password'] = $data['password1'];
|
||||
$data['activation'] = '';
|
||||
|
||||
// Update the user object.
|
||||
if (!$user->bind($data)) {
|
||||
return new \Exception($user->getError(), 500);
|
||||
}
|
||||
|
||||
// Save the user to the database.
|
||||
if (!$user->save(true)) {
|
||||
return new \Exception(Text::sprintf('COM_USERS_USER_SAVE_FAILED', $user->getError()), 500);
|
||||
}
|
||||
|
||||
// Destroy all active sessions for the user
|
||||
UserHelper::destroyUserSessions($user->id);
|
||||
|
||||
// Flush the user data from the session.
|
||||
$app->setUserState('com_users.reset.token', null);
|
||||
$app->setUserState('com_users.reset.user', null);
|
||||
|
||||
$event = AbstractEvent::create(
|
||||
'onUserAfterResetComplete',
|
||||
[
|
||||
'subject' => $user,
|
||||
]
|
||||
);
|
||||
$app->getDispatcher()->dispatch($event->getName(), $event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the reset password request
|
||||
*
|
||||
* @param array $data The data expected for the form.
|
||||
*
|
||||
* @return mixed \Exception | boolean
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function processResetConfirm($data)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->getResetConfirmForm();
|
||||
|
||||
// Check for an error.
|
||||
if ($form instanceof \Exception) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
// Filter and validate the form data.
|
||||
$data = $form->filter($data);
|
||||
$return = $form->validate($data);
|
||||
|
||||
// Check for an error.
|
||||
if ($return instanceof \Exception) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Check the validation results.
|
||||
if ($return === false) {
|
||||
// Get the validation messages from the form.
|
||||
foreach ($form->getErrors() as $formError) {
|
||||
$this->setError($formError->getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the user id for the given token.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName(['activation', 'id', 'block']))
|
||||
->from($db->quoteName('#__users'))
|
||||
->where($db->quoteName('username') . ' = :username')
|
||||
->bind(':username', $data['username']);
|
||||
|
||||
// Get the user id.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$user = $db->loadObject();
|
||||
} catch (\RuntimeException $e) {
|
||||
return new \Exception(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);
|
||||
}
|
||||
|
||||
// Check for a user.
|
||||
if (empty($user)) {
|
||||
$this->setError(Text::_('COM_USERS_USER_NOT_FOUND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$user->activation) {
|
||||
$this->setError(Text::_('COM_USERS_USER_NOT_FOUND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the token
|
||||
if (!UserHelper::verifyPassword($data['token'], $user->activation)) {
|
||||
$this->setError(Text::_('COM_USERS_USER_NOT_FOUND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the user isn't blocked.
|
||||
if ($user->block) {
|
||||
$this->setError(Text::_('COM_USERS_USER_BLOCKED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Push the user data into the session.
|
||||
$app = Factory::getApplication();
|
||||
$app->setUserState('com_users.reset.token', $user->activation);
|
||||
$app->setUserState('com_users.reset.user', $user->id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to start the password reset process.
|
||||
*
|
||||
* @param array $data The data expected for the form.
|
||||
*
|
||||
* @return mixed \Exception | boolean
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function processResetRequest($data)
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Get the form.
|
||||
$form = $this->getForm();
|
||||
|
||||
$data['email'] = PunycodeHelper::emailToPunycode($data['email']);
|
||||
|
||||
// Check for an error.
|
||||
if ($form instanceof \Exception) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
// Filter and validate the form data.
|
||||
$data = $form->filter($data);
|
||||
$return = $form->validate($data);
|
||||
|
||||
// Check for an error.
|
||||
if ($return instanceof \Exception) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Check the validation results.
|
||||
if ($return === false) {
|
||||
// Get the validation messages from the form.
|
||||
foreach ($form->getErrors() as $formError) {
|
||||
$this->setError($formError->getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the user id for the given email address.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('id'))
|
||||
->from($db->quoteName('#__users'))
|
||||
->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)')
|
||||
->bind(':email', $data['email']);
|
||||
|
||||
// Get the user object.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$userId = $db->loadResult();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError(Text::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a user.
|
||||
if (empty($userId)) {
|
||||
$this->setError(Text::_('COM_USERS_INVALID_EMAIL'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the user object.
|
||||
$user = $this->getUserFactory()->loadUserById($userId);
|
||||
|
||||
// Make sure the user isn't blocked.
|
||||
if ($user->block) {
|
||||
$this->setError(Text::_('COM_USERS_USER_BLOCKED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the user isn't a Super Admin.
|
||||
if ($user->authorise('core.admin')) {
|
||||
$this->setError(Text::_('COM_USERS_REMIND_SUPERADMIN_ERROR'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the user has not exceeded the reset limit
|
||||
if (!$this->checkResetLimit($user)) {
|
||||
$resetLimit = (int) Factory::getApplication()->getParams()->get('reset_time');
|
||||
$this->setError(Text::plural('COM_USERS_REMIND_LIMIT_ERROR_N_HOURS', $resetLimit));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the confirmation token.
|
||||
$token = ApplicationHelper::getHash(UserHelper::genRandomPassword());
|
||||
$hashedToken = UserHelper::hashPassword($token);
|
||||
|
||||
$user->activation = $hashedToken;
|
||||
|
||||
$event = AbstractEvent::create(
|
||||
'onUserBeforeResetRequest',
|
||||
[
|
||||
'subject' => $user,
|
||||
]
|
||||
);
|
||||
$app->getDispatcher()->dispatch($event->getName(), $event);
|
||||
|
||||
// Save the user to the database.
|
||||
if (!$user->save(true)) {
|
||||
return new \Exception(Text::sprintf('COM_USERS_USER_SAVE_FAILED', $user->getError()), 500);
|
||||
}
|
||||
|
||||
// Assemble the password reset confirmation link.
|
||||
$mode = $app->get('force_ssl', 0) == 2 ? 1 : (-1);
|
||||
$link = 'index.php?option=com_users&view=reset&layout=confirm&token=' . $token;
|
||||
|
||||
// Put together the email template data.
|
||||
$data = $user->getProperties();
|
||||
$data['sitename'] = $app->get('sitename');
|
||||
$data['link_text'] = Route::_($link, false, $mode);
|
||||
$data['link_html'] = Route::_($link, true, $mode);
|
||||
$data['token'] = $token;
|
||||
|
||||
$mailer = new MailTemplate('com_users.password_reset', $app->getLanguage()->getTag());
|
||||
$mailer->addTemplateData($data);
|
||||
$mailer->addRecipient($user->email, $user->name);
|
||||
|
||||
// Try to send the password reset request email.
|
||||
try {
|
||||
$return = $mailer->send();
|
||||
} catch (\Exception $exception) {
|
||||
try {
|
||||
Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror');
|
||||
|
||||
$return = false;
|
||||
} catch (\RuntimeException $exception) {
|
||||
$app->enqueueMessage(Text::_($exception->errorMessage()), 'warning');
|
||||
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an error.
|
||||
if ($return !== true) {
|
||||
return new \Exception(Text::_('COM_USERS_MAIL_FAILED'), 500);
|
||||
}
|
||||
|
||||
$event = AbstractEvent::create(
|
||||
'onUserAfterResetRequest',
|
||||
[
|
||||
'subject' => $user,
|
||||
]
|
||||
);
|
||||
$app->getDispatcher()->dispatch($event->getName(), $event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if user reset limit has been exceeded within the allowed time period.
|
||||
*
|
||||
* @param User $user User doing the password reset
|
||||
*
|
||||
* @return boolean true if user can do the reset, false if limit exceeded
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function checkResetLimit($user)
|
||||
{
|
||||
$params = Factory::getApplication()->getParams();
|
||||
$maxCount = (int) $params->get('reset_count');
|
||||
$resetHours = (int) $params->get('reset_time');
|
||||
$result = true;
|
||||
|
||||
$lastResetTime = strtotime($user->lastResetTime) ?: 0;
|
||||
$hoursSinceLastReset = (strtotime(Factory::getDate()->toSql()) - $lastResetTime) / 3600;
|
||||
|
||||
if ($hoursSinceLastReset > $resetHours) {
|
||||
// If it's been long enough, start a new reset count
|
||||
$user->lastResetTime = Factory::getDate()->toSql();
|
||||
$user->resetCount = 1;
|
||||
} elseif ($user->resetCount < $maxCount) {
|
||||
// If we are under the max count, just increment the counter
|
||||
++$user->resetCount;
|
||||
} else {
|
||||
// At this point, we know we have exceeded the maximum resets for the time period
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
66
components/com_users/src/Rule/LoginUniqueFieldRule.php
Normal file
66
components/com_users/src/Rule/LoginUniqueFieldRule.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Rule;
|
||||
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Form\FormRule;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* FormRule for com_users to be sure only one redirect login field has a value
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
class LoginUniqueFieldRule extends FormRule
|
||||
{
|
||||
/**
|
||||
* Method to test if two fields have a value in order to use only one field.
|
||||
* To use this rule, the form
|
||||
* XML needs a validate attribute of loginuniquefield and a field attribute
|
||||
* that is equal to the field to test against.
|
||||
*
|
||||
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
* @param ?Registry $input An optional Registry object with the entire data set to validate against the entire form.
|
||||
* @param ?Form $form The form object for which the field is being tested.
|
||||
*
|
||||
* @return boolean True if the value is valid, false otherwise.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public function test(\SimpleXMLElement $element, $value, $group = null, ?Registry $input = null, ?Form $form = null)
|
||||
{
|
||||
$loginRedirectUrl = $input['params']->login_redirect_url;
|
||||
$loginRedirectMenuitem = $input['params']->login_redirect_menuitem;
|
||||
|
||||
if ($form === null) {
|
||||
throw new \InvalidArgumentException(\sprintf('The value for $form must not be null in %s', \get_class($this)));
|
||||
}
|
||||
|
||||
if ($input === null) {
|
||||
throw new \InvalidArgumentException(\sprintf('The value for $input must not be null in %s', \get_class($this)));
|
||||
}
|
||||
|
||||
// Test the input values for login.
|
||||
if ($loginRedirectUrl != '' && $loginRedirectMenuitem != '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
66
components/com_users/src/Rule/LogoutUniqueFieldRule.php
Normal file
66
components/com_users/src/Rule/LogoutUniqueFieldRule.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Rule;
|
||||
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Form\FormRule;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* FormRule for com_users to be sure only one redirect logout field has a value
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
class LogoutUniqueFieldRule extends FormRule
|
||||
{
|
||||
/**
|
||||
* Method to test if two fields have a value in order to use only one field.
|
||||
* To use this rule, the form
|
||||
* XML needs a validate attribute of logoutuniquefield and a field attribute
|
||||
* that is equal to the field to test against.
|
||||
*
|
||||
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
* @param ?Registry $input An optional Registry object with the entire data set to validate against the entire form.
|
||||
* @param ?Form $form The form object for which the field is being tested.
|
||||
*
|
||||
* @return boolean True if the value is valid, false otherwise.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public function test(\SimpleXMLElement $element, $value, $group = null, ?Registry $input = null, ?Form $form = null)
|
||||
{
|
||||
$logoutRedirectUrl = $input['params']->logout_redirect_url;
|
||||
$logoutRedirectMenuitem = $input['params']->logout_redirect_menuitem;
|
||||
|
||||
if ($form === null) {
|
||||
throw new \InvalidArgumentException(\sprintf('The value for $form must not be null in %s', \get_class($this)));
|
||||
}
|
||||
|
||||
if ($input === null) {
|
||||
throw new \InvalidArgumentException(\sprintf('The value for $input must not be null in %s', \get_class($this)));
|
||||
}
|
||||
|
||||
// Test the input values for logout.
|
||||
if ($logoutRedirectUrl != '' && $logoutRedirectMenuitem != '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
89
components/com_users/src/Service/Router.php
Normal file
89
components/com_users/src/Service/Router.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\Service;
|
||||
|
||||
use Joomla\CMS\Application\SiteApplication;
|
||||
use Joomla\CMS\Component\Router\RouterView;
|
||||
use Joomla\CMS\Component\Router\RouterViewConfiguration;
|
||||
use Joomla\CMS\Component\Router\Rules\MenuRules;
|
||||
use Joomla\CMS\Component\Router\Rules\NomenuRules;
|
||||
use Joomla\CMS\Component\Router\Rules\StandardRules;
|
||||
use Joomla\CMS\Menu\AbstractMenu;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Routing class from com_users
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
class Router extends RouterView
|
||||
{
|
||||
/**
|
||||
* Users Component router constructor
|
||||
*
|
||||
* @param SiteApplication $app The application object
|
||||
* @param AbstractMenu $menu The menu object to work with
|
||||
*/
|
||||
public function __construct(SiteApplication $app, AbstractMenu $menu)
|
||||
{
|
||||
$this->registerView(new RouterViewConfiguration('login'));
|
||||
$profile = new RouterViewConfiguration('profile');
|
||||
$profile->addLayout('edit');
|
||||
$this->registerView($profile);
|
||||
$this->registerView(new RouterViewConfiguration('registration'));
|
||||
$this->registerView(new RouterViewConfiguration('remind'));
|
||||
$this->registerView(new RouterViewConfiguration('reset'));
|
||||
$this->registerView(new RouterViewConfiguration('callback'));
|
||||
$this->registerView(new RouterViewConfiguration('captive'));
|
||||
$this->registerView(new RouterViewConfiguration('methods'));
|
||||
|
||||
$method = new RouterViewConfiguration('method');
|
||||
$method->setKey('id');
|
||||
$this->registerView($method);
|
||||
|
||||
parent::__construct($app, $menu);
|
||||
|
||||
$this->attachRule(new MenuRules($this));
|
||||
$this->attachRule(new StandardRules($this));
|
||||
$this->attachRule(new NomenuRules($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the method ID from a URL segment
|
||||
*
|
||||
* @param string $segment The URL segment
|
||||
* @param array $query The URL query parameters
|
||||
*
|
||||
* @return integer
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function getMethodId($segment, $query)
|
||||
{
|
||||
return (int) $segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a segment from a method ID
|
||||
*
|
||||
* @param integer $id The method ID
|
||||
* @param array $query The URL query parameters
|
||||
*
|
||||
* @return int[]
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function getMethodSegment($id, $query)
|
||||
{
|
||||
return [$id => (int) $id];
|
||||
}
|
||||
}
|
||||
24
components/com_users/src/View/Captive/HtmlView.php
Normal file
24
components/com_users/src/View/Captive/HtmlView.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Captive;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View for Multi-factor Authentication captive page
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class HtmlView extends \Joomla\Component\Users\Administrator\View\Captive\HtmlView
|
||||
{
|
||||
}
|
||||
158
components/com_users/src/View/Login/HtmlView.php
Normal file
158
components/com_users/src/View/Login/HtmlView.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Login;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Helper\AuthenticationHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\User\User;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Login view class for Users.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The page parameters
|
||||
*
|
||||
* @var \Joomla\Registry\Registry|null
|
||||
*/
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The logged in user
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* The page class suffix
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pageclass_sfx = '';
|
||||
|
||||
/**
|
||||
* No longer used
|
||||
*
|
||||
* @var boolean
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Will be removed without replacement
|
||||
*/
|
||||
protected $tfa = false;
|
||||
|
||||
/**
|
||||
* Additional buttons to show on the login page
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extraButtons = [];
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.5
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get the view data.
|
||||
$this->user = $this->getCurrentUser();
|
||||
$this->form = $this->get('Form');
|
||||
$this->state = $this->get('State');
|
||||
$this->params = $this->state->get('params');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Check for layout override
|
||||
$active = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if (isset($active->query['layout'])) {
|
||||
$this->setLayout($active->query['layout']);
|
||||
}
|
||||
|
||||
$this->extraButtons = AuthenticationHelper::getLoginButtons('com-users-login__form');
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
$login = (bool) $this->getCurrentUser()->guest;
|
||||
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
|
||||
} else {
|
||||
$this->params->def('page_heading', $login ? Text::_('JLOGIN') : Text::_('JLOGOUT'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
24
components/com_users/src/View/Method/HtmlView.php
Normal file
24
components/com_users/src/View/Method/HtmlView.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Method;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View for Multi-factor Authentication method add/edit page
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class HtmlView extends \Joomla\Component\Users\Administrator\View\Method\HtmlView
|
||||
{
|
||||
}
|
||||
24
components/com_users/src/View/Methods/HtmlView.php
Normal file
24
components/com_users/src/View/Methods/HtmlView.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Methods;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View for Multi-factor Authentication methods list page
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class HtmlView extends \Joomla\Component\Users\Administrator\View\Methods\HtmlView
|
||||
{
|
||||
}
|
||||
190
components/com_users/src/View/Profile/HtmlView.php
Normal file
190
components/com_users/src/View/Profile/HtmlView.php
Normal file
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Profile;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\User\User;
|
||||
use Joomla\Component\Users\Administrator\Helper\Mfa;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Profile view class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* Profile form data for the user
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The page parameters
|
||||
*
|
||||
* @var \Joomla\Registry\Registry|null
|
||||
*/
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* An instance of DatabaseDriver.
|
||||
*
|
||||
* @var DatabaseDriver
|
||||
* @since 3.6.3
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Will be removed without replacement use database from the container instead
|
||||
* Example: Factory::getContainer()->get(DatabaseInterface::class);
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* The page class suffix
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pageclass_sfx = '';
|
||||
|
||||
/**
|
||||
* The Multi-factor Authentication configuration interface for the user.
|
||||
*
|
||||
* @var string|null
|
||||
* @since 4.2.0
|
||||
*/
|
||||
protected $mfaConfigurationUI;
|
||||
|
||||
/**
|
||||
* Execute and display a template script.
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void|boolean
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
// Get the view data.
|
||||
$this->data = $this->get('Data');
|
||||
$this->form = $this->getModel()->getForm(new CMSObject(['id' => $user->id]));
|
||||
$this->state = $this->get('State');
|
||||
$this->params = $this->state->get('params');
|
||||
$this->mfaConfigurationUI = Mfa::getConfigurationInterface($user);
|
||||
$this->db = Factory::getDbo();
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// View also takes responsibility for checking if the user logged in with remember me.
|
||||
$cookieLogin = $user->get('cookieLogin');
|
||||
|
||||
if (!empty($cookieLogin)) {
|
||||
// If so, the user must login to edit the password and other data.
|
||||
// What should happen here? Should we force a logout which destroys the cookies?
|
||||
$app = Factory::getApplication();
|
||||
$app->enqueueMessage(Text::_('JGLOBAL_REMEMBER_MUST_LOGIN'), 'message');
|
||||
$app->redirect(Route::_('index.php?option=com_users&view=login', false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if a user was found.
|
||||
if (!$this->data->id) {
|
||||
throw new \Exception(Text::_('JERROR_USERS_PROFILE_NOT_FOUND'), 404);
|
||||
}
|
||||
|
||||
PluginHelper::importPlugin('content');
|
||||
$this->data->text = '';
|
||||
Factory::getApplication()->triggerEvent('onContentPrepare', ['com_users.user', &$this->data, &$this->data->params, 0]);
|
||||
unset($this->data->text);
|
||||
|
||||
// Check for layout from menu item.
|
||||
$active = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if (
|
||||
$active && isset($active->query['layout'])
|
||||
&& isset($active->query['option']) && $active->query['option'] === 'com_users'
|
||||
&& isset($active->query['view']) && $active->query['view'] === 'profile'
|
||||
) {
|
||||
$this->setLayout($active->query['layout']);
|
||||
}
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''));
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $this->getCurrentUser()->name));
|
||||
} else {
|
||||
$this->params->def('page_heading', Text::_('COM_USERS_PROFILE'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
160
components/com_users/src/View/Registration/HtmlView.php
Normal file
160
components/com_users/src/View/Registration/HtmlView.php
Normal file
@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Registration;
|
||||
|
||||
use Joomla\CMS\Document\HtmlDocument;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Registration view class for Users.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* Registration form data
|
||||
*
|
||||
* @var \stdClass|false
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The page parameters
|
||||
*
|
||||
* @var \Joomla\Registry\Registry|null
|
||||
*/
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The HtmlDocument instance
|
||||
*
|
||||
* @var HtmlDocument
|
||||
*/
|
||||
public $document;
|
||||
|
||||
/**
|
||||
* Should we show a captcha form for the submission of the article?
|
||||
*
|
||||
* @var boolean
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected $captchaEnabled = false;
|
||||
|
||||
/**
|
||||
* The page class suffix
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pageclass_sfx = '';
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl The template file to include
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get the view data.
|
||||
$this->form = $this->get('Form');
|
||||
$this->data = $this->get('Data');
|
||||
$this->state = $this->get('State');
|
||||
$this->params = $this->state->get('params');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Check for layout override
|
||||
$active = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if (isset($active->query['layout'])) {
|
||||
$this->setLayout($active->query['layout']);
|
||||
}
|
||||
|
||||
$captchaSet = $this->params->get('captcha', Factory::getApplication()->get('captcha', '0'));
|
||||
|
||||
foreach (PluginHelper::getPlugin('captcha') as $plugin) {
|
||||
if ($captchaSet === $plugin->name) {
|
||||
$this->captchaEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
|
||||
} else {
|
||||
$this->params->def('page_heading', Text::_('COM_USERS_REGISTRATION'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
125
components/com_users/src/View/Remind/HtmlView.php
Normal file
125
components/com_users/src/View/Remind/HtmlView.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Remind;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Remind view class for Users.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The page parameters
|
||||
*
|
||||
* @var \Joomla\Registry\Registry|null
|
||||
*/
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The page class suffix
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pageclass_sfx = '';
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl The template file to include
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.5
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get the view data.
|
||||
$this->form = $this->get('Form');
|
||||
$this->state = $this->get('State');
|
||||
$this->params = $this->state->params;
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Check for layout override
|
||||
$active = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if (isset($active->query['layout'])) {
|
||||
$this->setLayout($active->query['layout']);
|
||||
}
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
|
||||
} else {
|
||||
$this->params->def('page_heading', Text::_('COM_USERS_REMIND'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
131
components/com_users/src/View/Reset/HtmlView.php
Normal file
131
components/com_users/src/View/Reset/HtmlView.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_users
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Users\Site\View\Reset;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Reset view class for Users.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The page parameters
|
||||
*
|
||||
* @var \Joomla\Registry\Registry|null
|
||||
*/
|
||||
protected $params;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The page class suffix
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pageclass_sfx = '';
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl The template file to include
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// This name will be used to get the model
|
||||
$name = $this->getLayout();
|
||||
|
||||
// Check that the name is valid - has an associated model.
|
||||
if (!\in_array($name, ['confirm', 'complete'])) {
|
||||
$name = 'default';
|
||||
}
|
||||
|
||||
if ('default' === $name) {
|
||||
$formname = 'Form';
|
||||
} else {
|
||||
$formname = ucfirst($this->_name) . ucfirst($name) . 'Form';
|
||||
}
|
||||
|
||||
// Get the view data.
|
||||
$this->form = $this->get($formname);
|
||||
$this->state = $this->get('State');
|
||||
$this->params = $this->state->params;
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
|
||||
} else {
|
||||
$this->params->def('page_heading', Text::_('COM_USERS_RESET'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user