Segregate right to edit sitewide CSS/JS
To limit the likelihood of incidents like T189665, the ability to edit sitewide CSS/JSON/JS is split out from editinterface, into separate 'editsitecss', 'editsitejson' and 'editsitejs' rights. editsitecss, editsitejs, and the right to edit another (potentially more privileged) user's personal CSS/JS is removed from sysops, and a new user group, interface-admin, is created specifically for that task (along with a new grant group 'editsiteconfig'). interface-admin is granted to the first user of a new wiki, along with sysop and bureaucrat. Bug: T120886 Bug: T190015 Depends-On: Ia9b2ea1450aff6121dc0f3777bf029292c8aaad9 Change-Id: Ifefd872640642441e26f8b2f144ffe4b88d2eb12
This commit is contained in:
parent
69a9b1af2b
commit
db888bc5ad
10 changed files with 158 additions and 32 deletions
|
|
@ -29,6 +29,14 @@ production.
|
|||
* The archive table's ar_rev_id field is now unique.
|
||||
* Special:BotPasswords now requires reauthentication.
|
||||
* (T194414) The default watchlist view time has been increased from 3 to 7 days.
|
||||
* The right to edit sitewide Javascript (e.g. MediaWiki:Common.js), CSS or JSON
|
||||
was separated from 'editinterface' and is available under
|
||||
'editsitejs'/'editsitecss'/'editsitejson'. Having 'editinterface' is still
|
||||
necessary to edit such pages.
|
||||
* A new user group, 'interface-admin', is added for controlling access to
|
||||
sitewide CSS/JS (and editing other users' CSS/JS). No other group has
|
||||
'editsitecss', 'editusercss', 'editsitejs' or 'edituserjs' by default.
|
||||
* A new grant group, 'editsiteconfig', is added for granting the above rights.
|
||||
|
||||
=== New features in 1.32 ===
|
||||
* (T112474) Generalized the ResourceLoader mechanism for overriding modules
|
||||
|
|
|
|||
|
|
@ -4548,6 +4548,12 @@ $wgPasswordPolicy = [
|
|||
'PasswordCannotMatchUsername' => true,
|
||||
'PasswordCannotBePopular' => 25,
|
||||
],
|
||||
'interface-admin' => [
|
||||
'MinimalPasswordLength' => 8,
|
||||
'MinimumPasswordLengthToLogin' => 1,
|
||||
'PasswordCannotMatchUsername' => true,
|
||||
'PasswordCannotBePopular' => 25,
|
||||
],
|
||||
'bot' => [
|
||||
'MinimalPasswordLength' => 8,
|
||||
'MinimumPasswordLengthToLogin' => 1,
|
||||
|
|
@ -5217,9 +5223,8 @@ $wgGroupPermissions['sysop']['deletedhistory'] = true;
|
|||
$wgGroupPermissions['sysop']['deletedtext'] = true;
|
||||
$wgGroupPermissions['sysop']['undelete'] = true;
|
||||
$wgGroupPermissions['sysop']['editinterface'] = true;
|
||||
$wgGroupPermissions['sysop']['editusercss'] = true;
|
||||
$wgGroupPermissions['sysop']['editsitejson'] = true;
|
||||
$wgGroupPermissions['sysop']['edituserjson'] = true;
|
||||
$wgGroupPermissions['sysop']['edituserjs'] = true;
|
||||
$wgGroupPermissions['sysop']['import'] = true;
|
||||
$wgGroupPermissions['sysop']['importupload'] = true;
|
||||
$wgGroupPermissions['sysop']['move'] = true;
|
||||
|
|
@ -5252,6 +5257,14 @@ $wgGroupPermissions['sysop']['mergehistory'] = true;
|
|||
$wgGroupPermissions['sysop']['managechangetags'] = true;
|
||||
$wgGroupPermissions['sysop']['deletechangetags'] = true;
|
||||
|
||||
$wgGroupPermissions['interface-admin']['editinterface'] = true;
|
||||
$wgGroupPermissions['interface-admin']['editsitecss'] = true;
|
||||
$wgGroupPermissions['interface-admin']['editsitejson'] = true;
|
||||
$wgGroupPermissions['interface-admin']['editsitejs'] = true;
|
||||
$wgGroupPermissions['interface-admin']['editusercss'] = true;
|
||||
$wgGroupPermissions['interface-admin']['edituserjson'] = true;
|
||||
$wgGroupPermissions['interface-admin']['edituserjs'] = true;
|
||||
|
||||
// Permission to change users' group assignments
|
||||
$wgGroupPermissions['bureaucrat']['userrights'] = true;
|
||||
$wgGroupPermissions['bureaucrat']['noratelimit'] = true;
|
||||
|
|
@ -5858,9 +5871,14 @@ $wgGrantPermissions['editmyoptions']['editmyoptions'] = true;
|
|||
|
||||
$wgGrantPermissions['editinterface'] = $wgGrantPermissions['editpage'];
|
||||
$wgGrantPermissions['editinterface']['editinterface'] = true;
|
||||
$wgGrantPermissions['editinterface']['editusercss'] = true;
|
||||
$wgGrantPermissions['editinterface']['edituserjson'] = true;
|
||||
$wgGrantPermissions['editinterface']['edituserjs'] = true;
|
||||
$wgGrantPermissions['editinterface']['editsitejson'] = true;
|
||||
|
||||
$wgGrantPermissions['editsiteconfig'] = $wgGrantPermissions['editinterface'];
|
||||
$wgGrantPermissions['editsiteconfig']['editusercss'] = true;
|
||||
$wgGrantPermissions['editsiteconfig']['edituserjs'] = true;
|
||||
$wgGrantPermissions['editsiteconfig']['editsitecss'] = true;
|
||||
$wgGrantPermissions['editsiteconfig']['editsitejs'] = true;
|
||||
|
||||
$wgGrantPermissions['createeditmovepage'] = $wgGrantPermissions['editpage'];
|
||||
$wgGrantPermissions['createeditmovepage']['createpage'] = true;
|
||||
|
|
@ -5939,6 +5957,7 @@ $wgGrantPermissionGroups = [
|
|||
'editmyoptions' => 'customization',
|
||||
|
||||
'editinterface' => 'administration',
|
||||
'editsiteconfig' => 'administration',
|
||||
'rollback' => 'administration',
|
||||
'blockusers' => 'administration',
|
||||
'delete' => 'administration',
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ class MWGrants {
|
|||
// Give grep a chance to find the usages:
|
||||
// grant-blockusers, grant-createeditmovepage, grant-delete,
|
||||
// grant-editinterface, grant-editmycssjs, grant-editmywatchlist,
|
||||
// grant-editpage, grant-editprotected, grant-highvolume,
|
||||
// grant-oversight, grant-patrol, grant-protect, grant-rollback,
|
||||
// grant-sendemail, grant-uploadeditmovefile, grant-uploadfile,
|
||||
// grant-basic, grant-viewdeleted, grant-viewmywatchlist,
|
||||
// grant-createaccount
|
||||
// grant-editsiteconfig, grant-editpage, grant-editprotected,
|
||||
// grant-highvolume, grant-oversight, grant-patrol, grant-protect,
|
||||
// grant-rollback, grant-sendemail, grant-uploadeditmovefile,
|
||||
// grant-uploadfile, grant-basic, grant-viewdeleted,
|
||||
// grant-viewmywatchlist, grant-createaccount
|
||||
$msg = wfMessage( "grant-$grant" );
|
||||
if ( $lang !== null ) {
|
||||
if ( is_string( $lang ) ) {
|
||||
|
|
|
|||
|
|
@ -1289,12 +1289,9 @@ class Title implements LinkTarget {
|
|||
*/
|
||||
public function isSiteConfigPage() {
|
||||
return (
|
||||
NS_MEDIAWIKI == $this->mNamespace
|
||||
&& (
|
||||
$this->hasContentModel( CONTENT_MODEL_CSS )
|
||||
|| $this->hasContentModel( CONTENT_MODEL_JSON )
|
||||
|| $this->hasContentModel( CONTENT_MODEL_JAVASCRIPT )
|
||||
)
|
||||
$this->isSiteCssConfigPage()
|
||||
|| $this->isSiteJsonConfigPage()
|
||||
|| $this->isSiteJsConfigPage()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1317,13 +1314,9 @@ class Title implements LinkTarget {
|
|||
*/
|
||||
public function isUserConfigPage() {
|
||||
return (
|
||||
NS_USER == $this->mNamespace
|
||||
&& $this->isSubpage()
|
||||
&& (
|
||||
$this->hasContentModel( CONTENT_MODEL_CSS )
|
||||
|| $this->hasContentModel( CONTENT_MODEL_JSON )
|
||||
|| $this->hasContentModel( CONTENT_MODEL_JAVASCRIPT )
|
||||
)
|
||||
$this->isUserCssConfigPage()
|
||||
|| $this->isUserJsonConfigPage()
|
||||
|| $this->isUserJsConfigPage()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1423,6 +1416,60 @@ class Title implements LinkTarget {
|
|||
return $this->isUserJsConfigPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a sitewide CSS "config" page?
|
||||
*
|
||||
* @return bool
|
||||
* @since 1.32
|
||||
*/
|
||||
public function isSiteCssConfigPage() {
|
||||
return (
|
||||
NS_MEDIAWIKI == $this->mNamespace
|
||||
&& (
|
||||
$this->hasContentModel( CONTENT_MODEL_CSS )
|
||||
// paranoia - a MediaWiki: namespace page with mismatching extension and content
|
||||
// model is probably by mistake and might get handled incorrectly (see e.g. T112937)
|
||||
|| substr( $this->getDBkey(), -4 ) === '.css'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a sitewide JSON "config" page?
|
||||
*
|
||||
* @return bool
|
||||
* @since 1.32
|
||||
*/
|
||||
public function isSiteJsonConfigPage() {
|
||||
return (
|
||||
NS_MEDIAWIKI == $this->mNamespace
|
||||
&& (
|
||||
$this->hasContentModel( CONTENT_MODEL_JSON )
|
||||
// paranoia - a MediaWiki: namespace page with mismatching extension and content
|
||||
// model is probably by mistake and might get handled incorrectly (see e.g. T112937)
|
||||
|| substr( $this->getDBkey(), -5 ) === '.json'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a sitewide JS "config" page?
|
||||
*
|
||||
* @return bool
|
||||
* @since 1.31
|
||||
*/
|
||||
public function isSiteJsConfigPage() {
|
||||
return (
|
||||
NS_MEDIAWIKI == $this->mNamespace
|
||||
&& (
|
||||
$this->hasContentModel( CONTENT_MODEL_JAVASCRIPT )
|
||||
// paranoia - a MediaWiki: namespace page with mismatching extension and content
|
||||
// model is probably by mistake and might get handled incorrectly (see e.g. T112937)
|
||||
|| substr( $this->getDBkey(), -3 ) === '.js'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a talk page of some sort?
|
||||
*
|
||||
|
|
@ -2313,6 +2360,33 @@ class Title implements LinkTarget {
|
|||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check sitewide CSS/JSON/JS permissions
|
||||
*
|
||||
* @param string $action The action to check
|
||||
* @param User $user User to check
|
||||
* @param array $errors List of current errors
|
||||
* @param string $rigor Same format as Title::getUserPermissionsErrors()
|
||||
* @param bool $short Short circuit on first error
|
||||
*
|
||||
* @return array List of errors
|
||||
*/
|
||||
private function checkSiteConfigPermissions( $action, $user, $errors, $rigor, $short ) {
|
||||
if ( $action != 'patrol' ) {
|
||||
// Sitewide CSS/JSON/JS changes, like all NS_MEDIAWIKI changes, also require the
|
||||
// editinterface right. That's implemented as a restriction so no check needed here.
|
||||
if ( $this->isSiteCssConfigPage() && !$user->isAllowed( 'editsitecss' ) ) {
|
||||
$errors[] = [ 'sitecssprotected', $action ];
|
||||
} elseif ( $this->isSiteJsonConfigPage() && !$user->isAllowed( 'editsitejson' ) ) {
|
||||
$errors[] = [ 'sitejsonprotected', $action ];
|
||||
} elseif ( $this->isSiteJsConfigPage() && !$user->isAllowed( 'editsitejs' ) ) {
|
||||
$errors[] = [ 'sitejsprotected', $action ];
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check CSS/JSON/JS sub-page permissions
|
||||
*
|
||||
|
|
@ -2701,10 +2775,10 @@ class Title implements LinkTarget {
|
|||
'checkReadPermissions',
|
||||
'checkUserBlock', // for wgBlockDisablesLogin
|
||||
];
|
||||
# Don't call checkSpecialsAndNSPermissions or checkUserConfigPermissions
|
||||
# here as it will lead to duplicate error messages. This is okay to do
|
||||
# since anywhere that checks for create will also check for edit, and
|
||||
# those checks are called for edit.
|
||||
# Don't call checkSpecialsAndNSPermissions, checkSiteConfigPermissions
|
||||
# or checkUserConfigPermissions here as it will lead to duplicate
|
||||
# error messages. This is okay to do since anywhere that checks for
|
||||
# create will also check for edit, and those checks are called for edit.
|
||||
} elseif ( $action == 'create' ) {
|
||||
$checks = [
|
||||
'checkQuickPermissions',
|
||||
|
|
@ -2719,6 +2793,7 @@ class Title implements LinkTarget {
|
|||
'checkQuickPermissions',
|
||||
'checkPermissionHooks',
|
||||
'checkSpecialsAndNSPermissions',
|
||||
'checkSiteConfigPermissions',
|
||||
'checkUserConfigPermissions',
|
||||
'checkPageRestrictions',
|
||||
'checkCascadingSourcesRestrictions',
|
||||
|
|
|
|||
|
|
@ -1606,7 +1606,7 @@ abstract class Installer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create the first user account, grant it sysop and bureaucrat rights
|
||||
* Create the first user account, grant it sysop, bureaucrat and interface-admin rights
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
|
|
@ -1630,6 +1630,7 @@ abstract class Installer {
|
|||
|
||||
$user->addGroup( 'sysop' );
|
||||
$user->addGroup( 'bureaucrat' );
|
||||
$user->addGroup( 'interface-admin' );
|
||||
if ( $this->getVar( '_AdminEmail' ) ) {
|
||||
$user->setEmail( $this->getVar( '_AdminEmail' ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ class WebInstallerName extends WebInstallerPage {
|
|||
$status = $upp->checkUserPasswordForGroups(
|
||||
$user,
|
||||
$pwd,
|
||||
[ 'bureaucrat', 'sysop' ] // per Installer::createSysop()
|
||||
[ 'bureaucrat', 'sysop', 'interface-admin' ] // per Installer::createSysop()
|
||||
);
|
||||
$valid = $status->isGood() ? true : $status->getMessage();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -147,6 +147,9 @@ class User implements IDBAccessObject, UserIdentity {
|
|||
'editmyuserjs',
|
||||
'editmywatchlist',
|
||||
'editsemiprotected',
|
||||
'editsitecss',
|
||||
'editsitejson',
|
||||
'editsitejs',
|
||||
'editusercss',
|
||||
'edituserjson',
|
||||
'edituserjs',
|
||||
|
|
|
|||
|
|
@ -365,6 +365,9 @@
|
|||
"customcssprotected": "You do not have permission to edit this CSS page because it contains another user's personal settings.",
|
||||
"customjsonprotected": "You do not have permission to edit this JSON page because it contains another user's personal settings.",
|
||||
"customjsprotected": "You do not have permission to edit this JavaScript page because it contains another user's personal settings.",
|
||||
"sitecssprotected": "You do not have permission to edit this CSS page because it may affect all visitors",
|
||||
"sitejsonprotected": "You do not have permission to edit this JSON page because it may affect all visitors",
|
||||
"sitejsprotected": "You do not have permission to edit this JavaScript page because it may affect all visitors",
|
||||
"mycustomcssprotected": "You do not have permission to edit this CSS page.",
|
||||
"mycustomjsonprotected": "You do not have permission to edit this JSON page.",
|
||||
"mycustomjsprotected": "You do not have permission to edit this JavaScript page.",
|
||||
|
|
@ -1178,6 +1181,7 @@
|
|||
"group-autoconfirmed": "Autoconfirmed users",
|
||||
"group-bot": "Bots",
|
||||
"group-sysop": "Administrators",
|
||||
"group-interface-admin": "Interface administrators",
|
||||
"group-bureaucrat": "Bureaucrats",
|
||||
"group-suppress": "Suppressors",
|
||||
"group-all": "(all)",
|
||||
|
|
@ -1185,12 +1189,14 @@
|
|||
"group-autoconfirmed-member": "{{GENDER:$1|autoconfirmed user}}",
|
||||
"group-bot-member": "{{GENDER:$1|bot}}",
|
||||
"group-sysop-member": "{{GENDER:$1|administrator}}",
|
||||
"group-interface-admin-member": "{{GENDER:$1|interface administrator}}",
|
||||
"group-bureaucrat-member": "{{GENDER:$1|bureaucrat}}",
|
||||
"group-suppress-member": "{{GENDER:$1|suppressor}}",
|
||||
"grouppage-user": "{{ns:project}}:Users",
|
||||
"grouppage-autoconfirmed": "{{ns:project}}:Autoconfirmed users",
|
||||
"grouppage-bot": "{{ns:project}}:Bots",
|
||||
"grouppage-sysop": "{{ns:project}}:Administrators",
|
||||
"grouppage-interface-admin": "{{ns:project}}:Interface administrators",
|
||||
"grouppage-bureaucrat": "{{ns:project}}:Bureaucrats",
|
||||
"grouppage-suppress": "{{ns:project}}:Suppress",
|
||||
"right-read": "Read pages",
|
||||
|
|
@ -1241,6 +1247,9 @@
|
|||
"right-editusercss": "Edit other users' CSS files",
|
||||
"right-edituserjson": "Edit other users' JSON files",
|
||||
"right-edituserjs": "Edit other users' JavaScript files",
|
||||
"right-editsitecss": "Edit sitewide CSS",
|
||||
"right-editsitejson": "Edit sitewide JSON",
|
||||
"right-editsitejs": "Edit sitewide JavaScript",
|
||||
"right-editmyusercss": "Edit your own user CSS files",
|
||||
"right-editmyuserjson": "Edit your own user JSON files",
|
||||
"right-editmyuserjs": "Edit your own user JavaScript files",
|
||||
|
|
@ -1282,10 +1291,11 @@
|
|||
"grant-createaccount": "Create accounts",
|
||||
"grant-createeditmovepage": "Create, edit, and move pages",
|
||||
"grant-delete": "Delete pages, revisions, and log entries",
|
||||
"grant-editinterface": "Edit the MediaWiki namespace and user CSS/JSON/JavaScript",
|
||||
"grant-editinterface": "Edit the MediaWiki namespace and sitewide/user JSON",
|
||||
"grant-editmycssjs": "Edit your user CSS/JSON/JavaScript",
|
||||
"grant-editmyoptions": "Edit your user preferences",
|
||||
"grant-editmywatchlist": "Edit your watchlist",
|
||||
"grant-editsiteconfig": "Edit sitewide and user CSS/JS",
|
||||
"grant-editpage": "Edit existing pages",
|
||||
"grant-editprotected": "Edit protected pages",
|
||||
"grant-highvolume": "High-volume editing",
|
||||
|
|
|
|||
|
|
@ -565,6 +565,9 @@
|
|||
"customcssprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"customjsonprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"customjsprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"sitecssprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"sitejsonprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"sitejsprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"mycustomcssprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"mycustomjsonprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
"mycustomjsprotected": "Used as error message. Parameters:\n* $1 - (Unused) the action the user attempted to perform",
|
||||
|
|
@ -1378,6 +1381,7 @@
|
|||
"group-autoconfirmed": "{{doc-group|autoconfirmed}}\nOn Wikimedia sites autoconfirmed users are users which are older than 4 days. After those 4 days, they have more rights.",
|
||||
"group-bot": "{{doc-group|bot}}\n{{Identical|Bot}}",
|
||||
"group-sysop": "{{doc-group|sysop}}\n{{Identical|Administrator}}",
|
||||
"group-interface-admin": "{{doc-group|interface-admin}}",
|
||||
"group-bureaucrat": "{{doc-group|bureaucrat}}",
|
||||
"group-suppress": "{{doc-group|suppress}}\nThis is an optional (disabled by default) user group, meant for the suppression feature in [[mw:Flow|Flow]]. It is not to be confused with the Oversighters group, which also has access to the [[mw:RevisionDelete|RevisionDelete]] feature, to change the visibility of revisions through [[Special:RevisionDelete]].\n\n{{Identical|Suppress}}",
|
||||
"group-all": "The name of the user group that contains all users, including anonymous users\n\n{{Identical|All}}",
|
||||
|
|
@ -1385,12 +1389,14 @@
|
|||
"group-autoconfirmed-member": "{{doc-group|autoconfirmed|member}}",
|
||||
"group-bot-member": "{{doc-group|bot|member}}",
|
||||
"group-sysop-member": "{{doc-group|sysop|member}}\n{{Identical|Administrator}}",
|
||||
"group-interface-admin-member": "{{doc-group|interface-admin|member}}",
|
||||
"group-bureaucrat-member": "{{doc-group|bureaucrat|member}}",
|
||||
"group-suppress-member": "{{doc-group|suppress|member}}\nThis is a member of the optional (disabled by default) user group, meant for the [[mw:RevisionDelete|RevisionDelete]] feature, to change the visibility of revisions through [[Special:RevisionDelete]].\n\n{{Identical|Suppress}}",
|
||||
"grouppage-user": "{{doc-group|user|page}}\n{{Identical|User}}",
|
||||
"grouppage-autoconfirmed": "{{doc-group|autoconfirmed|page}}",
|
||||
"grouppage-bot": "{{doc-group|bot|page}}\n{{Identical|Bot}}",
|
||||
"grouppage-sysop": "{{doc-group|sysop|page}}",
|
||||
"grouppage-interface-admin": "{{doc-group|interface-admin|page}}",
|
||||
"grouppage-bureaucrat": "{{doc-group|bureaucrat|page}}",
|
||||
"grouppage-suppress": "{{doc-group|suppress|page}}\n{{Identical|Suppress}}",
|
||||
"right-read": "{{doc-right|read}}\nBasic right to read any page.",
|
||||
|
|
@ -1441,6 +1447,9 @@
|
|||
"right-editusercss": "{{doc-right|editusercss}}\nSee also:\n* {{msg-mw|Right-editmyusercss}}",
|
||||
"right-edituserjson": "{{doc-right|edituserjson}}\nSee also:\n* {{msg-mw|Right-editmyuserjson}}",
|
||||
"right-edituserjs": "{{doc-right|edituserjs}}\nSee also:\n* {{msg-mw|Right-editmyuserjs}}",
|
||||
"right-editsitecss": "{{doc-right|editsitecss}}",
|
||||
"right-editsitejson": "{{doc-right|editsitejson}}",
|
||||
"right-editsitejs": "{{doc-right|editsitejs}}",
|
||||
"right-editmyusercss": "{{doc-right|editmyusercss}}\nSee also:\n* {{msg-mw|Right-editusercss}}",
|
||||
"right-editmyuserjson": "{{doc-right|editmyuserjson}}\nSee also:\n* {{msg-mw|Right-edituserjson}}",
|
||||
"right-editmyuserjs": "{{doc-right|editmyuserjs}}\nSee also:\n* {{msg-mw|Right-edituserjs}}",
|
||||
|
|
@ -1468,7 +1477,7 @@
|
|||
"right-applychangetags": "{{doc-right|applychangetags}}",
|
||||
"right-changetags": "{{doc-right|changetags}}",
|
||||
"right-deletechangetags": "{{doc-right|deletechangetags}}",
|
||||
"grant-generic": "Used if the grant name is not defined. Parameters:\n* $1 - grant name\n\nDefined grants (grant name refers: blockusers, createeditmovepage, ...):\n* {{msg-mw|grant-checkuser}}\n* {{msg-mw|grant-blockusers}}\n* {{msg-mw|grant-createaccount}}\n* {{msg-mw|grant-createeditmovepage}}\n* {{msg-mw|grant-delete}}\n* {{msg-mw|grant-editinterface}}\n* {{msg-mw|grant-editmycssjs}}\n* {{msg-mw|grant-editmyoptions}}\n* {{msg-mw|grant-editmywatchlist}}\n* {{msg-mw|grant-editpage}}\n* {{msg-mw|grant-editprotected}}\n* {{msg-mw|grant-highvolume}}\n* {{msg-mw|grant-oversight}}\n* {{msg-mw|grant-patrol}}\n* {{msg-mw|grant-privateinfo}}\n* {{msg-mw|grant-protect}}\n* {{msg-mw|grant-rollback}}\n* {{msg-mw|grant-sendemail}}\n* {{msg-mw|grant-uploadeditmovefile}}\n* {{msg-mw|grant-uploadfile}}\n* {{msg-mw|grant-basic}}\n* {{msg-mw|grant-viewdeleted}}\n* {{msg-mw|grant-viewmywatchlist}}",
|
||||
"grant-generic": "Used if the grant name is not defined. Parameters:\n* $1 - grant name\n\nDefined grants (grant name refers: blockusers, createeditmovepage, ...):\n* {{msg-mw|grant-checkuser}}\n* {{msg-mw|grant-blockusers}}\n* {{msg-mw|grant-createaccount}}\n* {{msg-mw|grant-createeditmovepage}}\n* {{msg-mw|grant-delete}}\n* {{msg-mw|grant-editinterface}}\n* {{msg-mw|grant-editmycssjs}}\n* {{msg-mw|grant-editmyoptions}}\n* {{msg-mw|grant-editmywatchlist}}\n* {{msg-mw|grant-editsiteconfig}}\n* {{msg-mw|grant-editpage}}\n* {{msg-mw|grant-editprotected}}\n* {{msg-mw|grant-highvolume}}\n* {{msg-mw|grant-oversight}}\n* {{msg-mw|grant-patrol}}\n* {{msg-mw|grant-privateinfo}}\n* {{msg-mw|grant-protect}}\n* {{msg-mw|grant-rollback}}\n* {{msg-mw|grant-sendemail}}\n* {{msg-mw|grant-uploadeditmovefile}}\n* {{msg-mw|grant-uploadfile}}\n* {{msg-mw|grant-basic}}\n* {{msg-mw|grant-viewdeleted}}\n* {{msg-mw|grant-viewmywatchlist}}",
|
||||
"grant-group-page-interaction": "{{Related|Grant-group}}",
|
||||
"grant-group-file-interaction": "{{Related|Grant-group}}",
|
||||
"grant-group-watchlist-interaction": "{{Related|Grant-group}}",
|
||||
|
|
@ -1482,10 +1491,11 @@
|
|||
"grant-createaccount": "Name for grant \"createaccount\".\n{{Related|Grant}}\n{{Identical|Create account}}",
|
||||
"grant-createeditmovepage": "Name for grant \"createeditmovepage\".\n{{Related|Grant}}",
|
||||
"grant-delete": "Name for grant \"delete\".\n{{Related|Grant}}",
|
||||
"grant-editinterface": "Name for grant \"editinterface\".\n\n\"JS\" stands for \"JavaScript\".\n{{Related|Grant}}",
|
||||
"grant-editinterface": "Name for grant \"editinterface\".\n{{Related|Grant}}",
|
||||
"grant-editmycssjs": "Name for grant \"editmycssjs\".\n\n\"JS\" stands for \"JavaScript\".\n{{Related|Grant}}",
|
||||
"grant-editmyoptions": "Name for grant \"editmyoptions\".\n{{Related|Grant}}",
|
||||
"grant-editmywatchlist": "Name for grant \"editmywatchlist\".\n{{Related|Grant}}\n{{Identical|Edit your watchlist}}",
|
||||
"grant-editsiteconfig": "Name for grant \"editsiteconfig\".\n{{Related|Grant}}",
|
||||
"grant-editpage": "Name for grant \"editpage\".\n{{Related|Grant}}",
|
||||
"grant-editprotected": "Name for grant \"editprotected\".\n{{Related|Grant}}",
|
||||
"grant-highvolume": "Name for grant \"highvolume\".\n{{Related|Grant}}",
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ require_once __DIR__ . '/Maintenance.php';
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
class CreateAndPromote extends Maintenance {
|
||||
private static $permitRoles = [ 'sysop', 'bureaucrat', 'bot' ];
|
||||
private static $permitRoles = [ 'sysop', 'bureaucrat', 'interface-admin', 'bot' ];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
|
|
|||
Loading…
Reference in a new issue