From fe34083c8a620664e86b80f44ef4e610a5cc9363 Mon Sep 17 00:00:00 2001
From: Sam Smith <phuedx@wikimedia.org>
Date: Mon, 20 Sep 2021 13:23:00 +0100
Subject: [PATCH] SECURITY: Require securepoll-view-voter-pii right to view
 voter's PII

Extract PII fields from ListPager::$adminFields to
ListPager::$piiFields. Only include those fields if:

1. In the electionadmin group;
2. An admin of the election; and
3. Has the securepoll-view-voter-pii right

Bug: T290808
Change-Id: Ic7510be487a1bf9215de9ae6cf4a26fad96384c9
---
 includes/Pages/ListPager.php | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/includes/Pages/ListPager.php b/includes/Pages/ListPager.php
index f85b44f..82f6893 100644
--- a/includes/Pages/ListPager.php
+++ b/includes/Pages/ListPager.php
@@ -4,14 +4,15 @@ namespace MediaWiki\Extensions\SecurePoll\Pages;
 
 use MediaWiki\Extensions\SecurePoll\Entities\Election;
 use MediaWiki\Extensions\SecurePoll\User\Voter;
+use MediaWiki\MediaWikiServices;
 use TablePager;
 use Wikimedia\IPUtils;
 use Xml;
 
 /**
  * A TablePager for showing a list of votes in a given election.
- * Shows much more information, and a strike/unstrike interface, if the user
- * is an admin.
+ * Shows much more information, including voter's Personally Identifiable Information, and a strike/unstrike interface,
+ * if the global user is an admin.
  */
 class ListPager extends TablePager {
 	/** @var ListPage */
@@ -35,17 +36,36 @@ class ListPager extends TablePager {
 		'vote_timestamp' => 'securepoll-header-timestamp',
 		'vote_voter_name' => 'securepoll-header-voter-name',
 		'vote_voter_domain' => 'securepoll-header-voter-domain',
+		'vote_token_match' => 'securepoll-header-token-match',
+		'vote_cookie_dup' => 'securepoll-header-cookie-dup',
+	];
+
+	/** @var string[] */
+	public static $piiFields = [
 		'vote_ip' => 'securepoll-header-ip',
 		'vote_xff' => 'securepoll-header-xff',
 		'vote_ua' => 'securepoll-header-ua',
-		'vote_token_match' => 'securepoll-header-token-match',
-		'vote_cookie_dup' => 'securepoll-header-cookie-dup',
 	];
 
+	/**
+	 * Whether to include voter's Personally Identifiable Information.
+	 *
+	 * @var bool
+	 */
+	private $includeVoterPii;
+
 	public function __construct( $listPage ) {
 		$this->listPage = $listPage;
 		$this->election = $listPage->election;
-		$this->isAdmin = $this->election->isAdmin( $this->getUser() );
+
+		$user = $this->getUser();
+
+		$this->isAdmin = $this->election->isAdmin( $user );
+
+		$permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+		$this->includeVoterPii =
+			$this->isAdmin && $permissionManager->userHasRight( $user, 'securepoll-view-voter-pii' );
+
 		parent::__construct();
 	}
 
@@ -180,6 +200,10 @@ class ListPager extends TablePager {
 		$names = [];
 		if ( $this->isAdmin ) {
 			$fields = self::$adminFields;
+
+			if ( $this->includeVoterPii ) {
+				$fields += self::$piiFields;
+			}
 		} else {
 			$fields = self::$publicFields;
 		}
-- 
2.32.0

