/plugins/user/token/src/Field/JoomlatokenField.php

https://github.com/Hackwar/joomla-cms · PHP · 164 lines · 70 code · 21 blank · 73 comment · 7 complexity · bdb3c3121ff26feed0785641683b78d1 MD5 · raw file

  1. <?php
  2. /**
  3. * @package Joomla.Plugin
  4. * @subpackage User.token
  5. *
  6. * @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. namespace Joomla\Plugin\User\Token\Field;
  10. \defined('_JEXEC') or die;
  11. use Joomla\CMS\Factory;
  12. use Joomla\CMS\Form\Field\TextField;
  13. /**
  14. * Joomlatoken field class
  15. *
  16. * @since 4.0.0
  17. */
  18. class JoomlatokenField extends TextField
  19. {
  20. /**
  21. * Name of the layout being used to render the field
  22. *
  23. * @var string
  24. * @since 4.0.0
  25. */
  26. protected $layout = 'plugins.user.token.token';
  27. /**
  28. * Method to attach a Form object to the field.
  29. *
  30. * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>`
  31. * tag for the form field object.
  32. * @param mixed $value The form field value to validate.
  33. * @param string $group The field name group control value. This acts as an
  34. * array container for the field. For example if the
  35. * field has name="foo" and the group value is set to
  36. * "bar" then the full field name would end up being
  37. * "bar[foo]".
  38. *
  39. * @return boolean True on success.
  40. *
  41. * @see FormField::setup()
  42. * @since 4.0.0
  43. */
  44. public function setup(\SimpleXMLElement $element, $value, $group = null)
  45. {
  46. $ret = parent::setup($element, $value, $group);
  47. /**
  48. * Security and privacy precaution: do not display the token field when the user being
  49. * edited is not the same as the logged in user. Tokens are conceptually a combination of
  50. * a username and password, therefore they should be treated in the same mode of
  51. * confidentiality and privacy as passwords i.e. you can reset them for other users but NOT
  52. * be able to see them, thus preventing impersonation attacks by a malicious administrator.
  53. */
  54. $userId = $this->form->getData()->get('id');
  55. if ($userId != Factory::getUser()->id)
  56. {
  57. $this->hidden = true;
  58. }
  59. return $ret;
  60. }
  61. /**
  62. * Method to get the field input markup.
  63. *
  64. * @return string The field input markup.
  65. *
  66. * @since 4.0.0
  67. */
  68. protected function getInput()
  69. {
  70. // Do not display the token field when the user being edited is not the same as the logged in user
  71. if ($this->hidden)
  72. {
  73. return '';
  74. }
  75. return parent::getInput();
  76. }
  77. /**
  78. * Returns the token formatted suitably for the user to copy.
  79. *
  80. * @param string $tokenSeed The token seed data stored in the database
  81. *
  82. * @return string
  83. * @since 4.0.0
  84. */
  85. private function getTokenForDisplay(string $tokenSeed): string
  86. {
  87. if (empty($tokenSeed))
  88. {
  89. return '';
  90. }
  91. $algorithm = $this->getAttribute('algo', 'sha256');
  92. try
  93. {
  94. $siteSecret = Factory::getApplication()->get('secret');
  95. }
  96. catch (\Exception $e)
  97. {
  98. $siteSecret = '';
  99. }
  100. // NO site secret? You monster!
  101. if (empty($siteSecret))
  102. {
  103. return '';
  104. }
  105. $rawToken = base64_decode($tokenSeed);
  106. $tokenHash = hash_hmac($algorithm, $rawToken, $siteSecret);
  107. $userId = $this->form->getData()->get('id');
  108. $message = base64_encode("$algorithm:$userId:$tokenHash");
  109. if ($userId != Factory::getUser()->id)
  110. {
  111. $message = '';
  112. }
  113. return $message;
  114. }
  115. /**
  116. * Get the data for the layout
  117. *
  118. * @return array
  119. *
  120. * @since 4.0.0
  121. */
  122. protected function getLayoutData()
  123. {
  124. $data = parent::getLayoutData();
  125. $data['value'] = $this->getTokenForDisplay($this->value);
  126. return $data;
  127. }
  128. /**
  129. * Get the layout paths
  130. *
  131. * @return array
  132. *
  133. * @since 4.0.0
  134. */
  135. protected function getLayoutPaths()
  136. {
  137. $template = Factory::getApplication()->getTemplate();
  138. return [
  139. JPATH_THEMES . '/' . $template . '/html/layouts',
  140. JPATH_SITE . '/layouts',
  141. ];
  142. }
  143. }