| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- <?php
- /**
- * Login
- *
- * Copyright 2010 by Jason Coward <jason@modxcms.com> and Shaun McCormick
- * <shaun@modxcms.com>
- *
- * Login is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option) any
- * later version.
- *
- * Login is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * Login; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @package login
- */
- /**
- * Handle register form
- *
- * @package login
- * @subpackage processors
- */
- class LoginRegisterProcessor extends LoginProcessor {
- /** @var modUser $user */
- public $user;
- /** @var modUserProfile $profile */
- public $profile;
- /** @var array $userGroups */
- public $userGroups = array();
- public $persistParams = array();
- public $live = true;
- /**
- * @return mixed
- */
- public function process() {
- $this->cleanseFields();
- /* create user and profile */
- $this->user = $this->modx->newObject('modUser');
- $this->profile = $this->modx->newObject('modUserProfile');
- if ($this->controller->getProperty('useExtended',true,'isset')) {
- $this->setExtended();
- }
- $this->setUserFields();
- /* save user */
- if ($this->live) {
- if (!$this->user->save()) {
- $this->modx->log(modX::LOG_LEVEL_ERROR,'[Login] Could not save newly registered user: '.$this->user->get('id').' with username: '.$this->user->get('username'));
- return $this->modx->lexicon('register.user_err_save');
- }
- }
- $this->preparePersistentParameters();
- /* send activation email (if chosen) */
- $email = $this->profile->get('email');
- $activation = $this->controller->getProperty('activation',true,'isset');
- $activationResourceId = $this->controller->getProperty('activationResourceId','','isset');
- $moderated = $this->checkForModeration();
- if ($activation && !empty($email) && !empty($activationResourceId) && !$moderated) {
- $this->sendActivationEmail();
- } else if (!$moderated) {
- $this->user->set('active',true);
- if ($this->live) {
- $this->user->save();
- }
- }
- $this->runPostHooks();
- if ($this->controller->getProperty('autoLogin') == true && $this->controller->getProperty('activation') == false) {
- $this->autoLogin();
- }
- $this->checkForModerationRedirect();
- $this->checkForRegisteredRedirect();
- $successMsg = $this->controller->getProperty('successMsg','');
- $this->modx->toPlaceholder('error.message',$successMsg);
- return true;
- }
- /**
- * Remove any fields used for anti-spam, submission or moderation from the submission returns
- * @return void
- */
- public function cleanseFields() {
- $this->dictionary->remove('nospam');
- $this->dictionary->remove('blank');
- $submitVar = $this->controller->getProperty('submitVar');
- if (!empty($submitVar)) {
- $this->dictionary->remove($submitVar);
- }
- }
- /**
- * If wanted, set extra values in the form to profile extended field
- * @return void
- */
- public function setExtended() {
- /* first cut out regular and unwanted fields */
- $excludeExtended = $this->controller->getProperty('excludeExtended','');
- $excludeExtended = explode(',',$excludeExtended);
- $profileFields = $this->profile->toArray();
- $userFields = $this->user->toArray();
- $extended = array();
- $fields = $this->dictionary->toArray();
- $fields = $this->filterAllowedFields($fields);
- $userGroupField = $this->controller->getProperty('usergroupsField','');
- foreach ($fields as $field => $value) {
- if (!isset($profileFields[$field])
- && !isset($userFields[$field])
- && $field != 'password_confirm'
- && $field != 'passwordconfirm'
- && $field != $userGroupField
- && !in_array($field,$excludeExtended)
- ) {
- $extended[$field] = $value;
- }
- }
- /* now set extended data */
- $this->profile->set('extended',$extended);
- }
- /**
- * Setup the user data and create the user/profile objects
- *
- * @return void
- */
- public function setUserFields() {
- $fields = $this->dictionary->toArray();
- /* allow overriding of class key */
- if (empty($fields['class_key'])) $fields['class_key'] = 'modUser';
- $fields = $this->filterAllowedFields($fields);
- /* set user and profile */
- $this->user->fromArray($fields);
- $this->user->set('username',$fields[$this->controller->getProperty('usernameField','username')]);
- $this->user->set('active',0);
- $version = $this->modx->getVersionData();
- /* 2.1.x+ */
- if (version_compare($version['full_version'],'2.1.0-rc1') >= 0) {
- $this->user->set('password',$fields[$this->controller->getProperty('passwordField','password')]);
- } else { /* 2.0.x */
- $this->user->set('password',md5($fields[$this->controller->getProperty('passwordField','password')]));
- }
- $this->profile->fromArray($fields);
- $this->profile->set('email',$this->dictionary->get($this->controller->getProperty('emailField','email')));
- $this->user->addOne($this->profile,'Profile');
- /* add user groups, if set */
- $userGroupsField = $this->controller->getProperty('usergroupsField','');
- $userGroups = !empty($userGroupsField) && array_key_exists($userGroupsField,$fields) ? $fields[$userGroupsField] : array();
- $this->setUserGroups($userGroups);
- }
- /**
- * Return an array of filtered fields if the allowedFields property is set and prevents setting of certain fields
- * @param array $fields
- * @return array
- */
- public function filterAllowedFields(array $fields = array()) {
- $allowedFields = $this->controller->getProperty('allowedFields','');
- if (!empty($allowedFields)) {
- $allowedFields = is_array($allowedFields) ? $allowedFields : explode(',',$allowedFields);
- $userGroupField = $this->controller->getProperty('usergroupsField','');
- $usernameField = $this->controller->getProperty('usernameField','username');
- $passwordField = $this->controller->getProperty('passwordField','password');
- $emailField = $this->controller->getProperty('emailField','email');
- array_push($allowedFields,$usernameField,$passwordField,'password_confirm',$emailField,'class_key');
- if (!empty($userGroupField)) array_push($allowedFields,$userGroupField);
- $allowedFields = array_unique($allowedFields);
- foreach ($fields as $k => $v) {
- if (!in_array($k,$allowedFields)) unset($fields[$k]);
- }
- }
- return $fields;
- }
- /**
- * If user groups were passed, set them here
- * @param string $userGroups
- * @return array
- */
- public function setUserGroups($userGroups) {
- $added = array();
- /* if $userGroups set in form, override here; otherwise use snippet property */
- $this->userGroups = !empty($userGroups) ? $userGroups : $this->controller->getProperty('usergroups', '');
- if (!empty($this->userGroups)) {
- $this->userGroups = is_array($this->userGroups) ? $this->userGroups : explode(',',$this->userGroups);
- foreach ($this->userGroups as $userGroupMeta) {
- $userGroupMeta = explode(':',$userGroupMeta);
- if (empty($userGroupMeta[0])) continue;
- /* get usergroup */
- $pk = array();
- $pk[intval($userGroupMeta[0]) > 0 ? 'id' : 'name'] = trim($userGroupMeta[0]);
- /** @var modUserGroup $userGroup */
- $userGroup = $this->modx->getObject('modUserGroup',$pk);
- if (!$userGroup) continue;
- /* get role */
- $rolePk = !empty($userGroupMeta[1]) ? $userGroupMeta[1] : 'Member';
- /** @var modUserGroupRole $role */
- $role = $this->modx->getObject('modUserGroupRole',array('name' => $rolePk));
- /* create membership */
- /** @var modUserGroupMember $member */
- $member = $this->modx->newObject('modUserGroupMember');
- $member->set('member',0);
- $member->set('user_group',$userGroup->get('id'));
- if (!empty($role)) {
- $member->set('role',$role->get('id'));
- } else {
- $member->set('role',1);
- }
- $rank = (isset($userGroupMeta[2])) ? $userGroupMeta[2] : 0;
- $member->set('rank', $rank);
- $this->user->addMany($member,'UserGroupMembers');
- $added[] = $userGroup->get('name');
- }
- }
- return $added;
- }
- /**
- * Setup persistent parameters to go through the request cycle
- * @return array
- */
- public function preparePersistentParameters() {
- $this->persistParams = $this->controller->getProperty('persistParams','');
- if (!empty($this->persistParams)) $this->persistParams = $this->modx->fromJSON($this->persistParams);
- if (empty($this->persistParams) || !is_array($this->persistParams)) $this->persistParams = array();
- return $this->persistParams;
- }
- /**
- * Send an activation email to the user with an encrypted username and password hash, to allow for secure
- * activation processes that are not vulnerable to middle-man attacks.
- *
- * @return boolean
- */
- public function sendActivationEmail() {
- $emailProperties = $this->gatherActivationEmailProperties();
- /* send either to user's email or a specified activation email */
- $activationEmail = $this->controller->getProperty('activationEmail',$this->profile->get('email'));
- $subject = $this->controller->getProperty('activationEmailSubject',$this->modx->lexicon('register.activation_email_subject'));
- return $this->login->sendEmail($activationEmail,$this->user->get('username'),$subject,$emailProperties);
- }
- /**
- * Get all the properties for the activation email
- * @return array
- */
- public function gatherActivationEmailProperties() {
- /* generate a password and encode it and the username into the url */
- $pword = $this->modx->user->generatePassword();
- $confirmParams['lp'] = $this->login->base64url_encode($pword);
- $confirmParams['lu'] = $this->login->base64url_encode($this->user->get('username'));
- $confirmParams = array_merge($this->persistParams,$confirmParams);
- /* if using redirectBack param, set here to allow dynamic redirection
- * handling from other forms.
- */
- $redirectBack = $this->modx->getOption('redirectBack',$_REQUEST,$this->controller->getProperty('redirectBack',''));
- if (!empty($redirectBack)) {
- $confirmParams['redirectBack'] = $redirectBack;
- }
- $redirectBackParams = $this->modx->getOption('redirectBackParams',$_REQUEST,$this->controller->getProperty('redirectBackParams',''));
- if (!empty($redirectBackParams)) {
- $confirmParams['redirectBackParams'] = $redirectBackParams;
- }
- /* generate confirmation url */
- if ($this->login->inTestMode) {
- $confirmUrl = $this->modx->makeUrl(1,'',$confirmParams,'full');
- } else {
- $confirmUrl = $this->modx->makeUrl($this->controller->getProperty('activationResourceId',1),'',$confirmParams,'full');
- }
- /* set confirmation email properties */
- $emailTpl = $this->controller->getProperty('activationEmailTpl','lgnActivateEmailTpl');
- $emailTplAlt = $this->controller->getProperty('activationEmailTplAlt','');
- $emailTplType = $this->controller->getProperty('activationEmailTplType','modChunk');
- $emailProperties = $this->user->toArray();
- $emailProperties['confirmUrl'] = $confirmUrl;
- $emailProperties['tpl'] = $emailTpl;
- $emailProperties['tplAlt'] = $emailTplAlt;
- $emailProperties['tplType'] = $emailTplType;
- $emailProperties['password'] = $this->dictionary->get($this->controller->getProperty('passwordField','password'));
- $this->setCachePassword($pword);
- return $emailProperties;
- }
- public function setCachePassword($password) {
- /* now set new password to registry to prevent middleman attacks.
- * Will read from the registry on the confirmation page. */
- $this->modx->getService('registry', 'registry.modRegistry');
- $this->modx->registry->addRegister('login','registry.modFileRegister');
- $this->modx->registry->login->connect();
- $this->modx->registry->login->subscribe('/useractivation/');
- $this->modx->registry->login->send('/useractivation/',array($this->user->get('username') => $password),array(
- 'ttl' => ($this->controller->getProperty('activationttl',180)*60),
- ));
- /* set cachepwd here to prevent re-registration of inactive users */
- $this->user->set('cachepwd',md5($password));
- if ($this->live) {
- $success = $this->user->save();
- } else {
- $success = true;
- }
- if (!$success) {
- $this->modx->log(modX::LOG_LEVEL_ERROR,'[Login] Could not update cachepwd for activation for User: '.$this->user->get('username'));
- }
- return $success;
- }
- /**
- * Check to see if a pre/post hook told Login to set the user to moderated (inactive) status
- * @return boolean
- */
- public function checkForModeration() {
- $moderate = $this->dictionary->get('register.moderate');
- return !empty($moderate);
- }
- /**
- * Run any post-registration hooks
- *
- * @return void
- */
- public function runPostHooks() {
- $postHooks = $this->controller->getProperty('postHooks','');
- $this->controller->loadHooks('postHooks');
- $fields = $this->dictionary->toArray();
- $fields['register.user'] =& $this->user;
- $fields['register.profile'] =& $this->profile;
- $fields['register.usergroups'] = $this->userGroups;
- $this->controller->postHooks->loadMultiple($postHooks,$fields);
- /* process hooks */
- if ($this->controller->postHooks->hasErrors()) {
- $errors = array();
- $hookErrors = $this->controller->postHooks->getErrors();
- foreach ($hookErrors as $key => $error) {
- $errors[$key] = str_replace('[[+error]]',$error,$this->controller->getProperty('errTpl'));
- }
- $this->modx->toPlaceholders($errors,'error');
- $errorMsg = $this->controller->postHooks->getErrorMessage();
- $this->modx->toPlaceholder('message',$errorMsg,'error');
- }
- }
- /**
- * if a hook set the user as moderated, if set, send to an optional other moderation resource id
- * @return boolean
- */
- public function checkForModerationRedirect() {
- $moderated = $this->checkForModeration();
- if (!empty($moderated)) {
- $moderatedResourceId = $this->controller->getProperty('moderatedResourceId','');
- if (!empty($moderatedResourceId)) {
- if ($this->controller->getProperty('redirectUnsetDefaultParams') == false) {
- $persistParams = array_merge($this->persistParams,array(
- 'username' => $this->user->get('username'),
- 'email' => $this->profile->get('email'),
- ));
- }
- $url = $this->modx->makeUrl($moderatedResourceId,'',$persistParams,'full');
- if (!$this->login->inTestMode) {
- $this->modx->sendRedirect($url);
- }
- return true;
- }
- }
- return false;
- }
- /**
- * Check for a redirect if the user was successfully registered. If one found, redirect.
- *
- * @return boolean
- */
- public function checkForRegisteredRedirect() {
- /* if provided a redirect id, will redirect to that resource, with the
- * GET params `username` and `email` for you to use */
- $submittedResourceId = $this->controller->getProperty('submittedResourceId','');
- if (!empty($submittedResourceId)) {
- if ($this->controller->getProperty('redirectUnsetDefaultParams') == false) {
- $persistParams = array_merge($this->persistParams,array(
- 'username' => $this->user->get('username'),
- 'email' => $this->profile->get('email'),
- ));
- }
- $url = $this->modx->makeUrl($submittedResourceId,'',$persistParams,'full');
- if (!$this->login->inTestMode) {
- $this->modx->sendRedirect($url);
- }
- return true;
- }
- return false;
- }
- public function autoLogin() {
- if ($this->user == null) { return false; }
- $contexts = $this->controller->getProperty('authenticateContexts', $this->modx->context->get('key'));
- $fields = $this->dictionary->toArray();
- $c = array(
- 'login_context' => $this->modx->context->key,
- 'add_contexts' => $contexts,
- 'username' => $this->user->username,
- 'password' => $fields[$this->controller->getProperty('passwordField','password')],
- 'returnUrl' => '',
- );
- $a = $this->modx->runProcessor('security/login',$c);
- return true;
- }
- }
- return 'LoginRegisterProcessor';
|