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