Skip to content

Commit 45a3970

Browse files
🔃 [Magento Community Engineering] Community Contributions
Accepted Community Pull Requests: - #22837: Short-term admin accounts #22833 (by @lfolco) Fixed GitHub Issues: - #22833: Short-term admin accounts (reported by @piotrekkaminski) has been fixed in #22837 by @lfolco in 2.4-develop branch Related commits: 1. fa1f103 2. 451fae8 3. 70821f0 4. b17c54d 5. c0c6825 6. 6e2043e 7. 9136564 8. 37c9d12 9. 8b5bec6 10. 0b78cbb 11. 976076f 12. db95a0d 13. cf66338 14. c552e5f 15. f44ac3e 16. d5855ba 17. 439f565 18. c6f455d 19. 32f8741 20. a6511f5 21. ae08dad 22. 54882c3 23. ad4628b 24. 3c608fd 25. e4ec0e2 26. 13bfde2 27. e51bf0a 28. 185d640 29. 071f993 30. b407c8c 31. 47a9ed7 32. b631f9d 33. 6407af8 34. 75664d4 35. c384fab 36. cd53ca4 37. 581ace6 38. 13038fc 39. 2122209 40. 192f8e8 41. c5ac841 42. 57dda2e 43. 05fae71 44. 6378fe6 45. 1535364 46. c8e1e93 47. 437cbf0 48. 60f5710 49. 9e82e91 50. 61d3ffa 51. e87d4e6 52. bad8f2b 53. 6406d93 54. e13b5e4 55. 83e393e 56. d2538ad 57. b16de6b 58. b195ca0 59. 1089987 60. 581988a 61. f185806 62. d8c8473 63. 0f91a9d 64. 8036e29 65. 45d648f 66. 970510c 67. 78dc3b5 68. 171c4c9 69. 89b8512 70. bcef590 71. 627273b 72. 6b8e89e 73. 9e6f316 74. 20f2f0e 75. 1b1c12e 76. 91e0604 77. 47dfddb 78. c6f9e6b 79. df0c97c 80. babc965 81. 4c4149f 82. 33a5d36 83. 0ed4e6a 84. 74389d7 85. 5111c05 86. 9d8ce1c 87. 95fce13 88. 932559d 89. 7fee060 90. 5e6fdeb 91. 3a67bc8 92. b03b0a0 93. c8a41b7 94. 107cb5f 95. bef0bd5 96. 6ef861e 97. d65e609 98. c8cfb5b
2 parents 58c2171 + 71d358f commit 45a3970

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2312
-5
lines changed

app/code/Magento/Analytics/Test/Mftf/Test/AdminConfigurationPermissionTest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@
3535
<waitForPageLoad time="30" stepKey="wait2"/>
3636
<seeInField selector="{{AdminEditUserSection.usernameTextField}}" userInput="$$noReportUser.username$$" stepKey="seeUsernameInField"/>
3737
<fillField selector="{{AdminEditUserSection.currentPasswordField}}" userInput="{{_ENV.MAGENTO_ADMIN_PASSWORD}}" stepKey="fillCurrentPassword"/>
38-
<click selector="{{AdminEditUserSection.userRoleTab}}" stepKey="clickUserRoleTab"/>
38+
<scrollToTopOfPage stepKey="scrollToTopOfPage"/>
3939

40+
<click selector="{{AdminEditUserSection.userRoleTab}}" stepKey="clickUserRoleTab"/>
4041
<fillField selector="{{AdminEditUserSection.roleNameFilterTextField}}" userInput="$$noReportUserRole.rolename$$" stepKey="fillRoleNameSearch"/>
4142
<click selector="{{AdminEditUserSection.searchButton}}" stepKey="clickSearchButtonUserRole"/>
4243
<waitForPageLoad time="10" stepKey="wait3"/>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Security\Api\Data;
10+
11+
use \Magento\Security\Api\Data\UserExpirationExtensionInterface;
12+
13+
/**
14+
* Interface UserExpirationInterface to be used as a DTO for expires_at property on User model.
15+
*/
16+
interface UserExpirationInterface extends \Magento\Framework\Api\ExtensibleDataInterface
17+
{
18+
19+
public const EXPIRES_AT = 'expires_at';
20+
21+
public const USER_ID = 'user_id';
22+
23+
/**
24+
* `expires_at` getter.
25+
*
26+
* @return string
27+
*/
28+
public function getExpiresAt();
29+
30+
/**
31+
* `expires_at` setter.
32+
*
33+
* @param string $expiresAt
34+
* @return $this
35+
*/
36+
public function setExpiresAt($expiresAt);
37+
38+
/**
39+
* `user_id` getter.
40+
*
41+
* @return string
42+
*/
43+
public function getUserId();
44+
45+
/**
46+
* `user_id` setter.
47+
*
48+
* @param string $userId
49+
* @return $this
50+
*/
51+
public function setUserId($userId);
52+
53+
/**
54+
* Retrieve existing extension attributes object or create a new one.
55+
*
56+
* @return \Magento\Security\Api\Data\UserExpirationExtensionInterface|null
57+
*/
58+
public function getExtensionAttributes();
59+
60+
/**
61+
* Set an extension attributes object.
62+
*
63+
* @param \Magento\Security\Api\Data\UserExpirationExtensionInterface $extensionAttributes
64+
* @return $this
65+
*/
66+
public function setExtensionAttributes(UserExpirationExtensionInterface $extensionAttributes);
67+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Security\Model\Plugin;
9+
10+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
11+
use Magento\Security\Model\ResourceModel\UserExpiration;
12+
use Magento\Security\Model\UserExpirationFactory;
13+
14+
/**
15+
* Add the `expires_at` form field to the User main form.
16+
*/
17+
class AdminUserForm
18+
{
19+
20+
/**
21+
* @var TimezoneInterface
22+
*/
23+
private $localeDate;
24+
25+
/**
26+
* @var UserExpiration
27+
*/
28+
private $userExpirationResource;
29+
30+
/**
31+
* @var UserExpirationFactory
32+
*/
33+
private $userExpirationFactory;
34+
35+
/**
36+
* UserForm constructor.
37+
*
38+
* @param TimezoneInterface $localeDate
39+
* @param UserExpirationFactory $userExpirationFactory
40+
* @param UserExpiration $userExpirationResource
41+
*/
42+
public function __construct(
43+
TimezoneInterface $localeDate,
44+
UserExpirationFactory $userExpirationFactory,
45+
UserExpiration $userExpirationResource
46+
) {
47+
$this->localeDate = $localeDate;
48+
$this->userExpirationResource = $userExpirationResource;
49+
$this->userExpirationFactory = $userExpirationFactory;
50+
}
51+
52+
/**
53+
* Add the `expires_at` field to the admin user edit form.
54+
*
55+
* @param \Magento\User\Block\User\Edit\Tab\Main $subject
56+
* @param \Closure $proceed
57+
* @return mixed
58+
*/
59+
public function aroundGetFormHtml(
60+
\Magento\User\Block\User\Edit\Tab\Main $subject,
61+
\Closure $proceed
62+
) {
63+
/** @var \Magento\Framework\Data\Form $form */
64+
$form = $subject->getForm();
65+
if (is_object($form)) {
66+
$dateFormat = $this->localeDate->getDateFormat(
67+
\IntlDateFormatter::MEDIUM
68+
);
69+
$timeFormat = $this->localeDate->getTimeFormat(
70+
\IntlDateFormatter::MEDIUM
71+
);
72+
$fieldset = $form->getElement('base_fieldset');
73+
$userIdField = $fieldset->getElements()->searchById('user_id');
74+
$userExpirationValue = null;
75+
if ($userIdField) {
76+
$userId = $userIdField->getValue();
77+
$userExpirationValue = $this->loadUserExpirationByUserId($userId);
78+
}
79+
$fieldset->addField(
80+
'expires_at',
81+
'date',
82+
[
83+
'name' => 'expires_at',
84+
'label' => __('Expiration Date'),
85+
'title' => __('Expiration Date'),
86+
'date_format' => $dateFormat,
87+
'time_format' => $timeFormat,
88+
'class' => 'validate-date',
89+
'value' => $userExpirationValue,
90+
]
91+
);
92+
93+
$subject->setForm($form);
94+
}
95+
96+
return $proceed();
97+
}
98+
99+
/**
100+
* Loads a user expiration record by user ID.
101+
*
102+
* @param string $userId
103+
* @return string
104+
*/
105+
private function loadUserExpirationByUserId($userId)
106+
{
107+
/** @var \Magento\Security\Model\UserExpiration $userExpiration */
108+
$userExpiration = $this->userExpirationFactory->create();
109+
$this->userExpirationResource->load($userExpiration, $userId);
110+
return $userExpiration->getExpiresAt();
111+
}
112+
}

app/code/Magento/Security/Model/Plugin/AuthSession.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
use Magento\Backend\Model\Auth\Session;
99
use Magento\Security\Model\AdminSessionsManager;
10+
use Magento\Security\Model\UserExpirationManager;
1011

1112
/**
1213
* Magento\Backend\Model\Auth\Session decorator
@@ -33,22 +34,32 @@ class AuthSession
3334
*/
3435
protected $securityCookie;
3536

37+
/**
38+
* @var UserExpirationManager
39+
*/
40+
private $userExpirationManager;
41+
3642
/**
3743
* @param \Magento\Framework\App\RequestInterface $request
3844
* @param \Magento\Framework\Message\ManagerInterface $messageManager
3945
* @param AdminSessionsManager $sessionsManager
4046
* @param \Magento\Security\Model\SecurityCookie $securityCookie
47+
* @param UserExpirationManager|null $userExpirationManager
4148
*/
4249
public function __construct(
4350
\Magento\Framework\App\RequestInterface $request,
4451
\Magento\Framework\Message\ManagerInterface $messageManager,
4552
AdminSessionsManager $sessionsManager,
46-
\Magento\Security\Model\SecurityCookie $securityCookie
53+
\Magento\Security\Model\SecurityCookie $securityCookie,
54+
\Magento\Security\Model\UserExpirationManager $userExpirationManager = null
4755
) {
4856
$this->request = $request;
4957
$this->messageManager = $messageManager;
5058
$this->sessionsManager = $sessionsManager;
5159
$this->securityCookie = $securityCookie;
60+
$this->userExpirationManager = $userExpirationManager ?:
61+
\Magento\Framework\App\ObjectManager::getInstance()
62+
->get(\Magento\Security\Model\UserExpirationManager::class);
5263
}
5364

5465
/**
@@ -64,6 +75,11 @@ public function aroundProlong(Session $session, \Closure $proceed)
6475
$session->destroy();
6576
$this->addUserLogoutNotification();
6677
return null;
78+
} elseif ($this->userExpirationManager->isUserExpired($session->getUser()->getId())) {
79+
$this->userExpirationManager->deactivateExpiredUsersById([$session->getUser()->getId()]);
80+
$session->destroy();
81+
$this->addUserLogoutNotification();
82+
return null;
6783
}
6884
$result = $proceed();
6985
$this->sessionsManager->processProlong();
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Security\Model\Plugin;
9+
10+
use Magento\Security\Model\UserExpiration\Validator;
11+
12+
/**
13+
* \Magento\User\Model\UserValidationRules decorator
14+
*/
15+
class UserValidationRules
16+
{
17+
/**@var Validator */
18+
private $validator;
19+
20+
/**
21+
* UserValidationRules constructor.
22+
*
23+
* @param Validator $validator
24+
*/
25+
public function __construct(Validator $validator)
26+
{
27+
$this->validator = $validator;
28+
}
29+
30+
/**
31+
* Add the Expires At validator to user validation rules.
32+
*
33+
* @param \Magento\User\Model\UserValidationRules $userValidationRules
34+
* @param \Magento\Framework\Validator\DataObject $result
35+
* @return \Magento\Framework\Validator\DataObject
36+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
37+
*/
38+
public function afterAddUserInfoRules(\Magento\User\Model\UserValidationRules $userValidationRules, $result)
39+
{
40+
return $result->addRule($this->validator, 'expires_at');
41+
}
42+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Security\Model\ResourceModel;
9+
10+
/**
11+
* Admin User Expiration resource model
12+
*/
13+
class UserExpiration extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
14+
{
15+
16+
/**
17+
* Flag that notifies whether Primary key of table is auto-incremented
18+
*
19+
* @var bool
20+
*/
21+
protected $_isPkAutoIncrement = false;
22+
23+
/**
24+
* @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
25+
*/
26+
private $timezone;
27+
28+
/**
29+
* UserExpiration constructor.
30+
*
31+
* @param \Magento\Framework\Model\ResourceModel\Db\Context $context
32+
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone
33+
* @param string $connectionName
34+
*/
35+
public function __construct(
36+
\Magento\Framework\Model\ResourceModel\Db\Context $context,
37+
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone,
38+
?string $connectionName = null
39+
) {
40+
parent::__construct($context, $connectionName);
41+
$this->timezone = $timezone;
42+
}
43+
44+
/**
45+
* Define main table
46+
*
47+
* @return void
48+
*/
49+
protected function _construct()
50+
{
51+
$this->_init('admin_user_expiration', 'user_id');
52+
}
53+
54+
/**
55+
* Convert to UTC time.
56+
*
57+
* @param \Magento\Framework\Model\AbstractModel $userExpiration
58+
* @return $this
59+
* @throws \Magento\Framework\Exception\LocalizedException
60+
*/
61+
protected function _beforeSave(\Magento\Framework\Model\AbstractModel $userExpiration)
62+
{
63+
/** @var $userExpiration \Magento\Security\Model\UserExpiration */
64+
$expiresAt = $userExpiration->getExpiresAt();
65+
$utcValue = $this->timezone->convertConfigTimeToUtc($expiresAt);
66+
$userExpiration->setExpiresAt($utcValue);
67+
68+
return $this;
69+
}
70+
71+
/**
72+
* Convert to store time.
73+
*
74+
* @param \Magento\Framework\Model\AbstractModel $userExpiration
75+
* @return $this|\Magento\Framework\Model\ResourceModel\Db\AbstractDb
76+
* @throws \Exception
77+
*/
78+
protected function _afterLoad(\Magento\Framework\Model\AbstractModel $userExpiration)
79+
{
80+
/** @var $userExpiration \Magento\Security\Model\UserExpiration */
81+
if ($userExpiration->getExpiresAt()) {
82+
$storeValue = $this->timezone->date($userExpiration->getExpiresAt());
83+
$userExpiration->setExpiresAt($storeValue->format('Y-m-d H:i:s'));
84+
}
85+
86+
return $this;
87+
}
88+
}

0 commit comments

Comments
 (0)