ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
class.ilLocalUserPasswordSettingsGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22use ILIAS\UI\Factory as UIFactory;
23use ILIAS\UI\Renderer as UIRenderer;
24use ILIAS\Refinery\Factory as Refinery;
25use Psr\Http\Message\ServerRequestInterface;
30
32{
33 private const string NEW_PASSWORD = 'new_password';
34 private const string CURRENT_PASSWORD = 'current_password';
35 public const string CMD_SHOW_PASSWORD = 'showPassword';
36 public const string CMD_SAVE_PASSWORD = 'savePassword';
37
38 private readonly ServerRequestInterface $request;
39 private readonly ilErrorHandling $error;
40 private readonly Refinery $refinery;
41 private readonly UIFactory $ui_factory;
42 private readonly UIRenderer $ui_renderer;
44 private readonly ilLanguage $lng;
45 private readonly ilObjUser $user;
46 private readonly ilCtrlInterface $ctrl;
48
49 public function __construct()
50 {
51 global $DIC;
52 $this->user = $DIC->user();
53 $this->ctrl = $DIC->ctrl();
54 $this->error = $DIC['ilErr'];
55 $this->lng = $DIC->language();
56 $this->refinery = $DIC->refinery();
57 $this->tpl = $DIC->ui()->mainTemplate();
58 $this->request = $DIC->http()->request();
59 $this->ui_factory = $DIC->ui()->factory();
60 $this->ui_renderer = $DIC->ui()->renderer();
61 $this->password_manager = LocalUserPasswordManager::getInstance();
62 $this->lng->loadLanguageModule('user');
63 }
64
65 public function executeCommand(): void
66 {
67 $this->tpl->setTitle($this->lng->txt('chg_password'));
68 $cmd = $this->ctrl->getCmd();
69 switch ($cmd) {
70 default:
71 if (method_exists($this, $cmd . 'Cmd')) {
72 $this->{$cmd . 'Cmd'}();
73 } else {
74 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
75 }
76 break;
77 }
78 }
79
80 public function showPasswordCmd(
81 ?Form $form = null,
82 bool $hide_form = false,
83 ?MessageBox $message_box = null
84 ): void {
85 // check whether password of user have to be changed
86 // due to first login or password of user is expired
87 if ($this->user->isPasswordChangeDemanded()) {
88 $this->tpl->setOnScreenMessage(
89 $this->tpl::MESSAGE_TYPE_INFO,
90 $this->lng->txt('password_change_on_first_login_demand')
91 );
92 } elseif ($this->user->isPasswordExpired()) {
93 $msg = $this->lng->txt('password_expired');
94 $password_age = $this->user->getPasswordAgeInDays();
95 $this->tpl->setOnScreenMessage($this->tpl::MESSAGE_TYPE_INFO, sprintf($msg, $password_age));
96 }
97
98 if (!$form && !$hide_form) {
99 $form = $this->getPasswordForm();
100 }
101
102 $this->tpl->setContent(
103 !$hide_form ? $this->ui_renderer->render($form) : $this->ui_renderer->render($message_box)
104 );
105 $this->tpl->printToStdout();
106 }
107
108 private function securePasswordConstraint(): \ILIAS\Refinery\Constraint
109 {
110 $custom_error = '';
111
112 return $this->refinery->custom()->constraint(function (Password $value) use (&$custom_error): bool {
113 return ilSecuritySettingsChecker::isPassword($value->toString(), $custom_error);
114 }, function (Closure $txt, Password $value) use (&$custom_error): string {
115 if ($custom_error !== '' && $custom_error !== null) {
116 return $custom_error;
117 }
118
119 return $this->lng->txt('passwd_invalid');
120 });
121 }
122
123 private function validInUserContextConstraint(): \ILIAS\Refinery\Constraint
124 {
125 $error_lng_var = null;
126
127 return $this->refinery->custom()->constraint(
128 function (Password $value) use (&$error_lng_var): bool {
130 $value->toString(),
131 $this->user,
132 $error_lng_var
133 );
134 },
135 function (Closure $cls, Password $value) use (&$error_lng_var): string {
136 return $this->lng->txt($error_lng_var ?? '');
137 }
138 );
139 }
140
141 private function passwordToString(): \ILIAs\Refinery\Transformation
142 {
143 return $this->refinery->custom()->transformation(
144 static function (ILIAS\Data\Password $value): string {
145 return trim($value->toString());
146 }
147 );
148 }
149
150 public function getPasswordForm(): Form
151 {
152 $entered_current_passwd = null;
153
154 $items = [];
155 if ($this->password_manager->allowPasswordChange($this->user)) {
156 $pw_info_set = false;
157 if ((int) $this->user->getAuthMode(true) === ilAuthUtils::AUTH_LOCAL) {
158 $current_passwd = $this->ui_factory
159 ->input()
160 ->field()
161 ->password(
162 $this->lng->txt(self::CURRENT_PASSWORD),
164 )
165 ->withRevelation(true)
166 ->withAdditionalTransformation(
167 $this->refinery->custom()->constraint(
168 function (Password $value) use (&$entered_current_passwd): bool {
169 $entered_current_passwd = $value;
170
171 return
172 ((int) $this->user->getAuthMode(true) !== ilAuthUtils::AUTH_LOCAL) ||
173 LocalUserPasswordManager::getInstance()->verifyPassword(
174 $this->user,
175 $value->toString()
176 );
177 },
178 $this->lng->txt('passwd_wrong')
179 )
180 )
181 ->withAdditionalTransformation($this->passwordToString());
182
183 $pw_info_set = true;
184 if ($this->user->getPasswd()) {
185 $current_passwd = $current_passwd->withRequired(true);
186 }
187
188 $items[self::CURRENT_PASSWORD] = $current_passwd;
189 }
190
191 $new_passwd = $this->ui_factory
192 ->input()
193 ->field()
194 ->password(
195 $this->lng->txt('desired_password'),
196 )
197 ->withRevelation(true)
198 ->withRequired(true)
199 ->withAdditionalTransformation($this->securePasswordConstraint())
200 ->withAdditionalTransformation($this->validInUserContextConstraint())
201 ->withAdditionalTransformation(
202 $this->refinery->custom()->constraint(
203 function (Password $value) use (&$entered_current_passwd): bool {
204 if ($entered_current_passwd === null) {
205 return true;
206 }
207
208 $passwords_equal = $entered_current_passwd->toString() === $value->toString();
209 $is_forced_change = $this->user->isPasswordChangeDemanded()
210 || $this->user->isPasswordExpired();
211
212 return !($passwords_equal && $is_forced_change);
213 },
214 $this->lng->txt('new_pass_equals_old_pass')
215 )
216 )
217 ->withAdditionalTransformation($this->passwordToString());
218
219 if ($pw_info_set === false) {
220 $new_passwd = $new_passwd->withByline(ilSecuritySettingsChecker::getPasswordRequirementsInfo());
221 }
222
223 $items[self::NEW_PASSWORD] = $new_passwd;
224
225 switch ($this->user->getAuthMode(true)) {
227 $title = $this->lng->txt('chg_password');
228
229 break;
231 default:
232 $title = $this->lng->txt('chg_ilias_password');
233
234 break;
235 }
236
237 $items = [
238 $this->ui_factory->input()->field()->section($items, $title)
239 ];
240 }
241
242 $form = $this->ui_factory
243 ->input()
244 ->container()
245 ->form()
246 ->standard(
247 $this->ctrl->getLinkTarget($this, 'savePassword'),
248 $items
249 )
250 ->withSubmitLabel($this->lng->txt('save'))
251 ->withAdditionalTransformation(
252 $this->refinery->custom()->transformation(static function (array $values): array {
253 return array_merge(...$values);
254 })
255 );
256
257 return $form;
258 }
259
260 public function savePasswordCmd(): void
261 {
262 if (!$this->password_manager->allowPasswordChange($this->user)) {
263 $this->ctrl->redirect($this, 'showPersonalData');
264 }
265
266 $form = $this->getPasswordForm()->withRequest($this->request);
267 if (!$form->getError()) {
268 $data = $form->getData();
269 $entered_current_passwd = $data[self::CURRENT_PASSWORD] ?? '';
270 $entered_new_passwd = $data[self::NEW_PASSWORD];
271
272 $this->user->resetPassword($entered_new_passwd, $entered_new_passwd);
273 if ($entered_current_passwd !== $entered_new_passwd) {
274 $this->user->setLastPasswordChangeToNow();
275 $this->user->setPasswordPolicyResetStatus(false);
276 $this->user->update();
277 }
278
279 if (ilSession::get('orig_request_target')) {
280 $this->tpl->setOnScreenMessage(
281 $this->tpl::MESSAGE_TYPE_SUCCESS,
282 $this->lng->txt('saved_successfully'),
283 true
284 );
285 $target = ilSession::get('orig_request_target');
286 ilSession::set('orig_request_target', '');
287 $this->ctrl->redirectToURL($target);
288 } else {
289 $this->showPasswordCmd(
290 null,
291 true,
292 $this->ui_factory->messageBox()->success($this->lng->txt('saved_successfully'))
293 );
294
295 return;
296 }
297 }
298
299 $this->showPasswordCmd($form);
300 }
301}
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
A password is used as part of credentials for authentication.
Definition: Password.php:31
error(string $a_errmsg)
const int AUTH_SHIBBOLETH
const int AUTH_LOCAL
Error Handling & global info handling.
language handling
readonly LocalUserPasswordManager $password_manager
showPasswordCmd(?Form $form=null, bool $hide_form=false, ?MessageBox $message_box=null)
User class.
static isPassword(string $a_passwd, ?string &$customError=null)
static isPasswordValidForUserContext(string $clear_text_password, $user, ?string &$error_language_variable=null)
static getPasswordRequirementsInfo()
infotext for ilPasswordInputGUI setInfo()
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.
This describes a standard form.
Definition: Standard.php:30
This describes password inputs.
Definition: Password.php:29
An entity that renders components to a string output.
Definition: Renderer.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26