first commit

This commit is contained in:
2025-06-17 11:53:18 +02:00
commit 9f0f7ba12b
8804 changed files with 1369176 additions and 0 deletions

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="params">
<!-- Basic user account settings. -->
<fieldset name="params" label="COM_USERS_SETTINGS_FIELDSET_LABEL">
<field
name="editor"
type="plugins"
label="COM_USERS_USER_FIELD_EDITOR_LABEL"
folder="editors"
useaccess="true"
>
<option value="">JOPTION_USE_DEFAULT</option>
</field>
<field
name="timezone"
type="timezone"
label="COM_USERS_USER_FIELD_TIMEZONE_LABEL"
>
<option value="">JOPTION_USE_DEFAULT</option>
</field>
<field
name="language"
type="language"
label="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_LABEL"
client="site"
filter="cmd"
>
<option value="">JOPTION_USE_DEFAULT</option>
</field>
</fieldset>
</fields>
</form>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="params">
<!-- Backend user account settings. -->
<fieldset name="params" label="COM_USERS_SETTINGS_FIELDSET_LABEL">
<field
name="admin_style"
type="templatestyle"
label="COM_USERS_USER_FIELD_BACKEND_TEMPLATE_LABEL"
client="administrator"
filter="uint"
>
<option value="">JOPTION_USE_DEFAULT</option>
</field>
<field
name="admin_language"
type="language"
label="COM_USERS_USER_FIELD_BACKEND_LANGUAGE_LABEL"
client="administrator"
filter="cmd"
>
<option value="">JOPTION_USE_DEFAULT</option>
</field>
</fieldset>
</fields>
</form>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="credentials" label="COM_USERS_LOGIN_DEFAULT_LABEL">
<field
name="username"
type="text"
label="COM_USERS_LOGIN_USERNAME_LABEL"
class="validate-username"
filter="username"
size="25"
required="true"
validate="username"
autofocus="true"
autocomplete="username"
/>
<field
name="password"
type="password"
label="JGLOBAL_PASSWORD"
required="true"
filter="raw"
size="25"
autocomplete="current-password"
/>
</fieldset>
<fieldset>
<field
name="return"
type="hidden"
/>
</fieldset>
</form>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="core" label="COM_USERS_PROFILE_DEFAULT_LABEL">
<field
name="id"
type="hidden"
filter="integer"
/>
<field
name="name"
type="text"
label="COM_USERS_PROFILE_NAME_LABEL"
filter="string"
required="true"
size="30"
/>
<field
name="username"
type="text"
label="COM_USERS_PROFILE_USERNAME_LABEL"
class="validate-username"
filter="username"
message="COM_USERS_PROFILE_USERNAME_MESSAGE"
required="true"
size="30"
validate="username"
/>
<field
name="password1"
type="password"
label="COM_USERS_PROFILE_PASSWORD1_LABEL"
autocomplete="new-password"
class="validate-password"
filter="raw"
size="30"
validate="password"
strengthmeter="true"
rules="true"
force="on"
/>
<field
name="password2"
type="password"
label="COM_USERS_PROFILE_PASSWORD2_LABEL"
autocomplete="new-password"
class="validate-password"
field="password1"
filter="raw"
message="COM_USERS_PROFILE_PASSWORD1_MESSAGE"
size="30"
validate="equals"
/>
<field
name="email1"
type="email"
label="COM_USERS_PROFILE_EMAIL1_LABEL"
filter="string"
required="true"
size="30"
unique="true"
validate="email"
validDomains="com_users.domains"
autocomplete="email"
/>
</fieldset>
</form>

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="default" label="COM_USERS_REGISTRATION_DEFAULT_LABEL">
<field
name="spacer"
type="spacer"
label="COM_USERS_REGISTER_REQUIRED"
class="text"
/>
<field
name="name"
type="text"
label="COM_USERS_REGISTER_NAME_LABEL"
filter="string"
required="true"
size="30"
/>
<field
name="username"
type="text"
label="COM_USERS_REGISTER_USERNAME_LABEL"
class="validate-username"
filter="username"
message="COM_USERS_REGISTER_USERNAME_MESSAGE"
required="true"
size="30"
validate="username"
autocomplete="username"
/>
<field
name="password1"
type="password"
label="COM_USERS_PROFILE_PASSWORD1_LABEL"
required="true"
autocomplete="new-password"
class="validate-password"
field="password1"
size="30"
validate="password"
strengthmeter="true"
rules="true"
force="on"
filter="raw"
/>
<field
name="password2"
type="password"
label="COM_USERS_PROFILE_PASSWORD2_LABEL"
autocomplete="new-password"
class="validate-password"
field="password1"
filter="raw"
message="COM_USERS_PROFILE_PASSWORD1_MESSAGE"
size="30"
validate="equals"
required="true"
/>
<field
name="email1"
type="email"
label="COM_USERS_REGISTER_EMAIL1_LABEL"
field="id"
filter="string"
required="true"
size="30"
unique="true"
validate="email"
validDomains="com_users.domains"
autocomplete="email"
/>
</fieldset>
<fieldset name="captcha">
<field
name="captcha"
type="captcha"
label="COM_USERS_CAPTCHA_LABEL"
validate="captcha"
/>
</fieldset>
</form>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="default" label="COM_USERS_REMIND_DEFAULT_LABEL">
<field
name="email"
type="email"
label="COM_USERS_FIELD_REMIND_EMAIL_LABEL"
required="true"
size="30"
validate="email"
autocomplete="email"
/>
<field
name="captcha"
type="captcha"
label="COM_USERS_CAPTCHA_LABEL"
validate="captcha"
/>
</fieldset>
</form>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="default" label="COM_USERS_RESET_COMPLETE_LABEL">
<field
name="password1"
type="password"
label="COM_USERS_FIELD_RESET_PASSWORD1_LABEL"
required="true"
autocomplete="new-password"
class="validate-password"
field="password2"
size="30"
validate="password"
strengthmeter="true"
rules="true"
force="on"
filter="raw"
/>
<field
name="password2"
type="password"
label="COM_USERS_FIELD_RESET_PASSWORD2_LABEL"
autocomplete="new-password"
class="validate-password"
field="password1"
filter="raw"
message="COM_USERS_FIELD_RESET_PASSWORD1_MESSAGE"
size="30"
validate="equals"
required="true"
/>
</fieldset>
</form>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="default" label="COM_USERS_RESET_CONFIRM_LABEL">
<field
name="username"
type="text"
label="COM_USERS_FIELD_RESET_CONFIRM_USERNAME_LABEL"
filter="username"
required="true"
size="30"
/>
<field
name="token"
type="text"
label="COM_USERS_FIELD_RESET_CONFIRM_TOKEN_LABEL"
filter="alnum"
required="true"
size="32"
/>
</fieldset>
</form>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="default" label="COM_USERS_RESET_REQUEST_LABEL">
<field
name="email"
type="email"
label="COM_USERS_FIELD_PASSWORD_RESET_LABEL"
required="true"
size="30"
validate="email"
autocomplete="email"
/>
<field
name="captcha"
type="captcha"
label="COM_USERS_CAPTCHA_LABEL"
validate="captcha"
/>
</fieldset>
</form>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="params">
<fieldset name="params" label="COM_USERS_SETTINGS_FIELDSET_LABEL">
<field
name="language"
type="language"
label="COM_USERS_USER_FIELD_FRONTEND_LANGUAGE_LABEL"
client="site"
filter="cmd"
default="active"
/>
</fieldset>
</fields>
</form>

View 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
{
}

View 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;
}
}

View 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->get('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;
// Handle view specific models.
case 'profile':
// If the user is a guest, redirect to the login page.
$user = $this->app->getIdentity();
if ($user->get('guest') == 1) {
// Redirect to login page.
$this->setRedirect(Route::_('index.php?option=com_users&view=login', false));
return;
}
$model = $this->getModel($vName);
break;
// Handle the default views.
case 'login':
$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->get('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();
}
}
}

View 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;
}
}

View 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;
}
}

View File

@ -0,0 +1,231 @@
<?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\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->get('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->get('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(), 'warning');
} else {
$app->enqueueMessage($errors[$i], 'warning');
}
}
// 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));
}
}

View File

@ -0,0 +1,250 @@
<?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\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->get('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(), 'error');
} else {
$app->enqueueMessage($errors[$i], '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;
}
}

View 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;
}
}

View 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;
}
}

View 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('index.php?option=com_users&task=user.logout&' . Session::getFormToken() . '=1&return=' . base64_encode($url));
}
/**
* 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');
}
}

View 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
{
}

View 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
{
}

View 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 '';
}
}
}

View 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
{
}

View 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
{
}

View 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->get('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', 'frontend_language', '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()->get('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['password']) {
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();
}
}

View File

@ -0,0 +1,654 @@
<?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', 'frontend_language', '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']);
$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);
$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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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];
}
}

View 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
{
}

View 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()->get('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'));
}
}
}

View 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
{
}

View 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
{
}

View File

@ -0,0 +1,189 @@
<?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.
$query = Factory::getApplication()->getMenu()->getActive()->query;
if (
isset($query['layout']) && isset($query['option']) && $query['option'] === 'com_users'
&& isset($query['view']) && $query['view'] === 'profile'
) {
$this->setLayout($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'));
}
}
}

View 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'));
}
}
}

View 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'));
}
}
}

View 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'));
}
}
}

View File

@ -0,0 +1,135 @@
<?php
/**
* @package Joomla.Site
* @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
*/
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Component\Users\Site\Model\CaptiveModel;
use Joomla\Component\Users\Site\View\Captive\HtmlView;
use Joomla\Utilities\ArrayHelper;
/**
* @var HtmlView $this View object
* @var CaptiveModel $model The model
*/
$model = $this->getModel();
$this->document->getWebAssetManager()
->useScript('com_users.two-factor-focus');
?>
<div class="users-mfa-captive card card-body">
<h2 id="users-mfa-title">
<?php if (!empty($this->renderOptions['help_url'])) : ?>
<span class="float-end">
<a href="<?php echo $this->renderOptions['help_url'] ?>"
class="btn btn-sm btn-secondary"
target="_blank"
>
<span class="icon icon-question-sign" aria-hidden="true"></span>
<span class="visually-hidden"><?php echo Text::_('JHELP') ?></span>
</a>
</span>
<?php endif;?>
<?php if (!empty($this->title)) : ?>
<?php echo $this->title ?> <small> &ndash;
<?php endif; ?>
<?php if (!$this->allowEntryBatching) : ?>
<?php echo $this->escape($this->record->title) ?>
<?php else : ?>
<?php echo $this->escape($this->getModel()->translateMethodName($this->record->method)) ?>
<?php endif; ?>
<?php if (!empty($this->title)) : ?>
</small>
<?php endif; ?>
</h2>
<?php if ($this->renderOptions['pre_message']) : ?>
<div class="users-mfa-captive-pre-message text-muted mb-3">
<?php echo $this->renderOptions['pre_message'] ?>
</div>
<?php endif; ?>
<form action="<?php echo Route::_('index.php?option=com_users&task=captive.validate&record_id=' . ((int) $this->record->id)) ?>"
id="users-mfa-captive-form"
method="post"
class="form-horizontal"
>
<?php echo HTMLHelper::_('form.token') ?>
<div id="users-mfa-captive-form-method-fields">
<?php if ($this->renderOptions['field_type'] == 'custom') : ?>
<?php echo $this->renderOptions['html']; ?>
<?php endif; ?>
<div class="row mb-3">
<?php if ($this->renderOptions['label']) : ?>
<label for="users-mfa-code" class="col-sm-3 col-form-label">
<?php echo $this->renderOptions['label'] ?>
</label>
<?php endif; ?>
<div class="col-sm-9 <?php echo $this->renderOptions['label'] ? '' : 'offset-sm-3' ?>">
<?php
$attributes = array_merge(
[
'type' => $this->renderOptions['input_type'],
'name' => 'code',
'value' => '',
'placeholder' => $this->renderOptions['placeholder'] ?? null,
'id' => 'users-mfa-code',
'class' => 'form-control',
'autocomplete' => $this->renderOptions['autocomplete'] ?? 'one-time-code'
],
$this->renderOptions['input_attributes']
);
if (strpos($attributes['class'], 'form-control') === false) {
$attributes['class'] .= ' form-control';
}
?>
<input <?php echo ArrayHelper::toString($attributes) ?>>
</div>
</div>
</div>
<div id="users-mfa-captive-form-standard-buttons" class="row my-3">
<div class="col-sm-9 offset-sm-3">
<button class="btn btn-primary me-3 <?php echo $this->renderOptions['submit_class'] ?>"
id="users-mfa-captive-button-submit"
style="<?php echo $this->renderOptions['hide_submit'] ? 'display: none' : '' ?>"
type="submit">
<span class="<?php echo $this->renderOptions['submit_icon'] ?>" aria-hidden="true"></span>
<?php echo Text::_($this->renderOptions['submit_text']); ?>
</button>
<a href="<?php echo Route::_('index.php?option=com_users&task=user.logout&' . Factory::getApplication()->getFormToken() . '=1') ?>"
class="btn btn-danger btn-sm" id="users-mfa-captive-button-logout">
<span class="icon icon-lock" aria-hidden="true"></span>
<?php echo Text::_('COM_USERS_MFA_LOGOUT'); ?>
</a>
<?php if (count($this->records) > 1) : ?>
<div id="users-mfa-captive-form-choose-another" class="my-3">
<a href="<?php echo Route::_('index.php?option=com_users&view=captive&task=select') ?>">
<?php echo Text::_('COM_USERS_MFA_USE_DIFFERENT_METHOD'); ?>
</a>
</div>
<?php endif; ?>
</div>
</div>
</form>
<?php if ($this->renderOptions['post_message']) : ?>
<div class="users-mfa-captive-post-message">
<?php echo $this->renderOptions['post_message'] ?>
</div>
<?php endif; ?>
</div>

View File

@ -0,0 +1,78 @@
<?php
/**
* @package Joomla.Site
* @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
*/
// Prevent direct access
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Users\Site\View\Captive\HtmlView;
/** @var HtmlView $this */
$shownMethods = [];
?>
<div id="com-users-select">
<h2 id="com-users-select-heading">
<?php echo Text::_('COM_USERS_MFA_SELECT_PAGE_HEAD'); ?>
</h2>
<div id="com-users-select-information">
<p>
<?php echo Text::_('COM_USERS_LBL_SELECT_INSTRUCTIONS'); ?>
</p>
</div>
<div class="com-users-select-methods p-2">
<?php foreach ($this->records as $record) :
if (!array_key_exists($record->method, $this->mfaMethods) && ($record->method != 'backupcodes')) {
continue;
}
$allowEntryBatching = isset($this->mfaMethods[$record->method]) ? $this->mfaMethods[$record->method]['allowEntryBatching'] : false;
if ($this->allowEntryBatching) {
if ($allowEntryBatching && in_array($record->method, $shownMethods)) {
continue;
}
$shownMethods[] = $record->method;
}
$methodName = $this->getModel()->translateMethodName($record->method);
?>
<a class="com-users-method p-2 border-top border-dark bg-light d-flex flex-row flex-wrap justify-content-start align-items-center text-decoration-none gap-2 text-body"
href="<?php echo Route::_('index.php?option=com_users&view=captive&record_id=' . $record->id)?>">
<img src="<?php echo Uri::root() . $this->getModel()->getMethodImage($record->method) ?>"
alt="<?php echo $this->escape(strip_tags($record->title)) ?>"
class="com-users-method-image img-fluid" />
<?php if (!$this->allowEntryBatching || !$allowEntryBatching) : ?>
<span class="com-users-method-title flex-grow-1 fs-5 fw-bold">
<?php if ($record->method === 'backupcodes') : ?>
<?php echo $record->title ?>
<?php else : ?>
<?php echo $this->escape($record->title) ?>
<?php endif; ?>
</span>
<small class="com-users-method-name text-muted">
<?php echo $methodName ?>
</small>
<?php else : ?>
<span class="com-users-method-title flex-grow-1 fs-5 fw-bold">
<?php echo $methodName ?>
</span>
<small class="com-users-method-name text-muted">
<?php echo $methodName ?>
</small>
<?php endif; ?>
</a>
<?php endforeach; ?>
</div>
</div>

View File

@ -0,0 +1,23 @@
<?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
*/
defined('_JEXEC') or die;
/** @var \Joomla\Component\Users\Site\View\Login\HtmlView $this */
$cookieLogin = $this->user->get('cookieLogin');
if (!empty($cookieLogin) || $this->user->get('guest')) {
// The user is not logged in or needs to provide a password.
echo $this->loadTemplate('login');
} else {
// The user is already logged in.
echo $this->loadTemplate('logout');
}

View File

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_USERS_LOGIN_VIEW_DEFAULT_TITLE" option="COM_USERS_LOGIN_VIEW_DEFAULT_OPTION">
<help
key = "Menu_Item:_Login_Form"
/>
<message>
<![CDATA[COM_USERS_LOGIN_VIEW_DEFAULT_DESC]]>
</message>
</layout>
<!-- Add fields to the parameters object for the layout. -->
<fields name="params">
<!-- Basic options. -->
<fieldset name="basic" addruleprefix="Joomla\Component\Users\Site\Rule" label="COM_MENUS_BASIC_FIELDSET_LABEL">
<fieldset name="login" label="COM_USERS_FIELD_OPTIONS_LOGIN">
<field
name="loginredirectchoice"
type="radio"
label="COM_USERS_FIELD_LOGIN_REDIRECT_CHOICE_LABEL"
layout="joomla.form.field.radio.switcher"
default="1"
>
<option value="0">COM_USERS_FIELD_LOGIN_URL</option>
<option value="1">COM_USERS_FIELD_LOGIN_MENUITEM</option>
</field>
<field
name="login_redirect_url"
type="text"
label="JFIELD_LOGIN_REDIRECT_URL_LABEL"
description="JFIELD_LOGIN_REDIRECT_URL_DESC"
validate="LoginUniqueField"
field="login_redirect_menuitem"
hint="COM_USERS_FIELD_LOGIN_REDIRECT_PLACEHOLDER"
message="COM_USERS_FIELD_LOGIN_REDIRECT_ERROR"
showon="loginredirectchoice:0"
/>
<field
name="login_redirect_menuitem"
type="modal_menu"
label="COM_USERS_FIELD_LOGIN_REDIRECTMENU_LABEL"
description="COM_USERS_FIELD_LOGIN_REDIRECTMENU_DESC"
disable="separator,alias,heading,url"
showon="loginredirectchoice:1"
select="true"
new="true"
edit="true"
clear="true"
>
<option value="">JOPTION_SELECT_MENU</option>
</field>
<field
name="logindescription_show"
type="list"
label="JFIELD_BASIC_LOGIN_DESCRIPTION_SHOW_LABEL"
default="1"
class="form-select-color-state"
validate="options"
>
<option value="0">JHIDE</option>
<option value="1">JSHOW</option>
</field>
<field
name="login_description"
type="textarea"
label="JFIELD_BASIC_LOGIN_DESCRIPTION_LABEL"
rows="3"
cols="40"
filter="safehtml"
showon="logindescription_show:1"
/>
<field
name="login_image"
type="media"
label="JFIELD_LOGIN_IMAGE_LABEL"
/>
<field
name="login_image_alt"
type="text"
label="COM_USERS_FIELD_IMAGE_ALT_LABEL"
/>
<field
name="login_image_alt_empty"
type="checkbox"
label="COM_USERS_FIELD_IMAGE_ALT_EMPTY_LABEL"
description="COM_USERS_FIELD_IMAGE_ALT_EMPTY_DESC"
/>
</fieldset>
<fieldset name="logout" label="COM_USERS_FIELD_OPTIONS_LOGOUT">
<field
name="logoutredirectchoice"
type="radio"
label="COM_USERS_FIELD_LOGOUT_REDIRECT_CHOICE_LABEL"
layout="joomla.form.field.radio.switcher"
default="1"
>
<option value="0">COM_USERS_FIELD_LOGIN_URL</option>
<option value="1">COM_USERS_FIELD_LOGIN_MENUITEM</option>
</field>
<field
name="logout_redirect_url"
type="text"
label="JFIELD_LOGOUT_REDIRECT_URL_LABEL"
field="logout_redirect_menuitem"
validate="LogoutUniqueField"
hint="COM_USERS_FIELD_LOGIN_REDIRECT_PLACEHOLDER"
message="COM_USERS_FIELD_LOGOUT_REDIRECT_ERROR"
showon="logoutredirectchoice:0"
/>
<field
name="logout_redirect_menuitem"
type="modal_menu"
label="COM_USERS_FIELD_LOGOUT_REDIRECTMENU_LABEL"
description="COM_USERS_FIELD_LOGOUT_REDIRECTMENU_DESC"
disable="separator,alias,heading,url"
showon="logoutredirectchoice:1"
select="true"
new="true"
edit="true"
clear="true"
>
<option value="">JOPTION_SELECT_MENU</option>
</field>
<field
name="logoutdescription_show"
type="list"
label="JFIELD_BASIC_LOGOUT_DESCRIPTION_SHOW_LABEL"
default="1"
class="form-select-color-state"
validate="options"
>
<option value="0">JHIDE</option>
<option value="1">JSHOW</option>
</field>
<field
name="logout_description"
type="textarea"
label="JFIELD_BASIC_LOGOUT_DESCRIPTION_LABEL"
rows="3"
cols="40"
filter="safehtml"
showon="logoutdescription_show:1"
/>
<field
name="logout_image"
type="media"
label="JFIELD_LOGOUT_IMAGE_LABEL"
/>
<field
name="logout_image_alt"
type="text"
label="COM_USERS_FIELD_IMAGE_ALT_LABEL"
/>
<field
name="logout_image_alt_empty"
type="checkbox"
label="COM_USERS_FIELD_IMAGE_ALT_EMPTY_LABEL"
description="COM_USERS_FIELD_IMAGE_ALT_EMPTY_DESC"
/>
</fieldset>
</fieldset>
</fields>
</metadata>

View File

@ -0,0 +1,129 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Router\Route;
/** @var \Joomla\Component\Users\Site\View\Login\HtmlView $cookieLogin */
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('keepalive')
->useScript('form.validate');
$usersConfig = ComponentHelper::getParams('com_users');
?>
<div class="com-users-login login">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<?php if (($this->params->get('logindescription_show') == 1 && str_replace(' ', '', $this->params->get('login_description', '')) != '') || $this->params->get('login_image') != '') : ?>
<div class="com-users-login__description login-description">
<?php endif; ?>
<?php if ($this->params->get('logindescription_show') == 1) : ?>
<?php echo $this->params->get('login_description'); ?>
<?php endif; ?>
<?php if ($this->params->get('login_image') != '') : ?>
<?php echo HTMLHelper::_('image', $this->params->get('login_image'), empty($this->params->get('login_image_alt')) && empty($this->params->get('login_image_alt_empty')) ? false : $this->params->get('login_image_alt'), ['class' => 'com-users-login__image login-image']); ?>
<?php endif; ?>
<?php if (($this->params->get('logindescription_show') == 1 && str_replace(' ', '', $this->params->get('login_description', '')) != '') || $this->params->get('login_image') != '') : ?>
</div>
<?php endif; ?>
<form action="<?php echo Route::_('index.php?option=com_users&task=user.login'); ?>" method="post" class="com-users-login__form form-validate form-horizontal well" id="com-users-login__form">
<fieldset>
<?php echo $this->form->renderFieldset('credentials', ['class' => 'com-users-login__input']); ?>
<?php if (PluginHelper::isEnabled('system', 'remember')) : ?>
<div class="com-users-login__remember">
<div class="form-check">
<input class="form-check-input" id="remember" type="checkbox" name="remember" value="yes">
<label class="form-check-label" for="remember">
<?php echo Text::_('COM_USERS_LOGIN_REMEMBER_ME'); ?>
</label>
</div>
</div>
<?php endif; ?>
<?php foreach ($this->extraButtons as $button) :
$dataAttributeKeys = array_filter(array_keys($button), function ($key) {
return substr($key, 0, 5) == 'data-';
});
?>
<div class="com-users-login__submit control-group">
<div class="controls">
<button type="button"
class="btn btn-secondary w-100 <?php echo $button['class'] ?? '' ?>"
<?php foreach ($dataAttributeKeys as $key) : ?>
<?php echo $key ?>="<?php echo $button[$key] ?>"
<?php endforeach; ?>
<?php if ($button['onclick']) : ?>
onclick="<?php echo $button['onclick'] ?>"
<?php endif; ?>
title="<?php echo Text::_($button['label']) ?>"
id="<?php echo $button['id'] ?>"
>
<?php if (!empty($button['icon'])) : ?>
<span class="<?php echo $button['icon'] ?>"></span>
<?php elseif (!empty($button['image'])) : ?>
<?php echo HTMLHelper::_('image', $button['image'], Text::_($button['tooltip'] ?? ''), [
'class' => 'icon',
], true) ?>
<?php elseif (!empty($button['svg'])) : ?>
<?php echo $button['svg']; ?>
<?php endif; ?>
<?php echo Text::_($button['label']) ?>
</button>
</div>
</div>
<?php endforeach; ?>
<div class="com-users-login__submit control-group">
<div class="controls">
<button type="submit" class="btn btn-primary">
<?php echo Text::_('JLOGIN'); ?>
</button>
</div>
</div>
<?php $return = $this->form->getValue('return', '', $this->params->get('login_redirect_url', $this->params->get('login_redirect_menuitem', ''))); ?>
<input type="hidden" name="return" value="<?php echo base64_encode($return); ?>">
<?php echo HTMLHelper::_('form.token'); ?>
</fieldset>
</form>
<div class="com-users-login__options list-group">
<a class="com-users-login__reset list-group-item" href="<?php echo Route::_('index.php?option=com_users&view=reset'); ?>">
<?php echo Text::_('COM_USERS_LOGIN_RESET'); ?>
</a>
<a class="com-users-login__remind list-group-item" href="<?php echo Route::_('index.php?option=com_users&view=remind'); ?>">
<?php echo Text::_('COM_USERS_LOGIN_REMIND'); ?>
</a>
<?php if ($usersConfig->get('allowUserRegistration')) : ?>
<a class="com-users-login__register list-group-item" href="<?php echo Route::_('index.php?option=com_users&view=registration'); ?>">
<?php echo Text::_('COM_USERS_LOGIN_REGISTER'); ?>
</a>
<?php endif; ?>
</div>
</div>

View File

@ -0,0 +1,60 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var \Joomla\Component\Users\Site\View\Login\HtmlView $this */
?>
<div class="com-users-logout logout">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<?php if (($this->params->get('logoutdescription_show') == 1 && str_replace(' ', '', $this->params->get('logout_description', '')) != '') || $this->params->get('logout_image') != '') : ?>
<div class="com-users-logout__description logout-description">
<?php endif; ?>
<?php if ($this->params->get('logoutdescription_show') == 1) : ?>
<?php echo $this->params->get('logout_description'); ?>
<?php endif; ?>
<?php if ($this->params->get('logout_image') != '') : ?>
<?php echo HTMLHelper::_('image', $this->params->get('logout_image'), empty($this->params->get('logout_image_alt')) && empty($this->params->get('logout_image_alt_empty')) ? false : $this->params->get('logout_image_alt'), ['class' => 'com-users-logout__image thumbnail float-end logout-image']); ?>
<?php endif; ?>
<?php if (($this->params->get('logoutdescription_show') == 1 && str_replace(' ', '', $this->params->get('logout_description', '')) != '') || $this->params->get('logout_image') != '') : ?>
</div>
<?php endif; ?>
<form action="<?php echo Route::_('index.php?option=com_users&task=user.logout'); ?>" method="post" class="com-users-logout__form form-horizontal well">
<div class="com-users-logout__submit control-group">
<div class="controls">
<button type="submit" class="btn btn-primary">
<span class="icon-backward-2 icon-white" aria-hidden="true"></span>
<?php echo Text::_('JLOGOUT'); ?>
</button>
</div>
</div>
<?php if ($this->params->get('logout_redirect_url')) : ?>
<input type="hidden" name="return" value="<?php echo base64_encode($this->params->get('logout_redirect_url', $this->form->getValue('return', null, ''))); ?>">
<?php else : ?>
<input type="hidden" name="return" value="<?php echo base64_encode($this->params->get('logout_redirect_menuitem', $this->form->getValue('return', null, ''))); ?>">
<?php endif; ?>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
</div>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_USERS_LOGOUT_VIEW_DEFAULT_TITLE" option="COM_USERS_LOGOUT_VIEW_DEFAULT_OPTION">
<help key = "Menu_Item:_Logout"/>
<message>
<![CDATA[COM_USERS_LOGOUT_VIEW_DEFAULT_DESC]]>
</message>
</layout>
<!-- Add fields to the request variables for the layout. -->
<fields name="request">
<fieldset name="request">
<field
name="task"
type="hidden"
default="user.menulogout"
/>
</fieldset>
</fields>
<!-- Add fields to the parameters object for the layout. -->
<fields name="params">
<fieldset name="basic" label="COM_MENUS_BASIC_FIELDSET_LABEL">
<field
name="logout"
type="modal_menu"
label="JFIELD_LOGOUT_REDIRECT_PAGE_LABEL"
description="JFIELD_LOGOUT_REDIRECT_PAGE_DESC"
disable="separator,alias,heading,url"
select="true"
new="true"
edit="true"
clear="true"
>
<option value="">JOPTION_SELECT_MENU</option>
</field>
</fieldset>
</fields>
</metadata>

View File

@ -0,0 +1,77 @@
<?php
/**
* @package Joomla.Site
* @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
*/
// Prevent direct access
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Component\Users\Site\View\Method\HtmlView;
/** @var HtmlView $this */
HTMLHelper::_('bootstrap.tooltip', '.hasTooltip');
$cancelURL = Route::_('index.php?option=com_users&task=methods.display&user_id=' . $this->user->id);
if (!empty($this->returnURL)) {
$cancelURL = $this->escape(base64_decode($this->returnURL));
}
if ($this->record->method != 'backupcodes') {
throw new RuntimeException(Text::_('JERROR_ALERTNOAUTHOR'), 403);
}
?>
<h2>
<?php echo Text::_('COM_USERS_USER_BACKUPCODES') ?>
</h2>
<div class="alert alert-info">
<?php echo Text::_('COM_USERS_USER_BACKUPCODES_DESC') ?>
</div>
<table class="table table-striped">
<?php for ($i = 0; $i < (count($this->backupCodes) / 2); $i++) : ?>
<tr>
<td>
<?php if (!empty($this->backupCodes[2 * $i])) : ?>
<?php // This is a Key emoji; we can hide it from screen readers ?>
<span aria-hidden="true">&#128273;</span>
<?php echo $this->backupCodes[2 * $i] ?>
<?php endif; ?>
</td>
<td>
<?php if (!empty($this->backupCodes[1 + 2 * $i])) : ?>
<?php // This is a Key emoji; we can hide it from screen readers ?>
<span aria-hidden="true">&#128273;</span>
<?php echo $this->backupCodes[1 + 2 * $i] ?>
<?php endif ;?>
</td>
</tr>
<?php endfor; ?>
</table>
<p>
<?php echo Text::_('COM_USERS_MFA_BACKUPCODES_RESET_INFO'); ?>
</p>
<a class="btn btn-danger" href="<?php echo Route::_(sprintf("index.php?option=com_users&task=method.regenerateBackupCodes&user_id=%s&%s=1%s", $this->user->id, Factory::getApplication()->getFormToken(), empty($this->returnURL) ? '' : '&returnurl=' . $this->returnURL)) ?>">
<span class="icon icon-refresh" aria-hidden="true"></span>
<?php echo Text::_('COM_USERS_MFA_BACKUPCODES_RESET'); ?>
</a>
<a href="<?php echo $cancelURL ?>"
class="btn btn-secondary">
<span class="icon icon-cancel-2 icon-ban-circle"></span>
<?php echo Text::_('JCANCEL'); ?>
</a>

View File

@ -0,0 +1,181 @@
<?php
/**
* @package Joomla.Site
* @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
*/
// Prevent direct access
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Component\Users\Site\View\Method\HtmlView;
use Joomla\Utilities\ArrayHelper;
/** @var HtmlView $this */
$cancelURL = Route::_('index.php?option=com_users&task=methods.display&user_id=' . $this->user->id);
if (!empty($this->returnURL)) {
$cancelURL = $this->escape(base64_decode($this->returnURL));
}
$recordId = (int) $this->record->id ?? 0;
$method = $this->record->method ?? $this->getModel()->getState('method');
$userId = (int) $this->user->id ?? 0;
$headingLevel = 2;
$hideSubmit = !$this->renderOptions['show_submit'] && !$this->isEditExisting
?>
<div class="card card-body">
<form action="<?php echo Route::_(sprintf("index.php?option=com_users&task=method.save&id=%d&method=%s&user_id=%d", $recordId, $method, $userId)) ?>"
class="form form-horizontal" id="com-users-method-edit" method="post">
<?php echo HTMLHelper::_('form.token') ?>
<?php if (!empty($this->returnURL)) : ?>
<input type="hidden" name="returnurl" value="<?php echo $this->escape($this->returnURL) ?>">
<?php endif; ?>
<?php if (!empty($this->renderOptions['hidden_data'])) : ?>
<?php foreach ($this->renderOptions['hidden_data'] as $key => $value) : ?>
<input type="hidden" name="<?php echo $this->escape($key) ?>" value="<?php echo $this->escape($value) ?>">
<?php endforeach; ?>
<?php endif; ?>
<?php if (!empty($this->title)) : ?>
<?php if (!empty($this->renderOptions['help_url'])) : ?>
<span class="float-end">
<a href="<?php echo $this->renderOptions['help_url'] ?>"
class="btn btn-sm btn-dark"
target="_blank"
>
<span class="icon icon-question-sign" aria-hidden="true"></span>
<span class="visually-hidden"><?php echo Text::_('JHELP') ?></span>
</a>
</span>
<?php endif;?>
<h<?php echo $headingLevel ?> id="com-users-method-edit-head">
<?php echo Text::_($this->title) ?>
</h<?php echo $headingLevel ?>>
<?php $headingLevel++ ?>
<?php endif; ?>
<div class="row">
<label class="col-sm-3 col-form-label"
for="com-users-method-edit-title">
<?php echo Text::_('COM_USERS_MFA_EDIT_FIELD_TITLE'); ?>
</label>
<div class="col-sm-9">
<input type="text"
class="form-control"
id="com-users-method-edit-title"
name="title"
value="<?php echo $this->escape($this->record->title) ?>"
aria-describedby="com-users-method-edit-help">
<p class="form-text" id="com-users-method-edit-help">
<?php echo $this->escape(Text::_('COM_USERS_MFA_EDIT_FIELD_TITLE_DESC')) ?>
</p>
</div>
</div>
<div class="row">
<div class="col-sm-9 offset-sm-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="com-users-is-default-method" <?php echo $this->record->default ? 'checked="checked"' : ''; ?> name="default">
<label class="form-check-label" for="com-users-is-default-method">
<?php echo Text::_('COM_USERS_MFA_EDIT_FIELD_DEFAULT'); ?>
</label>
</div>
</div>
</div>
<?php if (!empty($this->renderOptions['pre_message'])) : ?>
<div class="com-users-method-edit-pre-message text-muted mt-4 mb-3">
<?php echo $this->renderOptions['pre_message'] ?>
</div>
<?php endif; ?>
<?php if (!empty($this->renderOptions['tabular_data'])) : ?>
<div class="com-users-method-edit-tabular-container">
<?php if (!empty($this->renderOptions['table_heading'])) : ?>
<h<?php echo $headingLevel ?> class="h3 border-bottom mb-3">
<?php echo $this->renderOptions['table_heading'] ?>
</h<?php echo $headingLevel ?>>
<?php endif; ?>
<table class="table table-striped">
<tbody>
<?php foreach ($this->renderOptions['tabular_data'] as $cell1 => $cell2) : ?>
<tr>
<td>
<?php echo $cell1 ?>
</td>
<td>
<?php echo $cell2 ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php if ($this->renderOptions['field_type'] == 'custom') : ?>
<?php echo $this->renderOptions['html']; ?>
<?php endif; ?>
<div class="row mb-3 <?php echo $this->renderOptions['input_type'] === 'hidden' ? 'd-none' : '' ?>">
<?php if ($this->renderOptions['label']) : ?>
<label class="col-sm-3 col-form-label" for="com-users-method-code">
<?php echo $this->renderOptions['label']; ?>
</label>
<?php endif; ?>
<div class="col-sm-9" <?php echo $this->renderOptions['label'] ? '' : 'offset-sm-3' ?>>
<?php
$attributes = array_merge(
[
'type' => $this->renderOptions['input_type'],
'name' => 'code',
'value' => $this->escape($this->renderOptions['input_value']),
'id' => 'com-users-method-code',
'class' => 'form-control',
'aria-describedby' => 'com-users-method-code-help',
],
$this->renderOptions['input_attributes']
);
if (strpos($attributes['class'], 'form-control') === false) {
$attributes['class'] .= ' form-control';
}
?>
<input <?php echo ArrayHelper::toString($attributes) ?>>
<p class="form-text" id="com-users-method-code-help">
<?php echo $this->escape($this->renderOptions['placeholder']) ?>
</p>
</div>
</div>
<div class="row mb-3">
<div class="col-sm-9 offset-sm-3">
<button type="submit" class="btn btn-primary me-3 <?php echo $hideSubmit ? 'd-none' : '' ?> <?php echo $this->renderOptions['submit_class'] ?>">
<span class="<?php echo $this->renderOptions['submit_icon'] ?>" aria-hidden="true"></span>
<?php echo Text::_($this->renderOptions['submit_text']); ?>
</button>
<a href="<?php echo $cancelURL ?>"
class="btn btn-sm btn-danger">
<span class="icon icon-cancel-2" aria-hidden="true"></span>
<?php echo Text::_('JCANCEL'); ?>
</a>
</div>
</div>
<?php if (!empty($this->renderOptions['post_message'])) : ?>
<div class="com-users-method-edit-post-message text-muted">
<?php echo $this->renderOptions['post_message'] ?>
</div>
<?php endif; ?>
</form>
</div>

View File

@ -0,0 +1,60 @@
<?php
/**
* @package Joomla.Site
* @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
*/
// Prevent direct access
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Component\Users\Site\View\Methods\HtmlView;
/** @var HtmlView $this */
?>
<div id="com-users-methods-list">
<?php if (!$this->get('forHMVC', false)) : ?>
<h2 id="com-users-methods-list-head">
<?php echo Text::_('COM_USERS_MFA_LIST_PAGE_HEAD'); ?>
</h2>
<?php endif ?>
<div id="com-users-methods-reset-container" class="d-flex align-items-center border border-1 rounded-3 p-2 bg-light">
<div id="com-users-methods-reset-message" class="flex-grow-1">
<?php echo Text::_('COM_USERS_MFA_LIST_STATUS_' . ($this->mfaActive ? 'ON' : 'OFF')) ?>
</div>
<?php if ($this->mfaActive) : ?>
<div>
<a href="<?php echo Route::_('index.php?option=com_users&task=methods.disable&' . Factory::getApplication()->getFormToken() . '=1' . ($this->returnURL ? '&returnurl=' . $this->escape(urlencode($this->returnURL)) : '') . '&user_id=' . $this->user->id) ?>"
class="btn btn-danger btn-sm">
<?php echo Text::_('COM_USERS_MFA_LIST_REMOVEALL'); ?>
</a>
</div>
<?php endif; ?>
</div>
<?php if (!count($this->methods)) : ?>
<div id="com-users-methods-list-instructions" class="alert alert-info mt-2">
<span class="icon icon-info-circle" aria-hidden="true"></span>
<?php echo Text::_('COM_USERS_MFA_LIST_INSTRUCTIONS'); ?>
</div>
<?php elseif ($this->isMandatoryMFASetup) : ?>
<div class="alert alert-info my-3">
<h3 class="alert-heading">
<?php echo Text::_('COM_USERS_MFA_MANDATORY_NOTICE_HEAD') ?>
</h3>
<p>
<?php echo Text::_('COM_USERS_MFA_MANDATORY_NOTICE_BODY') ?>
</p>
</div>
<?php endif ?>
<?php $this->setLayout('list');
echo $this->loadTemplate(); ?>
</div>

View File

@ -0,0 +1,50 @@
<?php
/**
* @package Joomla.Site
* @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
*/
// Prevent direct access
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Component\Users\Site\View\Methods\HtmlView;
/** @var HtmlView $this */
$headingLevel = 2;
?>
<div id="com-users-methods-list">
<?php if (!$this->isAdmin) : ?>
<h<?php echo $headingLevel ?> id="com-users-methods-list-head">
<?php echo Text::_('COM_USERS_MFA_FIRSTTIME_PAGE_HEAD'); ?>
</h<?php echo $headingLevel++ ?>>
<?php endif; ?>
<div id="com-users-methods-list-instructions" class="alert alert-info">
<h<?php echo $headingLevel ?> class="alert-heading">
<span class="fa fa-shield-alt" aria-hidden="true"></span>
<?php echo Text::_('COM_USERS_MFA_FIRSTTIME_INSTRUCTIONS_HEAD'); ?>
</h<?php echo $headingLevel ?>>
<p>
<?php echo Text::_('COM_USERS_MFA_FIRSTTIME_INSTRUCTIONS_WHATITDOES'); ?>
</p>
<a href="<?php echo Route::_(
'index.php?option=com_users&task=methods.doNotShowThisAgain' .
($this->returnURL ? '&returnurl=' . $this->escape(urlencode($this->returnURL)) : '') .
'&user_id=' . $this->user->id .
'&' . Factory::getApplication()->getFormToken() . '=1'
)?>"
class="btn btn-danger w-100">
<?php echo Text::_('COM_USERS_MFA_FIRSTTIME_NOTINTERESTED'); ?>
</a>
</div>
<?php $this->setLayout('list');
echo $this->loadTemplate(); ?>
</div>

View File

@ -0,0 +1,144 @@
<?php
/**
* @package Joomla.Site
* @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
*/
// Prevent direct access
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Users\Administrator\Helper\Mfa as MfaHelper;
use Joomla\Component\Users\Site\Model\MethodsModel;
use Joomla\Component\Users\Site\View\Methods\HtmlView;
/** @var HtmlView $this */
/** @var MethodsModel $model */
$model = $this->getModel();
$this->document->getWebAssetManager()->useScript('com_users.two-factor-list');
HTMLHelper::_('bootstrap.tooltip', '.hasTooltip');
$canAddEdit = MfaHelper::canAddEditMethod($this->user);
$canDelete = MfaHelper::canDeleteMethod($this->user);
?>
<div id="com-users-methods-list-container">
<?php foreach ($this->methods as $methodName => $method) :
$methodClass = 'com-users-methods-list-method-name-' . htmlentities($method['name'])
. ($this->defaultMethod == $methodName ? ' com-users-methods-list-method-default' : '');
?>
<div class="com-users-methods-list-method <?php echo $methodClass?> mx-1 my-3 card <?php echo count($method['active']) ? 'border-secondary' : '' ?>">
<div class="com-users-methods-list-method-header card-header <?php echo count($method['active']) ? 'border-secondary bg-secondary text-white' : '' ?> d-flex flex-wrap align-items-center gap-2">
<div class="com-users-methods-list-method-image pt-1 px-3 pb-2 bg-light rounded-2">
<img src="<?php echo Uri::root() . $method['image'] ?>"
alt="<?php echo $this->escape($method['display']) ?>"
class="img-fluid"
>
</div>
<div class="com-users-methods-list-method-title flex-grow-1 d-flex flex-column">
<h2 class="h4 p-0 m-0 d-flex gap-3 align-items-center">
<span class="me-1 flex-grow-1">
<?php echo $method['display'] ?>
</span>
<?php if ($this->defaultMethod == $methodName) : ?>
<span id="com-users-methods-list-method-default-tag" class="badge bg-info me-1 fs-6">
<?php echo Text::_('COM_USERS_MFA_LIST_DEFAULTTAG') ?>
</span>
<?php endif; ?>
</h2>
</div>
</div>
<div class="com-users-methods-list-method-records-container card-body">
<div class="com-users-methods-list-method-info my-1 pb-1 small text-muted">
<?php echo $method['shortinfo'] ?>
</div>
<?php if (count($method['active'])) : ?>
<div class="com-users-methods-list-method-records pt-2 my-2">
<?php foreach ($method['active'] as $record) : ?>
<div class="com-users-methods-list-method-record d-flex flex-row flex-wrap justify-content-start border-top py-2">
<div class="com-users-methods-list-method-record-info flex-grow-1 d-flex flex-column align-items-start gap-1">
<?php if ($methodName === 'backupcodes') : ?>
<?php if ($canAddEdit) : ?>
<div class="alert alert-info mt-1 w-100">
<?php echo Text::sprintf('COM_USERS_MFA_BACKUPCODES_PRINT_PROMPT_HEAD', Route::_('index.php?option=com_users&task=method.edit&id=' . (int) $record->id . ($this->returnURL ? '&returnurl=' . $this->escape(urlencode($this->returnURL)) : '') . '&user_id=' . $this->user->id)) ?>
</div>
<?php endif ?>
<?php else : ?>
<h3 class="com-users-methods-list-method-record-title-container mb-1 fs-5">
<?php if ($record->default) : ?>
<span id="com-users-methods-list-method-default-badge-small"
class="text-warning me-1 hasTooltip"
title="<?php echo $this->escape(Text::_('COM_USERS_MFA_LIST_DEFAULTTAG')) ?>">
<span class="icon icon-star" aria-hidden="true"></span>
<span class="visually-hidden"><?php echo $this->escape(Text::_('COM_USERS_MFA_LIST_DEFAULTTAG')) ?></span>
</span>
<?php endif; ?>
<span class="com-users-methods-list-method-record-title fw-bold">
<?php echo $this->escape($record->title); ?>
</span>
</h3>
<?php endif; ?>
<div class="com-users-methods-list-method-record-lastused my-1 d-flex flex-row flex-wrap justify-content-start gap-5 text-muted small w-100">
<span class="com-users-methods-list-method-record-createdon">
<?php echo Text::sprintf('COM_USERS_MFA_LBL_CREATEDON', $model->formatRelative($record->created_on)) ?>
</span>
<span class="com-users-methods-list-method-record-lastused-date">
<?php echo Text::sprintf('COM_USERS_MFA_LBL_LASTUSED', $model->formatRelative($record->last_used)) ?>
</span>
</div>
</div>
<?php if ($methodName !== 'backupcodes' && ($canAddEdit || $canDelete)) : ?>
<div class="com-users-methods-list-method-record-actions my-2 d-flex flex-row flex-wrap justify-content-center align-content-center align-items-start">
<?php if ($canAddEdit) : ?>
<a class="com-users-methods-list-method-record-edit btn btn-secondary btn-sm mx-1 hasTooltip"
href="<?php echo Route::_('index.php?option=com_users&task=method.edit&id=' . (int) $record->id . ($this->returnURL ? '&returnurl=' . $this->escape(urlencode($this->returnURL)) : '') . '&user_id=' . $this->user->id)?>"
title="<?php echo Text::_('JACTION_EDIT') ?> <?php echo $this->escape($record->title); ?>">
<span class="icon icon-pencil" aria-hidden="true"></span>
<span class="visually-hidden"><?php echo Text::_('JACTION_EDIT') ?> <?php echo $this->escape($record->title); ?></span>
</a>
<?php endif ?>
<?php if ($method['canDisable'] && $canDelete) : ?>
<a class="com-users-methods-list-method-record-delete btn btn-danger btn-sm mx-1 hasTooltip"
href="<?php echo Route::_('index.php?option=com_users&task=method.delete&id=' . (int) $record->id . ($this->returnURL ? '&returnurl=' . $this->escape(urlencode($this->returnURL)) : '') . '&user_id=' . $this->user->id . '&' . Factory::getApplication()->getFormToken() . '=1')?>"
title="<?php echo Text::_('JACTION_DELETE') ?> <?php echo $this->escape($record->title); ?>">
<span class="icon icon-trash" aria-hidden="true"></span>
<span class="visually-hidden"><?php echo Text::_('JACTION_DELETE') ?> <?php echo $this->escape($record->title); ?></span>
</a>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($canAddEdit && (empty($method['active']) || $method['allowMultiple'])) : ?>
<div class="com-users-methods-list-method-addnew-container border-top pt-2">
<a href="<?php echo Route::_('index.php?option=com_users&task=method.add&method=' . $this->escape(urlencode($method['name'])) . ($this->returnURL ? '&returnurl=' . $this->escape(urlencode($this->returnURL)) : '') . '&user_id=' . $this->user->id)?>"
class="com-users-methods-list-method-addnew btn btn-outline-primary btn-sm"
>
<span class="icon-plus-2" aria-hidden="true"></span>
<?php echo Text::sprintf('COM_USERS_MFA_ADD_AUTHENTICATOR_OF_TYPE', $method['display']) ?>
</a>
</div>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>

View File

@ -0,0 +1,39 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
?>
<div class="com-users-profile profile">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<?php if ($this->getCurrentUser()->id == $this->data->id) : ?>
<ul class="com-users-profile__edit btn-toolbar float-end">
<li class="btn-group">
<a class="btn btn-primary" href="<?php echo Route::_('index.php?option=com_users&task=profile.edit&user_id=' . (int) $this->data->id); ?>">
<span class="icon-user-edit" aria-hidden="true"></span> <?php echo Text::_('COM_USERS_EDIT_PROFILE'); ?>
</a>
</li>
</ul>
<?php endif; ?>
<?php echo $this->loadTemplate('core'); ?>
<?php echo $this->loadTemplate('params'); ?>
<?php echo $this->loadTemplate('custom'); ?>
</div>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_USERS_PROFILE_VIEW_DEFAULT_TITLE" option="COM_USERS_PROFILE_VIEW_DEFAULT_OPTION">
<help
key = "Menu_Item:_User_Profile"
/>
<message>
<![CDATA[COM_USERS_PROFILE_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>

View File

@ -0,0 +1,53 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
?>
<fieldset id="users-profile-core" class="com-users-profile__core">
<legend>
<?php echo Text::_('COM_USERS_PROFILE_CORE_LEGEND'); ?>
</legend>
<dl class="dl-horizontal">
<dt>
<?php echo Text::_('COM_USERS_PROFILE_NAME_LABEL'); ?>
</dt>
<dd>
<?php echo $this->escape($this->data->name); ?>
</dd>
<dt>
<?php echo Text::_('COM_USERS_PROFILE_USERNAME_LABEL'); ?>
</dt>
<dd>
<?php echo $this->escape($this->data->username); ?>
</dd>
<dt>
<?php echo Text::_('COM_USERS_PROFILE_REGISTERED_DATE_LABEL'); ?>
</dt>
<dd>
<?php echo HTMLHelper::_('date', $this->data->registerDate, Text::_('DATE_FORMAT_LC1')); ?>
</dd>
<dt>
<?php echo Text::_('COM_USERS_PROFILE_LAST_VISITED_DATE_LABEL'); ?>
</dt>
<?php if ($this->data->lastvisitDate !== null) : ?>
<dd>
<?php echo HTMLHelper::_('date', $this->data->lastvisitDate, Text::_('DATE_FORMAT_LC1')); ?>
</dd>
<?php else : ?>
<dd>
<?php echo Text::_('COM_USERS_PROFILE_NEVER_VISITED'); ?>
</dd>
<?php endif; ?>
</dl>
</fieldset>

View File

@ -0,0 +1,75 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
$fieldsets = $this->form->getFieldsets();
if (isset($fieldsets['core'])) {
unset($fieldsets['core']);
}
if (isset($fieldsets['params'])) {
unset($fieldsets['params']);
}
$tmp = $this->data->jcfields ?? [];
$customFields = [];
foreach ($tmp as $customField) {
$customFields[$customField->name] = $customField;
}
unset($tmp);
?>
<?php foreach ($fieldsets as $group => $fieldset) : ?>
<?php $fields = $this->form->getFieldset($group); ?>
<?php if (count($fields)) : ?>
<fieldset id="users-profile-custom-<?php echo $group; ?>" class="com-users-profile__custom users-profile-custom-<?php echo $group; ?>">
<?php if (isset($fieldset->label) && ($legend = trim(Text::_($fieldset->label))) !== '') : ?>
<legend><?php echo $legend; ?></legend>
<?php endif; ?>
<?php if (isset($fieldset->description) && trim($fieldset->description)) : ?>
<p><?php echo $this->escape(Text::_($fieldset->description)); ?></p>
<?php endif; ?>
<dl class="dl-horizontal">
<?php foreach ($fields as $field) : ?>
<?php // Correct the field name so that subform custom fields show up. ?>
<?php if ($field->type === 'Subform' && $field->fieldname === 'row') : ?>
<?php preg_match("/jform\[com_fields]\[(.*)]/", $field->name, $matches); ?>
<?php $field->fieldname = $matches[1]; ?>
<?php endif; ?>
<?php if (!$field->hidden && $field->type !== 'Spacer') : ?>
<dt>
<?php echo $field->title; ?>
</dt>
<dd>
<?php if (array_key_exists($field->fieldname, $customFields)) : ?>
<?php echo strlen($customFields[$field->fieldname]->value) ? $customFields[$field->fieldname]->value : Text::_('COM_USERS_PROFILE_VALUE_NOT_FOUND'); ?>
<?php elseif (HTMLHelper::isRegistered('users.' . $field->id)) : ?>
<?php echo HTMLHelper::_('users.' . $field->id, $field->value); ?>
<?php elseif (HTMLHelper::isRegistered('users.' . $field->fieldname)) : ?>
<?php echo HTMLHelper::_('users.' . $field->fieldname, $field->value); ?>
<?php elseif (HTMLHelper::isRegistered('users.' . $field->type)) : ?>
<?php echo HTMLHelper::_('users.' . $field->type, $field->value); ?>
<?php else : ?>
<?php echo HTMLHelper::_('users.value', $field->value); ?>
<?php endif; ?>
</dd>
<?php endif; ?>
<?php endforeach; ?>
</dl>
</fieldset>
<?php endif; ?>
<?php endforeach; ?>

View File

@ -0,0 +1,42 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
?>
<?php $fields = $this->form->getFieldset('params'); ?>
<?php if (count($fields)) : ?>
<fieldset id="users-profile-custom" class="com-users-profile__params">
<legend><?php echo Text::_('COM_USERS_SETTINGS_FIELDSET_LABEL'); ?></legend>
<dl class="dl-horizontal">
<?php foreach ($fields as $field) : ?>
<?php if (!$field->hidden) : ?>
<dt>
<?php echo $field->title; ?>
</dt>
<dd>
<?php if (HTMLHelper::isRegistered('users.' . $field->id)) : ?>
<?php echo HTMLHelper::_('users.' . $field->id, $field->value); ?>
<?php elseif (HTMLHelper::isRegistered('users.' . $field->fieldname)) : ?>
<?php echo HTMLHelper::_('users.' . $field->fieldname, $field->value); ?>
<?php elseif (HTMLHelper::isRegistered('users.' . $field->type)) : ?>
<?php echo HTMLHelper::_('users.' . $field->type, $field->value); ?>
<?php else : ?>
<?php echo HTMLHelper::_('users.value', $field->value); ?>
<?php endif; ?>
</dd>
<?php endif; ?>
<?php endforeach; ?>
</dl>
</fieldset>
<?php endif; ?>

View File

@ -0,0 +1,87 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var Joomla\Component\Users\Site\View\Profile\HtmlView $this */
HTMLHelper::_('bootstrap.tooltip', '.hasTooltip');
// Load user_profile plugin language
$lang = $this->getLanguage();
$lang->load('plg_user_profile', JPATH_ADMINISTRATOR);
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('keepalive')
->useScript('form.validate');
?>
<div class="com-users-profile__edit profile-edit">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form id="member-profile" action="<?php echo Route::_('index.php?option=com_users'); ?>" method="post" class="com-users-profile__edit-form form-validate form-horizontal well" enctype="multipart/form-data">
<?php // Iterate through the form fieldsets and display each one. ?>
<?php foreach ($this->form->getFieldsets() as $group => $fieldset) : ?>
<?php $fields = $this->form->getFieldset($group); ?>
<?php if (count($fields)) : ?>
<fieldset>
<?php // If the fieldset has a label set, display it as the legend. ?>
<?php if (isset($fieldset->label)) : ?>
<legend>
<?php echo Text::_($fieldset->label); ?>
</legend>
<?php endif; ?>
<?php if (isset($fieldset->description) && trim($fieldset->description)) : ?>
<p>
<?php echo $this->escape(Text::_($fieldset->description)); ?>
</p>
<?php endif; ?>
<?php // Iterate through the fields in the set and display them. ?>
<?php foreach ($fields as $field) : ?>
<?php echo $field->renderField(); ?>
<?php endforeach; ?>
</fieldset>
<?php endif; ?>
<?php endforeach; ?>
<?php if ($this->mfaConfigurationUI) : ?>
<fieldset class="com-users-profile__multifactor">
<legend><?php echo Text::_('COM_USERS_PROFILE_MULTIFACTOR_AUTH'); ?></legend>
<?php echo $this->mfaConfigurationUI ?>
</fieldset>
<?php endif; ?>
<div class="com-users-profile__edit-submit control-group">
<div class="controls">
<button type="submit" class="btn btn-primary validate" name="task" value="profile.save">
<span class="icon-check" aria-hidden="true"></span>
<?php echo Text::_('JSAVE'); ?>
</button>
<button type="submit" class="btn btn-danger" name="task" value="profile.cancel" formnovalidate>
<span class="icon-times" aria-hidden="true"></span>
<?php echo Text::_('JCANCEL'); ?>
</button>
<input type="hidden" name="option" value="com_users">
</div>
</div>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
</div>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_USERS_PROFILE_EDIT_DEFAULT_TITLE" option="COM_USERS_PROFILE_EDIT_DEFAULT_OPTION">
<help
key = "Menu_Item:_Edit_User_Profile"
/>
<message>
<![CDATA[COM_USERS_PROFILE_EDIT_DEFAULT_DESC]]>
</message>
</layout>
</metadata>

View File

@ -0,0 +1,20 @@
<?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
*/
defined('_JEXEC') or die;
?>
<div class="com-users-registration-complete registration-complete">
<?php if ($this->params->get('show_page_heading')) : ?>
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
<?php endif; ?>
</div>

View File

@ -0,0 +1,61 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('keepalive')
->useScript('form.validate');
?>
<div class="com-users-registration registration">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1><?php echo $this->escape($this->params->get('page_heading')); ?></h1>
</div>
<?php endif; ?>
<form id="member-registration" action="<?php echo Route::_('index.php?option=com_users&task=registration.register'); ?>" method="post" class="com-users-registration__form form-validate" enctype="multipart/form-data">
<?php // Iterate through the form fieldsets and display each one. ?>
<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
<?php if ($fieldset->name === 'captcha' && $this->captchaEnabled) : ?>
<?php continue; ?>
<?php endif; ?>
<?php $fields = $this->form->getFieldset($fieldset->name); ?>
<?php if (count($fields)) : ?>
<fieldset>
<?php // If the fieldset has a label set, display it as the legend. ?>
<?php if (isset($fieldset->label)) : ?>
<legend><?php echo Text::_($fieldset->label); ?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name); ?>
</fieldset>
<?php endif; ?>
<?php endforeach; ?>
<?php if ($this->captchaEnabled) : ?>
<?php echo $this->form->renderFieldset('captcha'); ?>
<?php endif; ?>
<div class="com-users-registration__submit control-group">
<div class="controls">
<button type="submit" class="com-users-registration__register btn btn-primary validate">
<?php echo Text::_('JREGISTER'); ?>
</button>
<input type="hidden" name="option" value="com_users">
<input type="hidden" name="task" value="registration.register">
</div>
</div>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
</div>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_USERS_REGISTRATION_VIEW_DEFAULT_TITLE" option="COM_USERS_REGISTRATION_VIEW_DEFAULT_OPTION">
<help
key="Menu_Item:_Registration_Form"
/>
<message>
<![CDATA[COM_USERS_REGISTRATION_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>

View File

@ -0,0 +1,49 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('keepalive')
->useScript('form.validate');
?>
<div class="com-users-remind remind">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form id="user-registration" action="<?php echo Route::_('index.php?option=com_users&task=remind.remind'); ?>" method="post" class="com-users-remind__form form-validate form-horizontal well">
<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
<fieldset>
<?php if (isset($fieldset->label)) : ?>
<legend><?php echo Text::_($fieldset->label); ?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name); ?>
</fieldset>
<?php endforeach; ?>
<div class="com-users-remind__submit control-group">
<div class="controls">
<button type="submit" class="btn btn-primary validate">
<?php echo Text::_('JSUBMIT'); ?>
</button>
</div>
</div>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
</div>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_USERS_REMIND_VIEW_DEFAULT_TITLE" option="COM_USERS_REMIND_VIEW_DEFAULT_OPTION">
<help
key = "Menu_Item:_Username_Reminder_Request"
/>
<message>
<![CDATA[COM_USERS_REMIND_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>

View File

@ -0,0 +1,49 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('keepalive')
->useScript('form.validate');
?>
<div class="com-users-reset-complete reset-complete">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form action="<?php echo Route::_('index.php?option=com_users&task=reset.complete'); ?>" method="post" class="com-users-reset-complete__form form-validate form-horizontal well">
<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
<fieldset>
<?php if (isset($fieldset->label)) : ?>
<legend><?php echo Text::_($fieldset->label); ?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name); ?>
</fieldset>
<?php endforeach; ?>
<div class="com-users-reset-complete__submit control-group">
<div class="controls">
<button type="submit" class="btn btn-primary validate">
<?php echo Text::_('JSUBMIT'); ?>
</button>
</div>
</div>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
</div>

View File

@ -0,0 +1,49 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('keepalive')
->useScript('form.validate');
?>
<div class="com-users-reset-confirm reset-confirm">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form action="<?php echo Route::_('index.php?option=com_users&task=reset.confirm'); ?>" method="post" class="com-users-reset-confirm__form form-validate form-horizontal well">
<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
<fieldset>
<?php if (isset($fieldset->label)) : ?>
<legend><?php echo Text::_($fieldset->label); ?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name); ?>
</fieldset>
<?php endforeach; ?>
<div class="com-users-reset-confirm__submit control-group">
<div class="controls">
<button type="submit" class="btn btn-primary validate">
<?php echo Text::_('JSUBMIT'); ?>
</button>
</div>
</div>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
</div>

View File

@ -0,0 +1,49 @@
<?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
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->document->getWebAssetManager();
$wa->useScript('keepalive')
->useScript('form.validate');
?>
<div class="com-users-reset reset">
<?php if ($this->params->get('show_page_heading')) : ?>
<div class="page-header">
<h1>
<?php echo $this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form id="user-registration" action="<?php echo Route::_('index.php?option=com_users&task=reset.request'); ?>" method="post" class="com-users-reset__form form-validate form-horizontal well">
<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
<fieldset>
<?php if (isset($fieldset->label)) : ?>
<legend><?php echo Text::_($fieldset->label); ?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name); ?>
</fieldset>
<?php endforeach; ?>
<div class="com-users-reset__submit control-group">
<div class="controls">
<button type="submit" class="btn btn-primary validate">
<?php echo Text::_('JSUBMIT'); ?>
</button>
</div>
</div>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
</div>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<layout title="COM_USERS_RESET_VIEW_DEFAULT_TITLE" option="COM_USERS_RESET_VIEW_DEFAULT_OPTION">
<help
key="Menu_Item:_Password_Reset"
/>
<message>
<![CDATA[COM_USERS_RESET_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>