/src/legacy/util/UserUtil.php
PHP | 2009 lines | 1028 code | 267 blank | 714 comment | 374 complexity | 0ead410f6ad0525ddc0a349f33f8d529 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, MIT
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * Copyright Zikula Foundation 2009 - Zikula Application Framework
- *
- * This work is contributed to the Zikula Foundation under one or more
- * Contributor Agreements and licensed to You under the following license:
- *
- * @license GNU/LGPv3 (or at your option any later version).
- * @package Util
- *
- * Please see the NOTICE file distributed with this source code for further
- * information regarding copyright and licensing.
- */
- use Zikula\Core\Event\GenericEvent;
- use UsersModule\Constants as UsersConstant;
- use Zikula\Framework\Exception\FatalException;
- use Zikula\Framework\Exception\RedirectException;
- use Zikula\Framework\Exception\ForbiddenException;
- /**
- * UserUtil
- */
- class UserUtil
- {
- /**
- * Cache for groups.
- *
- * @var array
- */
- protected static $groupCache = array();
- /**
- * Clear group cache.
- *
- * @return void
- */
- public function clearGroupCache()
- {
- self::$groupCache = array();
- }
- /**
- * Return a hash structure mapping uid to username.
- *
- * @param string $where The where clause to use (optional, default=array()).
- * @param string $orderBy The order by clause to use (optional, default=array()).
- * @param integer $limitOffset The select-limit offset (optional, default=null).
- * @param integer $limitNumRows The number of rows to fetch (optional, default=null).
- * @param string $assocKey The associative key to apply (optional) (default='uid').
- *
- * @deprecated since 1.3.0
- *
- * @return array An array mapping uid to username.
- */
- public static function getUsers($where = array(), $orderBy = array(), $limitOffset = null, $limitNumRows = null, $assocKey = 'uid')
- {
- $em = \ServiceUtil::get('doctrine')->getManager();
- $users = $em->getRepository('UsersModule\Entity\User')->findBy($where, $orderBy, $limitNumRows, $limitOffset);
- $items = array();
- foreach ($users as $user) {
- $items[$user[$assocKey]] = $user->toArray();
- }
- return $items;
- }
- /**
- * Return a group object.
- *
- * @param integer $gid The groupID to retrieve.
- *
- * @todo Decouple UserUtil and Groups?
- *
- * @return array The resulting group object.
- */
- public static function getGroup($gid)
- {
- return ModUtil::apiFunc('GroupsModule', 'user', 'get', array('gid' => $gid));
- }
- /**
- * Return a hash structure mapping gid to groupname.
- *
- * @param string $where The where clause to use (optional) (default=array()).
- * @param string $orderBy The order by clause to use (optional) (default=array()).
- * @param integer $limitOffset The select-limit offset (optional) (default=null).
- * @param integer $limitNumRows The number of rows to fetch (optional) (default=null).
- * @param string $assocKey The associative key to apply (optional) (default='gid').
- *
- * @return array An array mapping gid to groupname.
- */
- public static function getGroups($where = array(), $orderBy = array(), $limitOffset = null, $limitNumRows = null, $assocKey='gid')
- {
- $em = \ServiceUtil::get('doctrine')->getManager();
- $groups = $em->getRepository('GroupsModule\Entity\Group')->findBy($where, $orderBy, $limitNumRows, $limitOffset);
- $items = array();
- foreach ($groups as $group) {
- $items[$group[$assocKey]] = $group->toArray();
- }
- return $items;
- }
- /**
- * Return a (string) list of user-ids which can then be used in a SQL 'IN (...)' clause.
- *
- * @param string $where The where clause to use (optional).
- * @param string $orderBy The order by clause to use (optional).
- * @param string $separator The field separator to use (default=",") (optional).
- *
- * @return string A string list of user ids.
- */
- public static function getUserIdList($where = '', $orderBy = '', $separator = ',')
- {
- $userdata = self::getUsers($where, $orderBy);
- $list = '-1';
- if ($userdata && count($userdata)) {
- $uids = array_keys($userdata);
- sort($uids);
- $list = implode((string)$separator, $uids);
- }
- return $list;
- }
- /**
- * Return a (string) list of group-ids which can then be used in a SQL 'IN (...)' clause.
- *
- * @param string $where The where clause to use (optional).
- * @param string $orderBy The order by clause to use (optional).
- * @param string $separator The field separator to use (default=",") (optional).
- *
- * @return string A string list of group ids.
- */
- public static function getGroupIdList($where = array(), $orderBy = array(), $separator = ',')
- {
- $groupdata = self::getGroups($where, $orderBy);
- $list = '';
- if ($groupdata && count($groupdata)) {
- $gids = array_keys($groupdata);
- sort($gids);
- $list = implode((string)$separator, $gids);
- }
- return $list;
- }
- /**
- * Return an array group-ids for the specified user.
- *
- * @param integer $uid The user ID for which we want the groups.
- *
- * @return array An array of group IDs.
- */
- public static function getGroupsForUser($uid)
- {
- if (empty($uid)) {
- return array();
- }
- return ModUtil::apiFunc('GroupsModule', 'user', 'getusergroups', array('uid' => $uid, 'clean' => true));
- }
- /**
- * Return a string list of group-ids for the specified user.
- *
- * @param integer $uid The user ID for which we want the groups.
- * @param string $separator The field separator to use (default=",") (optional).
- *
- * @return string A string list of group ids.
- */
- public static function getGroupListForUser($uid = null, $separator = ',')
- {
- if (!$uid) {
- $uid = self::getVar('uid');
- }
- if (!$uid) {
- return '-1';
- }
- if (!isset(self::$groupCache[$uid])) {
- $gidArray = self::getGroupsForUser($uid);
- if ($gidArray && (bool)count($gidArray)) {
- sort($gidArray);
- self::$groupCache[$uid] = implode((string)$separator, $gidArray);
- } else {
- self::$groupCache[$uid] = '-1';
- }
- }
- return self::$groupCache[$uid];
- }
- /**
- * Return a string list of user-ids for the specified group.
- *
- * @param integer $gid The group ID for which we want the users.
- *
- * @return array An array of user IDs.
- */
- public static function getUsersForGroup($gid)
- {
- if (!$gid) {
- return array();
- }
- $group = ModUtil::apiFunc('GroupsModule', 'user', 'get', array('gid' => $gid));
- $members = $group['members'];
- $uids = array();
- foreach ($members as $uid => $membership) {
- $uids[] = $uid;
- }
- return $uids;
- }
- /**
- * Get a unique string for a user, depending on this group memberships.
- *
- * String ready to be used as part of the CacheID of the output views.
- * Useful when there aren't another user-based access privilegies, just group permissions.
- *
- * @param integer $uid User ID to get the group memberships from. Default: current user.
- *
- * @return string Cache GIDs string to use on Zikula_View.
- */
- public static function getGidCacheString($uid = null)
- {
- $str = UserUtil::getGroupListForUser($uid, '_');
- return $str == '-1' ? 'guest' : 'groups_'.$str;
- }
- /**
- * Get a unique string for a user, based on the uid.
- *
- * String ready to be used as part of the CacheID of the output views.
- * Useful for user-based access privilegies.
- *
- * @param integer $uid User ID to get string from. Default: current user.
- *
- * @return string Cache UID string to use on Zikula_View.
- */
- public static function getUidCacheString($uid = null)
- {
- $uid = $uid ? (int)$uid : self::getVar('uid');
- return !$uid ? 'guest' : 'uid_'.$uid;
- }
- /**
- * Return the defined dynamic user data fields.
- *
- * @return array An array of dynamic data field definitions.
- */
- public static function getDynamicDataFields()
- {
- // decide if we have to use the (obsolete) DUDs from the Profile module
- $profileModule = System::getVar('profilemodule', '');
- if (empty($profileModule) || $profileModule != 'Profile' || !ModUtil::available($profileModule)) {
- return array();
- }
- return DBUtil::selectObjectArray('user_property');
- }
- /**
- * Return a array structure for the user group selector.
- *
- * @param mixed $defaultValue The default value of the selector (default=0) (optional).
- * @param string $defaultText The text of the default value (optional).
- * @param array $ignore An array of keys to ignore (optional).
- * @param mixed $includeAll Whether to include an "All" choice (optional).
- * @param string $allText The text to display for the "All" choice (optional).
- *
- * @return array The array structure for the user group selector.
- */
- public static function getSelectorData_Group($defaultValue = 0, $defaultText = '', $ignore = array(), $includeAll = 0, $allText = '')
- {
- $dropdown = array();
- if ($defaultText) {
- $dropdown[] = array('id' => $defaultValue, 'name' => $defaultText);
- }
- $groupdata = self::getGroups(array(), array('name' => 'ASC'));
- if (!$groupdata || !count($groupdata)) {
- return $dropdown;
- }
- if ($includeAll) {
- $dropdown[] = array('id' => $includeAll, 'name' => $allText);
- }
- foreach (array_keys($groupdata) as $gid) {
- if (!isset($ignore[$gid])) {
- $gname = $groupdata[$gid]['name'];
- $dropdown[$gname] = array('id' => $gid, 'name' => $gname);
- }
- }
- ksort($dropdown);
- return $dropdown;
- }
- /**
- * Return a array strcuture for the user dropdown box.
- *
- * @param miexed $defaultValue The default value of the selector (optional) (default=0).
- * @param string $defaultText The text of the default value (optional) (default='').
- * @param array $ignore An array of keys to ignore (optional) (default=array()).
- * @param miexed $includeAll Whether to include an "All" choice (optional) (default=0).
- * @param string $allText The text to display for the "All" choice (optional) (default='').
- * @param string $exclude An SQL IN-LIST string to exclude specified uids.
- *
- * @return array The array structure for the user group selector.
- */
- public static function getSelectorData_User($defaultValue = 0, $defaultText = '', $ignore = array(), $includeAll = 0, $allText = '', $exclude = '')
- {
- $dropdown = array();
- if ($defaultText) {
- $dropdown[] = array('id' => $defaultValue, 'name' => $defaultText);
- }
- $where = '';
- if ($exclude) {
- $where = "WHERE uid NOT IN (" . DataUtil::formatForStore($exclude) . ")";
- }
- $userdata = self::getUsers($where, 'ORDER BY uname');
- if (!$userdata || !count($userdata)) {
- return $dropdown;
- }
- if ($includeAll) {
- $dropdown[] = array('id' => $includeAll, 'name' => $allText);
- }
- foreach (array_keys($userdata) as $uid) {
- if (!isset($ignore[$uid])) {
- $uname = $userdata[$uid]['uname'];
- $dropdown[$uname] = array('id' => $uid, 'name' => $uname);
- }
- }
- ksort($uname);
- return $dropdown;
- }
- /**
- * Retrieve the account recovery information for a user from the various authentication modules.
- *
- * @param numeric $uid The user id of the user for which account recovery information should be retrieved; optional, defaults to the
- * currently logged in user (an exception occurs if the current user is not logged in).
- *
- * @return array An array of account recovery information.
- *
- * @throws FatalException If the $uid parameter is not valid.
- */
- public static function getUserAccountRecoveryInfo($uid = -1)
- {
- if (!isset($uid) || !is_numeric($uid) || ((string)((int)$uid) != $uid) || (($uid < -1) || ($uid == 0) || ($uid == 1))) {
- throw new FatalException('Attempt to get authentication information for an invalid user id.');
- }
- if ($uid == -1) {
- if (self::isLoggedIn()) {
- $uid = self::getVar('uid');
- } else {
- throw new FatalException('Attempt to get authentication information for an invalid user id.');
- }
- }
- $userAuthenticationInfo = array();
- $authenticationModules = ModUtil::getModulesCapableOf(UsersConstant::CAPABILITY_AUTHENTICATION);
- if ($authenticationModules) {
- $accountRecoveryArgs = array (
- 'uid' => $uid,
- );
- foreach ($authenticationModules as $authenticationModule) {
- $moduleUserAuthenticationInfo = ModUtil::apiFunc($authenticationModule['name'], 'authentication', 'getAccountRecoveryInfoForUid', $accountRecoveryArgs, 'Zikula_Api_AbstractAuthentication');
- if (is_array($moduleUserAuthenticationInfo)) {
- $userAuthenticationInfo = array_merge($userAuthenticationInfo, $moduleUserAuthenticationInfo);
- }
- }
- }
- return $userAuthenticationInfo;
- }
- /**
- * Login.
- *
- * @param string $loginID Login Id.
- * @param string $userEnteredPassword The Password.
- * @param boolean $rememberme Whether or not to remember login.
- * @param boolean $checkPassword Whether or not to check the password.
- *
- * @return boolean
- */
- public static function login($loginID, $userEnteredPassword, $rememberme = false, $checkPassword = true)
- {
- LogUtil::log(__f('Warning! Function %1$s is deprecated. Please use %2$s instead.', array(__METHOD__, 'UserUtil::loginUsing()')), E_USER_DEPRECATED);
- $authenticationInfo = array(
- 'login_id' => $loginID,
- 'pass' => $userEnteredPassword,
- );
- $authenticationMethod = array(
- 'modname' => 'Users',
- );
- if (ModUtil::getVar(UsersConstant::MODNAME, UsersConstant::MODVAR_LOGIN_METHOD, UsersConstant::DEFAULT_LOGIN_METHOD) == UsersConstant::LOGIN_METHOD_EMAIL) {
- $authenticationMethod['method'] = 'email';
- } else {
- $authenticationMethod['method'] = 'uname';
- }
- return self::loginUsing($authenticationMethod, $authenticationInfo, $rememberme, null, $checkPassword);
- }
- /**
- * Validation method previous authentication.
- *
- * @param array $authenticationMethod Auth method.
- * @param string $reentrantURL Reentrant URL (optional).
- *
- * @throws FatalException
- *
- * @return true
- */
- private static function preAuthenticationValidation(array $authenticationMethod, $reentrantURL = null)
- {
- if (empty($authenticationMethod) || (count($authenticationMethod) != 2)) {
- throw new FatalException(__f('An invalid %1$s parameter was received.', array('authenticationMethod')));
- }
- if (!isset($authenticationMethod['modname']) || !is_string($authenticationMethod['modname']) || empty($authenticationMethod['modname'])) {
- throw new FatalException(__f('An invalid %1$s parameter was received.', array('modname')));
- } elseif (!ModUtil::getInfoFromName($authenticationMethod['modname'])) {
- throw new FatalException(__f('The authentication module \'%1$s\' could not be found.', array($authenticationMethod['modname'])));
- } elseif (!ModUtil::available($authenticationMethod['modname'])) {
- throw new FatalException(__f('The authentication module \'%1$s\' is not available.', array($authenticationMethod['modname'])));
- } elseif (!ModUtil::loadApi($authenticationMethod['modname'], 'Authentication')) {
- throw new FatalException(__f('The authentication module \'%1$s\' could not be loaded.', array($authenticationMethod['modname'])));
- }
- if (!isset($authenticationMethod['method']) || !is_string($authenticationMethod['method']) || empty($authenticationMethod['method'])) {
- throw new FatalException(__f('An invalid %1$s parameter was received.', array('method')));
- } elseif (!ModUtil::apiFunc($authenticationMethod['modname'], 'Authentication', 'supportsAuthenticationMethod', array('method' => $authenticationMethod['method']), 'Zikula_Api_AbstractAuthentication')) {
- throw new FatalException(__f('The authentication method \'%1$s\' is not supported by the authentication module \'%2$s\'.', array($authenticationMethod['method'], $authenticationMethod['modname'])));
- }
- if (ModUtil::apiFunc($authenticationMethod['modname'], 'Authentication', 'isReentrant', null, 'Zikula_Api_AbstractAuthentication') && (!isset($reentrantURL) || empty($reentrantURL))) {
- throw new FatalException(__f('The authentication module \'%1$s\' is reentrant. A %2$s is required.', array($authenticationMethod['modname'], 'reentrantURL')));
- }
- return true;
- }
- /**
- * Authenticate a user's credentials against an authentication module, without any attempt to log the user in or look up a Zikula user account record.
- *
- * NOTE: Checking a password with an authentication method defined by the Users module is a special case.
- * The password is stored along with the account information, therefore the account information has to be
- * looked up by the checkPassword function in that module. Authentication modules other than the Users module should
- * make no attempt to look up account information,
- *
- * This function is used to check that a user is who he says he is without any attempt to log the user into the
- * Zikula system or look up his account information or status. It could be used, for example, to check the user's
- * credentials prior to registering with an authentication method like OpenID or Google Federated Login.
- *
- * This function differs from {@link authenticateUserUsing()} in that it does not make any attempt to look up a Zikula account
- * record for the user (nor should the authentication method specified).
- *
- * This function differs from {@link loginUsing()} in that it does not make any attempt to look up a Zikula account
- * record for the user (nor should the authentication method specified), and additionally it makes no attempt to log the user into
- * the Zikula system.
- *
- * ATTENTION: The authentication module function(s) called during this process may redirect the user to an external server
- * to perform authorization and/or authentication. The function calling checkPasswordUsing must already have anticipated
- * the reentrant nature of this process, must already have saved pertinent user state, must have supplied a
- * reentrant URL pointing to a function that will handle reentry into the login process silently, and must clear
- * any save user state immediately following the return of this function.
- *
- * @param array $authenticationMethod Authentication module and method name.
- * @param array $authenticationInfo Auth info array.
- * @param string $reentrantURL If the authentication module needs to redirect to an external authentication server (e.g., OpenID), then
- * this is the URL to return to in order to re-enter the log-in process. The pertinent user
- * state must have already been saved by the function calling checkPasswordUsing(), and the URL must
- * point to a Zikula_AbstractController function that is equipped to detect reentry, restore the
- * saved user state, and get the user back to the point where loginUsing is re-executed. This
- * is only optional if the authentication module identified by $authenticationMethod reports that it is not
- * reentrant (e.g., Users is guaranteed to not be reentrant).
- *
- * @return bool True if authentication info authenticates; otherwise false.
- */
- public static function checkPasswordUsing(array $authenticationMethod, array $authenticationInfo, $reentrantURL = null)
- {
- if (self::preAuthenticationValidation($authenticationMethod, $reentrantURL)) {
- // Authenticate the loginID and userEnteredPassword against the specified authentication module.
- // This should return the uid of the user logging in. Note that there are two routes here, both get a uid.
- $checkPasswordArgs = array(
- 'authentication_info' => $authenticationInfo,
- 'authentication_method' => $authenticationMethod,
- 'reentrant_url' => $reentrantURL,
- );
- return ModUtil::apiFunc($authenticationMethod['modname'], 'Authentication', 'checkPassword', $checkPasswordArgs, 'Zikula_Api_AbstractAuthentication');
- } else {
- return false;
- }
- }
- /**
- * Authenticate a user's credentials against an authentication module, without any attempt to log the user in.
- *
- * This function is used to check that a user is who he says he is, and that he has a valid user account with the
- * Zikula system. No attempt is made to log the user in to the Zikula system. It could be used, for example, to check
- * the user's credentials and Zikula system accoun status prior to performing a sensitive operation.
- *
- * This function differs from {@link checkPasswordUsing()} in that it attempts to look up a Zikula account
- * record for the user, and takes the user's account status into account when returning a value.
- *
- * This function differs from {@link loginUsing()} in that it makes no attempt to log the user into the Zikula system.
- *
- * ATTENTION: The authentication module function(s) called during this process may redirect the user to an external server
- * to perform authorization and/or authentication. The function calling authenticateUserUsing must already have anticipated
- * the reentrant nature of this process, must already have saved pertinent user state, must have supplied a
- * reentrant URL pointing to a function that will handle reentry into the login process silently, and must clear
- * any save user state immediately following the return of this function.
- *
- * @param array $authenticationMethod The name of the authentication module to use for authentication and the method name as defined by that module.
- * @param array $authenticationInfo The information needed by the authentication module for authentication, typically a loginID and pass.
- * @param string $reentrantURL If the authentication module needs to redirect to an external authentication server (e.g., OpenID), then
- * this is the URL to return to in order to re-enter the log-in process. The pertinent user
- * state must have already been saved by the function calling authenticateUserUsing(), and the URL must
- * point to a Zikula_AbstractController function that is equipped to detect reentry, restore the
- * saved user state, and get the user back to the point where loginUsing is re-executed. This
- * is only optional if the authentication module identified by $authenticationMethod reports that it is not
- * reentrant (e.g., Users is guaranteed to not be reentrant).
- *
- * @return mixed Zikula uid if the authentication info authenticates with the authentication module; otherwise false.
- */
- private static function internalAuthenticateUserUsing(array $authenticationMethod, array $authenticationInfo, $reentrantURL = null)
- {
- $authenticatedUid = false;
- if (self::preAuthenticationValidation($authenticationMethod, $reentrantURL)) {
- $authenticateUserArgs = array(
- 'authentication_info' => $authenticationInfo,
- 'authentication_method' => $authenticationMethod,
- 'reentrant_url' => $reentrantURL,
- );
- $authenticatedUid = ModUtil::apiFunc($authenticationMethod['modname'], 'Authentication', 'authenticateUser', $authenticateUserArgs, 'Zikula_Api_AbstractAuthentication');
- }
- return $authenticatedUid;
- }
- private static function internalUserAccountValidation($uid, $reportErrors = false, $userObj = false)
- {
- if (!$uid || !is_numeric($uid) || ((int)$uid != $uid)) {
- // We got something other than a uid from the authentication process.
- if (!LogUtil::hasErrors() && $reportErrors) {
- LogUtil::registerError(__('Sorry! Login failed. The information you provided was incorrect.'));
- }
- } else {
- if (!$userObj) {
- // Need to make sure the Users module stuff is loaded and available, especially if we are authenticating during
- // an upgrade or install.
- ModUtil::loadApi('Users', 'user', true);
- // The user's credentials have authenticated with the authentication module's method, but
- // now we have to check the account status itself. If the account status would not allow the
- // user to log in, then we return false.
- $userObj = self::getVars($uid);
- if (!$userObj) {
- // Might be a registration
- $userObj = self::getVars($uid, false, 'uid', true);
- }
- }
- if (!$userObj || !is_array($userObj)) {
- // Note that we have not actually logged into anything yet, just authenticated.
- throw new FatalException(__f('A %1$s (%2$s) was returned by the authenticating module, but a user account record (or registration request record) could not be found.', array('uid', $uid)));
- }
- if (!isset($userObj['activated'])) {
- // Provide a sane value.
- $userObj['activated'] = UsersConstant::ACTIVATED_INACTIVE;
- }
- if ($userObj['activated'] != UsersConstant::ACTIVATED_ACTIVE) {
- if ($reportErrors) {
- $displayVerifyPending = ModUtil::getVar(UsersConstant::MODNAME, UsersConstant::MODVAR_LOGIN_DISPLAY_VERIFY_STATUS, UsersConstant::DEFAULT_LOGIN_DISPLAY_VERIFY_STATUS);
- $displayApprovalPending = ModUtil::getVar(UsersConstant::MODNAME, UsersConstant::MODVAR_LOGIN_DISPLAY_APPROVAL_STATUS, UsersConstant::DEFAULT_LOGIN_DISPLAY_VERIFY_STATUS);
- if (($userObj['activated'] == UsersConstant::ACTIVATED_PENDING_REG) && ($displayApprovalPending || $displayVerifyPending)) {
- $moderationOrder = ModUtil::getVar(UsersConstant::MODNAME, UsersConstant::MODVAR_REGISTRATION_APPROVAL_SEQUENCE, UsersConstant::DEFAULT_REGISTRATION_APPROVAL_SEQUENCE);
- if (!$userObj['isverified']
- && (($moderationOrder == UsersConstant::APPROVAL_AFTER) || ($moderationOrder == UsersConstant::APPROVAL_ANY)
- || (!empty($userObj['approved_by'])))
- && $displayVerifyPending
- ) {
- $message = __('Your request to register with this site is still waiting for verification of your e-mail address. Please check your inbox for a message from us.');
- } elseif (empty($userObj['approved_by'])
- && (($moderationOrder == UsersConstant::APPROVAL_BEFORE) || ($moderationOrder == UsersConstant::APPROVAL_ANY))
- && $displayApprovalPending
- ) {
- $message = __('Your request to register with this site is still waiting for approval from a site administrator.');
- }
- if (isset($message) && !empty($message)) {
- return LogUtil::registerError($message);
- }
- // It is a pending registration but the site admin elected to not display this to the user.
- // No exception here because the answer is simply "no." This will fall through to return false.
- } elseif (($userObj['activated'] == UsersConstant::ACTIVATED_INACTIVE) && ModUtil::getVar(UsersConstant::MODNAME, UsersConstant::MODVAR_LOGIN_DISPLAY_INACTIVE_STATUS, UsersConstant::DEFAULT_LOGIN_DISPLAY_INACTIVE_STATUS)) {
- $message = __('Your account has been disabled. Please contact a site administrator for more information.');
- } elseif (($userObj['activated'] == UsersConstant::ACTIVATED_PENDING_DELETE) && ModUtil::getVar(UsersConstant::MODNAME, UsersConstant::MODVAR_LOGIN_DISPLAY_DELETE_STATUS, UsersConstant::DEFAULT_LOGIN_DISPLAY_DELETE_STATUS)) {
- $message = __('Your account has been disabled and is scheduled for removal. Please contact a site administrator for more information.');
- } else {
- $message = __('Sorry! Either there is no active user in our system with that information, or the information you provided does not match the information for your account.');
- }
- LogUtil::registerError($message);
- }
- $userObj = false;
- }
- }
- return $userObj;
- }
- /**
- * Authenticate a user's credentials against an authentication module, without any attempt to log the user in.
- *
- * This function is used to check that a user is who he says he is, and that he has a valid user account with the
- * Zikula system. No attempt is made to log the user in to the Zikula system. It could be used, for example, to check
- * the user's credentials and Zikula system accoun status prior to performing a sensitive operation.
- *
- * This function differs from {@link checkPasswordUsing()} in that it attempts to look up a Zikula account
- * record for the user, and takes the user's account status into account when returning a value.
- *
- * This function differs from {@link loginUsing()} in that it makes no attempt to log the user into the Zikula system.
- *
- * ATTENTION: The authentication module function(s) called during this process may redirect the user to an external server
- * to perform authorization and/or authentication. The function calling authenticateUserUsing must already have anticipated
- * the reentrant nature of this process, must already have saved pertinent user state, must have supplied a
- * reentrant URL pointing to a function that will handle reentry into the login process silently, and must clear
- * any save user state immediately following the return of this function.
- *
- * @param array $authenticationMethod The name of the authentication module to use for authentication and the method name as defined by that module.
- * @param array $authenticationInfo The information needed by the authentication module for authentication, typically a loginID and pass.
- * @param string $reentrantURL If the authentication module needs to redirect to an external authentication server (e.g., OpenID), then
- * this is the URL to return to in order to re-enter the log-in process. The pertinent user
- * state must have already been saved by the function calling authenticateUserUsing(), and the URL must
- * point to a Zikula_AbstractController function that is equipped to detect reentry, restore the
- * saved user state, and get the user back to the point where loginUsing is re-executed. This
- * is only optional if the authentication module identified by $authenticationMethod reports that it is not
- * reentrant (e.g., Users is guaranteed to not be reentrant).
- * @param boolean $reportErrors If true, then when validation of the account's ability to log in is performed, if errors are detected then
- * they will be reported through registering errors with Zikula's logging and error reporting system. If
- * false, then error reporting is supressed, and only the return value will indicate success or failure.
- *
- * @return array|bool The user account record of the user with the given credentials, if his credentials authenticate; otherwise false
- */
- public static function authenticateUserUsing(array $authenticationMethod, array $authenticationInfo, $reentrantURL = null, $reportErrors = false)
- {
- $userObj = false;
- $authenticatedUid = self::internalAuthenticateUserUsing($authenticationMethod, $authenticationInfo, $reentrantURL);
- if ($authenticatedUid) {
- $userObj = self::internalUserAccountValidation($authenticatedUid, $reportErrors);
- }
- return $userObj;
- }
- /**
- * Authenticate a user's credentials against an authentication module, logging him into the Zikula system.
- *
- * If the user is already logged in, then this function should behave as if {@link authenticateUserUsing()} was called.
- *
- * This function is used to check that a user is who he says he is, and that he has a valid user account with the
- * Zikula system. If so, the user is logged in to the Zikula system (if he is not already logged in). This function
- * should be used only to log a user into the Zikula system.
- *
- * This function differs from {@link checkPasswordUsing()} in that it attempts to look up a Zikula account
- * record for the user, and takes the user's account status into account when returning a value. Additionally,
- * the user is logged into the Zikula system if his credentials are verified with the authentication module specified.
- *
- * This function differs from {@link authenticateUserUsing()} in that it attempts to log the user into the Zikula system,
- * if he is not already logged in. If he is already logged in, then it should behave similarly to authenticateUserUsing().
- *
- * ATTENTION: The authentication module function(s) called during this process may redirect the user to an external server
- * to perform authorization and/or authentication. The function calling loginUsing must already have anticipated
- * the reentrant nature of this process, must already have saved pertinent user state, must have supplied a
- * reentrant URL pointing to a function that will handle reentry into the login process silently, and must clear
- * any save user state immediately following the return of this function.
- *
- * @param array $authenticationMethod Auth module name.
- * @param array $authenticationInfo Auth info array.
- * @param boolean $rememberMe Whether or not to remember login.
- * @param string $reentrantURL If the authentication module needs to redirect to an external authentication server (e.g., OpenID), then
- * this is the URL to return to in order to re-enter the log-in process. The pertinent user
- * state must have already been saved by the function calling loginUsing(), and the URL must
- * point to a Zikula_AbstractController function that is equipped to detect reentry, restore the
- * saved user state, and get the user back to the point where loginUsing is re-executed. This
- * is only optional if the authentication module identified by $authenticationMethod reports that it is not
- * reentrant (e.g., Users is guaranteed to not be reentrant), or if $checkPassword is false.
- * @param boolean $checkPassword Whether or not to check the password.
- * @param boolean $preauthenticatedUser Whether ot not is a preauthenticated user.
- *
- * @return array|bool The user account record of the user that has logged in successfully, otherwise false
- */
- public static function loginUsing(array $authenticationMethod, array $authenticationInfo, $rememberMe = false, $reentrantURL = null, $checkPassword = true, $preauthenticatedUser = null)
- {
- $userObj = false;
- if (self::preAuthenticationValidation($authenticationMethod, $authenticationInfo, $reentrantURL)) {
- // Authenticate the loginID and userEnteredPassword against the specified authentication module.
- // This should return the uid of the user logging in. Note that there are two routes here, both get a uid.
- // We do the authentication check first, before checking any account status information, because if the
- // person logging in cannot supply the proper credentials, then we should not show any detailed account status
- // to them. Instead they should just get the generic "no such user found or bad password" message.
- if ($checkPassword) {
- $authenticatedUid = self::internalAuthenticateUserUsing($authenticationMethod, $authenticationInfo, $reentrantURL, true);
- } elseif (isset($preauthenticatedUser)) {
- if (is_numeric($preauthenticatedUser)) {
- $authenticatedUid = $preauthenticatedUser;
- } elseif (is_array($preauthenticatedUser)) {
- $authenticatedUid = $preauthenticatedUser['uid'];
- $userObj = $preauthenticatedUser;
- } else {
- throw new FatalException();
- }
- } else {
- $authArgs = array(
- 'authentication_info' => $authenticationInfo,
- 'authentication_method' => $authenticationMethod,
- );
- $authenticatedUid = ModUtil::apiFunc($authenticationMethod['modname'], 'Authentication', 'getUidForAuththenticationInfo', $authArgs, 'Zikula_Api_AbstractAuthentication');
- }
- $session = ServiceUtil::get('request')->getSession();
- $userObj = self::internalUserAccountValidation($authenticatedUid, true, isset($userObj) ? $userObj : null);
- if ($userObj && is_array($userObj)) {
- // BEGIN ACTUAL LOGIN
- // Made it through all the checks. We can actually log in now.
- // Give any interested module one last chance to prevent the login from happening.
- $eventArgs = array(
- 'authentication_method' => $authenticationMethod,
- 'uid' => $userObj['uid'],
- );
- $event = new GenericEvent($userObj, $eventArgs);
- $event = EventUtil::dispatch('user.login.veto', $event);
- if ($event->isPropagationStopped()) {
- // The login attempt has been vetoed by one or more modules.
- $eventData = $event->getData();
- if (isset($eventData['retry']) && $eventData['retry']) {
- $sessionVarName = 'Users_Controller_User_login';
- $sessionNamespace = 'Zikula_Users';
- $redirectURL = ModUtil::url('Users', 'user', 'login', array('csrftoken' => SecurityUtil::generateCsrfToken()));
- } elseif (isset($eventData['redirect_func'])) {
- if (isset($eventData['redirect_func']['session'])) {
- $sessionVarName = $eventData['redirect_func']['session']['var'];
- $sessionNamespace = isset($eventData['redirect_func']['session']['namespace']) ? $eventData['redirect_func']['session']['namespace'] : '';
- }
- $redirectURL = ModUtil::url($eventData['redirect_func']['modname'], $eventData['redirect_func']['type'], $eventData['redirect_func']['func'], $eventData['redirect_func']['args']);
- }
- if (isset($redirectURL)) {
- if (isset($sessionVarName)) {
- SessionUtil::requireSession();
- $sessionVars = $session->get('users/Users_User_Controller_login', array());
- $sessionVars = array(
- 'returnpage' => isset($sessionVars['returnpage']) ? $sessionVars['returnpage'] : '',
- 'authentication_info' => $authenticationInfo,
- 'authentication_method' => $authenticationMethod,
- 'rememberme' => $rememberMe,
- 'user_obj' => $userObj,
- );
- $session->set("$sessionNamespace/$sessionVarName", $sessionVars);
- }
- $userObj = false;
- throw new RedirectException($redirectURL);
- } else {
- throw new ForbiddenException();
- }
- } else {
- // The login has not been vetoed
- // This is what really does the Zikula login
- self::setUserByUid($userObj['uid'], $rememberMe, $authenticationMethod);
- }
- }
- }
- return $userObj;
- }
- /**
- * Sets the currently logged in active user to the user account for the given Users module uname.
- *
- * No events are fired from this function. To receive events, use {@link loginUsing()}.
- *
- * @param string $uname The user name of the user who should be logged into the system; required.
- * @param boolean $rememberMe If the user's login should be maintained on the computer from which the user is logging in, set this to true;
- * optional, defaults to false.
- *
- * @return void
- */
- public static function setUserByUname($uname, $rememberMe = false)
- {
- if (!isset($uname) || !is_string($uname) || empty($uname)) {
- throw new FatalException(__('Attempt to set the current user with an invalid uname.'));
- }
- $uid = self::getIdFromName($uname);
- $authenticationMethod = array(
- 'modname' => 'Users',
- 'method' => 'uname',
- );
- self::setUserByUid($uid, $rememberMe, $authenticationMethod);
- }
- /**
- * Sets the currently logged in active user to the user account for the given uid.
- *
- * No events are fired from this function. To receive events, use {@link loginUsing()}.
- *
- * @param numeric $uid The user id of the user who should be logged into the system; required.
- * @param boolean $rememberMe If the user's login should be maintained on the computer from which the user is logging in, set this to true;
- * optional, defaults to false.
- * @param array $authenticationMethod An array containing the authentication method used to log the user in; optional,
- * defaults to the 'Users' module 'uname' method.
- *
- * @return void
- */
- public static function setUserByUid($uid, $rememberMe = false, array $authenticationMethod = null)
- {
- if (!isset($uid) || empty($uid) || ((string)((int)$uid) != $uid)) {
- throw new FatalException(__('Attempt to set the current user with an invalid uid.'));
- }
- $userObj = self::getVars($uid);
- if (!isset($userObj) || !is_array($userObj) || empty($userObj)) {
- throw new FatalException(__('Attempt to set the current user with an unknown uid.'));
- }
- if (!isset($authenticationMethod)) {
- $authenticationMethod = array(
- 'modname' => 'Users',
- 'method' => 'uname',
- );
- } elseif (empty($authenticationMethod) || !isset($authenticationMethod['modname']) || empty($authenticationMethod['modname'])
- || !isset($authenticationMethod['method']) || empty($authenticationMethod['method'])
- ) {
- throw new FatalException(__('Attempt to set the current user with an invalid authentication method.'));
- }
- // Storing Last Login date -- store it in UTC! Do not use date() function!
- $nowUTC = new DateTime(null, new DateTimeZone('UTC'));
- if (!self::setVar('lastlogin', $nowUTC->format('Y-m-d H:i:s'), $userObj['uid'])) {
- // show messages but continue
- LogUtil::registerError(__('Error! Could not save the log-in date.'));
- }
- if (!System::isInstalling()) {
- SessionUtil::requireSession();
- }
- $session = ServiceUtil::get('request')->getSession();
- // Set session variables -- this is what really does the Zikula login
- $session->set('uid', $userObj['uid']);
- $session->set('users/authentication_method', $authenticationMethod);
- if (!empty($rememberMe)) {
- $session->set('rememberme', 1);
- }
- // now that we've logged in the permissions previously calculated (if any) are invalid
- $GLOBALS['authinfogathered'][$userObj['uid']] = 0;
- }
- /**
- * Log the user out.
- *
- * @return bool true if the user successfully logged out, false otherwise
- */
- public static function logout()
- {
- if (self::isLoggedIn()) {
- $userObj = self::getVars(self::getVar('uid'));
- $session = ServiceUtil::get('request')->getSession();
- $authenticationMethod = $session->get('users/authentication_method', array('modname' => '', 'method' => ''));
- $session->invalidate();
- }
- return true;
- }
- /**
- * Is the user logged in?
- *
- * @return bool true if the user is logged in, false if they are not
- */
- public static function isLoggedIn()
- {
- return (bool)ServiceUtil::getManager()->get('request')->getSession()->get('uid');
- }
- /**
- * Counts how many times a user name has been used by user accounts in the system.
- *
- * @param string $uname The e-mail address in question (required).
- * @param int $excludeUid The uid to exclude from the check, used when checking modifications.
- *
- * @return integer|boolean The count, or false on error.
- */
- public static function getUnameUsageCount($uname, $excludeUid = 0)
- {
- if (!is_numeric($excludeUid) || ((int)$excludeUid != $excludeUid)) {
- return false;
- }
- $uname = DataUtil::formatForStore(mb_strtolower($uname));
- // get doctrine manager
- $em = \ServiceUtil::get('doctrine')->getManager();
- // count of uname appearances in users table
- $dql = "SELECT count(u.uid) FROM UsersModule\Entity\User u WHERE u.uname = '{$uname}'";
- if ($excludeUid > 1) {
- $dql .= " AND u.uid <> {$excludeUid}";
- }
- $query = $em->createQuery($dql);
- $ucount = $query->getSingleScalarResult();
- return (int)$ucount;
- }
- /**
- * Counts how many times an e-mail address has been used by user accounts in the system.
- *
- * @param string $emailAddress The e-mail address in question (required).
- * @param int $excludeUid The uid to exclude from the check, used when checking modifications.
- *
- * @return integer|boolean the count, or false on error.
- */
- public static function getEmailUsageCount($emailAddress, $excludeUid = 0)
- {
- if (!is_numeric($excludeUid) || ((int)$excludeUid != $excludeUid)) {
- return false;
- }
- $emailAddress = DataUtil::formatForStore(mb_strtolower($emailAddress));
- // get doctrine manager
- $em = \ServiceUtil::get('doctrine')->getManager();
- // count of email appearances in users table
- $dql = "SELECT COUNT(u.uid) FROM UsersModule\Entity\User u WHERE u.email = '{$emailAddress}'";
- if ($excludeUid > 1) {
- $dql .= " AND u.uid <> {$excludeUid}";
- }
- $query = $em->createQuery($dql);
- $ucount = (int)$query->getSingleScalarResult();
- // count of email appearances in users verification table
- $dql = "SELECT COUNT(v.id) FROM UsersModule\Entity\UserVerification v WHERE v.newemail = '{$emailAddress}' AND v.changetype = " . UsersCon…
Large files files are truncated, but you can click here to view the full file