Show password policy flags on Special:PasswordPolicies
Follow-up to I28c31fc4ea. Also improves what policy values are considered disabled, documents how to extend core checks/flags and adds a structure test for it. Bug: T118774 Change-Id: I66bf396e8e8a8c310a47ba337abe9070e7e83ff6
This commit is contained in:
parent
56fa42d433
commit
22c8cda841
6 changed files with 92 additions and 14 deletions
|
|
@ -4483,6 +4483,13 @@ $wgCentralIdLookupProvider = 'local';
|
|||
* 100,000 commonly used passwords. Due to the size of the list this
|
||||
* is a probabilistic test.
|
||||
*
|
||||
* If you add custom checks, for Special:PasswordPolicies to display them correctly,
|
||||
* every check should have a corresponding passwordpolicies-policy-<check> message,
|
||||
* and every settings field other than 'value' should have a corresponding
|
||||
* passwordpolicies-policyflag-<flag> message (<check> and <flag> are in lowercase).
|
||||
* The check message receives the policy value as a parameter, the flag message
|
||||
* receives the flag value (or values if it's an array).
|
||||
*
|
||||
* @since 1.26
|
||||
* @see PasswordPolicyChecks
|
||||
* @see User::checkPasswordValidity()
|
||||
|
|
|
|||
|
|
@ -136,20 +136,37 @@ class SpecialPasswordPolicies extends SpecialPage {
|
|||
);
|
||||
|
||||
$ret = [];
|
||||
foreach ( $groupPolicies as $gp => $val ) {
|
||||
if ( $val === false ) {
|
||||
// Policy isn't enabled, so no need to dislpay it
|
||||
continue;
|
||||
} elseif ( $val === true ) {
|
||||
$msg = $this->msg( 'passwordpolicies-policy-' . strtolower( $gp ) );
|
||||
} else {
|
||||
$msg = $this->msg( 'passwordpolicies-policy-' . strtolower( $gp ) )->numParams( $val );
|
||||
foreach ( $groupPolicies as $gp => $settings ) {
|
||||
if ( !is_array( $settings ) ) {
|
||||
$settings = [ 'value' => $settings ];
|
||||
}
|
||||
$val = $settings['value'];
|
||||
$flags = array_diff_key( $settings, [ 'value' => true ] );
|
||||
if ( !$val ) {
|
||||
// Policy isn't enabled, so no need to display it
|
||||
continue;
|
||||
}
|
||||
$msg = $this->msg( 'passwordpolicies-policy-' . strtolower( $gp ) )->numParams( $val );
|
||||
$flagMsgs = [];
|
||||
foreach ( array_filter( $flags ) as $flag => $value ) {
|
||||
$flagMsg = $this->msg( 'passwordpolicies-policyflag-' . strtolower( $flag ) );
|
||||
$flagMsg->params( $value );
|
||||
$flagMsgs[] = $flagMsg;
|
||||
}
|
||||
if ( $flagMsgs ) {
|
||||
$ret[] = $this->msg(
|
||||
'passwordpolicies-policy-displaywithflags',
|
||||
$msg,
|
||||
'<span class="mw-passwordpolicies-policy-name">' . $gp . '</span>',
|
||||
$this->getLanguage()->commaList( $flagMsgs )
|
||||
)->parse();
|
||||
} else {
|
||||
$ret[] = $this->msg(
|
||||
'passwordpolicies-policy-display',
|
||||
$msg,
|
||||
'<span class="mw-passwordpolicies-policy-name">' . $gp . '</span>'
|
||||
)->parse();
|
||||
}
|
||||
$ret[] = $this->msg(
|
||||
'passwordpolicies-policy-display',
|
||||
$msg,
|
||||
'<span class="mw-passwordpolicies-policy-name">' . $gp . '</span>'
|
||||
)->parse();
|
||||
}
|
||||
if ( $ret === [] ) {
|
||||
return '';
|
||||
|
|
|
|||
|
|
@ -4173,6 +4173,7 @@
|
|||
"passwordpolicies-group": "Group",
|
||||
"passwordpolicies-policies": "Policies",
|
||||
"passwordpolicies-policy-display": "<span class=\"passwordpolicies-policy\">$1 <code>($2)</code></span>",
|
||||
"passwordpolicies-policy-displaywithflags": "<span class=\"passwordpolicies-policy\">$1 <code>($2)</code></span> <span class=\"passwordpolicies-policy-flags\">($3)</span>",
|
||||
"passwordpolicies-policy-minimalpasswordlength": "Password must be at least $1 {{PLURAL:$1|character|characters}} long",
|
||||
"passwordpolicies-policy-minimumpasswordlengthtologin": "Password must be at least $1 {{PLURAL:$1|character|characters}} long to be able to login",
|
||||
"passwordpolicies-policy-passwordcannotmatchusername": "Password cannot be the same as username",
|
||||
|
|
@ -4180,6 +4181,7 @@
|
|||
"passwordpolicies-policy-maximalpasswordlength": "Password must be less than $1 {{PLURAL:$1|character|characters}} long",
|
||||
"passwordpolicies-policy-passwordcannotbepopular": "Password cannot be {{PLURAL:$1|the popular password|in the list of $1 popular passwords}}",
|
||||
"passwordpolicies-policy-passwordnotinlargeblacklist": "Password cannot be in the list of 100,000 most commonly used passwords.",
|
||||
"passwordpolicies-policyflag-forcechange": "must change on login",
|
||||
"easydeflate-invaliddeflate": "Content provided is not properly deflated",
|
||||
"unprotected-js": "For security reasons JavaScript cannot be loaded from unprotected pages. Please only create javascript in the MediaWiki: namespace or as a User subpage"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4377,7 +4377,8 @@
|
|||
"passwordpolicies-summary": "The description used on [[Special:PasswordPolicies]].\n\nRefers to {{msg-mw|Passwordpolicies-helppage}}.",
|
||||
"passwordpolicies-group": "The title of the column in the table, about user groups (like you are in the ''translator'' group).\n\n{{Identical|Group}}\n{{Related|Passwordpolicies}}",
|
||||
"passwordpolicies-policies": "The title of the column in the table, about password policies.\n{{Related|Passwordpolicies}}",
|
||||
"passwordpolicies-policy-display": "{{optional}}\nParameters:\n* $1 - the text from the \"passwordpolicies-policy-...\" messages, i.e. {{msg-mw|passwordpolicies-policy-minimalpasswordlength}}\n* $2 - the name of this password policy",
|
||||
"passwordpolicies-policy-display": "{{optional}}\nParameters:\n* $1 - the text from the \"passwordpolicies-policy-...\" messages, e.g. {{msg-mw|passwordpolicies-policy-minimalpasswordlength}}\n* $2 - the name of this password policy",
|
||||
"passwordpolicies-policy-displaywithflags": "{{optional}}\nParameters:\n* $1 - the text from the \"passwordpolicies-policy-...\" messages, i.e. {{msg-mw|passwordpolicies-policy-minimalpasswordlength}}\n* $2 - the name of this password policy\n* $3 - comma-separated list of the text from the \"passwordpolicies-policyflag-...\" messages, e.g. {{msg-mw|passwordpolicies-policyflag-forcechange}}",
|
||||
"passwordpolicies-policy-minimalpasswordlength": "Password policy that enforces a minimum number of characters a password must be. $1 - minimum number of characters that a password can be",
|
||||
"passwordpolicies-policy-minimumpasswordlengthtologin": "Password policy that enforces a minimum number of characters a password must be to be able to login to the wiki. $1 - minimum number of characters that a password can be to be able to login",
|
||||
"passwordpolicies-policy-passwordcannotmatchusername": "Password policy that enforces that the password of the account cannot be the same as the username",
|
||||
|
|
@ -4385,6 +4386,7 @@
|
|||
"passwordpolicies-policy-maximalpasswordlength": "Password policy that enforces a maximum number of characters a password must be. $1 - maximum number of characters that a password can be",
|
||||
"passwordpolicies-policy-passwordcannotbepopular": "Password policy that enforces that a password is not in a list of $1 number of \"popular\" passwords. $1 - number of popular passwords the password will be checked against",
|
||||
"passwordpolicies-policy-passwordnotinlargeblacklist": "Password policy that enforces that a password is not in a list of 100,000 number of \"popular\" passwords.",
|
||||
"passwordpolicies-policyflag-forcechange": "Password policy flag that enforces changing invalid passwords on login.",
|
||||
"easydeflate-invaliddeflate": "Error message if the content passed to easydeflate was not deflated (compressed) properly",
|
||||
"unprotected-js": "Error message shown when trying to load javascript via action=raw that is not protected"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,3 +156,7 @@
|
|||
.mw-passwordpolicies-table tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.passwordpolicies-policy-flags {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
|
|
|||
46
tests/phpunit/structure/PasswordPolicyStructureTest.php
Normal file
46
tests/phpunit/structure/PasswordPolicyStructureTest.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @coversNothing
|
||||
*/
|
||||
class PasswordPolicyStructureTest extends MediaWikiTestCase {
|
||||
|
||||
public function provideChecks() {
|
||||
global $wgPasswordPolicy;
|
||||
|
||||
foreach ( $wgPasswordPolicy['checks'] as $name => $callback ) {
|
||||
yield [ $name ];
|
||||
}
|
||||
}
|
||||
|
||||
public function provideFlags() {
|
||||
global $wgPasswordPolicy;
|
||||
|
||||
// This won't actually find all flags, just the ones in use. Can't really be helped,
|
||||
// other than adding the core flags here.
|
||||
$flags = [ 'forceChange' ];
|
||||
foreach ( $wgPasswordPolicy['policies'] as $group => $checks ) {
|
||||
foreach ( $checks as $check => $settings ) {
|
||||
if ( is_array( $settings ) ) {
|
||||
$flags = array_merge( $flags, array_diff( $settings, [ 'value' ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ( $flags as $flag ) {
|
||||
yield [ $flag ];
|
||||
}
|
||||
}
|
||||
|
||||
/** @dataProvider provideChecks */
|
||||
public function testCheckMessage( $check ) {
|
||||
$msg = wfMessage( 'passwordpolicies-policy-' . strtolower( $check ) );
|
||||
$this->assertTrue( $msg->exists() );
|
||||
}
|
||||
|
||||
/** @dataProvider provideFlags */
|
||||
public function testFlagMessage( $flag ) {
|
||||
$msg = wfMessage( 'passwordpolicies-policyflag-' . strtolower( $flag ) );
|
||||
$this->assertTrue( $msg->exists() );
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue