@@ -25,279 +25,279 @@ |
||
| 25 | 25 | |
| 26 | 26 | class PageViewRequest extends InternalPageBase |
| 27 | 27 | { |
| 28 | - use RequestData; |
|
| 29 | - const STATUS_SYMBOL_OPEN = '☐'; |
|
| 30 | - const STATUS_SYMBOL_ACCEPTED = '☑'; |
|
| 31 | - const STATUS_SYMBOL_REJECTED = '☒'; |
|
| 32 | - |
|
| 33 | - /** |
|
| 34 | - * Main function for this page, when no specific actions are called. |
|
| 35 | - * @throws ApplicationLogicException |
|
| 36 | - */ |
|
| 37 | - protected function main() |
|
| 38 | - { |
|
| 39 | - // set up csrf protection |
|
| 40 | - $this->assignCSRFToken(); |
|
| 41 | - |
|
| 42 | - // get some useful objects |
|
| 43 | - $database = $this->getDatabase(); |
|
| 44 | - $request = $this->getRequest($database, WebRequest::getInt('id')); |
|
| 45 | - $config = $this->getSiteConfiguration(); |
|
| 46 | - $currentUser = User::getCurrent($database); |
|
| 47 | - |
|
| 48 | - // Test we should be able to look at this request |
|
| 49 | - if ($config->getEmailConfirmationEnabled()) { |
|
| 50 | - if ($request->getEmailConfirm() !== 'Confirmed') { |
|
| 51 | - // Not allowed to look at this yet. |
|
| 52 | - throw new ApplicationLogicException('The email address has not yet been confirmed for this request.'); |
|
| 53 | - } |
|
| 54 | - } |
|
| 55 | - |
|
| 56 | - $this->setupBasicData($request, $config); |
|
| 57 | - |
|
| 58 | - $this->setupUsernameData($request); |
|
| 59 | - |
|
| 60 | - $this->setupTitle($request); |
|
| 61 | - |
|
| 62 | - $this->setupReservationDetails($request->getReserved(), $database, $currentUser); |
|
| 63 | - $this->setupGeneralData($database); |
|
| 64 | - |
|
| 65 | - $this->assign('requestDataCleared', false); |
|
| 66 | - if ($request->getEmail() === $this->getSiteConfiguration()->getDataClearEmail()) { |
|
| 67 | - $this->assign('requestDataCleared', true); |
|
| 68 | - } |
|
| 69 | - |
|
| 70 | - $allowedPrivateData = $this->isAllowedPrivateData($request, $currentUser); |
|
| 71 | - |
|
| 72 | - $this->setupCreationTypes($currentUser); |
|
| 73 | - |
|
| 74 | - $this->setupLogData($request, $database); |
|
| 75 | - |
|
| 76 | - $this->addJs("/api.php?action=templates&targetVariable=templateconfirms"); |
|
| 77 | - |
|
| 78 | - $this->assign('showRevealLink', false); |
|
| 79 | - if ($request->getReserved() === $currentUser->getId() || |
|
| 80 | - $this->barrierTest('alwaysSeeHash', $currentUser, 'RequestData') |
|
| 81 | - ) { |
|
| 82 | - $this->assign('showRevealLink', true); |
|
| 83 | - $this->assign('revealHash', $request->getRevealHash()); |
|
| 84 | - } |
|
| 85 | - |
|
| 86 | - $this->assign('canSeeRelatedRequests', false); |
|
| 87 | - if ($allowedPrivateData || $this->barrierTest('seeRelatedRequests', $currentUser, 'RequestData')) { |
|
| 88 | - $this->setupRelatedRequests($request, $config, $database); |
|
| 89 | - } |
|
| 90 | - |
|
| 91 | - if ($allowedPrivateData) { |
|
| 92 | - $this->setTemplate('view-request/main-with-data.tpl'); |
|
| 93 | - $this->setupPrivateData($request); |
|
| 94 | - |
|
| 95 | - $this->assign('canSetBan', $this->barrierTest('set', $currentUser, PageBan::class)); |
|
| 96 | - $this->assign('canSeeCheckuserData', $this->barrierTest('seeUserAgentData', $currentUser, 'RequestData')); |
|
| 97 | - |
|
| 98 | - if ($this->barrierTest('seeUserAgentData', $currentUser, 'RequestData')) { |
|
| 99 | - $this->setTemplate('view-request/main-with-checkuser-data.tpl'); |
|
| 100 | - $this->setupCheckUserData($request); |
|
| 101 | - } |
|
| 102 | - } |
|
| 103 | - else { |
|
| 104 | - $this->setTemplate('view-request/main.tpl'); |
|
| 105 | - } |
|
| 106 | - } |
|
| 107 | - |
|
| 108 | - /** |
|
| 109 | - * @param Request $request |
|
| 110 | - */ |
|
| 111 | - protected function setupTitle(Request $request) |
|
| 112 | - { |
|
| 113 | - $statusSymbol = self::STATUS_SYMBOL_OPEN; |
|
| 114 | - if ($request->getStatus() === 'Closed') { |
|
| 115 | - if ($request->getWasCreated()) { |
|
| 116 | - $statusSymbol = self::STATUS_SYMBOL_ACCEPTED; |
|
| 117 | - } |
|
| 118 | - else { |
|
| 119 | - $statusSymbol = self::STATUS_SYMBOL_REJECTED; |
|
| 120 | - } |
|
| 121 | - } |
|
| 122 | - |
|
| 123 | - $this->setHtmlTitle($statusSymbol . ' #' . $request->getId()); |
|
| 124 | - } |
|
| 125 | - |
|
| 126 | - /** |
|
| 127 | - * Sets up data unrelated to the request, such as the email template information |
|
| 128 | - * |
|
| 129 | - * @param PdoDatabase $database |
|
| 130 | - */ |
|
| 131 | - protected function setupGeneralData(PdoDatabase $database) |
|
| 132 | - { |
|
| 133 | - $config = $this->getSiteConfiguration(); |
|
| 134 | - |
|
| 135 | - $this->assign('createAccountReason', 'Requested account at [[WP:ACC]], request #'); |
|
| 136 | - |
|
| 137 | - $this->assign('defaultRequestState', $config->getDefaultRequestStateKey()); |
|
| 138 | - |
|
| 139 | - $this->assign('requestStates', $config->getRequestStates()); |
|
| 140 | - |
|
| 141 | - /** @var EmailTemplate $createdTemplate */ |
|
| 142 | - $createdTemplate = EmailTemplate::getById($config->getDefaultCreatedTemplateId(), $database); |
|
| 143 | - |
|
| 144 | - $this->assign('createdHasJsQuestion', $createdTemplate->getJsquestion() != ''); |
|
| 145 | - $this->assign('createdId', $createdTemplate->getId()); |
|
| 146 | - $this->assign('createdName', $createdTemplate->getName()); |
|
| 147 | - |
|
| 148 | - $createReasons = EmailTemplate::getActiveTemplates(EmailTemplate::CREATED, $database); |
|
| 149 | - $this->assign("createReasons", $createReasons); |
|
| 150 | - $declineReasons = EmailTemplate::getActiveTemplates(EmailTemplate::NOT_CREATED, $database); |
|
| 151 | - $this->assign("declineReasons", $declineReasons); |
|
| 152 | - |
|
| 153 | - $allCreateReasons = EmailTemplate::getAllActiveTemplates(EmailTemplate::CREATED, $database); |
|
| 154 | - $this->assign("allCreateReasons", $allCreateReasons); |
|
| 155 | - $allDeclineReasons = EmailTemplate::getAllActiveTemplates(EmailTemplate::NOT_CREATED, $database); |
|
| 156 | - $this->assign("allDeclineReasons", $allDeclineReasons); |
|
| 157 | - $allOtherReasons = EmailTemplate::getAllActiveTemplates(false, $database); |
|
| 158 | - $this->assign("allOtherReasons", $allOtherReasons); |
|
| 159 | - } |
|
| 160 | - |
|
| 161 | - private function setupLogData(Request $request, PdoDatabase $database) |
|
| 162 | - { |
|
| 163 | - $currentUser = User::getCurrent($database); |
|
| 164 | - |
|
| 165 | - $logs = LogHelper::getRequestLogsWithComments($request->getId(), $database, $this->getSecurityManager()); |
|
| 166 | - $requestLogs = array(); |
|
| 167 | - |
|
| 168 | - /** @var User[] $nameCache */ |
|
| 169 | - $nameCache = array(); |
|
| 170 | - |
|
| 171 | - $editableComments = $this->barrierTest('editOthers', $currentUser, PageEditComment::class); |
|
| 172 | - |
|
| 173 | - /** @var Log|Comment $entry */ |
|
| 174 | - foreach ($logs as $entry) { |
|
| 175 | - // both log and comment have a 'user' field |
|
| 176 | - if (!array_key_exists($entry->getUser(), $nameCache)) { |
|
| 177 | - $entryUser = User::getById($entry->getUser(), $database); |
|
| 178 | - $nameCache[$entry->getUser()] = $entryUser; |
|
| 179 | - } |
|
| 180 | - |
|
| 181 | - if ($entry instanceof Comment) { |
|
| 182 | - $requestLogs[] = array( |
|
| 183 | - 'type' => 'comment', |
|
| 184 | - 'security' => $entry->getVisibility(), |
|
| 185 | - 'user' => $entry->getVisibility() == 'requester' ? $request->getName() : $nameCache[$entry->getUser()]->getUsername(), |
|
| 186 | - 'userid' => $entry->getUser() == -1 ? null : $entry->getUser(), |
|
| 187 | - 'entry' => null, |
|
| 188 | - 'time' => $entry->getTime(), |
|
| 189 | - 'canedit' => ($editableComments || $entry->getUser() == $currentUser->getId()), |
|
| 190 | - 'id' => $entry->getId(), |
|
| 191 | - 'comment' => $entry->getComment(), |
|
| 192 | - ); |
|
| 193 | - } |
|
| 194 | - |
|
| 195 | - if ($entry instanceof Log) { |
|
| 196 | - $invalidUserId = $entry->getUser() === -1 || $entry->getUser() === 0; |
|
| 197 | - $entryUser = $invalidUserId ? User::getCommunity() : $nameCache[$entry->getUser()]; |
|
| 198 | - |
|
| 199 | - $entryComment = $entry->getComment(); |
|
| 200 | - |
|
| 201 | - if ($entry->getAction() === 'JobIssueRequest' || $entry->getAction() === 'JobCompletedRequest') { |
|
| 202 | - $data = unserialize($entry->getComment()); |
|
| 203 | - /** @var JobQueue $job */ |
|
| 204 | - $job = JobQueue::getById($data['job'], $database); |
|
| 205 | - $requestLogs[] = array( |
|
| 206 | - 'type' => 'joblog', |
|
| 207 | - 'security' => 'user', |
|
| 208 | - 'userid' => $entry->getUser() == -1 ? null : $entry->getUser(), |
|
| 209 | - 'user' => $entryUser->getUsername(), |
|
| 210 | - 'entry' => LogHelper::getLogDescription($entry), |
|
| 211 | - 'time' => $entry->getTimestamp(), |
|
| 212 | - 'canedit' => false, |
|
| 213 | - 'id' => $entry->getId(), |
|
| 214 | - 'jobId' => $job->getId(), |
|
| 215 | - 'jobDesc' => JobQueue::getTaskDescriptions()[$job->getTask()], |
|
| 216 | - ); |
|
| 217 | - } else { |
|
| 218 | - $requestLogs[] = array( |
|
| 219 | - 'type' => 'log', |
|
| 220 | - 'security' => 'user', |
|
| 221 | - 'userid' => $entry->getUser() == -1 ? null : $entry->getUser(), |
|
| 222 | - 'user' => $entryUser->getUsername(), |
|
| 223 | - 'entry' => LogHelper::getLogDescription($entry), |
|
| 224 | - 'time' => $entry->getTimestamp(), |
|
| 225 | - 'canedit' => false, |
|
| 226 | - 'id' => $entry->getId(), |
|
| 227 | - 'comment' => $entryComment, |
|
| 228 | - ); |
|
| 229 | - } |
|
| 230 | - } |
|
| 231 | - } |
|
| 232 | - |
|
| 233 | - $this->addJs("/api.php?action=users&targetVariable=typeaheaddata"); |
|
| 234 | - |
|
| 235 | - $this->assign("requestLogs", $requestLogs); |
|
| 236 | - } |
|
| 237 | - |
|
| 238 | - /** |
|
| 239 | - * @param Request $request |
|
| 240 | - */ |
|
| 241 | - protected function setupUsernameData(Request $request) |
|
| 242 | - { |
|
| 243 | - $blacklistData = $this->getBlacklistHelper()->isBlacklisted($request->getName()); |
|
| 244 | - |
|
| 245 | - $this->assign('requestIsBlacklisted', $blacklistData !== false); |
|
| 246 | - $this->assign('requestBlacklist', $blacklistData); |
|
| 247 | - |
|
| 248 | - try { |
|
| 249 | - $spoofs = $this->getAntiSpoofProvider()->getSpoofs($request->getName()); |
|
| 250 | - } |
|
| 251 | - catch (Exception $ex) { |
|
| 252 | - $spoofs = $ex->getMessage(); |
|
| 253 | - } |
|
| 254 | - |
|
| 255 | - $this->assign("spoofs", $spoofs); |
|
| 256 | - } |
|
| 257 | - |
|
| 258 | - private function setupCreationTypes(User $user) |
|
| 259 | - { |
|
| 260 | - $this->assign('allowWelcomeSkip', false); |
|
| 261 | - $this->assign('forceWelcomeSkip', false); |
|
| 262 | - |
|
| 263 | - $oauth = new OAuthUserHelper($user, $this->getDatabase(), $this->getOAuthProtocolHelper(), $this->getSiteConfiguration()); |
|
| 264 | - |
|
| 265 | - if ($user->getWelcomeTemplate() != 0) { |
|
| 266 | - $this->assign('allowWelcomeSkip', true); |
|
| 267 | - |
|
| 268 | - if (!$oauth->canWelcome()) { |
|
| 269 | - $this->assign('forceWelcomeSkip', true); |
|
| 270 | - } |
|
| 271 | - } |
|
| 272 | - |
|
| 273 | - // test credentials |
|
| 274 | - $canManualCreate = $this->barrierTest(User::CREATION_MANUAL, $user, 'RequestCreation'); |
|
| 275 | - $canOauthCreate = $this->barrierTest(User::CREATION_OAUTH, $user, 'RequestCreation'); |
|
| 276 | - $canBotCreate = $this->barrierTest(User::CREATION_BOT, $user, 'RequestCreation'); |
|
| 277 | - |
|
| 278 | - $this->assign('canManualCreate', $canManualCreate); |
|
| 279 | - $this->assign('canOauthCreate', $canOauthCreate); |
|
| 280 | - $this->assign('canBotCreate', $canBotCreate); |
|
| 281 | - |
|
| 282 | - // show/hide the type radio buttons |
|
| 283 | - $creationHasChoice = count(array_filter([$canManualCreate, $canOauthCreate, $canBotCreate])) > 1; |
|
| 284 | - |
|
| 285 | - if (!$this->barrierTest($user->getCreationMode(), $user, 'RequestCreation')) { |
|
| 286 | - // user is not allowed to use their default. Force a choice. |
|
| 287 | - $creationHasChoice = true; |
|
| 288 | - } |
|
| 289 | - |
|
| 290 | - $this->assign('creationHasChoice', $creationHasChoice); |
|
| 291 | - |
|
| 292 | - // determine problems in creation types |
|
| 293 | - $this->assign('botProblem', false); |
|
| 294 | - if ($canBotCreate && $this->getSiteConfiguration()->getCreationBotPassword() === null) { |
|
| 295 | - $this->assign('botProblem', true); |
|
| 296 | - } |
|
| 297 | - |
|
| 298 | - $this->assign('oauthProblem', false); |
|
| 299 | - if ($canOauthCreate && !$oauth->canCreateAccount()) { |
|
| 300 | - $this->assign('oauthProblem', true); |
|
| 301 | - } |
|
| 302 | - } |
|
| 28 | + use RequestData; |
|
| 29 | + const STATUS_SYMBOL_OPEN = '☐'; |
|
| 30 | + const STATUS_SYMBOL_ACCEPTED = '☑'; |
|
| 31 | + const STATUS_SYMBOL_REJECTED = '☒'; |
|
| 32 | + |
|
| 33 | + /** |
|
| 34 | + * Main function for this page, when no specific actions are called. |
|
| 35 | + * @throws ApplicationLogicException |
|
| 36 | + */ |
|
| 37 | + protected function main() |
|
| 38 | + { |
|
| 39 | + // set up csrf protection |
|
| 40 | + $this->assignCSRFToken(); |
|
| 41 | + |
|
| 42 | + // get some useful objects |
|
| 43 | + $database = $this->getDatabase(); |
|
| 44 | + $request = $this->getRequest($database, WebRequest::getInt('id')); |
|
| 45 | + $config = $this->getSiteConfiguration(); |
|
| 46 | + $currentUser = User::getCurrent($database); |
|
| 47 | + |
|
| 48 | + // Test we should be able to look at this request |
|
| 49 | + if ($config->getEmailConfirmationEnabled()) { |
|
| 50 | + if ($request->getEmailConfirm() !== 'Confirmed') { |
|
| 51 | + // Not allowed to look at this yet. |
|
| 52 | + throw new ApplicationLogicException('The email address has not yet been confirmed for this request.'); |
|
| 53 | + } |
|
| 54 | + } |
|
| 55 | + |
|
| 56 | + $this->setupBasicData($request, $config); |
|
| 57 | + |
|
| 58 | + $this->setupUsernameData($request); |
|
| 59 | + |
|
| 60 | + $this->setupTitle($request); |
|
| 61 | + |
|
| 62 | + $this->setupReservationDetails($request->getReserved(), $database, $currentUser); |
|
| 63 | + $this->setupGeneralData($database); |
|
| 64 | + |
|
| 65 | + $this->assign('requestDataCleared', false); |
|
| 66 | + if ($request->getEmail() === $this->getSiteConfiguration()->getDataClearEmail()) { |
|
| 67 | + $this->assign('requestDataCleared', true); |
|
| 68 | + } |
|
| 69 | + |
|
| 70 | + $allowedPrivateData = $this->isAllowedPrivateData($request, $currentUser); |
|
| 71 | + |
|
| 72 | + $this->setupCreationTypes($currentUser); |
|
| 73 | + |
|
| 74 | + $this->setupLogData($request, $database); |
|
| 75 | + |
|
| 76 | + $this->addJs("/api.php?action=templates&targetVariable=templateconfirms"); |
|
| 77 | + |
|
| 78 | + $this->assign('showRevealLink', false); |
|
| 79 | + if ($request->getReserved() === $currentUser->getId() || |
|
| 80 | + $this->barrierTest('alwaysSeeHash', $currentUser, 'RequestData') |
|
| 81 | + ) { |
|
| 82 | + $this->assign('showRevealLink', true); |
|
| 83 | + $this->assign('revealHash', $request->getRevealHash()); |
|
| 84 | + } |
|
| 85 | + |
|
| 86 | + $this->assign('canSeeRelatedRequests', false); |
|
| 87 | + if ($allowedPrivateData || $this->barrierTest('seeRelatedRequests', $currentUser, 'RequestData')) { |
|
| 88 | + $this->setupRelatedRequests($request, $config, $database); |
|
| 89 | + } |
|
| 90 | + |
|
| 91 | + if ($allowedPrivateData) { |
|
| 92 | + $this->setTemplate('view-request/main-with-data.tpl'); |
|
| 93 | + $this->setupPrivateData($request); |
|
| 94 | + |
|
| 95 | + $this->assign('canSetBan', $this->barrierTest('set', $currentUser, PageBan::class)); |
|
| 96 | + $this->assign('canSeeCheckuserData', $this->barrierTest('seeUserAgentData', $currentUser, 'RequestData')); |
|
| 97 | + |
|
| 98 | + if ($this->barrierTest('seeUserAgentData', $currentUser, 'RequestData')) { |
|
| 99 | + $this->setTemplate('view-request/main-with-checkuser-data.tpl'); |
|
| 100 | + $this->setupCheckUserData($request); |
|
| 101 | + } |
|
| 102 | + } |
|
| 103 | + else { |
|
| 104 | + $this->setTemplate('view-request/main.tpl'); |
|
| 105 | + } |
|
| 106 | + } |
|
| 107 | + |
|
| 108 | + /** |
|
| 109 | + * @param Request $request |
|
| 110 | + */ |
|
| 111 | + protected function setupTitle(Request $request) |
|
| 112 | + { |
|
| 113 | + $statusSymbol = self::STATUS_SYMBOL_OPEN; |
|
| 114 | + if ($request->getStatus() === 'Closed') { |
|
| 115 | + if ($request->getWasCreated()) { |
|
| 116 | + $statusSymbol = self::STATUS_SYMBOL_ACCEPTED; |
|
| 117 | + } |
|
| 118 | + else { |
|
| 119 | + $statusSymbol = self::STATUS_SYMBOL_REJECTED; |
|
| 120 | + } |
|
| 121 | + } |
|
| 122 | + |
|
| 123 | + $this->setHtmlTitle($statusSymbol . ' #' . $request->getId()); |
|
| 124 | + } |
|
| 125 | + |
|
| 126 | + /** |
|
| 127 | + * Sets up data unrelated to the request, such as the email template information |
|
| 128 | + * |
|
| 129 | + * @param PdoDatabase $database |
|
| 130 | + */ |
|
| 131 | + protected function setupGeneralData(PdoDatabase $database) |
|
| 132 | + { |
|
| 133 | + $config = $this->getSiteConfiguration(); |
|
| 134 | + |
|
| 135 | + $this->assign('createAccountReason', 'Requested account at [[WP:ACC]], request #'); |
|
| 136 | + |
|
| 137 | + $this->assign('defaultRequestState', $config->getDefaultRequestStateKey()); |
|
| 138 | + |
|
| 139 | + $this->assign('requestStates', $config->getRequestStates()); |
|
| 140 | + |
|
| 141 | + /** @var EmailTemplate $createdTemplate */ |
|
| 142 | + $createdTemplate = EmailTemplate::getById($config->getDefaultCreatedTemplateId(), $database); |
|
| 143 | + |
|
| 144 | + $this->assign('createdHasJsQuestion', $createdTemplate->getJsquestion() != ''); |
|
| 145 | + $this->assign('createdId', $createdTemplate->getId()); |
|
| 146 | + $this->assign('createdName', $createdTemplate->getName()); |
|
| 147 | + |
|
| 148 | + $createReasons = EmailTemplate::getActiveTemplates(EmailTemplate::CREATED, $database); |
|
| 149 | + $this->assign("createReasons", $createReasons); |
|
| 150 | + $declineReasons = EmailTemplate::getActiveTemplates(EmailTemplate::NOT_CREATED, $database); |
|
| 151 | + $this->assign("declineReasons", $declineReasons); |
|
| 152 | + |
|
| 153 | + $allCreateReasons = EmailTemplate::getAllActiveTemplates(EmailTemplate::CREATED, $database); |
|
| 154 | + $this->assign("allCreateReasons", $allCreateReasons); |
|
| 155 | + $allDeclineReasons = EmailTemplate::getAllActiveTemplates(EmailTemplate::NOT_CREATED, $database); |
|
| 156 | + $this->assign("allDeclineReasons", $allDeclineReasons); |
|
| 157 | + $allOtherReasons = EmailTemplate::getAllActiveTemplates(false, $database); |
|
| 158 | + $this->assign("allOtherReasons", $allOtherReasons); |
|
| 159 | + } |
|
| 160 | + |
|
| 161 | + private function setupLogData(Request $request, PdoDatabase $database) |
|
| 162 | + { |
|
| 163 | + $currentUser = User::getCurrent($database); |
|
| 164 | + |
|
| 165 | + $logs = LogHelper::getRequestLogsWithComments($request->getId(), $database, $this->getSecurityManager()); |
|
| 166 | + $requestLogs = array(); |
|
| 167 | + |
|
| 168 | + /** @var User[] $nameCache */ |
|
| 169 | + $nameCache = array(); |
|
| 170 | + |
|
| 171 | + $editableComments = $this->barrierTest('editOthers', $currentUser, PageEditComment::class); |
|
| 172 | + |
|
| 173 | + /** @var Log|Comment $entry */ |
|
| 174 | + foreach ($logs as $entry) { |
|
| 175 | + // both log and comment have a 'user' field |
|
| 176 | + if (!array_key_exists($entry->getUser(), $nameCache)) { |
|
| 177 | + $entryUser = User::getById($entry->getUser(), $database); |
|
| 178 | + $nameCache[$entry->getUser()] = $entryUser; |
|
| 179 | + } |
|
| 180 | + |
|
| 181 | + if ($entry instanceof Comment) { |
|
| 182 | + $requestLogs[] = array( |
|
| 183 | + 'type' => 'comment', |
|
| 184 | + 'security' => $entry->getVisibility(), |
|
| 185 | + 'user' => $entry->getVisibility() == 'requester' ? $request->getName() : $nameCache[$entry->getUser()]->getUsername(), |
|
| 186 | + 'userid' => $entry->getUser() == -1 ? null : $entry->getUser(), |
|
| 187 | + 'entry' => null, |
|
| 188 | + 'time' => $entry->getTime(), |
|
| 189 | + 'canedit' => ($editableComments || $entry->getUser() == $currentUser->getId()), |
|
| 190 | + 'id' => $entry->getId(), |
|
| 191 | + 'comment' => $entry->getComment(), |
|
| 192 | + ); |
|
| 193 | + } |
|
| 194 | + |
|
| 195 | + if ($entry instanceof Log) { |
|
| 196 | + $invalidUserId = $entry->getUser() === -1 || $entry->getUser() === 0; |
|
| 197 | + $entryUser = $invalidUserId ? User::getCommunity() : $nameCache[$entry->getUser()]; |
|
| 198 | + |
|
| 199 | + $entryComment = $entry->getComment(); |
|
| 200 | + |
|
| 201 | + if ($entry->getAction() === 'JobIssueRequest' || $entry->getAction() === 'JobCompletedRequest') { |
|
| 202 | + $data = unserialize($entry->getComment()); |
|
| 203 | + /** @var JobQueue $job */ |
|
| 204 | + $job = JobQueue::getById($data['job'], $database); |
|
| 205 | + $requestLogs[] = array( |
|
| 206 | + 'type' => 'joblog', |
|
| 207 | + 'security' => 'user', |
|
| 208 | + 'userid' => $entry->getUser() == -1 ? null : $entry->getUser(), |
|
| 209 | + 'user' => $entryUser->getUsername(), |
|
| 210 | + 'entry' => LogHelper::getLogDescription($entry), |
|
| 211 | + 'time' => $entry->getTimestamp(), |
|
| 212 | + 'canedit' => false, |
|
| 213 | + 'id' => $entry->getId(), |
|
| 214 | + 'jobId' => $job->getId(), |
|
| 215 | + 'jobDesc' => JobQueue::getTaskDescriptions()[$job->getTask()], |
|
| 216 | + ); |
|
| 217 | + } else { |
|
| 218 | + $requestLogs[] = array( |
|
| 219 | + 'type' => 'log', |
|
| 220 | + 'security' => 'user', |
|
| 221 | + 'userid' => $entry->getUser() == -1 ? null : $entry->getUser(), |
|
| 222 | + 'user' => $entryUser->getUsername(), |
|
| 223 | + 'entry' => LogHelper::getLogDescription($entry), |
|
| 224 | + 'time' => $entry->getTimestamp(), |
|
| 225 | + 'canedit' => false, |
|
| 226 | + 'id' => $entry->getId(), |
|
| 227 | + 'comment' => $entryComment, |
|
| 228 | + ); |
|
| 229 | + } |
|
| 230 | + } |
|
| 231 | + } |
|
| 232 | + |
|
| 233 | + $this->addJs("/api.php?action=users&targetVariable=typeaheaddata"); |
|
| 234 | + |
|
| 235 | + $this->assign("requestLogs", $requestLogs); |
|
| 236 | + } |
|
| 237 | + |
|
| 238 | + /** |
|
| 239 | + * @param Request $request |
|
| 240 | + */ |
|
| 241 | + protected function setupUsernameData(Request $request) |
|
| 242 | + { |
|
| 243 | + $blacklistData = $this->getBlacklistHelper()->isBlacklisted($request->getName()); |
|
| 244 | + |
|
| 245 | + $this->assign('requestIsBlacklisted', $blacklistData !== false); |
|
| 246 | + $this->assign('requestBlacklist', $blacklistData); |
|
| 247 | + |
|
| 248 | + try { |
|
| 249 | + $spoofs = $this->getAntiSpoofProvider()->getSpoofs($request->getName()); |
|
| 250 | + } |
|
| 251 | + catch (Exception $ex) { |
|
| 252 | + $spoofs = $ex->getMessage(); |
|
| 253 | + } |
|
| 254 | + |
|
| 255 | + $this->assign("spoofs", $spoofs); |
|
| 256 | + } |
|
| 257 | + |
|
| 258 | + private function setupCreationTypes(User $user) |
|
| 259 | + { |
|
| 260 | + $this->assign('allowWelcomeSkip', false); |
|
| 261 | + $this->assign('forceWelcomeSkip', false); |
|
| 262 | + |
|
| 263 | + $oauth = new OAuthUserHelper($user, $this->getDatabase(), $this->getOAuthProtocolHelper(), $this->getSiteConfiguration()); |
|
| 264 | + |
|
| 265 | + if ($user->getWelcomeTemplate() != 0) { |
|
| 266 | + $this->assign('allowWelcomeSkip', true); |
|
| 267 | + |
|
| 268 | + if (!$oauth->canWelcome()) { |
|
| 269 | + $this->assign('forceWelcomeSkip', true); |
|
| 270 | + } |
|
| 271 | + } |
|
| 272 | + |
|
| 273 | + // test credentials |
|
| 274 | + $canManualCreate = $this->barrierTest(User::CREATION_MANUAL, $user, 'RequestCreation'); |
|
| 275 | + $canOauthCreate = $this->barrierTest(User::CREATION_OAUTH, $user, 'RequestCreation'); |
|
| 276 | + $canBotCreate = $this->barrierTest(User::CREATION_BOT, $user, 'RequestCreation'); |
|
| 277 | + |
|
| 278 | + $this->assign('canManualCreate', $canManualCreate); |
|
| 279 | + $this->assign('canOauthCreate', $canOauthCreate); |
|
| 280 | + $this->assign('canBotCreate', $canBotCreate); |
|
| 281 | + |
|
| 282 | + // show/hide the type radio buttons |
|
| 283 | + $creationHasChoice = count(array_filter([$canManualCreate, $canOauthCreate, $canBotCreate])) > 1; |
|
| 284 | + |
|
| 285 | + if (!$this->barrierTest($user->getCreationMode(), $user, 'RequestCreation')) { |
|
| 286 | + // user is not allowed to use their default. Force a choice. |
|
| 287 | + $creationHasChoice = true; |
|
| 288 | + } |
|
| 289 | + |
|
| 290 | + $this->assign('creationHasChoice', $creationHasChoice); |
|
| 291 | + |
|
| 292 | + // determine problems in creation types |
|
| 293 | + $this->assign('botProblem', false); |
|
| 294 | + if ($canBotCreate && $this->getSiteConfiguration()->getCreationBotPassword() === null) { |
|
| 295 | + $this->assign('botProblem', true); |
|
| 296 | + } |
|
| 297 | + |
|
| 298 | + $this->assign('oauthProblem', false); |
|
| 299 | + if ($canOauthCreate && !$oauth->canCreateAccount()) { |
|
| 300 | + $this->assign('oauthProblem', true); |
|
| 301 | + } |
|
| 302 | + } |
|
| 303 | 303 | } |
@@ -99,8 +99,7 @@ discard block |
||
| 99 | 99 | $this->setTemplate('view-request/main-with-checkuser-data.tpl'); |
| 100 | 100 | $this->setupCheckUserData($request); |
| 101 | 101 | } |
| 102 | - } |
|
| 103 | - else { |
|
| 102 | + } else { |
|
| 104 | 103 | $this->setTemplate('view-request/main.tpl'); |
| 105 | 104 | } |
| 106 | 105 | } |
@@ -114,8 +113,7 @@ discard block |
||
| 114 | 113 | if ($request->getStatus() === 'Closed') { |
| 115 | 114 | if ($request->getWasCreated()) { |
| 116 | 115 | $statusSymbol = self::STATUS_SYMBOL_ACCEPTED; |
| 117 | - } |
|
| 118 | - else { |
|
| 116 | + } else { |
|
| 119 | 117 | $statusSymbol = self::STATUS_SYMBOL_REJECTED; |
| 120 | 118 | } |
| 121 | 119 | } |
@@ -24,279 +24,279 @@ |
||
| 24 | 24 | |
| 25 | 25 | class PageCustomClose extends PageCloseRequest |
| 26 | 26 | { |
| 27 | - use RequestData; |
|
| 28 | - |
|
| 29 | - protected function main() |
|
| 30 | - { |
|
| 31 | - $database = $this->getDatabase(); |
|
| 32 | - |
|
| 33 | - $request = $this->getRequest($database); |
|
| 34 | - $currentUser = User::getCurrent($this->getDatabase()); |
|
| 35 | - |
|
| 36 | - if ($request->getStatus() === 'Closed') { |
|
| 37 | - throw new ApplicationLogicException('Request is already closed'); |
|
| 38 | - } |
|
| 39 | - |
|
| 40 | - // Dual-mode page |
|
| 41 | - if (WebRequest::wasPosted()) { |
|
| 42 | - $this->validateCSRFToken(); |
|
| 43 | - $this->doCustomClose($currentUser, $request, $database); |
|
| 44 | - |
|
| 45 | - $this->redirect(); |
|
| 46 | - } |
|
| 47 | - else { |
|
| 48 | - $this->assignCSRFToken(); |
|
| 49 | - $this->showCustomCloseForm($database, $request); |
|
| 50 | - } |
|
| 51 | - } |
|
| 52 | - |
|
| 53 | - /** |
|
| 54 | - * @param $database |
|
| 55 | - * |
|
| 56 | - * @return Request |
|
| 57 | - * @throws ApplicationLogicException |
|
| 58 | - */ |
|
| 59 | - protected function getRequest(PdoDatabase $database) |
|
| 60 | - { |
|
| 61 | - $requestId = WebRequest::getInt('request'); |
|
| 62 | - if ($requestId === null) { |
|
| 63 | - throw new ApplicationLogicException('Request ID not found'); |
|
| 64 | - } |
|
| 65 | - |
|
| 66 | - /** @var Request $request */ |
|
| 67 | - $request = Request::getById($requestId, $database); |
|
| 68 | - |
|
| 69 | - if ($request === false) { |
|
| 70 | - throw new ApplicationLogicException('Request not found'); |
|
| 71 | - } |
|
| 72 | - |
|
| 73 | - return $request; |
|
| 74 | - } |
|
| 75 | - |
|
| 76 | - /** |
|
| 77 | - * @param PdoDatabase $database |
|
| 78 | - * |
|
| 79 | - * @return EmailTemplate|null |
|
| 80 | - */ |
|
| 81 | - protected function getTemplate(PdoDatabase $database) |
|
| 82 | - { |
|
| 83 | - $templateId = WebRequest::getInt('template'); |
|
| 84 | - if ($templateId === null) { |
|
| 85 | - return null; |
|
| 86 | - } |
|
| 87 | - |
|
| 88 | - /** @var EmailTemplate $template */ |
|
| 89 | - $template = EmailTemplate::getById($templateId, $database); |
|
| 90 | - if ($template === false || !$template->getActive()) { |
|
| 91 | - return null; |
|
| 92 | - } |
|
| 93 | - |
|
| 94 | - return $template; |
|
| 95 | - } |
|
| 96 | - |
|
| 97 | - /** |
|
| 98 | - * @param $database |
|
| 99 | - * @param $request |
|
| 100 | - * |
|
| 101 | - * @throws Exception |
|
| 102 | - */ |
|
| 103 | - protected function showCustomCloseForm(PdoDatabase $database, Request $request) |
|
| 104 | - { |
|
| 105 | - $currentUser = User::getCurrent($database); |
|
| 106 | - $config = $this->getSiteConfiguration(); |
|
| 107 | - |
|
| 108 | - $allowedPrivateData = $this->isAllowedPrivateData($request, $currentUser); |
|
| 109 | - if (!$allowedPrivateData) { |
|
| 110 | - // we probably shouldn't be showing the user this form if they're not allowed to access private data... |
|
| 111 | - throw new AccessDeniedException($this->getSecurityManager()); |
|
| 112 | - } |
|
| 113 | - |
|
| 114 | - $template = $this->getTemplate($database); |
|
| 115 | - |
|
| 116 | - // Preload data |
|
| 117 | - $this->assign('defaultAction', ''); |
|
| 118 | - $this->assign('preloadText', ''); |
|
| 119 | - $this->assign('preloadTitle', ''); |
|
| 120 | - |
|
| 121 | - if ($template !== null) { |
|
| 122 | - $this->assign('defaultAction', $template->getDefaultAction()); |
|
| 123 | - $this->assign('preloadText', $template->getText()); |
|
| 124 | - $this->assign('preloadTitle', $template->getName()); |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - // Static data |
|
| 128 | - $this->assign('requeststates', $config->getRequestStates()); |
|
| 129 | - |
|
| 130 | - // request data |
|
| 131 | - $this->assign('requestId', $request->getIp()); |
|
| 132 | - $this->assign('updateVersion', $request->getUpdateVersion()); |
|
| 133 | - $this->setupBasicData($request, $config); |
|
| 134 | - $this->setupReservationDetails($request->getReserved(), $database, $currentUser); |
|
| 135 | - $this->setupPrivateData($request); |
|
| 136 | - $this->setupRelatedRequests($request, $config, $database); |
|
| 137 | - |
|
| 138 | - // IP location |
|
| 139 | - $trustedIp = $this->getXffTrustProvider()->getTrustedClientIp($request->getIp(), $request->getForwardedIp()); |
|
| 140 | - $this->assign('iplocation', $this->getLocationProvider()->getIpLocation($trustedIp)); |
|
| 141 | - |
|
| 142 | - // Confirmations |
|
| 143 | - $this->assign('confirmEmailAlreadySent', $this->checkEmailAlreadySent($request)); |
|
| 144 | - |
|
| 145 | - $this->assign('canSkipCcMailingList', $this->barrierTest('skipCcMailingList', $currentUser)); |
|
| 146 | - |
|
| 147 | - $this->assign('allowWelcomeSkip', false); |
|
| 148 | - $this->assign('forceWelcomeSkip', false); |
|
| 149 | - |
|
| 150 | - $oauth = new OAuthUserHelper($currentUser, $this->getDatabase(), $this->getOAuthProtocolHelper(), $config); |
|
| 151 | - |
|
| 152 | - if ($currentUser->getWelcomeTemplate() != 0) { |
|
| 153 | - $this->assign('allowWelcomeSkip', true); |
|
| 154 | - |
|
| 155 | - if (!$oauth->canWelcome()) { |
|
| 156 | - $this->assign('forceWelcomeSkip', true); |
|
| 157 | - } |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - |
|
| 161 | - // template |
|
| 162 | - $this->setTemplate('custom-close.tpl'); |
|
| 163 | - } |
|
| 164 | - |
|
| 165 | - /** |
|
| 166 | - * @param User $currentUser |
|
| 167 | - * @param Request $request |
|
| 168 | - * @param PdoDatabase $database |
|
| 169 | - * |
|
| 170 | - * @throws ApplicationLogicException |
|
| 171 | - */ |
|
| 172 | - protected function doCustomClose(User $currentUser, Request $request, PdoDatabase $database) |
|
| 173 | - { |
|
| 174 | - $messageBody = WebRequest::postString('msgbody'); |
|
| 175 | - if ($messageBody === null || trim($messageBody) === '') { |
|
| 176 | - throw new ApplicationLogicException('Message body cannot be blank'); |
|
| 177 | - } |
|
| 178 | - |
|
| 179 | - $ccMailingList = true; |
|
| 180 | - if ($this->barrierTest('skipCcMailingList', $currentUser)) { |
|
| 181 | - $ccMailingList = WebRequest::postBoolean('ccMailingList'); |
|
| 182 | - } |
|
| 183 | - |
|
| 184 | - if ($request->getStatus() === 'Closed') { |
|
| 185 | - throw new ApplicationLogicException('Request is already closed'); |
|
| 186 | - } |
|
| 187 | - |
|
| 188 | - if (!(WebRequest::postBoolean('confirmEmailAlreadySent')) |
|
| 189 | - ) { |
|
| 190 | - throw new ApplicationLogicException('Not all confirmations checked'); |
|
| 191 | - } |
|
| 192 | - |
|
| 193 | - $action = WebRequest::postString('action'); |
|
| 194 | - $availableRequestStates = $this->getSiteConfiguration()->getRequestStates(); |
|
| 195 | - |
|
| 196 | - if ($action === EmailTemplate::CREATED || $action === EmailTemplate::NOT_CREATED) { |
|
| 197 | - // Close request |
|
| 198 | - $this->closeRequest($request, $database, $action, $messageBody); |
|
| 199 | - |
|
| 200 | - $this->processWelcome($action); |
|
| 201 | - |
|
| 202 | - // Send the mail after the save, since save can be rolled back |
|
| 203 | - $this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
|
| 204 | - } |
|
| 205 | - else { |
|
| 206 | - if (array_key_exists($action, $availableRequestStates)) { |
|
| 207 | - // Defer to other state |
|
| 208 | - $this->deferRequest($request, $database, $action, $availableRequestStates, $messageBody); |
|
| 209 | - |
|
| 210 | - // Send the mail after the save, since save can be rolled back |
|
| 211 | - $this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
|
| 212 | - } |
|
| 213 | - else { |
|
| 214 | - $request->setReserved(null); |
|
| 215 | - $request->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
| 216 | - $request->save(); |
|
| 217 | - |
|
| 218 | - // Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE |
|
| 219 | - // and be rolled back. |
|
| 220 | - |
|
| 221 | - // Send mail |
|
| 222 | - $this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
|
| 223 | - |
|
| 224 | - Logger::sentMail($database, $request, $messageBody); |
|
| 225 | - Logger::unreserve($database, $request); |
|
| 226 | - |
|
| 227 | - $this->getNotificationHelper()->sentMail($request); |
|
| 228 | - SessionAlert::success("Sent mail to Request {$request->getId()}"); |
|
| 229 | - } |
|
| 230 | - } |
|
| 231 | - } |
|
| 232 | - |
|
| 233 | - /** |
|
| 234 | - * @param Request $request |
|
| 235 | - * @param PdoDatabase $database |
|
| 236 | - * @param string $action |
|
| 237 | - * @param string $messageBody |
|
| 238 | - * |
|
| 239 | - * @throws Exception |
|
| 240 | - * @throws OptimisticLockFailedException |
|
| 241 | - */ |
|
| 242 | - protected function closeRequest(Request $request, PdoDatabase $database, $action, $messageBody) |
|
| 243 | - { |
|
| 244 | - $request->setStatus('Closed'); |
|
| 245 | - $request->setReserved(null); |
|
| 246 | - $request->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
| 247 | - $request->save(); |
|
| 248 | - |
|
| 249 | - // Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE and |
|
| 250 | - // be rolled back. |
|
| 251 | - |
|
| 252 | - if ($action == EmailTemplate::CREATED) { |
|
| 253 | - $logCloseType = 'custom-y'; |
|
| 254 | - $notificationCloseType = "Custom, Created"; |
|
| 255 | - } |
|
| 256 | - else { |
|
| 257 | - $logCloseType = 'custom-n'; |
|
| 258 | - $notificationCloseType = "Custom, Not Created"; |
|
| 259 | - } |
|
| 260 | - |
|
| 261 | - Logger::closeRequest($database, $request, $logCloseType, $messageBody); |
|
| 262 | - $this->getNotificationHelper()->requestClosed($request, $notificationCloseType); |
|
| 263 | - |
|
| 264 | - $requestName = htmlentities($request->getName(), ENT_COMPAT, 'UTF-8'); |
|
| 265 | - SessionAlert::success("Request {$request->getId()} ({$requestName}) closed as {$notificationCloseType}."); |
|
| 266 | - } |
|
| 267 | - |
|
| 268 | - /** |
|
| 269 | - * @param Request $request |
|
| 270 | - * @param PdoDatabase $database |
|
| 271 | - * @param string $action |
|
| 272 | - * @param $availableRequestStates |
|
| 273 | - * @param string $messageBody |
|
| 274 | - * |
|
| 275 | - * @throws Exception |
|
| 276 | - * @throws OptimisticLockFailedException |
|
| 277 | - */ |
|
| 278 | - protected function deferRequest( |
|
| 279 | - Request $request, |
|
| 280 | - PdoDatabase $database, |
|
| 281 | - $action, |
|
| 282 | - $availableRequestStates, |
|
| 283 | - $messageBody |
|
| 284 | - ) { |
|
| 285 | - $request->setStatus($action); |
|
| 286 | - $request->setReserved(null); |
|
| 287 | - $request->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
| 288 | - $request->save(); |
|
| 289 | - |
|
| 290 | - // Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE |
|
| 291 | - // and be rolled back. |
|
| 292 | - |
|
| 293 | - $deferToLog = $availableRequestStates[$action]['defertolog']; |
|
| 294 | - Logger::sentMail($database, $request, $messageBody); |
|
| 295 | - Logger::deferRequest($database, $request, $deferToLog); |
|
| 296 | - |
|
| 297 | - $this->getNotificationHelper()->requestDeferredWithMail($request); |
|
| 298 | - |
|
| 299 | - $deferTo = $availableRequestStates[$action]['deferto']; |
|
| 300 | - SessionAlert::success("Request {$request->getId()} deferred to $deferTo, sending an email."); |
|
| 301 | - } |
|
| 27 | + use RequestData; |
|
| 28 | + |
|
| 29 | + protected function main() |
|
| 30 | + { |
|
| 31 | + $database = $this->getDatabase(); |
|
| 32 | + |
|
| 33 | + $request = $this->getRequest($database); |
|
| 34 | + $currentUser = User::getCurrent($this->getDatabase()); |
|
| 35 | + |
|
| 36 | + if ($request->getStatus() === 'Closed') { |
|
| 37 | + throw new ApplicationLogicException('Request is already closed'); |
|
| 38 | + } |
|
| 39 | + |
|
| 40 | + // Dual-mode page |
|
| 41 | + if (WebRequest::wasPosted()) { |
|
| 42 | + $this->validateCSRFToken(); |
|
| 43 | + $this->doCustomClose($currentUser, $request, $database); |
|
| 44 | + |
|
| 45 | + $this->redirect(); |
|
| 46 | + } |
|
| 47 | + else { |
|
| 48 | + $this->assignCSRFToken(); |
|
| 49 | + $this->showCustomCloseForm($database, $request); |
|
| 50 | + } |
|
| 51 | + } |
|
| 52 | + |
|
| 53 | + /** |
|
| 54 | + * @param $database |
|
| 55 | + * |
|
| 56 | + * @return Request |
|
| 57 | + * @throws ApplicationLogicException |
|
| 58 | + */ |
|
| 59 | + protected function getRequest(PdoDatabase $database) |
|
| 60 | + { |
|
| 61 | + $requestId = WebRequest::getInt('request'); |
|
| 62 | + if ($requestId === null) { |
|
| 63 | + throw new ApplicationLogicException('Request ID not found'); |
|
| 64 | + } |
|
| 65 | + |
|
| 66 | + /** @var Request $request */ |
|
| 67 | + $request = Request::getById($requestId, $database); |
|
| 68 | + |
|
| 69 | + if ($request === false) { |
|
| 70 | + throw new ApplicationLogicException('Request not found'); |
|
| 71 | + } |
|
| 72 | + |
|
| 73 | + return $request; |
|
| 74 | + } |
|
| 75 | + |
|
| 76 | + /** |
|
| 77 | + * @param PdoDatabase $database |
|
| 78 | + * |
|
| 79 | + * @return EmailTemplate|null |
|
| 80 | + */ |
|
| 81 | + protected function getTemplate(PdoDatabase $database) |
|
| 82 | + { |
|
| 83 | + $templateId = WebRequest::getInt('template'); |
|
| 84 | + if ($templateId === null) { |
|
| 85 | + return null; |
|
| 86 | + } |
|
| 87 | + |
|
| 88 | + /** @var EmailTemplate $template */ |
|
| 89 | + $template = EmailTemplate::getById($templateId, $database); |
|
| 90 | + if ($template === false || !$template->getActive()) { |
|
| 91 | + return null; |
|
| 92 | + } |
|
| 93 | + |
|
| 94 | + return $template; |
|
| 95 | + } |
|
| 96 | + |
|
| 97 | + /** |
|
| 98 | + * @param $database |
|
| 99 | + * @param $request |
|
| 100 | + * |
|
| 101 | + * @throws Exception |
|
| 102 | + */ |
|
| 103 | + protected function showCustomCloseForm(PdoDatabase $database, Request $request) |
|
| 104 | + { |
|
| 105 | + $currentUser = User::getCurrent($database); |
|
| 106 | + $config = $this->getSiteConfiguration(); |
|
| 107 | + |
|
| 108 | + $allowedPrivateData = $this->isAllowedPrivateData($request, $currentUser); |
|
| 109 | + if (!$allowedPrivateData) { |
|
| 110 | + // we probably shouldn't be showing the user this form if they're not allowed to access private data... |
|
| 111 | + throw new AccessDeniedException($this->getSecurityManager()); |
|
| 112 | + } |
|
| 113 | + |
|
| 114 | + $template = $this->getTemplate($database); |
|
| 115 | + |
|
| 116 | + // Preload data |
|
| 117 | + $this->assign('defaultAction', ''); |
|
| 118 | + $this->assign('preloadText', ''); |
|
| 119 | + $this->assign('preloadTitle', ''); |
|
| 120 | + |
|
| 121 | + if ($template !== null) { |
|
| 122 | + $this->assign('defaultAction', $template->getDefaultAction()); |
|
| 123 | + $this->assign('preloadText', $template->getText()); |
|
| 124 | + $this->assign('preloadTitle', $template->getName()); |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + // Static data |
|
| 128 | + $this->assign('requeststates', $config->getRequestStates()); |
|
| 129 | + |
|
| 130 | + // request data |
|
| 131 | + $this->assign('requestId', $request->getIp()); |
|
| 132 | + $this->assign('updateVersion', $request->getUpdateVersion()); |
|
| 133 | + $this->setupBasicData($request, $config); |
|
| 134 | + $this->setupReservationDetails($request->getReserved(), $database, $currentUser); |
|
| 135 | + $this->setupPrivateData($request); |
|
| 136 | + $this->setupRelatedRequests($request, $config, $database); |
|
| 137 | + |
|
| 138 | + // IP location |
|
| 139 | + $trustedIp = $this->getXffTrustProvider()->getTrustedClientIp($request->getIp(), $request->getForwardedIp()); |
|
| 140 | + $this->assign('iplocation', $this->getLocationProvider()->getIpLocation($trustedIp)); |
|
| 141 | + |
|
| 142 | + // Confirmations |
|
| 143 | + $this->assign('confirmEmailAlreadySent', $this->checkEmailAlreadySent($request)); |
|
| 144 | + |
|
| 145 | + $this->assign('canSkipCcMailingList', $this->barrierTest('skipCcMailingList', $currentUser)); |
|
| 146 | + |
|
| 147 | + $this->assign('allowWelcomeSkip', false); |
|
| 148 | + $this->assign('forceWelcomeSkip', false); |
|
| 149 | + |
|
| 150 | + $oauth = new OAuthUserHelper($currentUser, $this->getDatabase(), $this->getOAuthProtocolHelper(), $config); |
|
| 151 | + |
|
| 152 | + if ($currentUser->getWelcomeTemplate() != 0) { |
|
| 153 | + $this->assign('allowWelcomeSkip', true); |
|
| 154 | + |
|
| 155 | + if (!$oauth->canWelcome()) { |
|
| 156 | + $this->assign('forceWelcomeSkip', true); |
|
| 157 | + } |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + |
|
| 161 | + // template |
|
| 162 | + $this->setTemplate('custom-close.tpl'); |
|
| 163 | + } |
|
| 164 | + |
|
| 165 | + /** |
|
| 166 | + * @param User $currentUser |
|
| 167 | + * @param Request $request |
|
| 168 | + * @param PdoDatabase $database |
|
| 169 | + * |
|
| 170 | + * @throws ApplicationLogicException |
|
| 171 | + */ |
|
| 172 | + protected function doCustomClose(User $currentUser, Request $request, PdoDatabase $database) |
|
| 173 | + { |
|
| 174 | + $messageBody = WebRequest::postString('msgbody'); |
|
| 175 | + if ($messageBody === null || trim($messageBody) === '') { |
|
| 176 | + throw new ApplicationLogicException('Message body cannot be blank'); |
|
| 177 | + } |
|
| 178 | + |
|
| 179 | + $ccMailingList = true; |
|
| 180 | + if ($this->barrierTest('skipCcMailingList', $currentUser)) { |
|
| 181 | + $ccMailingList = WebRequest::postBoolean('ccMailingList'); |
|
| 182 | + } |
|
| 183 | + |
|
| 184 | + if ($request->getStatus() === 'Closed') { |
|
| 185 | + throw new ApplicationLogicException('Request is already closed'); |
|
| 186 | + } |
|
| 187 | + |
|
| 188 | + if (!(WebRequest::postBoolean('confirmEmailAlreadySent')) |
|
| 189 | + ) { |
|
| 190 | + throw new ApplicationLogicException('Not all confirmations checked'); |
|
| 191 | + } |
|
| 192 | + |
|
| 193 | + $action = WebRequest::postString('action'); |
|
| 194 | + $availableRequestStates = $this->getSiteConfiguration()->getRequestStates(); |
|
| 195 | + |
|
| 196 | + if ($action === EmailTemplate::CREATED || $action === EmailTemplate::NOT_CREATED) { |
|
| 197 | + // Close request |
|
| 198 | + $this->closeRequest($request, $database, $action, $messageBody); |
|
| 199 | + |
|
| 200 | + $this->processWelcome($action); |
|
| 201 | + |
|
| 202 | + // Send the mail after the save, since save can be rolled back |
|
| 203 | + $this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
|
| 204 | + } |
|
| 205 | + else { |
|
| 206 | + if (array_key_exists($action, $availableRequestStates)) { |
|
| 207 | + // Defer to other state |
|
| 208 | + $this->deferRequest($request, $database, $action, $availableRequestStates, $messageBody); |
|
| 209 | + |
|
| 210 | + // Send the mail after the save, since save can be rolled back |
|
| 211 | + $this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
|
| 212 | + } |
|
| 213 | + else { |
|
| 214 | + $request->setReserved(null); |
|
| 215 | + $request->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
| 216 | + $request->save(); |
|
| 217 | + |
|
| 218 | + // Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE |
|
| 219 | + // and be rolled back. |
|
| 220 | + |
|
| 221 | + // Send mail |
|
| 222 | + $this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
|
| 223 | + |
|
| 224 | + Logger::sentMail($database, $request, $messageBody); |
|
| 225 | + Logger::unreserve($database, $request); |
|
| 226 | + |
|
| 227 | + $this->getNotificationHelper()->sentMail($request); |
|
| 228 | + SessionAlert::success("Sent mail to Request {$request->getId()}"); |
|
| 229 | + } |
|
| 230 | + } |
|
| 231 | + } |
|
| 232 | + |
|
| 233 | + /** |
|
| 234 | + * @param Request $request |
|
| 235 | + * @param PdoDatabase $database |
|
| 236 | + * @param string $action |
|
| 237 | + * @param string $messageBody |
|
| 238 | + * |
|
| 239 | + * @throws Exception |
|
| 240 | + * @throws OptimisticLockFailedException |
|
| 241 | + */ |
|
| 242 | + protected function closeRequest(Request $request, PdoDatabase $database, $action, $messageBody) |
|
| 243 | + { |
|
| 244 | + $request->setStatus('Closed'); |
|
| 245 | + $request->setReserved(null); |
|
| 246 | + $request->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
| 247 | + $request->save(); |
|
| 248 | + |
|
| 249 | + // Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE and |
|
| 250 | + // be rolled back. |
|
| 251 | + |
|
| 252 | + if ($action == EmailTemplate::CREATED) { |
|
| 253 | + $logCloseType = 'custom-y'; |
|
| 254 | + $notificationCloseType = "Custom, Created"; |
|
| 255 | + } |
|
| 256 | + else { |
|
| 257 | + $logCloseType = 'custom-n'; |
|
| 258 | + $notificationCloseType = "Custom, Not Created"; |
|
| 259 | + } |
|
| 260 | + |
|
| 261 | + Logger::closeRequest($database, $request, $logCloseType, $messageBody); |
|
| 262 | + $this->getNotificationHelper()->requestClosed($request, $notificationCloseType); |
|
| 263 | + |
|
| 264 | + $requestName = htmlentities($request->getName(), ENT_COMPAT, 'UTF-8'); |
|
| 265 | + SessionAlert::success("Request {$request->getId()} ({$requestName}) closed as {$notificationCloseType}."); |
|
| 266 | + } |
|
| 267 | + |
|
| 268 | + /** |
|
| 269 | + * @param Request $request |
|
| 270 | + * @param PdoDatabase $database |
|
| 271 | + * @param string $action |
|
| 272 | + * @param $availableRequestStates |
|
| 273 | + * @param string $messageBody |
|
| 274 | + * |
|
| 275 | + * @throws Exception |
|
| 276 | + * @throws OptimisticLockFailedException |
|
| 277 | + */ |
|
| 278 | + protected function deferRequest( |
|
| 279 | + Request $request, |
|
| 280 | + PdoDatabase $database, |
|
| 281 | + $action, |
|
| 282 | + $availableRequestStates, |
|
| 283 | + $messageBody |
|
| 284 | + ) { |
|
| 285 | + $request->setStatus($action); |
|
| 286 | + $request->setReserved(null); |
|
| 287 | + $request->setUpdateVersion(WebRequest::postInt('updateversion')); |
|
| 288 | + $request->save(); |
|
| 289 | + |
|
| 290 | + // Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE |
|
| 291 | + // and be rolled back. |
|
| 292 | + |
|
| 293 | + $deferToLog = $availableRequestStates[$action]['defertolog']; |
|
| 294 | + Logger::sentMail($database, $request, $messageBody); |
|
| 295 | + Logger::deferRequest($database, $request, $deferToLog); |
|
| 296 | + |
|
| 297 | + $this->getNotificationHelper()->requestDeferredWithMail($request); |
|
| 298 | + |
|
| 299 | + $deferTo = $availableRequestStates[$action]['deferto']; |
|
| 300 | + SessionAlert::success("Request {$request->getId()} deferred to $deferTo, sending an email."); |
|
| 301 | + } |
|
| 302 | 302 | } |
@@ -24,326 +24,326 @@ |
||
| 24 | 24 | |
| 25 | 25 | trait RequestData |
| 26 | 26 | { |
| 27 | - /** |
|
| 28 | - * @var array Array of IP address classed as 'private' by RFC1918. |
|
| 29 | - */ |
|
| 30 | - protected static $rfc1918ips = array( |
|
| 31 | - "10.0.0.0" => "10.255.255.255", |
|
| 32 | - "172.16.0.0" => "172.31.255.255", |
|
| 33 | - "192.168.0.0" => "192.168.255.255", |
|
| 34 | - "169.254.0.0" => "169.254.255.255", |
|
| 35 | - "127.0.0.0" => "127.255.255.255", |
|
| 36 | - ); |
|
| 37 | - |
|
| 38 | - /** |
|
| 39 | - * Gets a request object |
|
| 40 | - * |
|
| 41 | - * @param PdoDatabase $database The database connection |
|
| 42 | - * @param int|null $requestId The ID of the request to retrieve |
|
| 43 | - * |
|
| 44 | - * @return Request |
|
| 45 | - * @throws ApplicationLogicException |
|
| 46 | - */ |
|
| 47 | - protected function getRequest(PdoDatabase $database, $requestId) |
|
| 48 | - { |
|
| 49 | - if ($requestId === null) { |
|
| 50 | - throw new ApplicationLogicException("No request specified"); |
|
| 51 | - } |
|
| 52 | - |
|
| 53 | - $request = Request::getById($requestId, $database); |
|
| 54 | - if ($request === false || !is_a($request, Request::class)) { |
|
| 55 | - throw new ApplicationLogicException('Could not load the requested request!'); |
|
| 56 | - } |
|
| 57 | - |
|
| 58 | - return $request; |
|
| 59 | - } |
|
| 60 | - |
|
| 61 | - /** |
|
| 62 | - * Returns a value stating whether the user is allowed to see private data or not |
|
| 63 | - * |
|
| 64 | - * @param Request $request |
|
| 65 | - * @param User $currentUser |
|
| 66 | - * |
|
| 67 | - * @return bool |
|
| 68 | - * @category Security-Critical |
|
| 69 | - */ |
|
| 70 | - protected function isAllowedPrivateData(Request $request, User $currentUser) |
|
| 71 | - { |
|
| 72 | - // Test the main security barrier for private data access using SecurityManager |
|
| 73 | - if ($this->barrierTest('alwaysSeePrivateData', $currentUser, 'RequestData')) { |
|
| 74 | - // Tool admins/check-users can always see private data |
|
| 75 | - return true; |
|
| 76 | - } |
|
| 77 | - |
|
| 78 | - // reserving user is allowed to see the data |
|
| 79 | - if ($currentUser->getId() === $request->getReserved() |
|
| 80 | - && $request->getReserved() !== null |
|
| 81 | - && $this->barrierTest('seePrivateDataWhenReserved', $currentUser, 'RequestData') |
|
| 82 | - ) { |
|
| 83 | - return true; |
|
| 84 | - } |
|
| 85 | - |
|
| 86 | - // user has the reveal hash |
|
| 87 | - if (WebRequest::getString('hash') === $request->getRevealHash() |
|
| 88 | - && $this->barrierTest('seePrivateDataWithHash', $currentUser, 'RequestData') |
|
| 89 | - ) { |
|
| 90 | - return true; |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - // nope. Not allowed. |
|
| 94 | - return false; |
|
| 95 | - } |
|
| 96 | - |
|
| 97 | - /** |
|
| 98 | - * Tests the security barrier for a specified action. |
|
| 99 | - * |
|
| 100 | - * Don't use within templates |
|
| 101 | - * |
|
| 102 | - * @param string $action |
|
| 103 | - * |
|
| 104 | - * @param User $user |
|
| 105 | - * @param null|string $pageName |
|
| 106 | - * |
|
| 107 | - * @return bool |
|
| 108 | - * @category Security-Critical |
|
| 109 | - */ |
|
| 110 | - abstract protected function barrierTest($action, User $user, $pageName = null); |
|
| 111 | - |
|
| 112 | - /** |
|
| 113 | - * Gets the name of the route that has been passed from the request router. |
|
| 114 | - * @return string |
|
| 115 | - */ |
|
| 116 | - abstract protected function getRouteName(); |
|
| 117 | - |
|
| 118 | - /** @return SecurityManager */ |
|
| 119 | - abstract protected function getSecurityManager(); |
|
| 120 | - |
|
| 121 | - /** |
|
| 122 | - * Sets the name of the template this page should display. |
|
| 123 | - * |
|
| 124 | - * @param string $name |
|
| 125 | - */ |
|
| 126 | - abstract protected function setTemplate($name); |
|
| 127 | - |
|
| 128 | - /** @return IXffTrustProvider */ |
|
| 129 | - abstract protected function getXffTrustProvider(); |
|
| 130 | - |
|
| 131 | - /** @return ILocationProvider */ |
|
| 132 | - abstract protected function getLocationProvider(); |
|
| 133 | - |
|
| 134 | - /** @return IRDnsProvider */ |
|
| 135 | - abstract protected function getRdnsProvider(); |
|
| 136 | - |
|
| 137 | - /** |
|
| 138 | - * Assigns a Smarty variable |
|
| 139 | - * |
|
| 140 | - * @param array|string $name the template variable name(s) |
|
| 141 | - * @param mixed $value the value to assign |
|
| 142 | - */ |
|
| 143 | - abstract protected function assign($name, $value); |
|
| 144 | - |
|
| 145 | - /** |
|
| 146 | - * @param int|null $requestReservationId |
|
| 147 | - * @param PdoDatabase $database |
|
| 148 | - * @param User $currentUser |
|
| 149 | - */ |
|
| 150 | - protected function setupReservationDetails($requestReservationId, PdoDatabase $database, User $currentUser) |
|
| 151 | - { |
|
| 152 | - $requestIsReserved = $requestReservationId !== null; |
|
| 153 | - $this->assign('requestIsReserved', $requestIsReserved); |
|
| 154 | - $this->assign('requestIsReservedByMe', false); |
|
| 155 | - |
|
| 156 | - if ($requestIsReserved) { |
|
| 157 | - $this->assign('requestReservedByName', User::getById($requestReservationId, $database)->getUsername()); |
|
| 158 | - $this->assign('requestReservedById', $requestReservationId); |
|
| 159 | - |
|
| 160 | - if ($requestReservationId === $currentUser->getId()) { |
|
| 161 | - $this->assign('requestIsReservedByMe', true); |
|
| 162 | - } |
|
| 163 | - } |
|
| 164 | - |
|
| 165 | - $this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class)); |
|
| 166 | - } |
|
| 167 | - |
|
| 168 | - /** |
|
| 169 | - * Adds private request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED! |
|
| 170 | - * |
|
| 171 | - * @param Request $request |
|
| 172 | - */ |
|
| 173 | - protected function setupPrivateData( |
|
| 174 | - $request |
|
| 175 | - ) { |
|
| 176 | - $xffProvider = $this->getXffTrustProvider(); |
|
| 177 | - |
|
| 178 | - $this->assign('requestEmail', $request->getEmail()); |
|
| 179 | - $emailDomain = explode("@", $request->getEmail())[1]; |
|
| 180 | - $this->assign("emailurl", $emailDomain); |
|
| 181 | - |
|
| 182 | - $trustedIp = $xffProvider->getTrustedClientIp($request->getIp(), $request->getForwardedIp()); |
|
| 183 | - $this->assign('requestTrustedIp', $trustedIp); |
|
| 184 | - $this->assign('requestRealIp', $request->getIp()); |
|
| 185 | - $this->assign('requestForwardedIp', $request->getForwardedIp()); |
|
| 186 | - |
|
| 187 | - $trustedIpLocation = $this->getLocationProvider()->getIpLocation($trustedIp); |
|
| 188 | - $this->assign('requestTrustedIpLocation', $trustedIpLocation); |
|
| 189 | - |
|
| 190 | - $this->assign('requestHasForwardedIp', $request->getForwardedIp() !== null); |
|
| 191 | - |
|
| 192 | - $this->setupForwardedIpData($request); |
|
| 193 | - } |
|
| 194 | - |
|
| 195 | - /** |
|
| 196 | - * Adds related request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED! |
|
| 197 | - * |
|
| 198 | - * @param Request $request |
|
| 199 | - * @param SiteConfiguration $configuration |
|
| 200 | - * @param PdoDatabase $database |
|
| 201 | - */ |
|
| 202 | - protected function setupRelatedRequests( |
|
| 203 | - Request $request, |
|
| 204 | - SiteConfiguration $configuration, |
|
| 205 | - PdoDatabase $database) |
|
| 206 | - { |
|
| 207 | - $this->assign('canSeeRelatedRequests', true); |
|
| 208 | - |
|
| 209 | - $relatedEmailRequests = RequestSearchHelper::get($database) |
|
| 210 | - ->byEmailAddress($request->getEmail()) |
|
| 211 | - ->withConfirmedEmail() |
|
| 212 | - ->excludingPurgedData($configuration) |
|
| 213 | - ->excludingRequest($request->getId()) |
|
| 214 | - ->fetch(); |
|
| 215 | - |
|
| 216 | - $this->assign('requestRelatedEmailRequestsCount', count($relatedEmailRequests)); |
|
| 217 | - $this->assign('requestRelatedEmailRequests', $relatedEmailRequests); |
|
| 218 | - |
|
| 219 | - $trustedIp = $this->getXffTrustProvider()->getTrustedClientIp($request->getIp(), $request->getForwardedIp()); |
|
| 220 | - $relatedIpRequests = RequestSearchHelper::get($database) |
|
| 221 | - ->byIp($trustedIp) |
|
| 222 | - ->withConfirmedEmail() |
|
| 223 | - ->excludingPurgedData($configuration) |
|
| 224 | - ->excludingRequest($request->getId()) |
|
| 225 | - ->fetch(); |
|
| 226 | - |
|
| 227 | - $this->assign('requestRelatedIpRequestsCount', count($relatedIpRequests)); |
|
| 228 | - $this->assign('requestRelatedIpRequests', $relatedIpRequests); |
|
| 229 | - } |
|
| 230 | - |
|
| 231 | - /** |
|
| 232 | - * Adds checkuser request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED! |
|
| 233 | - * |
|
| 234 | - * @param Request $request |
|
| 235 | - */ |
|
| 236 | - protected function setupCheckUserData(Request $request) |
|
| 237 | - { |
|
| 238 | - $this->assign('requestUserAgent', $request->getUserAgent()); |
|
| 239 | - } |
|
| 240 | - |
|
| 241 | - /** |
|
| 242 | - * Sets up the basic data for this request, and adds it to Smarty |
|
| 243 | - * |
|
| 244 | - * @param Request $request |
|
| 245 | - * @param SiteConfiguration $config |
|
| 246 | - */ |
|
| 247 | - protected function setupBasicData(Request $request, SiteConfiguration $config) |
|
| 248 | - { |
|
| 249 | - $this->assign('requestId', $request->getId()); |
|
| 250 | - $this->assign('updateVersion', $request->getUpdateVersion()); |
|
| 251 | - $this->assign('requestName', $request->getName()); |
|
| 252 | - $this->assign('requestDate', $request->getDate()); |
|
| 253 | - $this->assign('requestStatus', $request->getStatus()); |
|
| 254 | - |
|
| 255 | - $isClosed = !array_key_exists($request->getStatus(), $config->getRequestStates()) |
|
| 256 | - && $request->getStatus() !== RequestStatus::HOSPITAL; |
|
| 257 | - $this->assign('requestIsClosed', $isClosed); |
|
| 258 | - } |
|
| 259 | - |
|
| 260 | - /** |
|
| 261 | - * Sets up the forwarded IP data for this request and adds it to Smarty |
|
| 262 | - * |
|
| 263 | - * @param Request $request |
|
| 264 | - */ |
|
| 265 | - protected function setupForwardedIpData(Request $request) |
|
| 266 | - { |
|
| 267 | - if ($request->getForwardedIp() !== null) { |
|
| 268 | - $requestProxyData = array(); // Initialize array to store data to be output in Smarty template. |
|
| 269 | - $proxyIndex = 0; |
|
| 270 | - |
|
| 271 | - // Assuming [client] <=> [proxy1] <=> [proxy2] <=> [proxy3] <=> [us], we will see an XFF header of [client], |
|
| 272 | - // [proxy1], [proxy2], and our actual IP will be [proxy3] |
|
| 273 | - $proxies = explode(",", $request->getForwardedIp()); |
|
| 274 | - $proxies[] = $request->getIp(); |
|
| 275 | - |
|
| 276 | - // Origin is the supposed "client" IP. |
|
| 277 | - $origin = $proxies[0]; |
|
| 278 | - $this->assign("forwardedOrigin", $origin); |
|
| 279 | - |
|
| 280 | - // We step through the servers in reverse order, from closest to furthest |
|
| 281 | - $proxies = array_reverse($proxies); |
|
| 282 | - |
|
| 283 | - // By default, we have trust, because the first in the chain is now REMOTE_ADDR, which is hardest to spoof. |
|
| 284 | - $trust = true; |
|
| 285 | - |
|
| 286 | - /** |
|
| 287 | - * @var int $index The zero-based index of the proxy. |
|
| 288 | - * @var string $proxyData The proxy IP address (although possibly not!) |
|
| 289 | - */ |
|
| 290 | - foreach ($proxies as $index => $proxyData) { |
|
| 291 | - $proxyAddress = trim($proxyData); |
|
| 292 | - $requestProxyData[$proxyIndex]['ip'] = $proxyAddress; |
|
| 293 | - |
|
| 294 | - // get data on this IP. |
|
| 295 | - $thisProxyIsTrusted = $this->getXffTrustProvider()->isTrusted($proxyAddress); |
|
| 296 | - |
|
| 297 | - $proxyIsInPrivateRange = $this->getXffTrustProvider() |
|
| 298 | - ->ipInRange(self::$rfc1918ips, $proxyAddress); |
|
| 299 | - |
|
| 300 | - if (!$proxyIsInPrivateRange) { |
|
| 301 | - $proxyReverseDns = $this->getRdnsProvider()->getReverseDNS($proxyAddress); |
|
| 302 | - $proxyLocation = $this->getLocationProvider()->getIpLocation($proxyAddress); |
|
| 303 | - } |
|
| 304 | - else { |
|
| 305 | - // this is going to fail, so why bother trying? |
|
| 306 | - $proxyReverseDns = false; |
|
| 307 | - $proxyLocation = false; |
|
| 308 | - } |
|
| 309 | - |
|
| 310 | - // current trust chain status BEFORE this link |
|
| 311 | - $preLinkTrust = $trust; |
|
| 312 | - |
|
| 313 | - // is *this* link trusted? Note, this will be true even if there is an untrusted link before this! |
|
| 314 | - $requestProxyData[$proxyIndex]['trustedlink'] = $thisProxyIsTrusted; |
|
| 315 | - |
|
| 316 | - // set the trust status of the chain to this point |
|
| 317 | - $trust = $trust & $thisProxyIsTrusted; |
|
| 318 | - |
|
| 319 | - // If this is the origin address, and the chain was trusted before this point, then we can trust |
|
| 320 | - // the origin. |
|
| 321 | - if ($preLinkTrust && $proxyAddress == $origin) { |
|
| 322 | - // if this is the origin, then we are at the last point in the chain. |
|
| 323 | - // @todo: this is probably the cause of some bugs when an IP appears twice - we're missing a check |
|
| 324 | - // to see if this is *really* the last in the chain, rather than just the same IP as it. |
|
| 325 | - $trust = true; |
|
| 326 | - } |
|
| 327 | - |
|
| 328 | - $requestProxyData[$proxyIndex]['trust'] = $trust; |
|
| 329 | - |
|
| 330 | - $requestProxyData[$proxyIndex]['rdnsfailed'] = $proxyReverseDns === false; |
|
| 331 | - $requestProxyData[$proxyIndex]['rdns'] = $proxyReverseDns; |
|
| 332 | - $requestProxyData[$proxyIndex]['routable'] = !$proxyIsInPrivateRange; |
|
| 333 | - |
|
| 334 | - $requestProxyData[$proxyIndex]['location'] = $proxyLocation; |
|
| 335 | - |
|
| 336 | - if ($proxyReverseDns === $proxyAddress && $proxyIsInPrivateRange === false) { |
|
| 337 | - $requestProxyData[$proxyIndex]['rdns'] = null; |
|
| 338 | - } |
|
| 339 | - |
|
| 340 | - $showLinks = (!$trust || $proxyAddress == $origin) && !$proxyIsInPrivateRange; |
|
| 341 | - $requestProxyData[$proxyIndex]['showlinks'] = $showLinks; |
|
| 342 | - |
|
| 343 | - $proxyIndex++; |
|
| 344 | - } |
|
| 345 | - |
|
| 346 | - $this->assign("requestProxyData", $requestProxyData); |
|
| 347 | - } |
|
| 348 | - } |
|
| 27 | + /** |
|
| 28 | + * @var array Array of IP address classed as 'private' by RFC1918. |
|
| 29 | + */ |
|
| 30 | + protected static $rfc1918ips = array( |
|
| 31 | + "10.0.0.0" => "10.255.255.255", |
|
| 32 | + "172.16.0.0" => "172.31.255.255", |
|
| 33 | + "192.168.0.0" => "192.168.255.255", |
|
| 34 | + "169.254.0.0" => "169.254.255.255", |
|
| 35 | + "127.0.0.0" => "127.255.255.255", |
|
| 36 | + ); |
|
| 37 | + |
|
| 38 | + /** |
|
| 39 | + * Gets a request object |
|
| 40 | + * |
|
| 41 | + * @param PdoDatabase $database The database connection |
|
| 42 | + * @param int|null $requestId The ID of the request to retrieve |
|
| 43 | + * |
|
| 44 | + * @return Request |
|
| 45 | + * @throws ApplicationLogicException |
|
| 46 | + */ |
|
| 47 | + protected function getRequest(PdoDatabase $database, $requestId) |
|
| 48 | + { |
|
| 49 | + if ($requestId === null) { |
|
| 50 | + throw new ApplicationLogicException("No request specified"); |
|
| 51 | + } |
|
| 52 | + |
|
| 53 | + $request = Request::getById($requestId, $database); |
|
| 54 | + if ($request === false || !is_a($request, Request::class)) { |
|
| 55 | + throw new ApplicationLogicException('Could not load the requested request!'); |
|
| 56 | + } |
|
| 57 | + |
|
| 58 | + return $request; |
|
| 59 | + } |
|
| 60 | + |
|
| 61 | + /** |
|
| 62 | + * Returns a value stating whether the user is allowed to see private data or not |
|
| 63 | + * |
|
| 64 | + * @param Request $request |
|
| 65 | + * @param User $currentUser |
|
| 66 | + * |
|
| 67 | + * @return bool |
|
| 68 | + * @category Security-Critical |
|
| 69 | + */ |
|
| 70 | + protected function isAllowedPrivateData(Request $request, User $currentUser) |
|
| 71 | + { |
|
| 72 | + // Test the main security barrier for private data access using SecurityManager |
|
| 73 | + if ($this->barrierTest('alwaysSeePrivateData', $currentUser, 'RequestData')) { |
|
| 74 | + // Tool admins/check-users can always see private data |
|
| 75 | + return true; |
|
| 76 | + } |
|
| 77 | + |
|
| 78 | + // reserving user is allowed to see the data |
|
| 79 | + if ($currentUser->getId() === $request->getReserved() |
|
| 80 | + && $request->getReserved() !== null |
|
| 81 | + && $this->barrierTest('seePrivateDataWhenReserved', $currentUser, 'RequestData') |
|
| 82 | + ) { |
|
| 83 | + return true; |
|
| 84 | + } |
|
| 85 | + |
|
| 86 | + // user has the reveal hash |
|
| 87 | + if (WebRequest::getString('hash') === $request->getRevealHash() |
|
| 88 | + && $this->barrierTest('seePrivateDataWithHash', $currentUser, 'RequestData') |
|
| 89 | + ) { |
|
| 90 | + return true; |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + // nope. Not allowed. |
|
| 94 | + return false; |
|
| 95 | + } |
|
| 96 | + |
|
| 97 | + /** |
|
| 98 | + * Tests the security barrier for a specified action. |
|
| 99 | + * |
|
| 100 | + * Don't use within templates |
|
| 101 | + * |
|
| 102 | + * @param string $action |
|
| 103 | + * |
|
| 104 | + * @param User $user |
|
| 105 | + * @param null|string $pageName |
|
| 106 | + * |
|
| 107 | + * @return bool |
|
| 108 | + * @category Security-Critical |
|
| 109 | + */ |
|
| 110 | + abstract protected function barrierTest($action, User $user, $pageName = null); |
|
| 111 | + |
|
| 112 | + /** |
|
| 113 | + * Gets the name of the route that has been passed from the request router. |
|
| 114 | + * @return string |
|
| 115 | + */ |
|
| 116 | + abstract protected function getRouteName(); |
|
| 117 | + |
|
| 118 | + /** @return SecurityManager */ |
|
| 119 | + abstract protected function getSecurityManager(); |
|
| 120 | + |
|
| 121 | + /** |
|
| 122 | + * Sets the name of the template this page should display. |
|
| 123 | + * |
|
| 124 | + * @param string $name |
|
| 125 | + */ |
|
| 126 | + abstract protected function setTemplate($name); |
|
| 127 | + |
|
| 128 | + /** @return IXffTrustProvider */ |
|
| 129 | + abstract protected function getXffTrustProvider(); |
|
| 130 | + |
|
| 131 | + /** @return ILocationProvider */ |
|
| 132 | + abstract protected function getLocationProvider(); |
|
| 133 | + |
|
| 134 | + /** @return IRDnsProvider */ |
|
| 135 | + abstract protected function getRdnsProvider(); |
|
| 136 | + |
|
| 137 | + /** |
|
| 138 | + * Assigns a Smarty variable |
|
| 139 | + * |
|
| 140 | + * @param array|string $name the template variable name(s) |
|
| 141 | + * @param mixed $value the value to assign |
|
| 142 | + */ |
|
| 143 | + abstract protected function assign($name, $value); |
|
| 144 | + |
|
| 145 | + /** |
|
| 146 | + * @param int|null $requestReservationId |
|
| 147 | + * @param PdoDatabase $database |
|
| 148 | + * @param User $currentUser |
|
| 149 | + */ |
|
| 150 | + protected function setupReservationDetails($requestReservationId, PdoDatabase $database, User $currentUser) |
|
| 151 | + { |
|
| 152 | + $requestIsReserved = $requestReservationId !== null; |
|
| 153 | + $this->assign('requestIsReserved', $requestIsReserved); |
|
| 154 | + $this->assign('requestIsReservedByMe', false); |
|
| 155 | + |
|
| 156 | + if ($requestIsReserved) { |
|
| 157 | + $this->assign('requestReservedByName', User::getById($requestReservationId, $database)->getUsername()); |
|
| 158 | + $this->assign('requestReservedById', $requestReservationId); |
|
| 159 | + |
|
| 160 | + if ($requestReservationId === $currentUser->getId()) { |
|
| 161 | + $this->assign('requestIsReservedByMe', true); |
|
| 162 | + } |
|
| 163 | + } |
|
| 164 | + |
|
| 165 | + $this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class)); |
|
| 166 | + } |
|
| 167 | + |
|
| 168 | + /** |
|
| 169 | + * Adds private request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED! |
|
| 170 | + * |
|
| 171 | + * @param Request $request |
|
| 172 | + */ |
|
| 173 | + protected function setupPrivateData( |
|
| 174 | + $request |
|
| 175 | + ) { |
|
| 176 | + $xffProvider = $this->getXffTrustProvider(); |
|
| 177 | + |
|
| 178 | + $this->assign('requestEmail', $request->getEmail()); |
|
| 179 | + $emailDomain = explode("@", $request->getEmail())[1]; |
|
| 180 | + $this->assign("emailurl", $emailDomain); |
|
| 181 | + |
|
| 182 | + $trustedIp = $xffProvider->getTrustedClientIp($request->getIp(), $request->getForwardedIp()); |
|
| 183 | + $this->assign('requestTrustedIp', $trustedIp); |
|
| 184 | + $this->assign('requestRealIp', $request->getIp()); |
|
| 185 | + $this->assign('requestForwardedIp', $request->getForwardedIp()); |
|
| 186 | + |
|
| 187 | + $trustedIpLocation = $this->getLocationProvider()->getIpLocation($trustedIp); |
|
| 188 | + $this->assign('requestTrustedIpLocation', $trustedIpLocation); |
|
| 189 | + |
|
| 190 | + $this->assign('requestHasForwardedIp', $request->getForwardedIp() !== null); |
|
| 191 | + |
|
| 192 | + $this->setupForwardedIpData($request); |
|
| 193 | + } |
|
| 194 | + |
|
| 195 | + /** |
|
| 196 | + * Adds related request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED! |
|
| 197 | + * |
|
| 198 | + * @param Request $request |
|
| 199 | + * @param SiteConfiguration $configuration |
|
| 200 | + * @param PdoDatabase $database |
|
| 201 | + */ |
|
| 202 | + protected function setupRelatedRequests( |
|
| 203 | + Request $request, |
|
| 204 | + SiteConfiguration $configuration, |
|
| 205 | + PdoDatabase $database) |
|
| 206 | + { |
|
| 207 | + $this->assign('canSeeRelatedRequests', true); |
|
| 208 | + |
|
| 209 | + $relatedEmailRequests = RequestSearchHelper::get($database) |
|
| 210 | + ->byEmailAddress($request->getEmail()) |
|
| 211 | + ->withConfirmedEmail() |
|
| 212 | + ->excludingPurgedData($configuration) |
|
| 213 | + ->excludingRequest($request->getId()) |
|
| 214 | + ->fetch(); |
|
| 215 | + |
|
| 216 | + $this->assign('requestRelatedEmailRequestsCount', count($relatedEmailRequests)); |
|
| 217 | + $this->assign('requestRelatedEmailRequests', $relatedEmailRequests); |
|
| 218 | + |
|
| 219 | + $trustedIp = $this->getXffTrustProvider()->getTrustedClientIp($request->getIp(), $request->getForwardedIp()); |
|
| 220 | + $relatedIpRequests = RequestSearchHelper::get($database) |
|
| 221 | + ->byIp($trustedIp) |
|
| 222 | + ->withConfirmedEmail() |
|
| 223 | + ->excludingPurgedData($configuration) |
|
| 224 | + ->excludingRequest($request->getId()) |
|
| 225 | + ->fetch(); |
|
| 226 | + |
|
| 227 | + $this->assign('requestRelatedIpRequestsCount', count($relatedIpRequests)); |
|
| 228 | + $this->assign('requestRelatedIpRequests', $relatedIpRequests); |
|
| 229 | + } |
|
| 230 | + |
|
| 231 | + /** |
|
| 232 | + * Adds checkuser request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED! |
|
| 233 | + * |
|
| 234 | + * @param Request $request |
|
| 235 | + */ |
|
| 236 | + protected function setupCheckUserData(Request $request) |
|
| 237 | + { |
|
| 238 | + $this->assign('requestUserAgent', $request->getUserAgent()); |
|
| 239 | + } |
|
| 240 | + |
|
| 241 | + /** |
|
| 242 | + * Sets up the basic data for this request, and adds it to Smarty |
|
| 243 | + * |
|
| 244 | + * @param Request $request |
|
| 245 | + * @param SiteConfiguration $config |
|
| 246 | + */ |
|
| 247 | + protected function setupBasicData(Request $request, SiteConfiguration $config) |
|
| 248 | + { |
|
| 249 | + $this->assign('requestId', $request->getId()); |
|
| 250 | + $this->assign('updateVersion', $request->getUpdateVersion()); |
|
| 251 | + $this->assign('requestName', $request->getName()); |
|
| 252 | + $this->assign('requestDate', $request->getDate()); |
|
| 253 | + $this->assign('requestStatus', $request->getStatus()); |
|
| 254 | + |
|
| 255 | + $isClosed = !array_key_exists($request->getStatus(), $config->getRequestStates()) |
|
| 256 | + && $request->getStatus() !== RequestStatus::HOSPITAL; |
|
| 257 | + $this->assign('requestIsClosed', $isClosed); |
|
| 258 | + } |
|
| 259 | + |
|
| 260 | + /** |
|
| 261 | + * Sets up the forwarded IP data for this request and adds it to Smarty |
|
| 262 | + * |
|
| 263 | + * @param Request $request |
|
| 264 | + */ |
|
| 265 | + protected function setupForwardedIpData(Request $request) |
|
| 266 | + { |
|
| 267 | + if ($request->getForwardedIp() !== null) { |
|
| 268 | + $requestProxyData = array(); // Initialize array to store data to be output in Smarty template. |
|
| 269 | + $proxyIndex = 0; |
|
| 270 | + |
|
| 271 | + // Assuming [client] <=> [proxy1] <=> [proxy2] <=> [proxy3] <=> [us], we will see an XFF header of [client], |
|
| 272 | + // [proxy1], [proxy2], and our actual IP will be [proxy3] |
|
| 273 | + $proxies = explode(",", $request->getForwardedIp()); |
|
| 274 | + $proxies[] = $request->getIp(); |
|
| 275 | + |
|
| 276 | + // Origin is the supposed "client" IP. |
|
| 277 | + $origin = $proxies[0]; |
|
| 278 | + $this->assign("forwardedOrigin", $origin); |
|
| 279 | + |
|
| 280 | + // We step through the servers in reverse order, from closest to furthest |
|
| 281 | + $proxies = array_reverse($proxies); |
|
| 282 | + |
|
| 283 | + // By default, we have trust, because the first in the chain is now REMOTE_ADDR, which is hardest to spoof. |
|
| 284 | + $trust = true; |
|
| 285 | + |
|
| 286 | + /** |
|
| 287 | + * @var int $index The zero-based index of the proxy. |
|
| 288 | + * @var string $proxyData The proxy IP address (although possibly not!) |
|
| 289 | + */ |
|
| 290 | + foreach ($proxies as $index => $proxyData) { |
|
| 291 | + $proxyAddress = trim($proxyData); |
|
| 292 | + $requestProxyData[$proxyIndex]['ip'] = $proxyAddress; |
|
| 293 | + |
|
| 294 | + // get data on this IP. |
|
| 295 | + $thisProxyIsTrusted = $this->getXffTrustProvider()->isTrusted($proxyAddress); |
|
| 296 | + |
|
| 297 | + $proxyIsInPrivateRange = $this->getXffTrustProvider() |
|
| 298 | + ->ipInRange(self::$rfc1918ips, $proxyAddress); |
|
| 299 | + |
|
| 300 | + if (!$proxyIsInPrivateRange) { |
|
| 301 | + $proxyReverseDns = $this->getRdnsProvider()->getReverseDNS($proxyAddress); |
|
| 302 | + $proxyLocation = $this->getLocationProvider()->getIpLocation($proxyAddress); |
|
| 303 | + } |
|
| 304 | + else { |
|
| 305 | + // this is going to fail, so why bother trying? |
|
| 306 | + $proxyReverseDns = false; |
|
| 307 | + $proxyLocation = false; |
|
| 308 | + } |
|
| 309 | + |
|
| 310 | + // current trust chain status BEFORE this link |
|
| 311 | + $preLinkTrust = $trust; |
|
| 312 | + |
|
| 313 | + // is *this* link trusted? Note, this will be true even if there is an untrusted link before this! |
|
| 314 | + $requestProxyData[$proxyIndex]['trustedlink'] = $thisProxyIsTrusted; |
|
| 315 | + |
|
| 316 | + // set the trust status of the chain to this point |
|
| 317 | + $trust = $trust & $thisProxyIsTrusted; |
|
| 318 | + |
|
| 319 | + // If this is the origin address, and the chain was trusted before this point, then we can trust |
|
| 320 | + // the origin. |
|
| 321 | + if ($preLinkTrust && $proxyAddress == $origin) { |
|
| 322 | + // if this is the origin, then we are at the last point in the chain. |
|
| 323 | + // @todo: this is probably the cause of some bugs when an IP appears twice - we're missing a check |
|
| 324 | + // to see if this is *really* the last in the chain, rather than just the same IP as it. |
|
| 325 | + $trust = true; |
|
| 326 | + } |
|
| 327 | + |
|
| 328 | + $requestProxyData[$proxyIndex]['trust'] = $trust; |
|
| 329 | + |
|
| 330 | + $requestProxyData[$proxyIndex]['rdnsfailed'] = $proxyReverseDns === false; |
|
| 331 | + $requestProxyData[$proxyIndex]['rdns'] = $proxyReverseDns; |
|
| 332 | + $requestProxyData[$proxyIndex]['routable'] = !$proxyIsInPrivateRange; |
|
| 333 | + |
|
| 334 | + $requestProxyData[$proxyIndex]['location'] = $proxyLocation; |
|
| 335 | + |
|
| 336 | + if ($proxyReverseDns === $proxyAddress && $proxyIsInPrivateRange === false) { |
|
| 337 | + $requestProxyData[$proxyIndex]['rdns'] = null; |
|
| 338 | + } |
|
| 339 | + |
|
| 340 | + $showLinks = (!$trust || $proxyAddress == $origin) && !$proxyIsInPrivateRange; |
|
| 341 | + $requestProxyData[$proxyIndex]['showlinks'] = $showLinks; |
|
| 342 | + |
|
| 343 | + $proxyIndex++; |
|
| 344 | + } |
|
| 345 | + |
|
| 346 | + $this->assign("requestProxyData", $requestProxyData); |
|
| 347 | + } |
|
| 348 | + } |
|
| 349 | 349 | } |
@@ -189,27 +189,27 @@ discard block |
||
| 189 | 189 | |
| 190 | 190 | // request states |
| 191 | 191 | $availableRequestStates = array( |
| 192 | - 'Open' => array( |
|
| 193 | - 'defertolog' => 'users', // don't change or you'll break old logs |
|
| 194 | - 'deferto' => 'users', |
|
| 195 | - 'header' => 'Open requests', |
|
| 196 | - 'api' => "open", |
|
| 197 | - 'queuehelp' => null |
|
| 198 | - ), |
|
| 199 | - 'Flagged users' => array( |
|
| 200 | - 'defertolog' => 'flagged users', // don't change or you'll break old logs |
|
| 201 | - 'deferto' => 'flagged users', |
|
| 202 | - 'header' => 'Flagged user needed', |
|
| 203 | - 'api' => "admin", |
|
| 204 | - 'queuehelp' => 'This queue lists the requests which require a user with the <code>accountcreator</code> flag to create.<br />If creation is determined to be the correct course of action, requests here will require the overriding the AntiSpoof checks or the title blacklist in order to create. It is recommended to try to create the account <em>without</em> checking the flags to validate the results of the AntiSpoof and/or title blacklist hits.' |
|
| 205 | - ), |
|
| 206 | - 'Checkuser' => array( |
|
| 207 | - 'defertolog' => 'checkusers', // don't change or you'll break old logs |
|
| 208 | - 'deferto' => 'checkusers', |
|
| 209 | - 'header' => 'Checkuser needed', |
|
| 210 | - 'api' => "checkuser", |
|
| 211 | - 'queuehelp' => null |
|
| 212 | - ), |
|
| 192 | + 'Open' => array( |
|
| 193 | + 'defertolog' => 'users', // don't change or you'll break old logs |
|
| 194 | + 'deferto' => 'users', |
|
| 195 | + 'header' => 'Open requests', |
|
| 196 | + 'api' => "open", |
|
| 197 | + 'queuehelp' => null |
|
| 198 | + ), |
|
| 199 | + 'Flagged users' => array( |
|
| 200 | + 'defertolog' => 'flagged users', // don't change or you'll break old logs |
|
| 201 | + 'deferto' => 'flagged users', |
|
| 202 | + 'header' => 'Flagged user needed', |
|
| 203 | + 'api' => "admin", |
|
| 204 | + 'queuehelp' => 'This queue lists the requests which require a user with the <code>accountcreator</code> flag to create.<br />If creation is determined to be the correct course of action, requests here will require the overriding the AntiSpoof checks or the title blacklist in order to create. It is recommended to try to create the account <em>without</em> checking the flags to validate the results of the AntiSpoof and/or title blacklist hits.' |
|
| 205 | + ), |
|
| 206 | + 'Checkuser' => array( |
|
| 207 | + 'defertolog' => 'checkusers', // don't change or you'll break old logs |
|
| 208 | + 'deferto' => 'checkusers', |
|
| 209 | + 'header' => 'Checkuser needed', |
|
| 210 | + 'api' => "checkuser", |
|
| 211 | + 'queuehelp' => null |
|
| 212 | + ), |
|
| 213 | 213 | ); |
| 214 | 214 | |
| 215 | 215 | $defaultRequestStateKey = 'Open'; |
@@ -262,24 +262,24 @@ discard block |
||
| 262 | 262 | require_once('config.local.inc.php'); |
| 263 | 263 | |
| 264 | 264 | $cDatabaseConfig = array( |
| 265 | - "acc" => array( |
|
| 266 | - "dsrcname" => "mysql:host=" . $toolserver_host . ";dbname=" . $toolserver_database, |
|
| 267 | - "username" => $toolserver_username, |
|
| 268 | - "password" => $toolserver_password, |
|
| 265 | + "acc" => array( |
|
| 266 | + "dsrcname" => "mysql:host=" . $toolserver_host . ";dbname=" . $toolserver_database, |
|
| 267 | + "username" => $toolserver_username, |
|
| 268 | + "password" => $toolserver_password, |
|
| 269 | 269 | "options" => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'), |
| 270 | - ), |
|
| 271 | - "wikipedia" => array( |
|
| 272 | - "dsrcname" => "mysql:host=" . $antispoof_host . ";dbname=" . $antispoof_db, |
|
| 273 | - "username" => $toolserver_username, |
|
| 274 | - "password" => $toolserver_password, |
|
| 275 | - "options" => array(), |
|
| 276 | - ), |
|
| 277 | - "notifications" => array( |
|
| 278 | - "dsrcname" => "mysql:host=" . $toolserver_notification_dbhost . ";dbname=" . $toolserver_notification_database, |
|
| 279 | - "username" => $notifications_username, |
|
| 280 | - "password" => $notifications_password, |
|
| 281 | - "options" => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'), |
|
| 282 | - ), |
|
| 270 | + ), |
|
| 271 | + "wikipedia" => array( |
|
| 272 | + "dsrcname" => "mysql:host=" . $antispoof_host . ";dbname=" . $antispoof_db, |
|
| 273 | + "username" => $toolserver_username, |
|
| 274 | + "password" => $toolserver_password, |
|
| 275 | + "options" => array(), |
|
| 276 | + ), |
|
| 277 | + "notifications" => array( |
|
| 278 | + "dsrcname" => "mysql:host=" . $toolserver_notification_dbhost . ";dbname=" . $toolserver_notification_database, |
|
| 279 | + "username" => $notifications_username, |
|
| 280 | + "password" => $notifications_password, |
|
| 281 | + "options" => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'), |
|
| 282 | + ), |
|
| 283 | 283 | ); |
| 284 | 284 | |
| 285 | 285 | // //Keep the included files from being executed. |
@@ -291,18 +291,18 @@ discard block |
||
| 291 | 291 | ini_set('user_agent', $toolUserAgent); |
| 292 | 292 | |
| 293 | 293 | foreach (array( |
| 294 | - "mbstring", // unicode and stuff |
|
| 295 | - "pdo", |
|
| 296 | - "pdo_mysql", // new database module |
|
| 297 | - "session", |
|
| 298 | - "date", |
|
| 299 | - "pcre", // core stuff |
|
| 300 | - "curl", // mediawiki api access etc |
|
| 301 | - "openssl", // token generation |
|
| 294 | + "mbstring", // unicode and stuff |
|
| 295 | + "pdo", |
|
| 296 | + "pdo_mysql", // new database module |
|
| 297 | + "session", |
|
| 298 | + "date", |
|
| 299 | + "pcre", // core stuff |
|
| 300 | + "curl", // mediawiki api access etc |
|
| 301 | + "openssl", // token generation |
|
| 302 | 302 | ) as $x) { |
| 303 | - if (!extension_loaded($x)) { |
|
| 304 | - die("extension $x is required."); |
|
| 305 | - } |
|
| 303 | + if (!extension_loaded($x)) { |
|
| 304 | + die("extension $x is required."); |
|
| 305 | + } |
|
| 306 | 306 | } |
| 307 | 307 | |
| 308 | 308 | // Set up the AutoLoader |
@@ -326,43 +326,43 @@ discard block |
||
| 326 | 326 | $siteConfiguration = new \Waca\SiteConfiguration(); |
| 327 | 327 | |
| 328 | 328 | $siteConfiguration->setBaseUrl($baseurl) |
| 329 | - ->setFilePath(__DIR__) |
|
| 330 | - ->setDebuggingTraceEnabled($enableErrorTrace) |
|
| 331 | - ->setForceIdentification($forceIdentification) |
|
| 332 | - ->setIdentificationCacheExpiry($identificationCacheExpiry) |
|
| 333 | - ->setMediawikiScriptPath($mediawikiScriptPath) |
|
| 334 | - ->setMediawikiWebServiceEndpoint($mediawikiWebServiceEndpoint) |
|
| 335 | - ->setMetaWikimediaWebServiceEndpoint($metaWikimediaWebServiceEndpoint) |
|
| 336 | - ->setEnforceOAuth($enforceOAuth) |
|
| 337 | - ->setEmailConfirmationEnabled($enableEmailConfirm == 1) |
|
| 338 | - ->setEmailConfirmationExpiryDays($emailConfirmationExpiryDays) |
|
| 339 | - ->setMiserModeLimit($requestLimitShowOnly) |
|
| 340 | - ->setRequestStates($availableRequestStates) |
|
| 341 | - ->setSquidList($squidIpList) |
|
| 342 | - ->setDefaultCreatedTemplateId($createdid) |
|
| 343 | - ->setDefaultRequestStateKey($defaultRequestStateKey) |
|
| 344 | - ->setUseStrictTransportSecurity($strictTransportSecurityExpiry) |
|
| 345 | - ->setUserAgent($toolUserAgent) |
|
| 346 | - ->setCurlDisableVerifyPeer($curlDisableSSLVerifyPeer) |
|
| 347 | - ->setUseOAuthSignup($useOauthSignup) |
|
| 348 | - ->setOAuthBaseUrl($oauthBaseUrl) |
|
| 349 | - ->setOAuthConsumerToken($oauthConsumerToken) |
|
| 350 | - ->setOAuthConsumerSecret($oauthSecretToken) |
|
| 351 | - ->setOauthMediaWikiCanonicalServer($oauthMediaWikiCanonicalServer) |
|
| 352 | - ->setDataClearInterval($dataclear_interval) |
|
| 353 | - ->setXffTrustedHostsFile($xff_trusted_hosts_file) |
|
| 354 | - ->setIrcNotificationsEnabled($ircBotNotificationsEnabled == 1) |
|
| 355 | - ->setIrcNotificationType($ircBotNotificationType) |
|
| 356 | - ->setIrcNotificationsInstance($whichami) |
|
| 357 | - ->setTitleBlacklistEnabled($enableTitleblacklist == 1) |
|
| 358 | - ->setTorExitPaths(array_merge(gethostbynamel('en.wikipedia.org'), gethostbynamel('accounts.wmflabs.org'))) |
|
| 359 | - ->setCreationBotUsername($creationBotUsername) |
|
| 360 | - ->setCreationBotPassword($creationBotPassword) |
|
| 361 | - ->setCurlCookieJar($curlCookieJar) |
|
| 362 | - ->setYubicoApiId($yubicoApiId) |
|
| 363 | - ->setYubicoApiKey($yubicoApiKey) |
|
| 364 | - ->setTotpEncryptionKey($totpEncryptionKey) |
|
| 365 | - ->setRegistrationAllowed($allowRegistration) |
|
| 366 | - ->setCspReportUri($cspReportUri) |
|
| 367 | - ->setResourceCacheEpoch($resourceCacheEpoch) |
|
| 368 | - ->setLocationProviderApiKey($locationProviderApiKey); |
|
| 329 | + ->setFilePath(__DIR__) |
|
| 330 | + ->setDebuggingTraceEnabled($enableErrorTrace) |
|
| 331 | + ->setForceIdentification($forceIdentification) |
|
| 332 | + ->setIdentificationCacheExpiry($identificationCacheExpiry) |
|
| 333 | + ->setMediawikiScriptPath($mediawikiScriptPath) |
|
| 334 | + ->setMediawikiWebServiceEndpoint($mediawikiWebServiceEndpoint) |
|
| 335 | + ->setMetaWikimediaWebServiceEndpoint($metaWikimediaWebServiceEndpoint) |
|
| 336 | + ->setEnforceOAuth($enforceOAuth) |
|
| 337 | + ->setEmailConfirmationEnabled($enableEmailConfirm == 1) |
|
| 338 | + ->setEmailConfirmationExpiryDays($emailConfirmationExpiryDays) |
|
| 339 | + ->setMiserModeLimit($requestLimitShowOnly) |
|
| 340 | + ->setRequestStates($availableRequestStates) |
|
| 341 | + ->setSquidList($squidIpList) |
|
| 342 | + ->setDefaultCreatedTemplateId($createdid) |
|
| 343 | + ->setDefaultRequestStateKey($defaultRequestStateKey) |
|
| 344 | + ->setUseStrictTransportSecurity($strictTransportSecurityExpiry) |
|
| 345 | + ->setUserAgent($toolUserAgent) |
|
| 346 | + ->setCurlDisableVerifyPeer($curlDisableSSLVerifyPeer) |
|
| 347 | + ->setUseOAuthSignup($useOauthSignup) |
|
| 348 | + ->setOAuthBaseUrl($oauthBaseUrl) |
|
| 349 | + ->setOAuthConsumerToken($oauthConsumerToken) |
|
| 350 | + ->setOAuthConsumerSecret($oauthSecretToken) |
|
| 351 | + ->setOauthMediaWikiCanonicalServer($oauthMediaWikiCanonicalServer) |
|
| 352 | + ->setDataClearInterval($dataclear_interval) |
|
| 353 | + ->setXffTrustedHostsFile($xff_trusted_hosts_file) |
|
| 354 | + ->setIrcNotificationsEnabled($ircBotNotificationsEnabled == 1) |
|
| 355 | + ->setIrcNotificationType($ircBotNotificationType) |
|
| 356 | + ->setIrcNotificationsInstance($whichami) |
|
| 357 | + ->setTitleBlacklistEnabled($enableTitleblacklist == 1) |
|
| 358 | + ->setTorExitPaths(array_merge(gethostbynamel('en.wikipedia.org'), gethostbynamel('accounts.wmflabs.org'))) |
|
| 359 | + ->setCreationBotUsername($creationBotUsername) |
|
| 360 | + ->setCreationBotPassword($creationBotPassword) |
|
| 361 | + ->setCurlCookieJar($curlCookieJar) |
|
| 362 | + ->setYubicoApiId($yubicoApiId) |
|
| 363 | + ->setYubicoApiKey($yubicoApiKey) |
|
| 364 | + ->setTotpEncryptionKey($totpEncryptionKey) |
|
| 365 | + ->setRegistrationAllowed($allowRegistration) |
|
| 366 | + ->setCspReportUri($cspReportUri) |
|
| 367 | + ->setResourceCacheEpoch($resourceCacheEpoch) |
|
| 368 | + ->setLocationProviderApiKey($locationProviderApiKey); |
|