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