[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @package Joomla.Administrator 5 * @subpackage com_users 6 * 7 * @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org> 8 * @license GNU General Public License version 2 or later; see LICENSE.txt 9 */ 10 11 namespace Joomla\Component\Users\Administrator\Model; 12 13 use DateInterval; 14 use DateTimeZone; 15 use Exception; 16 use Joomla\CMS\Date\Date; 17 use Joomla\CMS\Factory; 18 use Joomla\CMS\Language\Text; 19 use Joomla\CMS\MVC\Model\BaseDatabaseModel; 20 use Joomla\CMS\User\User; 21 use Joomla\CMS\User\UserFactoryInterface; 22 use Joomla\Component\Users\Administrator\Helper\Mfa as MfaHelper; 23 use Joomla\Database\ParameterType; 24 use RuntimeException; 25 26 // phpcs:disable PSR1.Files.SideEffects 27 \defined('_JEXEC') or die; 28 // phpcs:enable PSR1.Files.SideEffects 29 30 /** 31 * Multi-factor Authentication Methods list page's model 32 * 33 * @since 4.2.0 34 */ 35 class MethodsModel extends BaseDatabaseModel 36 { 37 /** 38 * Returns a list of all available MFA methods and their currently active records for a given user. 39 * 40 * @param User|null $user The user object. Skip to use the current user. 41 * 42 * @return array 43 * @throws Exception 44 * 45 * @since 4.2.0 46 */ 47 public function getMethods(?User $user = null): array 48 { 49 if (is_null($user)) { 50 $user = Factory::getApplication()->getIdentity() 51 ?: Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById(0); 52 } 53 54 if ($user->guest) { 55 return []; 56 } 57 58 // Get an associative array of MFA Methods 59 $rawMethods = MfaHelper::getMfaMethods(); 60 $methods = []; 61 62 foreach ($rawMethods as $method) { 63 $method['active'] = []; 64 $methods[$method['name']] = $method; 65 } 66 67 // Put the user MFA records into the Methods array 68 $userMfaRecords = MfaHelper::getUserMfaRecords($user->id); 69 70 if (!empty($userMfaRecords)) { 71 foreach ($userMfaRecords as $record) { 72 if (!isset($methods[$record->method])) { 73 continue; 74 } 75 76 $methods[$record->method]->addActiveMethod($record); 77 } 78 } 79 80 return $methods; 81 } 82 83 /** 84 * Delete all Multi-factor Authentication Methods for the given user. 85 * 86 * @param User|null $user The user object to reset MFA for. Null to use the current user. 87 * 88 * @return void 89 * @throws Exception 90 * 91 * @since 4.2.0 92 */ 93 public function deleteAll(?User $user = null): void 94 { 95 // Make sure we have a user object 96 if (is_null($user)) { 97 $user = Factory::getApplication()->getIdentity() ?: Factory::getUser(); 98 } 99 100 // If the user object is a guest (who can't have MFA) we abort with an error 101 if ($user->guest) { 102 throw new RuntimeException(Text::_('JERROR_ALERTNOAUTHOR'), 403); 103 } 104 105 $db = $this->getDatabase(); 106 $query = $db->getQuery(true) 107 ->delete($db->quoteName('#__user_mfa')) 108 ->where($db->quoteName('user_id') . ' = :user_id') 109 ->bind(':user_id', $user->id, ParameterType::INTEGER); 110 $db->setQuery($query)->execute(); 111 } 112 113 /** 114 * Format a relative timestamp. It deals with timestamps today and yesterday in a special manner. Example returns: 115 * Yesterday, 13:12 116 * Today, 08:33 117 * January 1, 2015 118 * 119 * @param string $dateTimeText The database time string to use, e.g. "2017-01-13 13:25:36" 120 * 121 * @return string The formatted, human-readable date 122 * @throws Exception 123 * 124 * @since 4.2.0 125 */ 126 public function formatRelative(?string $dateTimeText): string 127 { 128 if (empty($dateTimeText)) { 129 return Text::_('JNEVER'); 130 } 131 132 // The timestamp is given in UTC. Make sure Joomla! parses it as such. 133 $utcTimeZone = new DateTimeZone('UTC'); 134 $jDate = new Date($dateTimeText, $utcTimeZone); 135 $unixStamp = $jDate->toUnix(); 136 137 // I'm pretty sure we didn't have MFA in Joomla back in 1970 ;) 138 if ($unixStamp < 0) { 139 return Text::_('JNEVER'); 140 } 141 142 // I need to display the date in the user's local timezone. That's how you do it. 143 $user = Factory::getApplication()->getIdentity() 144 ?: Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById(0); 145 $userTZ = $user->getParam('timezone', 'UTC'); 146 $tz = new DateTimeZone($userTZ); 147 $jDate->setTimezone($tz); 148 149 // Default format string: way in the past, the time of the day is not important 150 $formatString = Text::_('COM_USERS_MFA_LBL_DATE_FORMAT_PAST'); 151 $containerString = Text::_('COM_USERS_MFA_LBL_PAST'); 152 153 // If the timestamp is within the last 72 hours we may need a special format 154 if ($unixStamp > (time() - (72 * 3600))) { 155 // Is this timestamp today? 156 $jNow = new Date(); 157 $jNow->setTimezone($tz); 158 $checkNow = $jNow->format('Ymd', true); 159 $checkDate = $jDate->format('Ymd', true); 160 161 if ($checkDate == $checkNow) { 162 $formatString = Text::_('COM_USERS_MFA_LBL_DATE_FORMAT_TODAY'); 163 $containerString = Text::_('COM_USERS_MFA_LBL_TODAY'); 164 } else { 165 // Is this timestamp yesterday? 166 $jYesterday = clone $jNow; 167 $jYesterday->setTime(0, 0, 0); 168 $oneSecond = new DateInterval('PT1S'); 169 $jYesterday->sub($oneSecond); 170 $checkYesterday = $jYesterday->format('Ymd', true); 171 172 if ($checkDate == $checkYesterday) { 173 $formatString = Text::_('COM_USERS_MFA_LBL_DATE_FORMAT_YESTERDAY'); 174 $containerString = Text::_('COM_USERS_MFA_LBL_YESTERDAY'); 175 } 176 } 177 } 178 179 return sprintf($containerString, $jDate->format($formatString, true)); 180 } 181 182 /** 183 * Set the user's "don't show this again" flag. 184 * 185 * @param User $user The user to check 186 * @param bool $flag True to set the flag, false to unset it (it will be set to 0, actually) 187 * 188 * @return void 189 * 190 * @since 4.2.0 191 */ 192 public function setFlag(User $user, bool $flag = true): void 193 { 194 $db = $this->getDatabase(); 195 $profileKey = 'mfa.dontshow'; 196 $query = $db->getQuery(true) 197 ->select($db->quoteName('profile_value')) 198 ->from($db->quoteName('#__user_profiles')) 199 ->where($db->quoteName('user_id') . ' = :user_id') 200 ->where($db->quoteName('profile_key') . ' = :profileKey') 201 ->bind(':user_id', $user->id, ParameterType::INTEGER) 202 ->bind(':profileKey', $profileKey, ParameterType::STRING); 203 204 try { 205 $result = $db->setQuery($query)->loadResult(); 206 } catch (Exception $e) { 207 return; 208 } 209 210 $exists = !is_null($result); 211 212 $object = (object) [ 213 'user_id' => $user->id, 214 'profile_key' => 'mfa.dontshow', 215 'profile_value' => ($flag ? 1 : 0), 216 'ordering' => 1, 217 ]; 218 219 if (!$exists) { 220 $db->insertObject('#__user_profiles', $object); 221 } else { 222 $db->updateObject('#__user_profiles', $object, ['user_id', 'profile_key']); 223 } 224 } 225 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |