Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
85.11% |
40 / 47 |
|
80.00% |
12 / 15 |
CRAP | |
0.00% |
0 / 1 |
PermissionChecker | |
85.11% |
40 / 47 |
|
80.00% |
12 / 15 |
39.05 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
userCanEnableRegistrations | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
userCanEnableRegistration | |
66.67% |
6 / 9 |
|
0.00% |
0 / 1 |
4.59 | |||
userCanOrganizeEvents | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
userCanEditRegistration | |
72.73% |
8 / 11 |
|
0.00% |
0 / 1 |
6.73 | |||
userCanDeleteRegistration | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
userCanDeleteRegistrations | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
userCanRegisterForEvent | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
3 | |||
userCanCancelRegistration | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
userCanRemoveParticipants | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
userCanViewPrivateParticipants | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
userCanViewSensitiveEventData | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
userCanViewNonPIIParticipantsData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
userCanEmailParticipants | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
userCanUseInvitationLists | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | declare( strict_types=1 ); |
4 | |
5 | namespace MediaWiki\Extension\CampaignEvents\Permissions; |
6 | |
7 | use MediaWiki\Extension\CampaignEvents\Event\ExistingEventRegistration; |
8 | use MediaWiki\Extension\CampaignEvents\MWEntity\CampaignsCentralUserLookup; |
9 | use MediaWiki\Extension\CampaignEvents\MWEntity\ICampaignsAuthority; |
10 | use MediaWiki\Extension\CampaignEvents\MWEntity\ICampaignsPage; |
11 | use MediaWiki\Extension\CampaignEvents\MWEntity\IPermissionsLookup; |
12 | use MediaWiki\Extension\CampaignEvents\MWEntity\PageAuthorLookup; |
13 | use MediaWiki\Extension\CampaignEvents\MWEntity\UserNotGlobalException; |
14 | use MediaWiki\Extension\CampaignEvents\Organizers\OrganizersStore; |
15 | |
16 | class PermissionChecker { |
17 | public const SERVICE_NAME = 'CampaignEventsPermissionChecker'; |
18 | |
19 | public const ENABLE_REGISTRATIONS_RIGHT = 'campaignevents-enable-registration'; |
20 | public const ORGANIZE_EVENTS_RIGHT = 'campaignevents-organize-events'; |
21 | public const SEND_EVENTS_EMAIL_RIGHT = 'campaignevents-email-participants'; |
22 | |
23 | private OrganizersStore $organizersStore; |
24 | private PageAuthorLookup $pageAuthorLookup; |
25 | private CampaignsCentralUserLookup $centralUserLookup; |
26 | private IPermissionsLookup $permissionsLookup; |
27 | |
28 | /** |
29 | * @param OrganizersStore $organizersStore |
30 | * @param PageAuthorLookup $pageAuthorLookup |
31 | * @param CampaignsCentralUserLookup $centralUserLookup |
32 | * @param IPermissionsLookup $permissionsLookup |
33 | */ |
34 | public function __construct( |
35 | OrganizersStore $organizersStore, |
36 | PageAuthorLookup $pageAuthorLookup, |
37 | CampaignsCentralUserLookup $centralUserLookup, |
38 | IPermissionsLookup $permissionsLookup |
39 | ) { |
40 | $this->organizersStore = $organizersStore; |
41 | $this->pageAuthorLookup = $pageAuthorLookup; |
42 | $this->centralUserLookup = $centralUserLookup; |
43 | $this->permissionsLookup = $permissionsLookup; |
44 | } |
45 | |
46 | /** |
47 | * NOTE: This should be kept in sync with the special page, which has its own ways of requiring named account, |
48 | * unblock, and rights. |
49 | * @param ICampaignsAuthority $performer |
50 | * @return bool |
51 | */ |
52 | public function userCanEnableRegistrations( ICampaignsAuthority $performer ): bool { |
53 | return $performer->isNamed() |
54 | && $performer->hasRight( self::ENABLE_REGISTRATIONS_RIGHT ) |
55 | && !$performer->isSitewideBlocked(); |
56 | } |
57 | |
58 | /** |
59 | * @param ICampaignsAuthority $performer |
60 | * @param ICampaignsPage $eventPage |
61 | * @return bool |
62 | */ |
63 | public function userCanEnableRegistration( ICampaignsAuthority $performer, ICampaignsPage $eventPage ): bool { |
64 | if ( !$this->userCanEnableRegistrations( $performer ) ) { |
65 | return false; |
66 | } |
67 | |
68 | $pageAuthor = $this->pageAuthorLookup->getAuthor( $eventPage ); |
69 | if ( !$pageAuthor ) { |
70 | return false; |
71 | } |
72 | |
73 | try { |
74 | $centralUser = $this->centralUserLookup->newFromAuthority( $performer ); |
75 | } catch ( UserNotGlobalException $_ ) { |
76 | return false; |
77 | } |
78 | return $pageAuthor->equals( $centralUser ); |
79 | } |
80 | |
81 | /** |
82 | * @param string $username |
83 | * @return bool |
84 | */ |
85 | public function userCanOrganizeEvents( string $username ): bool { |
86 | return $this->permissionsLookup->userIsNamed( $username ) && |
87 | $this->permissionsLookup->userHasRight( $username, self::ORGANIZE_EVENTS_RIGHT ) && |
88 | !$this->permissionsLookup->userIsSitewideBlocked( $username ); |
89 | } |
90 | |
91 | /** |
92 | * @param ICampaignsAuthority $performer |
93 | * @param ExistingEventRegistration $event |
94 | * @return bool |
95 | */ |
96 | public function userCanEditRegistration( ICampaignsAuthority $performer, ExistingEventRegistration $event ): bool { |
97 | if ( |
98 | !$event->isOnLocalWiki() || |
99 | ( |
100 | !$this->userCanEnableRegistrations( $performer ) && |
101 | !$this->userCanOrganizeEvents( $performer->getName() ) |
102 | ) |
103 | ) { |
104 | return false; |
105 | } |
106 | try { |
107 | $centralUser = $this->centralUserLookup->newFromAuthority( $performer ); |
108 | } catch ( UserNotGlobalException $_ ) { |
109 | return false; |
110 | } |
111 | $eventID = $event->getID(); |
112 | if ( $eventID ) { |
113 | return $this->organizersStore->isEventOrganizer( $eventID, $centralUser ); |
114 | } |
115 | return false; |
116 | } |
117 | |
118 | /** |
119 | * @param ICampaignsAuthority $performer |
120 | * @param ExistingEventRegistration $event |
121 | * @return bool |
122 | */ |
123 | public function userCanDeleteRegistration( |
124 | ICampaignsAuthority $performer, |
125 | ExistingEventRegistration $event |
126 | ): bool { |
127 | return $event->isOnLocalWiki() && ( |
128 | $this->userCanDeleteRegistrations( $performer ) || |
129 | $this->userCanEditRegistration( $performer, $event ) |
130 | ); |
131 | } |
132 | |
133 | /** |
134 | * @param ICampaignsAuthority $performer |
135 | * @return bool |
136 | */ |
137 | public function userCanDeleteRegistrations( ICampaignsAuthority $performer ): bool { |
138 | return $performer->isNamed() && |
139 | $performer->hasRight( 'campaignevents-delete-registration' ) && |
140 | !$performer->isSitewideBlocked(); |
141 | } |
142 | |
143 | /** |
144 | * NOTE: This should be kept in sync with the special page, which has its own ways of requiring named account |
145 | * and unblock. |
146 | * @param ICampaignsAuthority $performer |
147 | * @param ExistingEventRegistration $event |
148 | * @return bool |
149 | */ |
150 | public function userCanRegisterForEvent( ICampaignsAuthority $performer, ExistingEventRegistration $event ): bool { |
151 | // TODO Do we need another user right for this? |
152 | return $event->isOnLocalWiki() && $performer->isNamed() && !$performer->isSitewideBlocked(); |
153 | } |
154 | |
155 | /** |
156 | * NOTE: This should be kept in sync with the special page, which has its own way of requiring a named account. |
157 | * @param ICampaignsAuthority $performer |
158 | * @return bool |
159 | */ |
160 | public function userCanCancelRegistration( ICampaignsAuthority $performer ): bool { |
161 | // Note that blocked users can cancel their own registration, see T322380. |
162 | return $performer->isNamed(); |
163 | } |
164 | |
165 | /** |
166 | * @param ICampaignsAuthority $performer |
167 | * @param ExistingEventRegistration $event |
168 | * @return bool |
169 | */ |
170 | public function userCanRemoveParticipants( |
171 | ICampaignsAuthority $performer, |
172 | ExistingEventRegistration $event |
173 | ): bool { |
174 | return $this->userCanEditRegistration( $performer, $event ); |
175 | } |
176 | |
177 | /** |
178 | * @param ICampaignsAuthority $performer |
179 | * @param ExistingEventRegistration $event |
180 | * @return bool |
181 | */ |
182 | public function userCanViewPrivateParticipants( |
183 | ICampaignsAuthority $performer, |
184 | ExistingEventRegistration $event |
185 | ): bool { |
186 | return $this->userCanEditRegistration( $performer, $event ); |
187 | } |
188 | |
189 | /** |
190 | * @param ICampaignsAuthority $performer |
191 | * @return bool |
192 | */ |
193 | public function userCanViewSensitiveEventData( ICampaignsAuthority $performer ): bool { |
194 | return !$performer->isSitewideBlocked(); |
195 | } |
196 | |
197 | /** |
198 | * @param ICampaignsAuthority $performer |
199 | * @param ExistingEventRegistration $event |
200 | * @return bool |
201 | */ |
202 | public function userCanViewNonPIIParticipantsData( |
203 | ICampaignsAuthority $performer, |
204 | ExistingEventRegistration $event |
205 | ): bool { |
206 | return $this->userCanEditRegistration( $performer, $event ); |
207 | } |
208 | |
209 | /** |
210 | * @param ICampaignsAuthority $performer |
211 | * @param ExistingEventRegistration $event |
212 | * @return bool |
213 | */ |
214 | public function userCanEmailParticipants( ICampaignsAuthority $performer, ExistingEventRegistration $event ): bool { |
215 | return $this->userCanEditRegistration( $performer, $event ) |
216 | && $performer->hasRight( self::SEND_EVENTS_EMAIL_RIGHT ); |
217 | } |
218 | |
219 | public function userCanUseInvitationLists( ICampaignsAuthority $performer ): bool { |
220 | return $this->userCanOrganizeEvents( $performer->getName() ) || |
221 | $this->userCanEnableRegistrations( $performer ); |
222 | } |
223 | } |