[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/plugins/system/webauthn/src/PluginTraits/ -> UserProfileFields.php (source)

   1  <?php
   2  
   3  /**
   4   * @package         Joomla.Plugin
   5   * @subpackage      System.Webauthn
   6   *
   7   * @copyright   (C) 2020 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\Plugin\System\Webauthn\PluginTraits;
  12  
  13  use Exception;
  14  use Joomla\CMS\Factory;
  15  use Joomla\CMS\Form\Form;
  16  use Joomla\CMS\HTML\HTMLHelper;
  17  use Joomla\CMS\Language\Text;
  18  use Joomla\CMS\Log\Log;
  19  use Joomla\CMS\Uri\Uri;
  20  use Joomla\CMS\User\User;
  21  use Joomla\CMS\User\UserFactoryInterface;
  22  use Joomla\Event\Event;
  23  use Joomla\Plugin\System\Webauthn\Extension\Webauthn;
  24  use Joomla\Registry\Registry;
  25  
  26  // phpcs:disable PSR1.Files.SideEffects
  27  \defined('_JEXEC') or die;
  28  // phpcs:enable PSR1.Files.SideEffects
  29  
  30  /**
  31   * Add extra fields in the User Profile page.
  32   *
  33   * This class only injects the custom form fields. The actual interface is rendered through
  34   * JFormFieldWebauthn.
  35   *
  36   * @see     JFormFieldWebauthn::getInput()
  37   *
  38   * @since   4.0.0
  39   */
  40  trait UserProfileFields
  41  {
  42      /**
  43       * User object derived from the displayed user profile data.
  44       *
  45       * This is required to display the number and names of authenticators already registered when
  46       * the user displays the profile view page.
  47       *
  48       * @var   User|null
  49       * @since 4.0.0
  50       */
  51      private static $userFromFormData = null;
  52  
  53      /**
  54       * HTMLHelper method to render the WebAuthn user profile field in the profile view page.
  55       *
  56       * Instead of showing a nonsensical "Website default" label next to the field, this method
  57       * displays the number and names of authenticators already registered by the user.
  58       *
  59       * This static method is set up for use in the onContentPrepareData method of this plugin.
  60       *
  61       * @param   mixed  $value  Ignored. The WebAuthn profile field is virtual, it doesn't have a
  62       *                         stored value. We only use it as a proxy to render a sub-form.
  63       *
  64       * @return  string
  65       * @since   4.0.0
  66       */
  67      public static function renderWebauthnProfileField($value): string
  68      {
  69          if (\is_null(self::$userFromFormData)) {
  70              return '';
  71          }
  72  
  73          /** @var Webauthn $plugin */
  74          $plugin               = Factory::getApplication()->bootPlugin('webauthn', 'system');
  75          $credentialRepository = $plugin->getAuthenticationHelper()->getCredentialsRepository();
  76          $credentials          = $credentialRepository->getAll(self::$userFromFormData->id);
  77          $authenticators       = array_map(
  78              function (array $credential) {
  79                  return $credential['label'];
  80              },
  81              $credentials
  82          );
  83  
  84          return Text::plural('PLG_SYSTEM_WEBAUTHN_FIELD_N_AUTHENTICATORS_REGISTERED', \count($authenticators), implode(', ', $authenticators));
  85      }
  86  
  87      /**
  88       * Adds additional fields to the user editing form
  89       *
  90       * @param   Event  $event  The event we are handling
  91       *
  92       * @return  void
  93       *
  94       * @throws  Exception
  95       * @since   4.0.0
  96       */
  97      public function onContentPrepareForm(Event $event)
  98      {
  99          /**
 100           * @var   Form  $form The form to be altered.
 101           * @var   mixed $data The associated data for the form.
 102           */
 103          [$form, $data] = $event->getArguments();
 104  
 105          // This feature only applies to HTTPS sites.
 106          if (!Uri::getInstance()->isSsl()) {
 107              return;
 108          }
 109  
 110          $name = $form->getName();
 111  
 112          $allowedForms = [
 113              'com_admin.profile', 'com_users.user', 'com_users.profile', 'com_users.registration',
 114          ];
 115  
 116          if (!\in_array($name, $allowedForms)) {
 117              return;
 118          }
 119  
 120          // Get the user object
 121          $user = $this->getUserFromData($data);
 122  
 123          // Make sure the loaded user is the correct one
 124          if (\is_null($user)) {
 125              return;
 126          }
 127  
 128          // Make sure I am either editing myself OR I am a Super User
 129          if (!$this->canEditUser($user)) {
 130              return;
 131          }
 132  
 133          // Add the fields to the form.
 134          if ($name !== 'com_users.registration') {
 135              Log::add('Injecting WebAuthn Passwordless Login fields in user profile edit page', Log::DEBUG, 'webauthn.system');
 136  
 137              Form::addFormPath(JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name . '/forms');
 138              $form->loadFile('webauthn', false);
 139          }
 140      }
 141  
 142      /**
 143       * @param   Event  $event  The event we are handling
 144       *
 145       * @return  void
 146       *
 147       * @throws  Exception
 148       * @since   4.0.0
 149       */
 150      public function onContentPrepareData(Event $event): void
 151      {
 152          /**
 153           * @var   string|null        $context  The context for the data
 154           * @var   array|object|null  $data     An object or array containing the data for the form.
 155           */
 156          [$context, $data] = $event->getArguments();
 157  
 158          if (!\in_array($context, ['com_users.profile', 'com_users.user'])) {
 159              return;
 160          }
 161  
 162          self::$userFromFormData = $this->getUserFromData($data);
 163  
 164          if (!HTMLHelper::isRegistered('users.webauthnWebauthn')) {
 165              HTMLHelper::register('users.webauthn', [__CLASS__, 'renderWebauthnProfileField']);
 166          }
 167      }
 168  
 169      /**
 170       * Get the user object based on the ID found in the provided user form data
 171       *
 172       * @param   array|object|null  $data  The user form data
 173       *
 174       * @return  User|null  A user object or null if no match is found
 175       *
 176       * @throws  Exception
 177       * @since   4.0.0
 178       */
 179      private function getUserFromData($data): ?User
 180      {
 181          $id = null;
 182  
 183          if (\is_array($data)) {
 184              $id = $data['id'] ?? null;
 185          } elseif (\is_object($data) && ($data instanceof Registry)) {
 186              $id = $data->get('id');
 187          } elseif (\is_object($data)) {
 188              $id = $data->id ?? null;
 189          }
 190  
 191          $user = empty($id) ? Factory::getApplication()->getIdentity() : Factory::getContainer()
 192              ->get(UserFactoryInterface::class)
 193              ->loadUserById($id);
 194  
 195          // Make sure the loaded user is the correct one
 196          if ($user->id != $id) {
 197              return null;
 198          }
 199  
 200          return $user;
 201      }
 202  
 203      /**
 204       * Is the current user allowed to edit the WebAuthn configuration of $user?
 205       *
 206       * To do so I must either be editing my own account OR I have to be a Super User.
 207       *
 208       * @param   ?User   $user   The user you want to know if we're allowed to edit
 209       *
 210       * @return  boolean
 211       *
 212       * @since   4.2.0
 213       */
 214      private function canEditUser(?User $user = null): bool
 215      {
 216          // I can edit myself, but Guests can't have passwordless logins associated
 217          if (empty($user) || $user->guest) {
 218              return true;
 219          }
 220  
 221          // Get the currently logged in used
 222          $myUser = $this->getApplication()->getIdentity() ?? new User();
 223  
 224          // I can edit myself. If I'm a Super user I can edit other users too.
 225          return ($myUser->id == $user->id) || $myUser->authorise('core.admin');
 226      }
 227  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer