first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-06-08 17:09:23 -04:00
commit df3a033196
17887 changed files with 8637778 additions and 0 deletions
@@ -0,0 +1,146 @@
<?php
/**
* @file classes/user/form/APIProfileForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class APIProfileForm
*
* @ingroup user_form
*
* @brief Form to edit user's API key settings.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\notification\NotificationManager;
use APP\template\TemplateManager;
use Firebase\JWT\JWT;
use PKP\config\Config;
use PKP\notification\PKPNotification;
use PKP\user\User;
class APIProfileForm extends BaseProfileForm
{
public const API_KEY_NEW = 1;
public const API_KEY_DELETE = 0;
/**
* Constructor.
*
* @param User $user
*/
public function __construct($user)
{
parent::__construct('user/apiProfileForm.tpl', $user);
}
/**
* @copydoc Form::initData()
*/
public function initData()
{
$user = $this->getUser();
$this->setData('apiKeyEnabled', (bool) $user->getData('apiKeyEnabled'));
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars([
'apiKeyEnabled',
'generateApiKey',
'apiKeyAction',
]);
}
/**
* Fetch the form to edit user's API key settings.
*
* @see BaseProfileForm::fetch
*
* @param null|mixed $template
*
* @return string JSON-encoded form contents.
*/
public function fetch($request, $template = null, $display = false)
{
$user = $request->getUser();
$secret = Config::getVar('security', 'api_key_secret', '');
$templateMgr = TemplateManager::getManager($request);
if ($secret === '') {
$this->handleOnMissingAPISecret($templateMgr, $user);
return parent::fetch($request, $template, $display);
}
$templateMgr->assign(
$user->getData('apiKey') ? [
'apiKey' => JWT::encode($user->getData('apiKey'), $secret, 'HS256'),
'apiKeyAction' => self::API_KEY_DELETE,
'apiKeyActionTextKey' => 'user.apiKey.remove',
] : [
'apiKeyAction' => self::API_KEY_NEW,
'apiKeyActionTextKey' => 'user.apiKey.generate',
]
);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$request = Application::get()->getRequest();
$user = $request->getUser();
$templateMgr = TemplateManager::getManager($request);
if (Config::getVar('security', 'api_key_secret', '') === '') {
$this->handleOnMissingAPISecret($templateMgr, $user);
parent::execute(...$functionArgs);
}
$apiKeyAction = (int)$this->getData('apiKeyAction');
$user->setData('apiKeyEnabled', $apiKeyAction === self::API_KEY_NEW ? 1 : null);
$user->setData('apiKey', $apiKeyAction === self::API_KEY_NEW ? sha1(time()) : null);
$this->setData('apiKeyAction', (int)!$apiKeyAction);
parent::execute(...$functionArgs);
}
/**
* Handle on missing API secret
*
*
*/
protected function handleOnMissingAPISecret(TemplateManager $templateMgr, User $user): void
{
$notificationManager = new NotificationManager();
$notificationManager->createTrivialNotification(
$user->getId(),
PKPNotification::NOTIFICATION_TYPE_WARNING,
[
'contents' => __('user.apiKey.secretRequired'),
]
);
$templateMgr->assign([
'apiSecretMissing' => true,
]);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\APIProfileForm', '\APIProfileForm');
}
@@ -0,0 +1,81 @@
<?php
/**
* @file classes/user/form/BaseProfileForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class BaseProfileForm
*
* @ingroup user_form
*
* @brief Base form to edit an aspect of user profile.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\facades\Repo;
use PKP\form\Form;
use PKP\session\SessionManager;
use PKP\user\User;
abstract class BaseProfileForm extends Form
{
/** @var User */
public $_user;
/**
* Constructor.
*
* @param string $template
* @param User $user
*/
public function __construct($template, $user)
{
parent::__construct($template);
$this->_user = $user;
assert(isset($user));
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
}
/**
* Get the user associated with this profile
*/
public function getUser()
{
return $this->_user;
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
parent::execute(...$functionArgs);
$request = Application::get()->getRequest();
$user = $request->getUser();
Repo::user()->edit($user);
if ($functionArgs['emailUpdated'] ?? false) {
$sessionManager = SessionManager::getManager();
$session = $sessionManager->getUserSession();
if ($session->getSessionVar('email')) {
$session->setSessionVar('email', $user->getEmail());
}
$sessionManager->invalidateSessions($user->getId(), $sessionManager->getUserSession()->getId());
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\BaseProfileForm', '\BaseProfileForm');
}
@@ -0,0 +1,118 @@
<?php
/**
* @file classes/user/form/ChangePasswordForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class ChangePasswordForm
*
* @ingroup user_form
*
* @brief Form to change a user's password.
*/
namespace PKP\user\form;
use APP\facades\Repo;
use APP\template\TemplateManager;
use PKP\form\Form;
use PKP\security\Validation;
use PKP\site\Site;
use PKP\user\User;
class ChangePasswordForm extends Form
{
/** @var User */
public $_user;
/** @var Site */
public $_site;
/**
* Constructor.
*
* @param User $user
* @param Site $site
*/
public function __construct($user, $site)
{
parent::__construct('user/changePassword.tpl');
$this->_user = $user;
$this->_site = $site;
// Validation checks for this form
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'oldPassword', 'required', 'user.profile.form.oldPasswordInvalid', function ($password) use ($user) {
return Validation::checkCredentials($user->getUsername(), $password);
}));
$this->addCheck(new \PKP\form\validation\FormValidatorLength($this, 'password', 'required', 'user.register.form.passwordLengthRestriction', '>=', $site->getMinPasswordLength()));
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'password', 'required', 'user.profile.form.newPasswordRequired'));
$form = $this;
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'password', 'required', 'user.register.form.passwordsDoNotMatch', function ($password) use ($form) {
return $password == $form->getData('password2');
}));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'password', 'required', 'user.profile.form.passwordSameAsOld', function ($password) use ($form) {
return $password != $form->getData('oldPassword');
}));
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
}
/**
* Get the user associated with this password
*/
public function getUser()
{
return $this->_user;
}
/**
* Get the site
*/
public function getSite()
{
return $this->_site;
}
/**
* @copydoc Form::fetch
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager();
$templateMgr->assign([
'minPasswordLength' => $this->getSite()->getMinPasswordLength(),
'username' => $this->getUser()->getUsername(),
]);
return parent::fetch($request, $template, $display);
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars(['oldPassword', 'password', 'password2']);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$user = $this->getUser();
$user->setPassword(Validation::encryptCredentials($user->getUsername(), $this->getData('password')));
parent::execute(...$functionArgs);
Repo::user()->edit($user);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\ChangePasswordForm', '\ChangePasswordForm');
}
+143
View File
@@ -0,0 +1,143 @@
<?php
/**
* @file classes/user/form/ContactForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class ContactForm
*
* @ingroup user_form
*
* @brief Form to edit user's contact information.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\facades\Repo;
use APP\template\TemplateManager;
use PKP\facades\Locale;
use PKP\user\User;
class ContactForm extends BaseProfileForm
{
/**
* Constructor.
*
* @param User $user
*/
public function __construct($user)
{
parent::__construct('user/contactForm.tpl', $user);
// Validation checks for this form
$this->addCheck(new \PKP\form\validation\FormValidatorEmail($this, 'email', 'required', 'user.profile.form.emailRequired'));
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'country', 'required', 'user.profile.form.countryRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom(
$this,
'email',
'required',
'user.register.form.emailExists',
function (string $email, int $userId) {
if ($user = Repo::user()->getByEmail($email, true)) {
return (int)$user->getId() === $userId;
}
return true;
},
[(int)$user->getId()]
));
}
/**
* @copydoc BaseProfileForm::fetch
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$site = $request->getSite();
$countries = [];
foreach (Locale::getCountries() as $country) {
$countries[$country->getAlpha2()] = $country->getLocalName();
}
asort($countries);
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'countries' => $countries,
'availableLocales' => $site->getSupportedLocaleNames(),
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc BaseProfileForm::initData()
*/
public function initData()
{
$user = $this->getUser();
$this->_data = [
'country' => $user->getCountry(),
'email' => $user->getEmail(),
'phone' => $user->getPhone(),
'signature' => $user->getSignature(null), // Localized
'mailingAddress' => $user->getMailingAddress(),
'affiliation' => $user->getAffiliation(null), // Localized
'locales' => $user->getLocales(),
];
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars([
'country', 'email', 'signature', 'phone', 'mailingAddress', 'affiliation', 'locales',
]);
if ($this->getData('locales') == null || !is_array($this->getData('locales'))) {
$this->setData('locales', []);
}
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$user = $this->getUser();
$functionArgs['emailUpdated'] = $user->getEmail() !== $this->getData('email');
$user->setCountry($this->getData('country'));
$user->setEmail($this->getData('email'));
$user->setSignature($this->getData('signature'), null); // Localized
$user->setPhone($this->getData('phone'));
$user->setMailingAddress($this->getData('mailingAddress'));
$user->setAffiliation($this->getData('affiliation'), null); // Localized
$request = Application::get()->getRequest();
$site = $request->getSite();
$availableLocales = $site->getSupportedLocales();
$locales = [];
foreach ($this->getData('locales') as $locale) {
if (Locale::isLocaleValid($locale) && in_array($locale, $availableLocales)) {
array_push($locales, $locale);
}
}
$user->setLocales($locales);
parent::execute(...$functionArgs);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\ContactForm', '\ContactForm');
}
+114
View File
@@ -0,0 +1,114 @@
<?php
/**
* @file classes/user/form/IdentityForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class IdentityForm
*
* @ingroup user_form
*
* @brief Form to edit user's identity information.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\template\TemplateManager;
use PKP\user\User;
class IdentityForm extends BaseProfileForm
{
/**
* Constructor.
*
* @param User $user
*/
public function __construct($user)
{
parent::__construct('user/identityForm.tpl', $user);
// the users register for the site, thus
// the site primary locale is the required default locale
$site = Application::get()->getRequest()->getSite();
$this->addSupportedFormLocale($site->getPrimaryLocale());
// Validation checks for this form
$form = $this;
$this->addCheck(new \PKP\form\validation\FormValidatorLocale($this, 'givenName', 'required', 'user.profile.form.givenNameRequired', $site->getPrimaryLocale()));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'familyName', 'optional', 'user.profile.form.givenNameRequired.locale', function ($familyName) use ($form) {
$givenNames = $form->getData('givenName');
foreach ($familyName as $locale => $value) {
if (!empty($value) && empty($givenNames[$locale])) {
return false;
}
}
return true;
}));
}
/**
* @copydoc BaseProfileForm::fetch
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$user = $this->getUser();
$templateMgr->assign([
'username' => $user->getUsername(),
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc BaseProfileForm::initData()
*/
public function initData()
{
$user = $this->getUser();
$this->_data = [
'givenName' => $user->getGivenName(null),
'familyName' => $user->getFamilyName(null),
'preferredPublicName' => $user->getPreferredPublicName(null),
];
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars([
'givenName', 'familyName', 'preferredPublicName',
]);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$request = Application::get()->getRequest();
$user = $request->getUser();
$user->setGivenName($this->getData('givenName'), null);
$user->setFamilyName($this->getData('familyName'), null);
$user->setPreferredPublicName($this->getData('preferredPublicName'), null);
parent::execute(...$functionArgs);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\IdentityForm', '\IdentityForm');
}
@@ -0,0 +1,94 @@
<?php
/**
* @file classes/user/form/LoginChangePasswordForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class LoginChangePasswordForm
*
* @ingroup user_form
*
* @brief Form to change a user's password in order to login.
*/
namespace PKP\user\form;
use APP\facades\Repo;
use APP\template\TemplateManager;
use PKP\form\Form;
use PKP\security\Validation;
use PKP\site\Site;
class LoginChangePasswordForm extends Form
{
/**
* Constructor.
*
* @param Site $site
*/
public function __construct($site)
{
parent::__construct('user/loginChangePassword.tpl');
// Validation checks for this form
$form = $this;
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'oldPassword', 'required', 'user.profile.form.oldPasswordInvalid', function ($password) use ($form) {
return Validation::checkCredentials($form->getData('username'), $password);
}));
$this->addCheck(new \PKP\form\validation\FormValidatorLength($this, 'password', 'required', 'user.register.form.passwordLengthRestriction', '>=', $site->getMinPasswordLength()));
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'password', 'required', 'user.profile.form.newPasswordRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'password', 'required', 'user.register.form.passwordsDoNotMatch', function ($password) use ($form) {
return $password == $form->getData('password2');
}));
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
}
/**
* @copydoc Form::display
*
* @param null|mixed $request
* @param null|mixed $template
*/
public function display($request = null, $template = null)
{
$templateMgr = TemplateManager::getManager($request);
$site = $request->getSite();
$templateMgr->assign('minPasswordLength', $site->getMinPasswordLength());
parent::display($request, $template);
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars(['username', 'oldPassword', 'password', 'password2']);
}
/**
* @copydoc Form::execute()
*
* @return bool success
*/
public function execute(...$functionArgs)
{
$user = Repo::user()->getByUsername($this->getData('username'), false);
parent::execute(...$functionArgs);
if ($user != null) {
$user->setPassword(Validation::encryptCredentials($user->getUsername(), $this->getData('password')));
$user->setMustChangePassword(0);
Repo::user()->edit($user);
return true;
} else {
return false;
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\LoginChangePasswordForm', '\LoginChangePasswordForm');
}
@@ -0,0 +1,184 @@
<?php
/**
* @file classes/user/form/PublicProfileForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PublicProfileForm
*
* @ingroup user_form
*
* @brief Form to edit user's public profile.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\facades\Repo;
use APP\file\PublicFileManager;
use APP\template\TemplateManager;
use PKP\core\Core;
use PKP\user\User;
class PublicProfileForm extends BaseProfileForm
{
public const PROFILE_IMAGE_MAX_WIDTH = 150;
public const PROFILE_IMAGE_MAX_HEIGHT = 150;
/**
* Constructor.
*
* @param User $user
*/
public function __construct($user)
{
parent::__construct('user/publicProfileForm.tpl', $user);
// Validation checks for this form
$this->addCheck(new \PKP\form\validation\FormValidatorORCID($this, 'orcid', 'optional', 'user.orcid.orcidInvalid'));
$this->addCheck(new \PKP\form\validation\FormValidatorUrl($this, 'userUrl', 'optional', 'user.profile.form.urlInvalid'));
}
/**
* @copydoc BaseProfileForm::initData()
*/
public function initData()
{
$user = $this->getUser();
$this->_data = [
'orcid' => $user->getOrcid(),
'userUrl' => $user->getUrl(),
'biography' => $user->getBiography(null), // Localized
];
parent::initData();
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars([
'orcid', 'userUrl', 'biography',
]);
}
/**
* Upload a profile image.
*
* @return bool True iff success.
*/
public function uploadProfileImage()
{
if (!Application::get()->getRequest()->checkCSRF()) {
throw new \Exception('CSRF mismatch!');
}
$publicFileManager = new PublicFileManager();
$user = $this->getUser();
$type = $publicFileManager->getUploadedFileType('uploadedFile');
$extension = $publicFileManager->getImageExtension($type);
if (!$extension) {
return false;
}
$uploadName = 'profileImage-' . (int) $user->getId() . $extension;
if (!$publicFileManager->uploadSiteFile('uploadedFile', $uploadName)) {
return false;
}
$filePath = $publicFileManager->getSiteFilesPath();
[$width, $height] = getimagesize($filePath . '/' . $uploadName);
if ($width > self::PROFILE_IMAGE_MAX_WIDTH || $height > self::PROFILE_IMAGE_MAX_HEIGHT || $width <= 0 || $height <= 0) {
$userSetting = null;
$user->setData('profileImage', $userSetting);
Repo::user()->edit($user, ['profileImage']);
$publicFileManager->removeSiteFile($filePath);
return false;
}
$user->setData('profileImage', [
'name' => $publicFileManager->getUploadedFileName('uploadedFile'),
'uploadName' => $uploadName,
'width' => $width,
'height' => $height,
'dateUploaded' => Core::getCurrentDate(),
]);
Repo::user()->edit($user, ['profileImage']);
return true;
}
/**
* Delete a profile image.
*
* @return bool True iff success.
*/
public function deleteProfileImage()
{
if (!Application::get()->getRequest()->checkCSRF()) {
throw new \Exception('CSRF mismatch!');
}
$user = $this->getUser();
$profileImage = $user->getData('profileImage');
if (!$profileImage) {
return false;
}
$publicFileManager = new PublicFileManager();
if ($publicFileManager->removeSiteFile($profileImage['uploadName'])) {
$user->setData('profileImage', null);
Repo::user()->edit($user, ['profileImage']);
return true;
} else {
return false;
}
}
/**
* @copydoc BaseProfileForm::fetch
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$publicFileManager = new PublicFileManager();
$templateMgr->assign([
'profileImage' => $request->getUser()->getData('profileImage'),
'profileImageMaxWidth' => self::PROFILE_IMAGE_MAX_WIDTH,
'profileImageMaxHeight' => self::PROFILE_IMAGE_MAX_HEIGHT,
'publicSiteFilesPath' => $publicFileManager->getSiteFilesPath(),
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$request = Application::get()->getRequest();
$user = $request->getUser();
$user->setOrcid($this->getData('orcid'));
$user->setUrl($this->getData('userUrl'));
$user->setBiography($this->getData('biography'), null); // Localized
parent::execute(...$functionArgs);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\PublicProfileForm', '\PublicProfileForm');
}
@@ -0,0 +1,313 @@
<?php
/**
* @defgroup user_form User Forms
*/
/**
* @file classes/user/form/RegistrationForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class RegistrationForm
*
* @ingroup user_form
*
* @brief Form for user registration.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\facades\Repo;
use APP\notification\form\NotificationSettingsForm;
use APP\template\TemplateManager;
use PKP\config\Config;
use PKP\core\Core;
use PKP\db\DAORegistry;
use PKP\facades\Locale;
use PKP\form\Form;
use PKP\security\Role;
use PKP\security\Validation;
use PKP\session\SessionManager;
use PKP\site\Site;
use PKP\user\InterestManager;
use PKP\user\User;
class RegistrationForm extends Form
{
/** @var User The user object being created (available to hooks during registrationform::execute hook) */
public $user;
/** @var bool user is already registered with another context */
public $existingUser;
/** @var bool whether or not captcha is enabled for this form */
public $captchaEnabled;
/**
* Constructor.
*
* @param Site $site
*/
public function __construct($site)
{
parent::__construct('frontend/pages/userRegister.tpl');
// Validation checks for this form
$form = $this;
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'username', 'required', 'user.register.form.usernameExists', [Repo::user(), 'getByUsername'], [true], true));
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'username', 'required', 'user.profile.form.usernameRequired'));
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'password', 'required', 'user.profile.form.passwordRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorUsername($this, 'username', 'required', 'user.register.form.usernameAlphaNumeric'));
$this->addCheck(new \PKP\form\validation\FormValidatorLength($this, 'password', 'required', 'user.register.form.passwordLengthRestriction', '>=', $site->getMinPasswordLength()));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'password', 'required', 'user.register.form.passwordsDoNotMatch', fn ($password) => $password == $form->getData('password2')));
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'givenName', 'required', 'user.profile.form.givenNameRequired'));
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'country', 'required', 'user.profile.form.countryRequired'));
// Email checks
$this->addCheck(new \PKP\form\validation\FormValidatorEmail($this, 'email', 'required', 'user.profile.form.emailRequired'));
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'email', 'required', 'user.register.form.emailExists', [Repo::user(), 'getByEmail'], [true], true));
$this->captchaEnabled = Config::getVar('captcha', 'captcha_on_register') && Config::getVar('captcha', 'recaptcha');
if ($this->captchaEnabled) {
$request = Application::get()->getRequest();
$this->addCheck(new \PKP\form\validation\FormValidatorReCaptcha($this, $request->getRemoteAddr(), 'common.captcha.error.invalid-input-response', $request->getServerHost()));
}
$context = Application::get()->getRequest()->getContext();
if ($context && $context->getData('privacyStatement')) {
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'privacyConsent', 'required', 'user.profile.form.privacyConsentRequired'));
}
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
}
/**
* @copydoc Form::fetch()
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$site = $request->getSite();
if ($this->captchaEnabled) {
$templateMgr->assign('recaptchaPublicKey', Config::getVar('captcha', 'recaptcha_public_key'));
}
$countries = [];
foreach (Locale::getCountries() as $country) {
$countries[$country->getAlpha2()] = $country->getLocalName();
}
asort($countries);
$templateMgr->assign('countries', $countries);
$userFormHelper = new UserFormHelper();
$userFormHelper->assignRoleContent($templateMgr, $request);
$templateMgr->assign([
'source' => $request->getUserVar('source'),
'minPasswordLength' => $site->getMinPasswordLength(),
'enableSiteWidePrivacyStatement' => Config::getVar('general', 'sitewide_privacy_statement'),
'siteWidePrivacyStatement' => $site->getData('privacyStatement'),
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::initData()
*/
public function initData()
{
$this->_data = [
'locales' => [],
'userGroupIds' => [],
];
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars([
'username',
'password',
'password2',
'givenName',
'familyName',
'affiliation',
'email',
'country',
'interests',
'emailConsent',
'privacyConsent',
'readerGroup',
'reviewerGroup',
]);
if ($this->captchaEnabled) {
$this->readUserVars([
'g-recaptcha-response',
]);
}
// Collect the specified user group IDs into a single piece of data
$this->setData('userGroupIds', array_merge(
array_keys((array) $this->getData('readerGroup')),
array_keys((array) $this->getData('reviewerGroup'))
));
}
/**
* @copydoc Form::validate()
*/
public function validate($callHooks = true)
{
$request = Application::get()->getRequest();
// Ensure the consent checkbox has been completed for the site and any user
// group sign-ups if we're in the site-wide registration form
if (!$request->getContext()) {
if ($request->getSite()->getData('privacyStatement')) {
$privacyConsent = $this->getData('privacyConsent');
if (!is_array($privacyConsent) || !array_key_exists(Application::CONTEXT_ID_NONE, $privacyConsent)) {
$this->addError('privacyConsent[' . Application::CONTEXT_ID_NONE . ']', __('user.register.form.missingSiteConsent'));
}
}
if (!Config::getVar('general', 'sitewide_privacy_statement')) {
$contextIds = [];
foreach ($this->getData('userGroupIds') as $userGroupId) {
$userGroup = Repo::userGroup()->get($userGroupId);
$contextIds[] = $userGroup->getContextId();
}
$contextIds = array_unique($contextIds);
if (!empty($contextIds)) {
$contextDao = Application::getContextDao();
$privacyConsent = (array) $this->getData('privacyConsent');
foreach ($contextIds as $contextId) {
$context = $contextDao->getById($contextId);
if ($context->getData('privacyStatement') && !array_key_exists($contextId, $privacyConsent)) {
$this->addError('privacyConsent[' . $contextId . ']', __('user.register.form.missingContextConsent'));
break;
}
}
}
}
}
return parent::validate($callHooks);
}
/**
* Register a new user.
*
* @return int|null User ID, or false on failure
*/
public function execute(...$functionArgs)
{
$requireValidation = Config::getVar('email', 'require_validation');
// New user
$this->user = $user = Repo::user()->newDataObject();
$user->setUsername($this->getData('username'));
// The multilingual user data (givenName, familyName and affiliation) will be saved
// in the current UI locale and copied in the site's primary locale too
$request = Application::get()->getRequest();
$site = $request->getSite();
$sitePrimaryLocale = $site->getPrimaryLocale();
$currentLocale = Locale::getLocale();
// Set the base user fields (name, etc.)
$user->setGivenName($this->getData('givenName'), $currentLocale);
$user->setFamilyName($this->getData('familyName'), $currentLocale);
$user->setEmail($this->getData('email'));
$user->setCountry($this->getData('country'));
$user->setAffiliation($this->getData('affiliation'), $currentLocale);
if ($sitePrimaryLocale != $currentLocale) {
$user->setGivenName($this->getData('givenName'), $sitePrimaryLocale);
$user->setFamilyName($this->getData('familyName'), $sitePrimaryLocale);
$user->setAffiliation($this->getData('affiliation'), $sitePrimaryLocale);
}
$user->setDateRegistered(Core::getCurrentDate());
$user->setInlineHelp(1); // default new users to having inline help visible.
$user->setPassword(Validation::encryptCredentials($this->getData('username'), $this->getData('password')));
if ($requireValidation) {
// The account should be created in a disabled
// state.
$user->setDisabled(true);
$user->setDisabledReason(__('user.login.accountNotValidated', ['email' => $this->getData('email')]));
}
parent::execute(...$functionArgs);
Repo::user()->add($user);
$userId = $user->getId();
if (!$userId) {
return false;
}
// Associate the new user with the existing session
$sessionManager = SessionManager::getManager();
$session = $sessionManager->getUserSession();
$session->setSessionVar('username', $user->getUsername());
// Save the selected roles or assign the Reader role if none selected
if ($request->getContext() && !$this->getData('reviewerGroup')) {
$defaultReaderGroup = Repo::userGroup()->getByRoleIds([Role::ROLE_ID_READER], $request->getContext()->getId(), true)->first();
if ($defaultReaderGroup) {
Repo::userGroup()->assignUserToGroup($user->getId(), $defaultReaderGroup->getId(), $request->getContext()->getId());
}
} else {
$userFormHelper = new UserFormHelper();
$userFormHelper->saveRoleContent($this, $user);
}
// Save the email notification preference
if ($request->getContext() && !$this->getData('emailConsent')) {
// Get the public notification types
$notificationSettingsForm = new NotificationSettingsForm();
$notificationCategories = $notificationSettingsForm->getNotificationSettingCategories($request->getContext());
foreach ($notificationCategories as $notificationCategory) {
if ($notificationCategory['categoryKey'] === 'notification.type.public') {
$publicNotifications = $notificationCategory['settings'];
}
}
if (isset($publicNotifications)) {
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); /** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
$notificationSubscriptionSettingsDao->updateNotificationSubscriptionSettings(
'blocked_emailed_notification',
$publicNotifications,
$user->getId(),
$request->getContext()->getId()
);
}
}
// Insert the user interests
$interestManager = new InterestManager();
$interestManager->setInterestsForUser($user, $this->getData('interests'));
return $userId;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\RegistrationForm', '\RegistrationForm');
}
@@ -0,0 +1,160 @@
<?php
/**
* @file classes/user/form/ResetPasswordForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class ResetPasswordForm
*
* @ingroup user_form
*
* @brief Form to reset a user's password.
*/
namespace PKP\user\form;
use APP\facades\Repo;
use APP\template\TemplateManager;
use PKP\form\Form;
use PKP\form\validation\FormValidator;
use PKP\form\validation\FormValidatorCSRF;
use PKP\form\validation\FormValidatorCustom;
use PKP\form\validation\FormValidatorLength;
use PKP\form\validation\FormValidatorPost;
use PKP\security\Validation;
use PKP\session\SessionManager;
class ResetPasswordForm extends Form
{
/** @var object */
protected $_user;
/** @var object */
protected $_site;
/** @var string */
protected $_hash;
/**
* Constructor.
*/
public function __construct($user, $site, $hash)
{
parent::__construct('user/userPasswordReset.tpl');
$this->_user = $user;
$this->_site = $site;
$this->_hash = $hash;
$this->addCheck(new FormValidatorLength($this, 'password', 'required', 'user.register.form.passwordLengthRestriction', '>=', $site->getMinPasswordLength()));
$this->addCheck(new FormValidator($this, 'password', 'required', 'user.profile.form.newPasswordRequired'));
$form = $this;
$this->addCheck(new FormValidatorCustom($this, 'password', 'required', 'user.register.form.passwordsDoNotMatch', function ($password) use ($form) {
return $password == $form->getData('password2');
}));
$this->addCheck(new FormValidatorPost($this));
$this->addCheck(new FormValidatorCSRF($this));
}
/**
* Get the user associated with this password
*/
public function getUser()
{
return $this->_user;
}
/**
* Get the site
*/
public function getSite()
{
return $this->_site;
}
/**
* Get the password reset hash
*/
public function getHash()
{
return $this->_hash;
}
/**
* @copydoc Form::display
*
* @param null|mixed $request
* @param null|mixed $template
*/
public function display($request = null, $template = null)
{
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'minPasswordLength' => $this->getSite()->getMinPasswordLength(),
'username' => $this->getUser()->getUsername(),
'hash' => $this->getHash(),
]);
parent::display($request, $template);
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$this->readUserVars(['username', 'hash', 'password', 'password2']);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$user = $this->getUser();
$user->setPassword(Validation::encryptCredentials($user->getUsername(), $this->getData('password')));
$user->setMustChangePassword(0);
SessionManager::getManager()->invalidateSessions($user->getId());
Repo::user()->edit($user);
parent::execute(...$functionArgs);
return true;
}
/**
* Validate the password reset hash
*/
public function validatePasswordResetHash()
{
if (Validation::verifyPasswordResetHash($this->getUser()->getId(), $this->getHash())) {
return true;
}
return false;
}
/**
* Display the error page when passed invalid password reset hash
*
* @param null|mixed $template
*/
public function displayInvalidHashErrorMessage($request, $template = null)
{
$this->setTemplate('frontend/pages/error.tpl');
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'errorMsg' => 'user.login.lostPassword.invalidHash',
'backLink' => $request->url(null, null, 'lostPassword'),
'backLinkLabel' => 'user.login.resetPassword',
]);
parent::display($request, $template);
}
}
+110
View File
@@ -0,0 +1,110 @@
<?php
/**
* @file classes/user/form/RolesForm.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class RolesForm
*
* @ingroup user_form
*
* @brief Form to edit the roles area of the user profile.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\facades\Repo;
use APP\template\TemplateManager;
use PKP\user\InterestManager;
use PKP\user\User;
class RolesForm extends BaseProfileForm
{
/**
* Constructor.
*
* @param User $user
*/
public function __construct($user)
{
parent::__construct('user/rolesForm.tpl', $user);
}
/**
* @copydoc BaseProfileForm::fetch
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$templateMgr = TemplateManager::getManager($request);
$userGroupIds = Repo::userGroup()->getCollector()
->filterByUserIds([$request->getUser()->getId()])
->getIds()
->toArray();
$templateMgr->assign('userGroupIds', $userGroupIds);
$userFormHelper = new UserFormHelper();
$userFormHelper->assignRoleContent($templateMgr, $request);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc BaseProfileForm::initData()
*/
public function initData()
{
$interestManager = new InterestManager();
$user = $this->getUser();
$this->_data = [
'interests' => $interestManager->getInterestsForUser($user),
];
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
parent::readInputData();
$this->readUserVars([
'authorGroup',
'reviewerGroup',
'readerGroup',
'interests',
]);
}
/**
* @copydoc Form::execute()
*/
public function execute(...$functionArgs)
{
$request = Application::get()->getRequest();
$user = $request->getUser();
// Save the roles
$userFormHelper = new UserFormHelper();
$userFormHelper->saveRoleContent($this, $user);
// Insert the user interests
$interestManager = new InterestManager();
$interestManager->setInterestsForUser($user, $this->getData('interests'));
parent::execute(...$functionArgs);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\RolesForm', '\RolesForm');
}
@@ -0,0 +1,128 @@
<?php
/**
* @file classes/user/form/UserFormHelper.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class UserFormHelper
*
* @ingroup user_form
*
* @brief Helper functions for shared user form concerns.
*/
namespace PKP\user\form;
use APP\core\Application;
use APP\facades\Repo;
use PKP\core\PKPRequest;
use PKP\form\Form;
use PKP\security\Role;
use PKP\template\PKPTemplateManager;
use PKP\user\User;
class UserFormHelper
{
/**
* Constructor
*/
public function __construct()
{
}
/**
* Assign role selection content to the template manager.
*
* @param PKPTemplateManager $templateMgr
* @param PKPRequest $request
*/
public function assignRoleContent($templateMgr, $request)
{
// Need the count in order to determine whether to display
// extras-on-demand for role selection in other contexts.
$contextDao = Application::getContextDAO();
$contexts = $contextDao->getAll(true)->toArray();
$contextsWithUserRegistration = [];
foreach ($contexts as $context) {
if (!$context->getData('disableUserReg')) {
$contextsWithUserRegistration[] = $context;
}
}
$templateMgr->assign([
'contexts' => $contexts,
'showOtherContexts' => !$request->getContext() || count($contextsWithUserRegistration) > 1,
]);
// Expose potential self-registration user groups to template
$authorUserGroups = $reviewerUserGroups = $readerUserGroups = [];
foreach ($contexts as $context) {
if ($context->getData('disableUserReg')) {
continue;
}
$reviewerUserGroups[$context->getId()] = Repo::userGroup()->getByRoleIds([Role::ROLE_ID_REVIEWER], $context->getId())->toArray();
$authorUserGroups[$context->getId()] = Repo::userGroup()->getByRoleIds([Role::ROLE_ID_AUTHOR], $context->getId())->toArray();
$readerUserGroups[$context->getId()] = Repo::userGroup()->getByRoleIds([Role::ROLE_ID_READER], $context->getId())->toArray();
}
$templateMgr->assign([
'reviewerUserGroups' => $reviewerUserGroups,
'authorUserGroups' => $authorUserGroups,
'readerUserGroups' => $readerUserGroups,
]);
}
/**
* Save role elements of an executed user form.
*
* @param Form $form The form from which to fetch elements
* @param User $user The current user
*/
public function saveRoleContent($form, $user)
{
$contextDao = Application::getContextDAO();
$contexts = $contextDao->getAll(true);
while ($context = $contexts->next()) {
if ($context->getData('disableUserReg')) {
continue;
}
foreach ([
[
'roleId' => Role::ROLE_ID_REVIEWER,
'formElement' => 'reviewerGroup'
],
[
'roleId' => Role::ROLE_ID_AUTHOR,
'formElement' => 'authorGroup'
],
[
'roleId' => Role::ROLE_ID_READER,
'formElement' => 'readerGroup'
],
] as $groupData) {
$groupFormData = (array) $form->getData($groupData['formElement']);
$userGroups = Repo::userGroup()->getByRoleIds([$groupData['roleId']], $context->getId());
foreach ($userGroups as $userGroup) {
if (!$userGroup->getPermitSelfRegistration()) {
continue;
}
$groupId = $userGroup->getId();
$inGroup = Repo::userGroup()->userInGroup($user->getId(), $groupId);
if (!$inGroup && array_key_exists($groupId, $groupFormData)) {
Repo::userGroup()->assignUserToGroup($user->getId(), $groupId);
} elseif ($inGroup && !array_key_exists($groupId, $groupFormData)) {
Repo::userGroup()->removeUserFromGroup($user->getId(), $groupId, $context->getId());
}
}
}
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\user\form\UserFormHelper', '\UserFormHelper');
}