Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 107
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
LocalAuth
0.00% covered (danger)
0.00%
0 / 107
0.00% covered (danger)
0.00%
0 / 7
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 autoLogin
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 getUserParams
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
6
 getUserParamsFast
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
6
 getLists
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getCentralLists
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 getCentralBlockCount
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace MediaWiki\Extension\SecurePoll\User;
4
5use MediaWiki\Context\RequestContext;
6use MediaWiki\Extension\CentralAuth\User\CentralAuthUser;
7use MediaWiki\Extension\SecurePoll\Entities\Election;
8use MediaWiki\Extension\SecurePoll\Hooks\HookRunner;
9use MediaWiki\MainConfigNames;
10use MediaWiki\MediaWikiServices;
11use MediaWiki\Registration\ExtensionRegistry;
12use MediaWiki\Status\Status;
13use MediaWiki\User\User;
14use MediaWiki\WikiMap\WikiMap;
15
16/**
17 * Authorization class for locally created accounts.
18 * Certain functions in this class are also used for sending local voter
19 * parameters to a remote SecurePoll installation.
20 */
21class LocalAuth extends Auth {
22    /** @var HookRunner */
23    private $hookRunner;
24
25    /** @var MediaWikiServices */
26    private $services;
27
28    /**
29     * @inheritDoc
30     */
31    public function __construct( $context ) {
32        parent::__construct( $context );
33        $this->hookRunner = new HookRunner(
34            MediaWikiServices::getInstance()->getHookContainer()
35        );
36        $this->services = MediaWikiServices::getInstance();
37    }
38
39    /**
40     * Create a voter transparently, without user interaction.
41     * Sessions authorized against local accounts are created this way.
42     * @param Election $election
43     * @return Status
44     */
45    public function autoLogin( $election ) {
46        $user = RequestContext::getMain()->getUser();
47        if ( !$user->isNamed() ) {
48            return Status::newFatal( 'securepoll-not-logged-in' );
49        }
50        $params = $this->getUserParams( $user );
51        $params['electionId'] = $election->getId();
52        $qualStatus = $election->getQualifiedStatus( $params );
53        if ( !$qualStatus->isOK() ) {
54            return $qualStatus;
55        }
56        $voter = $this->getVoter( $params );
57
58        return Status::newGood( $voter );
59    }
60
61    /**
62     * Get voter parameters for a local User object.
63     * @param User $user
64     * @return array
65     */
66    public function getUserParams( $user ) {
67        $block = $user->getBlock();
68        $blockCounts = $this->getCentralBlockCount( $user );
69        $server = $this->services->getMainConfig()->get( MainConfigNames::Server );
70
71        $params = [
72            'name' => $user->getName(),
73            'type' => 'local',
74            'domain' => preg_replace( '!.*/(.*)$!', '$1', $server ),
75            'url' => $user->getUserPage()->getCanonicalURL(),
76            'properties' => [
77                'wiki' => WikiMap::getCurrentWikiId(),
78                'blocked' => (bool)$block,
79                'isSitewideBlocked' => $block ? $block->isSitewide() : null,
80                'central-block-count' => $blockCounts['blockCount'],
81                'central-sitewide-block-count' => $blockCounts['sitewideBlockCount'],
82                'edit-count' => $user->getEditCount(),
83                'bot' => $user->isAllowed( 'bot' ),
84                'language' => $this->services
85                    ->getUserOptionsLookup()->getOption( $user, 'language' ),
86                'groups' => $this->services
87                    ->getUserGroupManager()->getUserGroups( $user ),
88                'lists' => $this->getLists( $user ),
89                'central-lists' => $this->getCentralLists( $user ),
90                'registration' => $user->getRegistration(),
91            ]
92        ];
93
94        $this->hookRunner->onSecurePoll_GetUserParams( $this, $user, $params );
95
96        return $params;
97    }
98
99    /**
100     * Get voter parameters for a local User object, except without central block count.
101     *
102     * @param User $user
103     * @return array
104     */
105    public function getUserParamsFast( $user ) {
106        $server = $this->services->getMainConfig()->get( 'Server' );
107        $block = $user->getBlock();
108        $params = [
109            'name' => $user->getName(),
110            'type' => 'local',
111            'domain' => preg_replace( '!.*/(.*)$!', '$1', $server ),
112            'url' => $user->getUserPage()->getCanonicalURL(),
113            'properties' => [
114                'wiki' => WikiMap::getCurrentWikiId(),
115                'blocked' => (bool)$block,
116                'isSitewideBlocked' => $block ? $block->isSitewide() : null,
117                'central-block-count' => 0,
118                'edit-count' => $user->getEditCount(),
119                'bot' => $user->isAllowed( 'bot' ),
120                'language' => $this->services
121                    ->getUserOptionsLookup()->getOption( $user, 'language' ),
122                'groups' => $this->services
123                    ->getUserGroupManager()->getUserGroups( $user ),
124                'lists' => $this->getLists( $user ),
125                'central-lists' => $this->getCentralLists( $user ),
126                'registration' => $user->getRegistration(),
127            ]
128        ];
129
130        $this->hookRunner->onSecurePoll_GetUserParams( $this, $user, $params );
131
132        return $params;
133    }
134
135    /**
136     * Get the lists a given local user belongs to
137     * @param User $user
138     * @return array
139     */
140    public function getLists( $user ) {
141        $dbr = $this->context->getDB();
142        return $dbr->newSelectQueryBuilder()
143            ->select( 'li_name' )
144            ->from( 'securepoll_lists' )
145            ->where( [ 'li_member' => $user->getId() ] )
146            ->caller( __METHOD__ )
147            ->fetchFieldValues();
148    }
149
150    /**
151     * Get the CentralAuth lists the user belongs to
152     * @param User $user
153     * @return array
154     */
155    public function getCentralLists( $user ) {
156        if ( !ExtensionRegistry::getInstance()->isLoaded( 'CentralAuth' ) ) {
157            return [];
158        }
159        $centralUser = CentralAuthUser::getInstance( $user );
160        if ( !$centralUser->isAttached() ) {
161            return [];
162        }
163        $caDbManager = MediaWikiServices::getInstance()->getService(
164            'CentralAuth.CentralAuthDatabaseManager'
165        );
166        $dbc = $caDbManager->getCentralReplicaDB();
167        return $dbc->newSelectQueryBuilder()
168            ->select( 'li_name' )
169            ->from( 'securepoll_lists' )
170            ->where( [ 'li_member' => $centralUser->getId() ] )
171            ->caller( __METHOD__ )
172            ->fetchFieldValues();
173    }
174
175    /**
176     * Checks how many central wikis the user is blocked on
177     * @param User $user
178     * @return array the number of wikis the user is blocked on, both partial and sitewide
179     */
180    public function getCentralBlockCount( $user ) {
181        if ( !ExtensionRegistry::getInstance()->isLoaded( 'CentralAuth' ) ) {
182            return [
183                'blockCount' => 0,
184                'sitewideBlockCount' => 0,
185            ];
186        }
187
188        $centralUser = CentralAuthUser::getInstanceByName( $user->getName() );
189
190        $attached = $centralUser->queryAttached();
191        $blockCount = 0;
192        $sitewideBlockCount = 0;
193
194        foreach ( $attached as $data ) {
195            if ( $data['blocked'] ) {
196                $blockCount++;
197                if ( $data['block-sitewide'] ) {
198                    $sitewideBlockCount++;
199                }
200            }
201        }
202
203        return [
204            'blockCount' => $blockCount,
205            'sitewideBlockCount' => $sitewideBlockCount,
206        ];
207    }
208}