Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
47.37% |
27 / 57 |
|
50.00% |
1 / 2 |
CRAP | |
0.00% |
0 / 1 |
CheckMatch | |
47.37% |
27 / 57 |
|
50.00% |
1 / 2 |
59.13 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
execute | |
42.31% |
22 / 52 |
|
0.00% |
0 / 1 |
51.64 | |||
getAllowedParams | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
getExamplesMessages | n/a |
0 / 0 |
n/a |
0 / 0 |
1 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\AbuseFilter\Api; |
4 | |
5 | use ApiBase; |
6 | use ApiMain; |
7 | use ApiResult; |
8 | use FormatJson; |
9 | use LogEventsList; |
10 | use LogicException; |
11 | use LogPage; |
12 | use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager; |
13 | use MediaWiki\Extension\AbuseFilter\Parser\RuleCheckerFactory; |
14 | use MediaWiki\Extension\AbuseFilter\Special\SpecialAbuseLog; |
15 | use MediaWiki\Extension\AbuseFilter\VariableGenerator\VariableGeneratorFactory; |
16 | use MediaWiki\Extension\AbuseFilter\Variables\VariableHolder; |
17 | use MediaWiki\Extension\AbuseFilter\Variables\VariablesBlobStore; |
18 | use MediaWiki\Revision\RevisionRecord; |
19 | use RecentChange; |
20 | use Wikimedia\ParamValidator\ParamValidator; |
21 | |
22 | class CheckMatch extends ApiBase { |
23 | |
24 | /** @var RuleCheckerFactory */ |
25 | private $ruleCheckerFactory; |
26 | |
27 | /** @var AbuseFilterPermissionManager */ |
28 | private $afPermManager; |
29 | |
30 | /** @var VariablesBlobStore */ |
31 | private $afVariablesBlobStore; |
32 | |
33 | /** @var VariableGeneratorFactory */ |
34 | private $afVariableGeneratorFactory; |
35 | |
36 | /** |
37 | * @param ApiMain $main |
38 | * @param string $action |
39 | * @param RuleCheckerFactory $ruleCheckerFactory |
40 | * @param AbuseFilterPermissionManager $afPermManager |
41 | * @param VariablesBlobStore $afVariablesBlobStore |
42 | * @param VariableGeneratorFactory $afVariableGeneratorFactory |
43 | */ |
44 | public function __construct( |
45 | ApiMain $main, |
46 | $action, |
47 | RuleCheckerFactory $ruleCheckerFactory, |
48 | AbuseFilterPermissionManager $afPermManager, |
49 | VariablesBlobStore $afVariablesBlobStore, |
50 | VariableGeneratorFactory $afVariableGeneratorFactory |
51 | ) { |
52 | parent::__construct( $main, $action ); |
53 | $this->ruleCheckerFactory = $ruleCheckerFactory; |
54 | $this->afPermManager = $afPermManager; |
55 | $this->afVariablesBlobStore = $afVariablesBlobStore; |
56 | $this->afVariableGeneratorFactory = $afVariableGeneratorFactory; |
57 | } |
58 | |
59 | /** |
60 | * @inheritDoc |
61 | */ |
62 | public function execute() { |
63 | $performer = $this->getAuthority(); |
64 | $params = $this->extractRequestParams(); |
65 | $this->requireOnlyOneParameter( $params, 'vars', 'rcid', 'logid' ); |
66 | |
67 | // "Anti-DoS" |
68 | if ( !$this->afPermManager->canUseTestTools( $performer ) ) { |
69 | $this->dieWithError( 'apierror-abusefilter-canttest', 'permissiondenied' ); |
70 | } |
71 | |
72 | $vars = null; |
73 | if ( $params['vars'] ) { |
74 | $pairs = FormatJson::decode( $params['vars'], true ); |
75 | $vars = VariableHolder::newFromArray( $pairs ); |
76 | } elseif ( $params['rcid'] ) { |
77 | $rc = RecentChange::newFromId( $params['rcid'] ); |
78 | |
79 | if ( !$rc ) { |
80 | $this->dieWithError( [ 'apierror-nosuchrcid', $params['rcid'] ] ); |
81 | } |
82 | |
83 | $type = (int)$rc->getAttribute( 'rc_type' ); |
84 | $deletedValue = $rc->getAttribute( 'rc_deleted' ); |
85 | if ( |
86 | ( |
87 | $type === RC_LOG && |
88 | !LogEventsList::userCanBitfield( |
89 | $deletedValue, |
90 | LogPage::SUPPRESSED_ACTION | LogPage::SUPPRESSED_USER, |
91 | $performer |
92 | ) |
93 | ) || ( |
94 | $type !== RC_LOG && |
95 | !RevisionRecord::userCanBitfield( $deletedValue, RevisionRecord::SUPPRESSED_ALL, $performer ) |
96 | ) |
97 | ) { |
98 | // T223654 - Same check as in AbuseFilterChangesList |
99 | $this->dieWithError( 'apierror-permissiondenied-generic', 'deletedrc' ); |
100 | } |
101 | |
102 | $varGenerator = $this->afVariableGeneratorFactory->newRCGenerator( $rc, $this->getUser() ); |
103 | $vars = $varGenerator->getVars(); |
104 | } elseif ( $params['logid'] ) { |
105 | $row = $this->getDB()->selectRow( |
106 | 'abuse_filter_log', |
107 | '*', |
108 | [ 'afl_id' => $params['logid'] ], |
109 | __METHOD__ |
110 | ); |
111 | |
112 | if ( !$row ) { |
113 | $this->dieWithError( [ 'apierror-abusefilter-nosuchlogid', $params['logid'] ], 'nosuchlogid' ); |
114 | } |
115 | |
116 | $visibility = SpecialAbuseLog::getEntryVisibilityForUser( $row, $performer, $this->afPermManager ); |
117 | if ( $visibility !== SpecialAbuseLog::VISIBILITY_VISIBLE ) { |
118 | // T223654 - Same check as in SpecialAbuseLog. Both the visibility of the AbuseLog entry |
119 | // and the corresponding revision are checked. |
120 | $this->dieWithError( 'apierror-permissiondenied-generic', 'deletedabuselog' ); |
121 | } |
122 | |
123 | $vars = $this->afVariablesBlobStore->loadVarDump( $row->afl_var_dump ); |
124 | } |
125 | if ( $vars === null ) { |
126 | // @codeCoverageIgnoreStart |
127 | throw new LogicException( 'Impossible.' ); |
128 | // @codeCoverageIgnoreEnd |
129 | } |
130 | |
131 | $ruleChecker = $this->ruleCheckerFactory->newRuleChecker( $vars ); |
132 | if ( !$ruleChecker->checkSyntax( $params['filter'] )->isValid() ) { |
133 | $this->dieWithError( 'apierror-abusefilter-badsyntax', 'badsyntax' ); |
134 | } |
135 | |
136 | $result = [ |
137 | ApiResult::META_BC_BOOLS => [ 'result' ], |
138 | 'result' => $ruleChecker->checkConditions( $params['filter'] )->getResult(), |
139 | ]; |
140 | |
141 | $this->getResult()->addValue( |
142 | null, |
143 | $this->getModuleName(), |
144 | $result |
145 | ); |
146 | } |
147 | |
148 | /** |
149 | * @codeCoverageIgnore Merely declarative |
150 | * @inheritDoc |
151 | */ |
152 | public function getAllowedParams() { |
153 | return [ |
154 | 'filter' => [ |
155 | ParamValidator::PARAM_REQUIRED => true, |
156 | ], |
157 | 'vars' => null, |
158 | 'rcid' => [ |
159 | ParamValidator::PARAM_TYPE => 'integer' |
160 | ], |
161 | 'logid' => [ |
162 | ParamValidator::PARAM_TYPE => 'integer' |
163 | ], |
164 | ]; |
165 | } |
166 | |
167 | /** |
168 | * @codeCoverageIgnore Merely declarative |
169 | * @inheritDoc |
170 | */ |
171 | protected function getExamplesMessages() { |
172 | return [ |
173 | 'action=abusefiltercheckmatch&filter=!("autoconfirmed"%20in%20user_groups)&rcid=15' |
174 | => 'apihelp-abusefiltercheckmatch-example-1', |
175 | ]; |
176 | } |
177 | } |