Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
54.55% covered (warning)
54.55%
12 / 22
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
TokenQueryManager
54.55% covered (warning)
54.55%
12 / 22
75.00% covered (warning)
75.00%
3 / 4
19.39
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPagingQueries
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
 updateToken
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getDataFromRequest
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace MediaWiki\CheckUser\Services;
4
5use MediaWiki\Request\WebRequest;
6
7class TokenQueryManager {
8    public TokenManager $tokenManager;
9
10    /**
11     * @param TokenManager $tokenManager
12     */
13    public function __construct( TokenManager $tokenManager ) {
14        $this->tokenManager = $tokenManager;
15    }
16
17    /**
18     * Conceal the offset in pager pagination params
19     * which may reveal sensitive data.
20     *
21     * @param WebRequest $request
22     * @param array $queries
23     * @return array
24     */
25    public function getPagingQueries( WebRequest $request, array $queries ): array {
26        $tokenData = $this->getDataFromRequest( $request );
27        foreach ( $queries as &$query ) {
28            if ( $query === false ) {
29                continue;
30            }
31
32            if ( isset( $query['offset'] ) ) {
33                // Move the offset into the token since it may contain sensitive information
34                $query['token'] = $this->updateToken( $request, [ 'offset' => $query['offset'] ] );
35                unset( $query['offset'] );
36            } elseif ( isset( $tokenData['offset'] ) ) {
37                // Remove the offset.
38                $query['token'] = $this->updateToken( $request, [ 'offset' => null ] );
39            }
40        }
41
42        return $queries;
43    }
44
45    /**
46     * Preforms an array merge on the updates with what is in the current token.
47     * Setting a value to null will remove it.
48     *
49     * @param WebRequest $request
50     * @param array $update
51     * @return string
52     */
53    public function updateToken( WebRequest $request, array $update ): string {
54        $tokenData = $this->getDataFromRequest( $request );
55        $data = array_filter( array_merge( $tokenData, $update ), static function ( $value ) {
56            return $value !== null;
57        } );
58
59        return $this->tokenManager->encode( $request->getSession(), $data );
60    }
61
62    /**
63     * Get token data
64     *
65     * @param WebRequest $request
66     * @return array
67     */
68    public function getDataFromRequest( WebRequest $request ): array {
69        $token = $request->getVal( 'token', '' );
70
71        if ( $token === '' ) {
72            return [];
73        }
74
75        try {
76            return $this->tokenManager->decode( $request->getSession(), $token );
77        } catch ( \Exception $e ) {
78            return [];
79        }
80    }
81}