Merge branch 'MDL-67309' of https://github.com/Peterburnett/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 17 Feb 2020 21:40:45 +0000 (22:40 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 17 Feb 2020 21:40:45 +0000 (22:40 +0100)
1  2 
lang/en/admin.php
lang/en/moodle.php
lib/moodlelib.php

diff --combined lang/en/admin.php
@@@ -307,7 -307,9 +307,9 @@@ $string['confignotifyloginthreshold'] 
  $string['confignotloggedinroleid'] = 'Users who are not logged in to the site will be treated as if they have this role granted to them at the site context.  Guest is almost always what you want here, but you might want to create roles that are less or more restrictive.  Things like creating posts still require the user to log in properly.';
  $string['configopentowebcrawlers'] = 'If you enable this setting, then search engines will be allowed to enter your site as a guest.  In addition, people coming in to your site via a search engine will automatically be logged in as a guest.  Note that this only provides transparent access to courses that already allow guest access.';
  $string['configoverride'] = 'Defined in config.php';
- $string['configpasswordpolicy'] = 'If enabled, user passwords will be checked against the password policy as specified in the settings below. Enabling the password policy will not affect existing users until they decide to, or are required to, change their password.';
+ $string['configpasswordpolicy'] = 'If enabled, user passwords will be checked against the password policy as specified in the settings below. Enabling the password policy will not affect existing users until they decide to, or are required to, change their password, or the \'Check password on login\' setting is enabled.';
+ $string['configpasswordpolicycheckonlogin'] = 'If enabled, user passwords will be checked against the password policy each time users log in. If the check fails, the user will be required to change their password before proceeding.
+ It is useful to enable this setting after updating the password policy.';
  $string['configpasswordresettime'] = 'This specifies the amount of time people have to validate a password reset request before it expires. Usually 30 minutes is a good value.';
  $string['configpathtodu'] = 'Path to du. Probably something like /usr/bin/du. If you enter this, pages that display directory contents will run much faster for directories with a lot of files.';
  $string['configpathtophp'] = 'Path to PHP CLI. Probably something like /usr/bin/php. If you enter this, cron scripts can be executed from admin web interface.';
@@@ -480,7 -482,6 +482,7 @@@ $string['devicedetectregex_desc'] = '<p
  $string['devicedetectregexexpression'] = 'Regular expression';
  $string['devicedetectregexvalue'] = 'Return value';
  $string['devicetype'] = 'Device type';
 +$string['disabled'] = 'Disabled';
  $string['disableuserimages'] = 'Disable user profile images';
  $string['displayerrorswarning'] = 'Enabling the PHP setting <em>display_errors</em> is not recommended on production sites because some error messages may reveal sensitive information about your server.';
  $string['displayloginfailures'] = 'Display login failures';
@@@ -895,6 -896,7 +897,7 @@@ $string['passwordchangelogout_desc'] = 
  $string['passwordchangetokendeletion'] = 'Remove web service access tokens after password change';
  $string['passwordchangetokendeletion_desc'] = 'If enabled, when a password is changed, all the user web service access tokens are deleted.';
  $string['passwordpolicy'] = 'Password policy';
+ $string['passwordpolicycheckonlogin'] = 'Check password on login';
  $string['passwordresettime'] = 'Maximum time to validate password reset request';
  $string['passwordreuselimit'] = 'Password rotation limit';
  $string['passwordreuselimit_desc'] = 'Number of times a user must change their password before they are allowed to reuse a password. Hashes of previously used passwords are stored in local database table. This feature might not be compatible with some external authentication plugins.';
diff --combined lang/en/moodle.php
@@@ -43,7 -43,6 +43,7 @@@ $string['activityselect'] = 'Select thi
  $string['activitysince'] = 'Activity since {$a}';
  $string['activitytypetitle'] = '{$a->activity} - {$a->type}';
  $string['activityweighted'] = 'Activity per user';
 +$string['actionsfor'] = 'Actions for {$a}';
  $string['add'] = 'Add';
  $string['addactivity'] = 'Add an activity...';
  $string['addactivitytosection'] = 'Add an activity to section \'{$a}\'';
@@@ -59,7 -58,6 +59,7 @@@ $string['addedtogroupnot'] = 'Not adde
  $string['addedtogroupnotenrolled'] = 'Not added to group "{$a}", because not enrolled in course';
  $string['addfilehere'] = 'Add file(s) here';
  $string['addinganew'] = 'Adding a new {$a}';
 +$string['addnew'] = 'Add a new {$a}';
  $string['addinganewto'] = 'Adding a new {$a->what} to {$a->to}';
  $string['addingdatatoexisting'] = 'Adding data to existing';
  $string['additionalnames'] = 'Additional names';
@@@ -799,6 -797,7 +799,7 @@@ $string['eventusercreated'] = 'User cre
  $string['eventuserdeleted'] = 'User deleted';
  $string['eventuserlistviewed'] = 'User list viewed';
  $string['eventuserloggedout'] = 'User logged out';
+ $string['eventuserpasswordpolicyfailed'] = 'User password failed password policy';
  $string['eventuserpasswordupdated'] = 'User password updated';
  $string['eventuserprofileviewed'] = 'User profile viewed';
  $string['eventuserupdated'] = 'User updated';
@@@ -859,6 -858,10 +860,10 @@@ $string['forcepasswordchange_help'] = '
  $string['forcepasswordchangecheckfull'] = 'Are you absolutely sure you want to force a password change to {$a} ?';
  $string['forcepasswordchangenot'] = 'Could not force a password change to {$a}';
  $string['forcepasswordchangenotice'] = 'You must change your password to proceed.';
+ $string['forcepasswordresetfailurenotice'] = 'Your current password no longer passes the set password policy. Please contact your Moodle administrator for assistance.
+    {$a}';
+ $string['forcepasswordresetnotice'] = 'Your current password no longer passes the set password policy, you must reset your password to login.
+    {$a}';
  $string['forcetheme'] = 'Force theme';
  $string['forgotaccount'] = 'Lost password?';
  $string['forgotten'] = 'Forgotten your username or password?';
@@@ -1517,6 -1520,8 +1522,8 @@@ $string['passwordforgotteninstructions'
  $string['passwordforgotteninstructions2'] = 'To reset your password, submit your username or your email address below. If we can find you in the database, an email will be sent to your email address, with instructions how to get access again.';
  $string['passwordchanged'] = 'Password has been changed';
  $string['passwordnohelp'] = 'No help is available to find your lost password. Please contact your Moodle administrator.';
+ $string['passwordpolicynomatch'] = 'Your current password no longer matches the set password policy.
+    {$a}';
  $string['passwordrecovery'] = 'Yes, help me log in';
  $string['passwordsdiffer'] = 'These passwords do not match';
  $string['passwordsent'] = 'Password has been sent';
diff --combined lib/moodlelib.php
@@@ -4248,9 -4248,6 +4248,9 @@@ function delete_user(stdClass $user) 
      // This might be slow but it is really needed - modules might do some extra cleanup!
      role_unassign_all(array('userid' => $user->id));
  
 +    // Notify the competency subsystem.
 +    \core_competency\api::hook_user_deleted($user->id);
 +
      // Now do a brute force cleanup.
  
      // Delete all user events and subscription events.
@@@ -4398,7 -4395,7 +4398,7 @@@ function guest_user() 
   * @return stdClass|false A {@link $USER} object or false if error
   */
  function authenticate_user_login($username, $password, $ignorelockout=false, &$failurereason=null, $logintoken=false) {
-     global $CFG, $DB;
+     global $CFG, $DB, $PAGE;
      require_once("$CFG->libdir/authlib.php");
  
      if ($user = get_complete_user_data('username', $username, $CFG->mnet_localhost_id)) {
              continue;
          }
  
+         // Before performing login actions, check if user still passes password policy, if admin setting is enabled.
+         if (!empty($CFG->passwordpolicycheckonlogin)) {
+             $errmsg = '';
+             $passed = check_password_policy($password, $errmsg, $user);
+             if (!$passed) {
+                 // First trigger event for failure.
+                 $failedevent = \core\event\user_password_policy_failed::create_from_user($user);
+                 $failedevent->trigger();
+                 // If able to change password, set flag and move on.
+                 if ($authplugin->can_change_password()) {
+                     // Check if we are on internal change password page, or service is external, don't show notification.
+                     $internalchangeurl = new moodle_url('/login/change_password.php');
+                     if (!($PAGE->has_set_url() && $internalchangeurl->compare($PAGE->url)) && $authplugin->is_internal()) {
+                         \core\notification::error(get_string('passwordpolicynomatch', '', $errmsg));
+                     }
+                     set_user_preference('auth_forcepasswordchange', 1, $user);
+                 } else if ($authplugin->can_reset_password()) {
+                     // Else force a reset if possible.
+                     \core\notification::error(get_string('forcepasswordresetnotice', '', $errmsg));
+                     redirect(new moodle_url('/login/forgot_password.php'));
+                 } else {
+                     $notifymsg = get_string('forcepasswordresetfailurenotice', '', $errmsg);
+                     // If support page is set, add link for help.
+                     if (!empty($CFG->supportpage)) {
+                         $link = \html_writer::link($CFG->supportpage, $CFG->supportpage);
+                         $link = \html_writer::tag('p', $link);
+                         $notifymsg .= $link;
+                     }
+                     // If no change or reset is possible, add a notification for user.
+                     \core\notification::error($notifymsg);
+                 }
+             }
+         }
          // Successful authentication.
          if ($user->id) {
              // User already exists in database.
@@@ -4980,7 -5013,8 +5016,8 @@@ function get_complete_user_data($field
   *
   * @param string $password the password to be checked against the password policy
   * @param string $errmsg the error message to display when the password doesn't comply with the policy.
-  * @param stdClass $user the user object to perform password validation against. Defaults to null if not provided
+  * @param stdClass $user the user object to perform password validation against. Defaults to null if not provided.
+  *
   * @return bool true if the password is valid according to the policy. false otherwise.
   */
  function check_password_policy($password, &$errmsg, $user = null) {