Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 42 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
EditPermissionHandler | |
0.00% |
0 / 42 |
|
0.00% |
0 / 2 |
600 | |
0.00% |
0 / 1 |
onGetUserPermissionsErrors | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
56 | |||
onJsonValidateSave | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
306 |
1 | <?php |
2 | // phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName |
3 | |
4 | namespace MediaWiki\Extension\AbuseFilter\Hooks\Handlers; |
5 | |
6 | use MediaWiki\Content\Hook\JsonValidateSaveHook; |
7 | use MediaWiki\Content\JsonContent; |
8 | use MediaWiki\Extension\AbuseFilter\BlockedDomainStorage; |
9 | use MediaWiki\MediaWikiServices; |
10 | use MediaWiki\Page\PageIdentity; |
11 | use MediaWiki\Permissions\Hook\GetUserPermissionsErrorsHook; |
12 | use MediaWiki\Title\Title; |
13 | use MediaWiki\Title\TitleValue; |
14 | use MediaWiki\User\User; |
15 | use StatusValue; |
16 | use Wikimedia\Message\MessageSpecifier; |
17 | |
18 | /** |
19 | * This hook handler is for very simple checks, rather than the much more advanced ones |
20 | * undertaken by the FilteredActionsHandler. |
21 | */ |
22 | class EditPermissionHandler implements GetUserPermissionsErrorsHook, JsonValidateSaveHook { |
23 | |
24 | /** @var string[] */ |
25 | private const JSON_OBJECT_FIELDS = [ |
26 | 'domain', |
27 | 'notes' |
28 | ]; |
29 | |
30 | private const JSON_OPTIONAL_FIELDS = [ 'addedBy' ]; |
31 | |
32 | /** |
33 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/getUserPermissionsErrors |
34 | * |
35 | * @param Title $title |
36 | * @param User $user |
37 | * @param string $action |
38 | * @param array|string|MessageSpecifier &$result |
39 | * @return bool|void |
40 | */ |
41 | public function onGetUserPermissionsErrors( $title, $user, $action, &$result ) { |
42 | $services = MediaWikiServices::getInstance(); |
43 | |
44 | // Only do anything if we're enabled on this wiki. |
45 | if ( !$services->getMainConfig()->get( 'AbuseFilterEnableBlockedExternalDomain' ) ) { |
46 | return; |
47 | } |
48 | |
49 | // Ignore all actions and pages except MediaWiki: edits (and creates) |
50 | // to the page we care about |
51 | if ( |
52 | !( $action == 'create' || $action == 'edit' ) || |
53 | !$title->inNamespace( NS_MEDIAWIKI ) || |
54 | $title->getDBkey() !== BlockedDomainStorage::TARGET_PAGE |
55 | ) { |
56 | return; |
57 | } |
58 | |
59 | if ( $services->getPermissionManager()->userHasRight( $user, 'editinterface' ) ) { |
60 | return; |
61 | } |
62 | |
63 | // Prohibit direct actions on our page. |
64 | $result = [ 'abusefilter-blocked-domains-cannot-edit-directly', BlockedDomainStorage::TARGET_PAGE ]; |
65 | return false; |
66 | } |
67 | |
68 | /** |
69 | * @param JsonContent $content |
70 | * @param PageIdentity $pageIdentity |
71 | * @param StatusValue $status |
72 | * @return bool|void |
73 | */ |
74 | public function onJsonValidateSave( JsonContent $content, PageIdentity $pageIdentity, StatusValue $status ) { |
75 | $services = MediaWikiServices::getInstance(); |
76 | |
77 | // Only do anything if we're enabled on this wiki. |
78 | if ( !$services->getMainConfig()->get( 'AbuseFilterEnableBlockedExternalDomain' ) ) { |
79 | return; |
80 | } |
81 | |
82 | $title = TitleValue::newFromPage( $pageIdentity ); |
83 | if ( !$title->inNamespace( NS_MEDIAWIKI ) || $title->getText() !== BlockedDomainStorage::TARGET_PAGE ) { |
84 | return; |
85 | } |
86 | $data = $content->getData()->getValue(); |
87 | |
88 | if ( !is_array( $data ) ) { |
89 | $status->fatal( 'abusefilter-blocked-domains-json-error' ); |
90 | return; |
91 | } |
92 | |
93 | $isValid = true; |
94 | $entryNumber = 0; |
95 | foreach ( $data as $element ) { |
96 | $entryNumber++; |
97 | // Check if each element is an object with all known fields, allow optional fields but no other fields |
98 | if ( is_object( $element ) && count( get_object_vars( $element ) ) >= count( self::JSON_OBJECT_FIELDS ) ) { |
99 | foreach ( self::JSON_OBJECT_FIELDS as $field ) { |
100 | if ( !property_exists( $element, $field ) || !is_string( $element->{$field} ) ) { |
101 | $isValid = false; |
102 | break 2; |
103 | } |
104 | } |
105 | |
106 | foreach ( self::JSON_OPTIONAL_FIELDS as $field ) { |
107 | if ( property_exists( $element, $field ) && !is_string( $element->{$field} ) ) { |
108 | $isValid = false; |
109 | break 2; |
110 | } |
111 | } |
112 | foreach ( $element as $field => $value ) { |
113 | if ( |
114 | !in_array( $field, array_merge( self::JSON_OPTIONAL_FIELDS, self::JSON_OBJECT_FIELDS ) ) |
115 | ) { |
116 | $isValid = false; |
117 | break; |
118 | } |
119 | } |
120 | } else { |
121 | $isValid = false; |
122 | break; |
123 | } |
124 | } |
125 | |
126 | if ( !$isValid ) { |
127 | $status->fatal( 'abusefilter-blocked-domains-invalid-entry', $entryNumber ); |
128 | } |
129 | } |
130 | |
131 | } |