Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.44% covered (success)
94.44%
17 / 18
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReadingListsTokenAwareHandlerTrait
94.44% covered (success)
94.44%
17 / 18
50.00% covered (danger)
50.00%
1 / 2
6.01
0.00% covered (danger)
0.00%
0 / 1
 getReadingListsTokenParamDefinition
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 getToken
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
5.02
1<?php
2
3namespace MediaWiki\Extension\ReadingLists\Rest;
4
5use LogicException;
6use MediaWiki\Rest\Handler;
7use MediaWiki\Rest\TokenAwareHandlerTrait;
8use Wikimedia\ParamValidator\ParamValidator;
9
10/**
11 * Adds csrf token handling for Reading Lists.
12 *
13 * The Reading Lists REST endpoints replaced endpoints of the same contract in RESTBase.
14 * They therefore have to accept csrf tokens in an unusual way: as a query parameter
15 * named "csrf_token". They will also accept tokens in the usual way: as a body
16 * parameter named "token". If callers can eventually convert to the usual way, then this
17 * class can be removed in favor of using only the core TokenAwareHandlerTrait.
18 *
19 * Handlers that use this trait should:
20 * 1) override getBodyValidator() to use getTokenParamDefinition()
21 * 2) extend validate() to call validateToken()
22 * 3) extend getParamSettings() to include the return value from getTokenParamSettings()
23 *
24 * @see Handler::requireSafeAgainstCsrf()
25 * @see TokenAwareHandlerTrait
26 *
27 * @package MediaWiki\Rest
28 */
29trait ReadingListsTokenAwareHandlerTrait {
30    use TokenAwareHandlerTrait;
31
32    /**
33     * Returns the definition for the token parameter, to be used in getParamSettings().
34     *
35     * @return array[]
36     */
37    public function getReadingListsTokenParamDefinition() {
38        return [
39            'csrf_token' => [
40                Handler::PARAM_SOURCE => 'query',
41                ParamValidator::PARAM_TYPE => 'string',
42                ParamValidator::PARAM_REQUIRED => false,
43            ]
44        ];
45    }
46
47    /**
48     * Determines the CSRF token to be used, possibly taking it from the request.
49     *
50     * Returns an empty string if the request isn't known to be safe and
51     * no token was supplied by the client.
52     * Returns null if the session provider is safe against CSRF (and thus no token
53     * is needed)
54     *
55     * @return string|null
56     */
57    protected function getToken(): ?string {
58        if ( !$this instanceof Handler ) {
59            throw new LogicException( 'This trait must be used on handler classes.' );
60        }
61
62        if ( $this->getSession()->getProvider()->safeAgainstCsrf() ) {
63            return null;
64        }
65
66        $body = $this->getValidatedBody();
67        if ( !empty( $body['token'] ) ) {
68            return $body['token'];
69        }
70
71        $params = $this->getValidatedParams();
72        if ( isset( $params['csrf_token'] ) ) {
73            return $params['csrf_token'];
74        }
75
76        return '';
77    }
78}