Alex Monk has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/74678


Change subject: WIP - Special:GroupPermissions (CA-like group editor)
......................................................................

WIP - Special:GroupPermissions (CA-like group editor)

This currently relies on CentralAuth because there's a lot of useful i18n 
messages there that'll
be annoying to move (it's also missing qqq docs, messages.inc entries, etc.)
For now I would just like feedback on the rest. Those messages should be moved 
to core before
merging though of course.

Bug: 27035
Change-Id: I16917a36b7d80fa33d25392b39b8bb73c53b305c
---
M includes/AutoLoader.php
M includes/DefaultSettings.php
M includes/SpecialPageFactory.php
M includes/Wiki.php
M includes/installer/MysqlUpdater.php
A includes/specials/SpecialGroupPermissions.php
M languages/messages/MessagesEn.php
A maintenance/archives/patch-groups.sql
A maintenance/migrateGroupsToDatabase.php
9 files changed, 329 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/78/74678/1

diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index 33a244b..3d27fca 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -943,6 +943,7 @@
        'SpecialEmailUser' => 'includes/specials/SpecialEmailuser.php',
        'SpecialExport' => 'includes/specials/SpecialExport.php',
        'SpecialFilepath' => 'includes/specials/SpecialFilepath.php',
+       'SpecialGroupPermissions' => 
'includes/specials/SpecialGroupPermissions.php',
        'SpecialImport' => 'includes/specials/SpecialImport.php',
        'SpecialJavaScriptTest' => 
'includes/specials/SpecialJavaScriptTest.php',
        'SpecialListFiles' => 'includes/specials/SpecialListfiles.php',
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index d660f50..91c6e3c 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -3951,6 +3951,33 @@
 #$wgGroupPermissions['bureaucrat']['userrights-interwiki'] = true;
 // Permission to export pages including linked pages regardless of 
$wgExportMaxLinkDepth
 #$wgGroupPermissions['bureaucrat']['override-export-depth'] = true;
+// Permission to edit group permissions
+#$wgGroupConfigSource = 'database';
+#$wgGroupPermissions['bureaucrat']['editgrouppermissions'] = true;
+$wgRestrictedRights = array(
+       'bigdelete',
+       'siteadmin',
+       'suppressionlog',
+       'suppressrevision',
+       'userrights-interwiki',
+
+       # Rights defined by extensions. These should remain listed in core for 
security reasons (people using an old version of an extension with a new 
version of core etc.), but extensions should also add to it (duplicates won't 
really hurt)
+       'centralauth-oversight',
+       'centralauth-lock',
+       'centralauth-unmerge',
+
+       'checkuser',
+       'checkuser-log',
+
+       'globalblock',
+       'globalgroupmembership',
+       'globalgrouppermissions',
+       'globalunblock',
+
+       'hiderevision',
+       'oversight',
+       'hideuser',
+);
 
 #$wgGroupPermissions['sysop']['deletelogentry'] = true;
 #$wgGroupPermissions['sysop']['deleterevision'] = true;
diff --git a/includes/SpecialPageFactory.php b/includes/SpecialPageFactory.php
index a53b901..4734c95 100644
--- a/includes/SpecialPageFactory.php
+++ b/includes/SpecialPageFactory.php
@@ -101,6 +101,7 @@
                'Listbots'                  => 'SpecialListBots',
                'Userrights'                => 'UserrightsPage',
                'EditWatchlist'             => 'SpecialEditWatchlist',
+               'GroupPermissions'          => 'SpecialGroupPermissions',
 
                // Recent changes and logs
                'Newimages'                 => 'SpecialNewFiles',
diff --git a/includes/Wiki.php b/includes/Wiki.php
index f8f699c..307d927 100644
--- a/includes/Wiki.php
+++ b/includes/Wiki.php
@@ -496,7 +496,7 @@
        }
 
        private function main() {
-               global $wgUseFileCache, $wgTitle, $wgUseAjax;
+               global $wgUseFileCache, $wgTitle, $wgUseAjax, 
$wgGroupConfigSource, $wgGroupPermissions;
 
                wfProfileIn( __METHOD__ );
 
@@ -519,6 +519,20 @@
                        return;
                }
 
+               if ( $wgGroupConfigSource == 'database' ) {
+                       $wgGroupPermissions = array(); // !
+                       foreach ( wfGetDB( DB_SLAVE )->select(
+                               'groups',
+                               array( 'group_internal_name', 
'group_permissions' ),
+                               array(),
+                               __METHOD__
+                       ) as $row ) {
+                               foreach ( json_decode( $row->group_permissions 
) as $permission => $value ) {
+                                       
$wgGroupPermissions[$row->group_internal_name][$permission] = $value;
+                               }
+                       }
+               }
+
                // Send Ajax requests to the Ajax dispatcher.
                if ( $wgUseAjax && $request->getVal( 'action', 'view' ) == 
'ajax' ) {
 
diff --git a/includes/installer/MysqlUpdater.php 
b/includes/installer/MysqlUpdater.php
index df1f610..2664ad2 100644
--- a/includes/installer/MysqlUpdater.php
+++ b/includes/installer/MysqlUpdater.php
@@ -231,6 +231,7 @@
                        // 1.22
                        array( 'doIwlinksIndexNonUnique' ),
                        array( 'addIndex', 'iwlinks', 'iwl_prefix_from_title',  
'patch-iwlinks-from-title-index.sql' ),
+                       array( 'addTable', 'groups', 'patch-groups.sql' ),
                );
        }
 
diff --git a/includes/specials/SpecialGroupPermissions.php 
b/includes/specials/SpecialGroupPermissions.php
new file mode 100644
index 0000000..f5e10fe
--- /dev/null
+++ b/includes/specials/SpecialGroupPermissions.php
@@ -0,0 +1,213 @@
+<?php
+/*
+Lots of this file is heavily based on CentralAuth's 
SpecialGlobalGroupPermissionss
+TODO: Move loads of i18n stuff to core
+*/
+class SpecialGroupPermissions extends SpecialPage {
+       public function __construct() {
+               parent::__construct( 'GroupPermissions' );
+       }
+
+       public function execute( $subpage ) {
+               if ( !$this->userCanExecute( $this->getUser() ) ) {
+                       $this->displayRestrictionError();
+                       return;
+               }
+
+               $this->getOutput()->setPageTitle( $this->msg( 
'grouppermissions' ) );
+               $this->getOutput()->setRobotPolicy( "noindex,nofollow" );
+               $this->getOutput()->setArticleRelated( false );
+               $this->getOutput()->enableClientCache( false );
+
+               if ( $subpage == '' ) {
+                       $subpage = $this->getRequest()->getVal( 'wpGroup' );
+               }
+
+               if ( $subpage != '' && $this->getUser()->matchEditToken( 
$this->getRequest()->getVal( 'wpEditToken' ) ) ) {
+                       $this->doSubmit( $subpage );
+               } elseif ( $subpage != '' ) {
+                       $this->buildGroupView( $subpage );
+               } else {
+                       $this->buildMainView();
+               }
+       }
+
+       private function userCanEdit( User $user ) {
+               return $user->isAllowed( 'editgrouppermissions' );
+       }
+
+       private function buildMainView() {
+               global $wgScript, $wgGroupPermissions;
+
+               $groups = array_keys( $wgGroupPermissions );
+
+               // Existing groups
+               $html = Xml::fieldset( $this->msg( 
'centralauth-existinggroup-legend' )->text() );
+
+               $this->getOutput()->addHTML( $html );
+
+               if ( count( $groups ) ) {
+                       $this->getOutput()->addWikiMsg( 
'grouppermissions-grouplistheader' );
+                       $this->getOutput()->addHTML( '<ul>' );
+
+                       foreach ( $groups as $group ) {
+                               $text = $this->msg(
+                                       'grouppermissions-grouplistitem',
+                                       $group == '*' ? '<nowiki>*</nowiki>' : 
User::getGroupName( $group ),
+                                       $group,
+                                       '<span 
class="centralauth-globalgroupperms-groupname">' . $group . '</span>'
+                               )->parse();
+
+                               $this->getOutput()->addHTML( "<li> $text </li>" 
);
+                       }
+               } else {
+                       $this->getOutput()->addWikiMsg( 
'centralauth-globalgroupperms-nogroups' );
+               }
+
+               $this->getOutput()->addHTML( Xml::closeElement( 'ul' ) . 
Xml::closeElement( 'fieldset' ) );
+
+               if ( $this->userCanEdit( $this->getUser() ) ) {
+                       // "Create a group" prompt
+                       $html = Xml::fieldset( $this->msg( 
'centralauth-newgroup-legend' )->text() );
+                       $html .= $this->msg( 'centralauth-newgroup-intro' 
)->parseAsBlock();
+                       $html .= Xml::openElement( 'form', array( 'method' => 
'post', 'action' => $wgScript, 'name' => 'centralauth-globalgroups-newgroup' ) 
);
+                       $html .= Html::hidden( 'title',  
SpecialPage::getTitleFor( 'GroupPermissions' )->getPrefixedText() );
+
+                       $fields = array( 
'centralauth-globalgroupperms-newgroupname' => Xml::input( 'wpGroup' ) );
+
+                       $html .= Xml::buildForm( $fields, 
'centralauth-globalgroupperms-creategroup-submit' );
+                       $html .= Xml::closeElement( 'form' );
+                       $html .= Xml::closeElement( 'fieldset' );
+
+                       $this->getOutput()->addHTML( $html );
+               }
+       }
+
+       /**
+        * @param $group
+        */
+       private function buildGroupView( $group ) {
+               global $wgImplicitGroups;
+               $editable = $this->userCanEdit( $this->getUser() );
+
+               $subtitleMessage = $editable ? 'centralauth-editgroup-subtitle' 
: 'centralauth-editgroup-subtitle-readonly';
+               $this->getOutput()->setSubtitle( $this->msg( $subtitleMessage, 
$group ) );
+
+               $fieldsetClass = $editable ? 'mw-centralauth-editgroup' : 
'mw-centralauth-editgroup-readonly';
+               $html = Xml::fieldset( $this->msg( 
'centralauth-editgroup-fieldset', $group )->text(), false, array( 'class' => 
$fieldsetClass ) );
+
+               if ( $editable ) {
+                       $html .= Xml::openElement( 'form', array( 'method' => 
'post', 'action' => SpecialPage::getTitleFor( 'GroupPermissions', $group 
)->getLocalUrl(), 'name' => 'centralauth-globalgroups-newgroup' ) );
+                       $html .= Html::hidden( 'wpGroup', $group );
+                       $html .= Html::hidden( 'wpEditToken', 
$this->getUser()->getEditToken() );
+               }
+
+               $fields = array( 'centralauth-editgroup-name' => $group );
+
+               $fields['grouppermissions-grouptype'] = $this->msg( 
'grouppermissions-' . ( in_array( $group, $wgImplicitGroups ) ? 'im' : 'ex' ) . 
'plicit' );
+
+               if ( $group != '*' ) {
+                       if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
+                               # Show edit link only to user with the 
editinterface right
+                               $fields['centralauth-editgroup-display'] = 
$this->msg( 'centralauth-editgroup-display-edit', $group, User::getGroupName( 
$group ) )->parse();
+                               $fields['centralauth-editgroup-member'] = 
$this->msg( 'centralauth-editgroup-member-edit', $group, User::getGroupMember( 
$group ) )->parse();
+                       } else {
+                               $fields['centralauth-editgroup-display'] = 
User::getGroupName( $group );
+                               $fields['centralauth-editgroup-member'] = 
User::getGroupMember( $group );
+                       }
+               }
+
+               if ( !in_array( $group, $wgImplicitGroups ) ) {
+                       $fields['centralauth-editgroup-members'] = $this->msg( 
'grouppermissions-members-link', $group, User::getGroupMember( $group ) 
)->parse();
+               }
+               $fields['centralauth-editgroup-perms'] = 
$this->buildCheckboxes( $group );
+
+               if ( $editable ) {
+                       $fields['centralauth-editgroup-reason'] = Xml::input( 
'wpReason', 60 );
+               }
+
+               $html .= Xml::buildForm( $fields,  $editable ? 
'grouppermissions-submit' : null );
+
+               if ( $editable ) {
+                       $html .= Xml::closeElement( 'form' );
+               }
+
+               $html .= Xml::closeElement( 'fieldset' );
+
+               $this->getOutput()->addHTML( $html );
+
+               $this->showLogFragment( $group, $this->getOutput() );
+       }
+
+       /**
+        * @param $group
+        * @return string
+        */
+       function buildCheckboxes( $group ) {
+               global $wgGroupPermissions, $wgGroupConfigSource, 
$wgRestrictedRights;
+               $rights = User::getAllRights();
+               $assignedRights = array();
+               if ( isset( $wgGroupPermissions[$group] ) ) {
+                       foreach ( $wgGroupPermissions[$group] as $permission => 
$value ) {
+                               if ( $value ) {
+                                       $assignedRights[] = $permission;
+                               }
+                       }
+               }
+
+               sort( $rights );
+
+               $checkboxes = array();
+
+               foreach ( $rights as $right ) {
+                       # Build a checkbox.
+                       $checked = in_array( $right, $assignedRights );
+
+                       $desc = $this->getOutput()->parseInline( 
User::getRightDescription( $right ) ) . ' ' .
+                                               Xml::element( 'code', null, 
$this->msg( 'parentheses', $right )->text() );
+
+                       $disabled = !( $this->getUser()->isAllowed( 
'editgrouppermissions' ) && $wgGroupConfigSource == 'database' && !in_array( 
$right, $wgRestrictedRights ) );
+                       $checkbox = Xml::check( "wpRightAssigned-$right", 
$checked,
+                               array_merge( $disabled ? array( 'disabled' => 
'disabled' ) : array(), array( 'id' => "wpRightAssigned-$right" ) ) );
+                       $label = Xml::tags( 'label', array( 'for' => 
"wpRightAssigned-$right" ),
+                                       $desc );
+
+                       $liClass = $checked ? 
'mw-centralauth-editgroup-checked' : 'mw-centralauth-editgroup-unchecked';
+                       $checkboxes[] = Html::rawElement( 'li', array( 'class' 
=> $liClass ), "$checkbox&#160;$label" );
+               }
+
+               $count = count( $checkboxes );
+
+               $firstCol = round( $count / 2 );
+
+               $checkboxes1 = array_slice( $checkboxes, 0, $firstCol );
+               $checkboxes2 = array_slice( $checkboxes, $firstCol );
+
+               $html = '<table><tbody><tr><td><ul>';
+
+               foreach ( $checkboxes1 as $cb ) {
+                       $html .= $cb;
+               }
+
+               $html .= '</ul></td><td><ul>';
+
+               foreach ( $checkboxes2 as $cb ) {
+                       $html .= $cb;
+               }
+
+               $html .= '</ul></td></tr></tbody></table>';
+
+               return $html;
+       }
+
+       /**
+        * @param $group
+        * @param $output OutputPage
+        */
+       protected function showLogFragment( $group, $output ) {
+               $title = SpecialPage::getTitleFor( 'ListUsers', $group );
+               $logPage = new LogPage( 'rights' );
+               $output->addHTML( Xml::element( 'h2', null, 
$logPage->getName()->text() . "\n" ) );
+               LogEventsList::showLogExtract( $output, 'rights', 
$title->getPrefixedText() );
+       }
+}
diff --git a/languages/messages/MessagesEn.php 
b/languages/messages/MessagesEn.php
index c5dba69..137c0f4 100644
--- a/languages/messages/MessagesEn.php
+++ b/languages/messages/MessagesEn.php
@@ -398,6 +398,7 @@
        'Fewestrevisions'           => array( 'FewestRevisions' ),
        'FileDuplicateSearch'       => array( 'FileDuplicateSearch' ),
        'Filepath'                  => array( 'FilePath' ),
+       'GroupPermissions'          => array( 'GroupPermissions' ),
        'Import'                    => array( 'Import' ),
        'Invalidateemail'           => array( 'InvalidateEmail' ),
        'JavaScriptTest'            => array( 'JavaScriptTest' ),
@@ -4970,4 +4971,15 @@
 # Image rotation
 'rotate-comment' => 'Image rotated by $1 {{PLURAL:$1|degree|degrees}} 
clockwise',
 
+# Special:GroupPermissions
+'grouppermissions' => 'Group permissions',
+'grouppermissions-grouplistitem'      => '$1 
([[Special:GroupPermissions/$2|view/edit]])',
+'grouppermissions-grouplistheader' => 'The following groups have been 
configured.
+You may view or edit the permissions assigned to a group, if you have 
permission to.
+A group may be deleted by removing all rights from it.',
+'grouppermissions-members-link' => '[[Special:ListUsers/$1|List of users with 
$2 rights]]',
+'grouppermissions-submit' => 'Save group changes',
+'grouppermissions-grouptype' => 'Group type',
+'grouppermissions-implicit' => 'Implicit',
+'grouppermissions-explicit' => 'Explicit',
 );
diff --git a/maintenance/archives/patch-groups.sql 
b/maintenance/archives/patch-groups.sql
new file mode 100644
index 0000000..cb672c3
--- /dev/null
+++ b/maintenance/archives/patch-groups.sql
@@ -0,0 +1,4 @@
+CREATE TABLE IF NOT EXISTS /*_*/groups (
+  group_internal_name varbinary(32) NOT NULL,
+  group_permissions BLOB
+) /*$wgDBTableOptions*/;
diff --git a/maintenance/migrateGroupsToDatabase.php 
b/maintenance/migrateGroupsToDatabase.php
new file mode 100644
index 0000000..d5a11d9
--- /dev/null
+++ b/maintenance/migrateGroupsToDatabase.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Migrates groups from config to database.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once( __DIR__ . '/Maintenance.php' );
+
+/**
+ * Maintenance script that migrates groups from config to database.
+ *
+ * @ingroup Maintenance
+ */
+class MigrateGroupsToDatabase extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->mDescription = "Migrates groups from config to 
database.";
+       }
+
+       public function execute() {
+               global $wgGroupPermissions;
+               $db = wfGetDB( DB_MASTER );
+
+               if ( $db->select( 'groups', 'COUNT(*)', array(), __METHOD__ 
)->fetchRow()[0] != 0 ) {
+                       $this->error( "Groups table already has information.", 
1 );
+               }
+
+               foreach ( $wgGroupPermissions as $group => $rightsMap ) {
+                       $dataToInsert[] = array( 'group_internal_name' => 
$group, 'group_permissions' => json_encode( $rightsMap ) );
+               }
+
+               $db->insert( 'groups', $dataToInsert, __METHOD__ );
+               $this->output( "Done! Now set \$wgGroupConfigSource = 
'database';\n" );
+       }
+}
+
+$maintClass = "MigrateGroupsToDatabase";
+require_once( RUN_MAINTENANCE_IF_MAIN );

-- 
To view, visit https://gerrit.wikimedia.org/r/74678
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I16917a36b7d80fa33d25392b39b8bb73c53b305c
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Alex Monk <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to