Merge branch 'MDL-87556-main-v3' of https://github.com/yusufwib01/moodle

This commit is contained in:
Huong Nguyen
2026-03-12 14:54:23 +07:00
17 changed files with 108 additions and 103 deletions
@@ -88,7 +88,12 @@ class login_form extends \moodleform {
$this->globalmanager->definition_after_data($mform);
$buttonarray = [];
$buttonarray[] = &$mform->createElement('submit', 'submitbutton', get_string('loginsubmit', 'factor_' . $factor->name));
$buttonarray[] = &$mform->createElement(
'submit',
'submitbutton',
get_string('loginsubmit', 'factor_' . $factor->name),
['class' => 'tool-mfa-verify-submit w-100'],
);
$mform->addGroup($buttonarray, 'buttonar', '', [' '], false);
$mform->closeHeaderBefore('buttonar');
}
@@ -53,7 +53,7 @@ class verification_field extends \MoodleQuickForm_text {
$attributes['inputmode'] = 'numeric';
$attributes['pattern'] = '[0-9]*';
// Overwrite default classes if set.
$attributes['class'] = isset($attributes['class']) ? $attributes['class'] : 'tool-mfa-verification-code fw-bold';
$attributes['class'] = isset($attributes['class']) ? $attributes['class'] : 'tool-mfa-verification-code';
$attributes['maxlength'] = 6;
// If we aren't on the auth page, this might be part of a larger form such as for setup.
@@ -640,7 +640,6 @@ class renderer extends \plugin_renderer_base {
if ($loginfactor->name != $factor->name) {
$additionalfactor = [
'name' => $loginfactor->name,
'icon' => $loginfactor->get_icon(),
'loginoption' => get_string('loginoption', 'factor_' . $loginfactor->name),
];
// We mark the factor as disabled if it is locked.
@@ -687,9 +686,8 @@ class renderer extends \plugin_renderer_base {
}
$context = [
'logintitle' => get_string('logintitle', 'factor_'.$factor->name),
'logintitle' => get_string('logintitle', 'tool_mfa'),
'logindesc' => $factor->get_login_desc(),
'factoricon' => $factor->get_icon(),
'form' => $form->render(),
'hasadditionalfactors' => $hasadditionalfactors,
'additionalfactors' => $alladitionalfactors,
@@ -0,0 +1 @@
logintitle,factor_email
@@ -44,11 +44,10 @@ $string['error:parameters'] = 'Incorrect page parameters.';
$string['error:wrongverification'] = 'Wrong code. Try again.';
$string['event:unauthemail'] = 'Unauthorised email received';
$string['info'] = 'You are using email {$a} to authenticate. This has been set up by your site administrator.';
$string['logindesc'] = 'We\'ve just sent a 6-digit code to your email: {$a}';
$string['loginoption'] = 'Have a code emailed to you';
$string['logindesc'] = 'To keep your account safe, we need to check that it\'s really you. We\'ve sent a code to <strong>{$a}</strong>. Please enter the code below to continue.';
$string['loginoption'] = 'Receive code via email';
$string['loginskip'] = "I didn't receive a code";
$string['loginsubmit'] = 'Continue';
$string['logintitle'] = "Verify it's you by email";
$string['managefactor'] = 'Manage email';
$string['manageinfo'] = '\'{$a}\' is being used to authenticate. This has been set up by your administrator.';
$string['pluginname'] = 'Email';
@@ -66,3 +65,6 @@ IP {$a->ip} with browser agent {$a->useragent}.';
$string['unauthemail'] = 'Unauthorised email';
$string['verificationcode'] = 'Enter verification code for confirmation';
$string['verificationcode_help'] = 'A verification code has been sent to your email.';
// Deprecated since Moodle 5.2.
$string['logintitle'] = "Verify it's you by email";
@@ -13,3 +13,4 @@ settings:gateway_help,factor_sms
errorawsconection,factor_sms
event:smssentdescription,factor_sms
event:smssent,factor_sms
logintitle,factor_sms
@@ -34,8 +34,8 @@ $string['error:emptyverification'] = 'Empty code. Try again.';
$string['error:wrongphonenumber'] = 'The phone number you provided is not in a valid format.';
$string['error:wrongverification'] = 'Wrong code. Try again.';
$string['info'] = 'Have a verification code sent to the mobile number you choose.';
$string['logindesc'] = 'SMS message containing a 6-digit code sent to mobile number {$a}';
$string['loginoption'] = 'Have a code sent to your mobile phone';
$string['logindesc'] = 'To keep your account safe, we need to check that it\'s really you. We\'ve sent a code to <strong>{$a}</strong>. Please enter the code below to continue.';
$string['loginoption'] = 'Receive code via SMS';
$string['loginskip'] = "I didn't receive a code";
$string['loginsubmit'] = 'Continue';
$string['managefactor'] = 'Manage SMS';
@@ -43,7 +43,6 @@ $string['managefactorbutton'] = 'Manage';
$string['manageinfo'] = 'You are using \'{$a}\' to authenticate.';
$string['notification:smsgatewaymigration'] = 'SMS settings have moved';
$string['notification:smsgatewaymigrationinfo'] = 'A new SMS subsystem is now available for managing and configuring all SMS-related functions. Your existing SMS configurations have been migrated to the page <a href="{$a}">SMS gateways</a>.';
$string['logintitle'] = 'Enter the verification code sent to your mobile';
$string['phonehelp'] = 'Enter your mobile number (including country code) to receive a verification code.';
$string['pluginname'] = 'SMS';
$string['privacy:metadata'] = 'The SMS factor plugin does not store any personal data.';
@@ -84,3 +83,6 @@ $string['settings:gateway_help'] = 'The SMS provider you wish to send messages v
$string['errorawsconection'] = 'Error connecting to AWS server: {$a}';
$string['event:smssentdescription'] = 'The user with ID {$a->userid} was sent a verification code via SMS. Information: {$a->debuginfo}';
$string['event:smssent'] = 'SMS message sent.';
// Deprecated since Moodle 5.2.
$string['logintitle'] = 'Enter the verification code sent to your mobile';
@@ -35,7 +35,7 @@ Feature: Login user with sms authentication factor
Scenario: Login user successfully with sms verification
Given I log out
And I log in as "admin"
And I should see "2-step verification"
And I should see "We need to verify your identity"
And I should see "Enter code"
When I set the field "Enter code" with valid code
And I click on "Continue" "button"
@@ -44,7 +44,7 @@ Feature: Login user with sms authentication factor
Scenario: Wrong code number end of possible attempts
Given I log out
And I log in as "admin"
And I should see "2-step verification"
And I should see "We need to verify your identity"
And I should see "Enter code"
When I set the field "Enter code" to "555556"
And I click on "Continue" "button"
@@ -0,0 +1 @@
logintitle,factor_totp
@@ -38,11 +38,10 @@ $string['error:oldcode'] = 'This code is too old. Please verify the time on your
$string['error:wrongverification'] = 'Incorrect verification code.';
$string['factorsetup'] = 'App setup';
$string['info'] = 'Generate a verification code using an authenticator app.';
$string['logindesc'] = 'Use the authenticator app in your mobile device to generate a code.';
$string['loginoption'] = 'Use Authenticator application';
$string['logindesc'] = 'To keep your account safe, we need to check that it\'s really you. Click continue to use your <strong>authenticator app.</strong>';
$string['loginoption'] = 'Receive code via authenticator app';
$string['loginskip'] = 'I don\'t have my device';
$string['loginsubmit'] = 'Continue';
$string['logintitle'] = 'Verify it\'s you by mobile app';
$string['managefactor'] = 'Manage authenticator app';
$string['managefactorbutton'] = 'Manage';
$string['manageinfo'] = 'You are using \'{$a}\' to authenticate.';
@@ -83,3 +82,6 @@ $string['summarycondition'] = 'using a TOTP app';
$string['systimeformat'] = '%l:%M:%S %P %Z';
$string['verificationcode'] = 'Enter your 6 digit verification code';
$string['verificationcode_help'] = 'Open your authenticator app such as Google Authenticator and look for the 6 digit code which matches this site and username';
// Deprecated since Moodle 5.2.
$string['logintitle'] = 'Verify it\'s you by mobile app';
@@ -0,0 +1 @@
logintitle,factor_webauthn
@@ -34,11 +34,10 @@ $string['authenticatorname'] = 'Security key name';
$string['error'] = 'Failed to authenticate';
$string['error:alreadyregistered'] = 'This security key secret has already been registered.';
$string['info'] = 'Use a physical security key or fingerprint scanner.';
$string['logindesc'] = 'Click continue to use your security key.';
$string['loginoption'] = 'Use security key';
$string['logindesc'] = 'To keep your account safe, we need to check that it\'s really you. Click continue to use your security key.';
$string['loginoption'] = 'Verify via security key';
$string['loginskip'] = 'I don\'t have my security key';
$string['loginsubmit'] = 'Continue';
$string['logintitle'] = 'Verify it\'s you by security key';
$string['pluginname'] = 'Security key';
$string['privacy:metadata'] = 'The Security key factor plugin does not store any personal data.';
$string['register'] = 'Register security key';
@@ -68,3 +67,6 @@ $string['manageinfo'] = 'You are using \'{$a}\' to authenticate.';
$string['userverification:discouraged'] = 'User verification should not be employed, for example to minimize user interaction';
$string['userverification:preferred'] = 'User verification is preferred, authentication will not fail if user verification is missing';
$string['userverification:required'] = 'User verification is required (e.g. by pin). Authentication fails if key does not have user verification';
// Deprecated since Moodle 5.2.
$string['logintitle'] = 'Verify it\'s you by security key';
@@ -1,2 +1,6 @@
inputrequired,tool_mfa
setuprequired,tool_mfa
cancellogin,tool_mfa
verification,tool_mfa
verification_desc,tool_mfa
verifyalt,tool_mfa
+8 -4
View File
@@ -29,7 +29,7 @@ $string['achievedweight'] = 'Achieved weight';
$string['added'] = 'Added';
$string['alltime'] = 'All time';
$string['areyousure'] = 'Are you sure you want to remove this factor?';
$string['cancellogin'] = 'Cancel login';
$string['backtologin'] = 'Back to Log in';
$string['combination'] = 'Combination';
$string['confirmationreplace'] = 'You will be immediately required to set up another \'{$a}\'. Please make sure you are ready to complete the setup process.';
$string['confirmationrevoke'] = 'You will no longer be able to use \'{$a}\' to log in to this site.';
@@ -73,6 +73,7 @@ $string['fallback_info'] = 'This factor is a fallback if no other factors are co
$string['guidance'] = 'Multi-factor authentication user guide';
$string['ipatcreation'] = 'IP address when factor created';
$string['lastused'] = 'Last used';
$string['logintitle'] = 'We need to verify your identity';
$string['locked'] = '{$a} (Unavailable)';
$string['lockedusersforallfactors'] = 'Locked users: All factors';
$string['lockedusersforfactor'] = 'Locked users: {$a}';
@@ -165,11 +166,8 @@ $string['userempty'] = 'User cannot be empty.';
$string['userlogs'] = 'User logs';
$string['usernotfound'] = 'Unable to locate user.';
$string['usersauthedinperiod'] = 'Logged in';
$string['verification'] = '2-step verification';
$string['verification_desc'] = 'To keep your account safe, we need to check that this is really you.';
$string['verificationcode'] = 'Verification code';
$string['verificationcode_help'] = 'The verification code provided by the current authentication factor.';
$string['verifyalt'] = 'Try another way to verify:';
$string['weight'] = 'Weight';
$string['yesremove'] = 'Yes, remove';
$string['yesreplace'] = 'Yes, replace';
@@ -177,3 +175,9 @@ $string['yesreplace'] = 'Yes, replace';
// Deprecated since Moodle 5.0.
$string['inputrequired'] = 'User input';
$string['setuprequired'] = 'User setup';
// Deprecated since Moodle 5.2.
$string['cancellogin'] = 'Cancel login';
$string['verification'] = '2-step verification';
$string['verification_desc'] = 'To keep your account safe, we need to check that this is really you.';
$string['verifyalt'] = 'Try another way to verify:';
+27 -27
View File
@@ -1,36 +1,12 @@
input.tool-mfa-verification-code,
.tool-mfa-verification-code input {
/* Some elements must be important to override form element*/
font-size: 1.5em !important; /* stylelint-disable-line declaration-no-important */
font-family: monospace;
text-align: center;
letter-spacing: 1.0em;
font-weight: bold;
}
.tool-mfa-factor-choose,
.tool-mfa-factor-choose:hover {
background-color: #fff;
border-color: #3584c9;
border-width: 1px;
width: 100%;
border-radius: 0.5rem;
}
.tool-mfa-factor-choose:hover,
.tool-mfa-factor-choose:hover .tool-mfa-factor-choose-text {
text-decoration: underline;
color: #094478;
background-color: #cfe2f2;
}
.mfa-verify-form input[type="submit"] {
height: 50px;
font-size: 1.05rem;
}
.mfa-verify-form .invalid-feedback {
font-weight: 700;
margin-top: 0.25rem;
background-color: #e9ecef;
border-color: #6a737b;
}
.mfa-verify-form .form-group.fitem,
@@ -38,3 +14,27 @@ input.tool-mfa-verification-code,
.mfa-verify-form .form-group.fitem > span > input {
width: 100%;
}
input.tool-mfa-verify-submit,
.tool-mfa-verify-submit input {
width: 100%;
margin-top: 1rem;
}
@media (max-width: 991.98px) {
.tool-mfa-verify-container {
padding-right: 16px;
padding-left: 16px;
}
.login-layout-right-content:has(.tool-mfa-verify-container) {
margin-top: 0;
}
}
@media (max-width: 767.98px) {
.tool-mfa-verify-container .mfa-verify-form {
margin-right: -16px;
margin-left: -16px;
}
}
@@ -21,78 +21,60 @@
Example context (json):
{
"logintitle": "We've just sent a 6-digit code to your email",
"logintitle": "We need to verify your identity",
"logindesc": "Use the Google Authenticator app to generate a code.",
"factoricon": "fa-envelope",
"form": "<form id=\"mfa-verify-form\" method=\"POST\" action=\"https:\/\/webserver\/admin\/tool\/mfa\/auth.php\"></form>",
"hasadditionalfactors": true,
"additionalfactors": [
{
"name": "webauthn",
"icon": "fa-hand-pointer",
"loginoption": "Use authenticator token"
}
],
"authurl": "https:\/\/webserver\/admin\/tool\/mfa\/auth.php",
"supportlink": "<a href=\"https:\/\/webserver\/user\/contactsitesupport.php\">Contact site support<\/a>",
"supportlink": "<a href=\"https:\/\/webserver\/user\/contactsitesupport.php\">Contact your site support<\/a>",
"disablefactor": false
}
}}
<div>
<div class="row">
<div class="col-12">
<h2>{{#str}} verification, tool_mfa {{/str}}</h2>
<p>{{#str}} verification_desc, tool_mfa {{/str}}</p>
</div>
</div>
<div class="mb-4 border-bottom"></div>
<div class="tool-mfa-verify-container">
<div class="d-flex align-items-start pb-2 {{#disablefactor}}text-muted{{/disablefactor}}">
<div class="pt-1" style="flex: 0 0 auto;">
<i class="fa {{factoricon}} fa-fw fa-2x" title="{{logintitle}}" role="img" aria-label="{{logintitle}}"></i>
</div>
<div style="flex: 1 1 auto; padding-left: 15px;" class="text-wrap">
<strong>{{logintitle}}</strong><br>
{{logindesc}}
<div class="mb-2">
<h1 class="h2 mb-2">{{logintitle}}</h1>
<p class="text-muted">{{{logindesc}}}</p>
</div>
</div>
</div>
<div class="mfa-verify-form">
{{{form}}}
</div>
{{#hasadditionalfactors}}
<div class="mb-6 mt-4 border-bottom"></div>
<p class="fw-bold mb-1">{{#str}} verifyalt, tool_mfa {{/str}}</p>
{{/hasadditionalfactors}}
{{#additionalfactors}}
<form id="{{uniqid}}-nextfactor" method="POST" action="{{{authurl}}}">
<div class="mfa-verify-form">
{{{form}}}
</div>
<div class="form-container text-center mt-3">
<div class="d-flex justify-content-center">
<form id="cancelmfa" method="POST" action="{{{authurl}}}">
<input type="hidden" id="{{uniqid}}-logout" name="logout" value="true">
<input type="hidden" name="sesskey" value="{{sesskey}}">
<input type="submit" class="btn btn-link"
name="cancelmfa" id="cancelmfa_button"
value="{{#str}} backtologin, tool_mfa {{/str}}">
</form>
</div>
</div>
{{#hasadditionalfactors}}
<div class="login-separator my-5">{{#str}}loginseparatoror{{/str}}</div>
{{/hasadditionalfactors}}
{{#additionalfactors}}
<form class="pt-2" id="{{uniqid}}-nextfactor" method="POST" action="{{{authurl}}}">
<input type="hidden" id="{{uniqid}}-factorname" name="factorname" value="{{name}}">
<button class="btn-link text-decoration-none tool-mfa-factor-choose d-flex align-items-center p-1 mb-2 {{#disable}}disabled{{/disable}}"
type="submit">
<span class="icon-no-margin icon-size-3 d-flex p-1 me-2">
<i class="fa {{icon}} fa-fw fa-2x"
title="{{logintitle}}"
role="img"
aria-label="{{logintitle}}"></i>
</span>
<span class="tool-mfa-factor-choose-text mfa-login-option">{{loginoption}}</span>
<button class="btn btn-secondary w-100 mb-2 {{#disable}}disabled{{/disable}}" type="submit">
<span>{{loginoption}}</span>
</button>
</form>
{{/additionalfactors}}
<div class="form-container text-center mt-3">
<div class="d-flex justify-content-center">
<form id="cancelmfa" method="POST" action="{{{authurl}}}">
<input type="hidden" id="{{uniqid}}-logout" name="logout" value="true">
<input type="hidden" name="sesskey" value="{{sesskey}}">
<input type="submit" class="btn btn-secondary"
name="cancelmfa" id="cancelmfa_button"
value="{{#str}} cancellogin, tool_mfa {{/str}}">
</form>
{{/additionalfactors}}
<div class="form-container text-center mt-3">
{{#supportlink}}
<div class="tool-mfa-site-support mt-4">
{{#str}} needhelp, tool_mfa {{/str}} {{{supportlink}}}
</div>
{{/supportlink}}
</div>
{{#supportlink}}
<div class="tool-mfa-site-support mt-4">
{{#str}} needhelp, tool_mfa {{/str}} {{{supportlink}}}
</div>
{{/supportlink}}
</div>
@@ -312,4 +312,4 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
When I press "Next"
Then I should see "2-step verification"
Then I should see "We need to verify your identity"