@@ -77,7 +77,7 @@ discard block |
||
| 77 | 77 | SessionAlert::success('Enabled YubiKey OTP.'); |
| 78 | 78 | |
| 79 | 79 | $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
| 80 | - if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 80 | + if ($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 81 | 81 | $scratchProvider->setCredential($currentUser, 2, null); |
| 82 | 82 | $tokens = $scratchProvider->getTokens(); |
| 83 | 83 | $this->assign('tokens', $tokens); |
@@ -86,7 +86,7 @@ discard block |
||
| 86 | 86 | } |
| 87 | 87 | } |
| 88 | 88 | catch (ApplicationLogicException $ex) { |
| 89 | - SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage()); |
|
| 89 | + SessionAlert::error('Error enabling YubiKey OTP: '.$ex->getMessage()); |
|
| 90 | 90 | } |
| 91 | 91 | |
| 92 | 92 | $this->redirect('multiFactor'); |
@@ -177,7 +177,7 @@ discard block |
||
| 177 | 177 | SessionAlert::success('Enabled TOTP.'); |
| 178 | 178 | |
| 179 | 179 | $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
| 180 | - if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 180 | + if ($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 181 | 181 | $scratchProvider->setCredential($currentUser, 2, null); |
| 182 | 182 | $tokens = $scratchProvider->getTokens(); |
| 183 | 183 | $this->assign('tokens', $tokens); |
@@ -257,7 +257,7 @@ discard block |
||
| 257 | 257 | |
| 258 | 258 | list($data, $reqs) = $otpCredentialProvider->getRegistrationData(); |
| 259 | 259 | |
| 260 | - $u2fRequest =json_encode($data); |
|
| 260 | + $u2fRequest = json_encode($data); |
|
| 261 | 261 | $u2fSigns = json_encode($reqs); |
| 262 | 262 | |
| 263 | 263 | $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js'); |
@@ -306,7 +306,7 @@ discard block |
||
| 306 | 306 | SessionAlert::success('Enabled U2F.'); |
| 307 | 307 | |
| 308 | 308 | $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
| 309 | - if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 309 | + if ($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 310 | 310 | $scratchProvider->setCredential($currentUser, 2, null); |
| 311 | 311 | $tokens = $scratchProvider->getTokens(); |
| 312 | 312 | $this->assign('tokens', $tokens); |
@@ -419,11 +419,11 @@ discard block |
||
| 419 | 419 | |
| 420 | 420 | if ($result) { |
| 421 | 421 | $otpCredentialProvider->deleteCredential($currentUser); |
| 422 | - SessionAlert::success('Disabled ' . $factorType . '.'); |
|
| 422 | + SessionAlert::success('Disabled '.$factorType.'.'); |
|
| 423 | 423 | $this->redirect('multiFactor'); |
| 424 | 424 | } |
| 425 | 425 | else { |
| 426 | - SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.'); |
|
| 426 | + SessionAlert::error('Error disabling '.$factorType.' - invalid credentials.'); |
|
| 427 | 427 | $this->redirect('multiFactor'); |
| 428 | 428 | } |
| 429 | 429 | } |
@@ -25,247 +25,247 @@ discard block |
||
| 25 | 25 | |
| 26 | 26 | class PageMultiFactor extends InternalPageBase |
| 27 | 27 | { |
| 28 | - /** |
|
| 29 | - * Main function for this page, when no specific actions are called. |
|
| 30 | - * @return void |
|
| 31 | - */ |
|
| 32 | - protected function main() |
|
| 33 | - { |
|
| 34 | - $database = $this->getDatabase(); |
|
| 35 | - $currentUser = User::getCurrent($database); |
|
| 36 | - |
|
| 37 | - $yubikeyOtpCredentialProvider = new YubikeyOtpCredentialProvider($database, $this->getSiteConfiguration(), |
|
| 38 | - $this->getHttpHelper()); |
|
| 39 | - $this->assign('yubikeyOtpIdentity', $yubikeyOtpCredentialProvider->getYubikeyData($currentUser->getId())); |
|
| 40 | - $this->assign('yubikeyOtpEnrolled', $yubikeyOtpCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 41 | - |
|
| 42 | - $totpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 43 | - $this->assign('totpEnrolled', $totpCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 44 | - |
|
| 45 | - $u2fCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 46 | - $this->assign('u2fEnrolled', $u2fCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 47 | - |
|
| 48 | - $scratchCredentialProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 49 | - $this->assign('scratchEnrolled', $scratchCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 50 | - $this->assign('scratchRemaining', $scratchCredentialProvider->getRemaining($currentUser->getId())); |
|
| 51 | - |
|
| 52 | - $this->assign('allowedTotp', $this->barrierTest('enableTotp', $currentUser)); |
|
| 53 | - $this->assign('allowedYubikey', $this->barrierTest('enableYubikeyOtp', $currentUser)); |
|
| 54 | - $this->assign('allowedU2f', $this->barrierTest('enableU2F', $currentUser)); |
|
| 55 | - |
|
| 56 | - $this->setTemplate('mfa/mfa.tpl'); |
|
| 57 | - } |
|
| 58 | - |
|
| 59 | - protected function enableYubikeyOtp() |
|
| 60 | - { |
|
| 61 | - $database = $this->getDatabase(); |
|
| 62 | - $currentUser = User::getCurrent($database); |
|
| 63 | - |
|
| 64 | - $otpCredentialProvider = new YubikeyOtpCredentialProvider($database, |
|
| 65 | - $this->getSiteConfiguration(), $this->getHttpHelper()); |
|
| 66 | - |
|
| 67 | - if (WebRequest::wasPosted()) { |
|
| 68 | - $this->validateCSRFToken(); |
|
| 69 | - |
|
| 70 | - $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 71 | - $this->getSiteConfiguration()); |
|
| 72 | - |
|
| 73 | - $password = WebRequest::postString('password'); |
|
| 74 | - $otp = WebRequest::postString('otp'); |
|
| 75 | - |
|
| 76 | - $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 77 | - |
|
| 78 | - if ($result) { |
|
| 79 | - try { |
|
| 80 | - $otpCredentialProvider->setCredential($currentUser, 2, $otp); |
|
| 81 | - SessionAlert::success('Enabled YubiKey OTP.'); |
|
| 82 | - |
|
| 83 | - $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 84 | - if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 85 | - $scratchProvider->setCredential($currentUser, 2, null); |
|
| 86 | - $tokens = $scratchProvider->getTokens(); |
|
| 87 | - $this->assign('tokens', $tokens); |
|
| 88 | - $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 89 | - return; |
|
| 90 | - } |
|
| 91 | - } |
|
| 92 | - catch (ApplicationLogicException $ex) { |
|
| 93 | - SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage()); |
|
| 94 | - } |
|
| 95 | - |
|
| 96 | - $this->redirect('multiFactor'); |
|
| 97 | - } |
|
| 98 | - else { |
|
| 99 | - SessionAlert::error('Error enabling YubiKey OTP - invalid credentials.'); |
|
| 100 | - $this->redirect('multiFactor'); |
|
| 101 | - } |
|
| 102 | - } |
|
| 103 | - else { |
|
| 104 | - if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 105 | - // user is not enrolled, we shouldn't have got here. |
|
| 106 | - throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism'); |
|
| 107 | - } |
|
| 108 | - |
|
| 109 | - $this->assignCSRFToken(); |
|
| 110 | - $this->setTemplate('mfa/enableYubikey.tpl'); |
|
| 111 | - } |
|
| 112 | - } |
|
| 113 | - |
|
| 114 | - protected function disableYubikeyOtp() |
|
| 115 | - { |
|
| 116 | - $database = $this->getDatabase(); |
|
| 117 | - $currentUser = User::getCurrent($database); |
|
| 118 | - |
|
| 119 | - $otpCredentialProvider = new YubikeyOtpCredentialProvider($database, |
|
| 120 | - $this->getSiteConfiguration(), $this->getHttpHelper()); |
|
| 121 | - |
|
| 122 | - $factorType = 'YubiKey OTP'; |
|
| 123 | - |
|
| 124 | - $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType); |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - protected function enableTotp() |
|
| 128 | - { |
|
| 129 | - $database = $this->getDatabase(); |
|
| 130 | - $currentUser = User::getCurrent($database); |
|
| 131 | - |
|
| 132 | - $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 133 | - |
|
| 134 | - if (WebRequest::wasPosted()) { |
|
| 135 | - $this->validateCSRFToken(); |
|
| 136 | - |
|
| 137 | - // used for routing only, not security |
|
| 138 | - $stage = WebRequest::postString('stage'); |
|
| 139 | - |
|
| 140 | - if ($stage === "auth") { |
|
| 141 | - $password = WebRequest::postString('password'); |
|
| 142 | - |
|
| 143 | - $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 144 | - $this->getSiteConfiguration()); |
|
| 145 | - $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 146 | - |
|
| 147 | - if ($result) { |
|
| 148 | - $otpCredentialProvider->setCredential($currentUser, 2, null); |
|
| 149 | - |
|
| 150 | - $provisioningUrl = $otpCredentialProvider->getProvisioningUrl($currentUser); |
|
| 151 | - |
|
| 152 | - $renderer = new Svg(); |
|
| 153 | - $renderer->setHeight(256); |
|
| 154 | - $renderer->setWidth(256); |
|
| 155 | - $writer = new Writer($renderer); |
|
| 156 | - $svg = $writer->writeString($provisioningUrl); |
|
| 157 | - |
|
| 158 | - $this->assign('svg', $svg); |
|
| 159 | - $this->assign('secret', $otpCredentialProvider->getSecret($currentUser)); |
|
| 160 | - |
|
| 161 | - $this->assignCSRFToken(); |
|
| 162 | - $this->setTemplate('mfa/enableTotpEnroll.tpl'); |
|
| 163 | - |
|
| 164 | - return; |
|
| 165 | - } |
|
| 166 | - else { |
|
| 167 | - SessionAlert::error('Error enabling TOTP - invalid credentials.'); |
|
| 168 | - $this->redirect('multiFactor'); |
|
| 169 | - |
|
| 170 | - return; |
|
| 171 | - } |
|
| 172 | - } |
|
| 173 | - |
|
| 174 | - if ($stage === "enroll") { |
|
| 175 | - // we *must* have a defined credential already here, |
|
| 176 | - if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) { |
|
| 177 | - $otp = WebRequest::postString('otp'); |
|
| 178 | - $result = $otpCredentialProvider->verifyEnable($currentUser, $otp); |
|
| 179 | - |
|
| 180 | - if ($result) { |
|
| 181 | - SessionAlert::success('Enabled TOTP.'); |
|
| 182 | - |
|
| 183 | - $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 184 | - if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 185 | - $scratchProvider->setCredential($currentUser, 2, null); |
|
| 186 | - $tokens = $scratchProvider->getTokens(); |
|
| 187 | - $this->assign('tokens', $tokens); |
|
| 188 | - $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 189 | - return; |
|
| 190 | - } |
|
| 191 | - } |
|
| 192 | - else { |
|
| 193 | - $otpCredentialProvider->deleteCredential($currentUser); |
|
| 194 | - SessionAlert::error('Error enabling TOTP: invalid token provided'); |
|
| 195 | - } |
|
| 196 | - |
|
| 197 | - |
|
| 198 | - $this->redirect('multiFactor'); |
|
| 199 | - return; |
|
| 200 | - } |
|
| 201 | - else { |
|
| 202 | - SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.'); |
|
| 203 | - $this->redirect('multiFactor'); |
|
| 28 | + /** |
|
| 29 | + * Main function for this page, when no specific actions are called. |
|
| 30 | + * @return void |
|
| 31 | + */ |
|
| 32 | + protected function main() |
|
| 33 | + { |
|
| 34 | + $database = $this->getDatabase(); |
|
| 35 | + $currentUser = User::getCurrent($database); |
|
| 36 | + |
|
| 37 | + $yubikeyOtpCredentialProvider = new YubikeyOtpCredentialProvider($database, $this->getSiteConfiguration(), |
|
| 38 | + $this->getHttpHelper()); |
|
| 39 | + $this->assign('yubikeyOtpIdentity', $yubikeyOtpCredentialProvider->getYubikeyData($currentUser->getId())); |
|
| 40 | + $this->assign('yubikeyOtpEnrolled', $yubikeyOtpCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 41 | + |
|
| 42 | + $totpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 43 | + $this->assign('totpEnrolled', $totpCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 44 | + |
|
| 45 | + $u2fCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 46 | + $this->assign('u2fEnrolled', $u2fCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 47 | + |
|
| 48 | + $scratchCredentialProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 49 | + $this->assign('scratchEnrolled', $scratchCredentialProvider->userIsEnrolled($currentUser->getId())); |
|
| 50 | + $this->assign('scratchRemaining', $scratchCredentialProvider->getRemaining($currentUser->getId())); |
|
| 51 | + |
|
| 52 | + $this->assign('allowedTotp', $this->barrierTest('enableTotp', $currentUser)); |
|
| 53 | + $this->assign('allowedYubikey', $this->barrierTest('enableYubikeyOtp', $currentUser)); |
|
| 54 | + $this->assign('allowedU2f', $this->barrierTest('enableU2F', $currentUser)); |
|
| 55 | + |
|
| 56 | + $this->setTemplate('mfa/mfa.tpl'); |
|
| 57 | + } |
|
| 204 | 58 | |
| 205 | - return; |
|
| 206 | - } |
|
| 207 | - } |
|
| 59 | + protected function enableYubikeyOtp() |
|
| 60 | + { |
|
| 61 | + $database = $this->getDatabase(); |
|
| 62 | + $currentUser = User::getCurrent($database); |
|
| 63 | + |
|
| 64 | + $otpCredentialProvider = new YubikeyOtpCredentialProvider($database, |
|
| 65 | + $this->getSiteConfiguration(), $this->getHttpHelper()); |
|
| 66 | + |
|
| 67 | + if (WebRequest::wasPosted()) { |
|
| 68 | + $this->validateCSRFToken(); |
|
| 69 | + |
|
| 70 | + $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 71 | + $this->getSiteConfiguration()); |
|
| 72 | + |
|
| 73 | + $password = WebRequest::postString('password'); |
|
| 74 | + $otp = WebRequest::postString('otp'); |
|
| 75 | + |
|
| 76 | + $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 77 | + |
|
| 78 | + if ($result) { |
|
| 79 | + try { |
|
| 80 | + $otpCredentialProvider->setCredential($currentUser, 2, $otp); |
|
| 81 | + SessionAlert::success('Enabled YubiKey OTP.'); |
|
| 82 | + |
|
| 83 | + $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 84 | + if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 85 | + $scratchProvider->setCredential($currentUser, 2, null); |
|
| 86 | + $tokens = $scratchProvider->getTokens(); |
|
| 87 | + $this->assign('tokens', $tokens); |
|
| 88 | + $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 89 | + return; |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | + catch (ApplicationLogicException $ex) { |
|
| 93 | + SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage()); |
|
| 94 | + } |
|
| 95 | + |
|
| 96 | + $this->redirect('multiFactor'); |
|
| 97 | + } |
|
| 98 | + else { |
|
| 99 | + SessionAlert::error('Error enabling YubiKey OTP - invalid credentials.'); |
|
| 100 | + $this->redirect('multiFactor'); |
|
| 101 | + } |
|
| 102 | + } |
|
| 103 | + else { |
|
| 104 | + if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 105 | + // user is not enrolled, we shouldn't have got here. |
|
| 106 | + throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism'); |
|
| 107 | + } |
|
| 108 | + |
|
| 109 | + $this->assignCSRFToken(); |
|
| 110 | + $this->setTemplate('mfa/enableYubikey.tpl'); |
|
| 111 | + } |
|
| 112 | + } |
|
| 208 | 113 | |
| 209 | - // urgh, dunno what happened, but it's not something expected. |
|
| 210 | - throw new ApplicationLogicException(); |
|
| 211 | - } |
|
| 212 | - else { |
|
| 213 | - if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 214 | - // user is not enrolled, we shouldn't have got here. |
|
| 215 | - throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism'); |
|
| 216 | - } |
|
| 114 | + protected function disableYubikeyOtp() |
|
| 115 | + { |
|
| 116 | + $database = $this->getDatabase(); |
|
| 117 | + $currentUser = User::getCurrent($database); |
|
| 217 | 118 | |
| 218 | - $this->assignCSRFToken(); |
|
| 119 | + $otpCredentialProvider = new YubikeyOtpCredentialProvider($database, |
|
| 120 | + $this->getSiteConfiguration(), $this->getHttpHelper()); |
|
| 219 | 121 | |
| 220 | - $this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.'); |
|
| 221 | - $this->assign('alertheader', 'Provide credentials'); |
|
| 222 | - $this->assign('continueText', 'Verify password'); |
|
| 223 | - $this->setTemplate('mfa/enableAuth.tpl'); |
|
| 224 | - } |
|
| 225 | - } |
|
| 122 | + $factorType = 'YubiKey OTP'; |
|
| 226 | 123 | |
| 227 | - protected function disableTotp() |
|
| 228 | - { |
|
| 229 | - $database = $this->getDatabase(); |
|
| 230 | - $currentUser = User::getCurrent($database); |
|
| 124 | + $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType); |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + protected function enableTotp() |
|
| 128 | + { |
|
| 129 | + $database = $this->getDatabase(); |
|
| 130 | + $currentUser = User::getCurrent($database); |
|
| 131 | + |
|
| 132 | + $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 133 | + |
|
| 134 | + if (WebRequest::wasPosted()) { |
|
| 135 | + $this->validateCSRFToken(); |
|
| 136 | + |
|
| 137 | + // used for routing only, not security |
|
| 138 | + $stage = WebRequest::postString('stage'); |
|
| 139 | + |
|
| 140 | + if ($stage === "auth") { |
|
| 141 | + $password = WebRequest::postString('password'); |
|
| 142 | + |
|
| 143 | + $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 144 | + $this->getSiteConfiguration()); |
|
| 145 | + $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 146 | + |
|
| 147 | + if ($result) { |
|
| 148 | + $otpCredentialProvider->setCredential($currentUser, 2, null); |
|
| 149 | + |
|
| 150 | + $provisioningUrl = $otpCredentialProvider->getProvisioningUrl($currentUser); |
|
| 151 | + |
|
| 152 | + $renderer = new Svg(); |
|
| 153 | + $renderer->setHeight(256); |
|
| 154 | + $renderer->setWidth(256); |
|
| 155 | + $writer = new Writer($renderer); |
|
| 156 | + $svg = $writer->writeString($provisioningUrl); |
|
| 157 | + |
|
| 158 | + $this->assign('svg', $svg); |
|
| 159 | + $this->assign('secret', $otpCredentialProvider->getSecret($currentUser)); |
|
| 160 | + |
|
| 161 | + $this->assignCSRFToken(); |
|
| 162 | + $this->setTemplate('mfa/enableTotpEnroll.tpl'); |
|
| 163 | + |
|
| 164 | + return; |
|
| 165 | + } |
|
| 166 | + else { |
|
| 167 | + SessionAlert::error('Error enabling TOTP - invalid credentials.'); |
|
| 168 | + $this->redirect('multiFactor'); |
|
| 169 | + |
|
| 170 | + return; |
|
| 171 | + } |
|
| 172 | + } |
|
| 173 | + |
|
| 174 | + if ($stage === "enroll") { |
|
| 175 | + // we *must* have a defined credential already here, |
|
| 176 | + if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) { |
|
| 177 | + $otp = WebRequest::postString('otp'); |
|
| 178 | + $result = $otpCredentialProvider->verifyEnable($currentUser, $otp); |
|
| 179 | + |
|
| 180 | + if ($result) { |
|
| 181 | + SessionAlert::success('Enabled TOTP.'); |
|
| 182 | + |
|
| 183 | + $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 184 | + if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 185 | + $scratchProvider->setCredential($currentUser, 2, null); |
|
| 186 | + $tokens = $scratchProvider->getTokens(); |
|
| 187 | + $this->assign('tokens', $tokens); |
|
| 188 | + $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 189 | + return; |
|
| 190 | + } |
|
| 191 | + } |
|
| 192 | + else { |
|
| 193 | + $otpCredentialProvider->deleteCredential($currentUser); |
|
| 194 | + SessionAlert::error('Error enabling TOTP: invalid token provided'); |
|
| 195 | + } |
|
| 196 | + |
|
| 197 | + |
|
| 198 | + $this->redirect('multiFactor'); |
|
| 199 | + return; |
|
| 200 | + } |
|
| 201 | + else { |
|
| 202 | + SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.'); |
|
| 203 | + $this->redirect('multiFactor'); |
|
| 204 | + |
|
| 205 | + return; |
|
| 206 | + } |
|
| 207 | + } |
|
| 208 | + |
|
| 209 | + // urgh, dunno what happened, but it's not something expected. |
|
| 210 | + throw new ApplicationLogicException(); |
|
| 211 | + } |
|
| 212 | + else { |
|
| 213 | + if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 214 | + // user is not enrolled, we shouldn't have got here. |
|
| 215 | + throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism'); |
|
| 216 | + } |
|
| 217 | + |
|
| 218 | + $this->assignCSRFToken(); |
|
| 219 | + |
|
| 220 | + $this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.'); |
|
| 221 | + $this->assign('alertheader', 'Provide credentials'); |
|
| 222 | + $this->assign('continueText', 'Verify password'); |
|
| 223 | + $this->setTemplate('mfa/enableAuth.tpl'); |
|
| 224 | + } |
|
| 225 | + } |
|
| 231 | 226 | |
| 232 | - $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 227 | + protected function disableTotp() |
|
| 228 | + { |
|
| 229 | + $database = $this->getDatabase(); |
|
| 230 | + $currentUser = User::getCurrent($database); |
|
| 231 | + |
|
| 232 | + $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 233 | + |
|
| 234 | + $factorType = 'TOTP'; |
|
| 235 | + |
|
| 236 | + $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType); |
|
| 237 | + } |
|
| 233 | 238 | |
| 234 | - $factorType = 'TOTP'; |
|
| 239 | + protected function enableU2F() { |
|
| 240 | + $database = $this->getDatabase(); |
|
| 241 | + $currentUser = User::getCurrent($database); |
|
| 235 | 242 | |
| 236 | - $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType); |
|
| 237 | - } |
|
| 243 | + $otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 238 | 244 | |
| 239 | - protected function enableU2F() { |
|
| 240 | - $database = $this->getDatabase(); |
|
| 241 | - $currentUser = User::getCurrent($database); |
|
| 245 | + if (WebRequest::wasPosted()) { |
|
| 246 | + $this->validateCSRFToken(); |
|
| 242 | 247 | |
| 243 | - $otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 244 | - |
|
| 245 | - if (WebRequest::wasPosted()) { |
|
| 246 | - $this->validateCSRFToken(); |
|
| 247 | - |
|
| 248 | - // used for routing only, not security |
|
| 249 | - $stage = WebRequest::postString('stage'); |
|
| 250 | - |
|
| 251 | - if ($stage === "auth") { |
|
| 252 | - $password = WebRequest::postString('password'); |
|
| 253 | - |
|
| 254 | - $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 255 | - $this->getSiteConfiguration()); |
|
| 256 | - $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 257 | - |
|
| 258 | - if ($result) { |
|
| 259 | - $otpCredentialProvider->setCredential($currentUser, 2, null); |
|
| 260 | - $this->assignCSRFToken(); |
|
| 261 | - |
|
| 262 | - list($data, $reqs) = $otpCredentialProvider->getRegistrationData(); |
|
| 263 | - |
|
| 264 | - $u2fRequest =json_encode($data); |
|
| 265 | - $u2fSigns = json_encode($reqs); |
|
| 266 | - |
|
| 267 | - $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js'); |
|
| 268 | - $this->setTailScript($this->getCspManager()->getNonce(), <<<JS |
|
| 248 | + // used for routing only, not security |
|
| 249 | + $stage = WebRequest::postString('stage'); |
|
| 250 | + |
|
| 251 | + if ($stage === "auth") { |
|
| 252 | + $password = WebRequest::postString('password'); |
|
| 253 | + |
|
| 254 | + $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 255 | + $this->getSiteConfiguration()); |
|
| 256 | + $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 257 | + |
|
| 258 | + if ($result) { |
|
| 259 | + $otpCredentialProvider->setCredential($currentUser, 2, null); |
|
| 260 | + $this->assignCSRFToken(); |
|
| 261 | + |
|
| 262 | + list($data, $reqs) = $otpCredentialProvider->getRegistrationData(); |
|
| 263 | + |
|
| 264 | + $u2fRequest =json_encode($data); |
|
| 265 | + $u2fSigns = json_encode($reqs); |
|
| 266 | + |
|
| 267 | + $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js'); |
|
| 268 | + $this->setTailScript($this->getCspManager()->getNonce(), <<<JS |
|
| 269 | 269 | var request = ${u2fRequest}; |
| 270 | 270 | var signs = ${u2fSigns}; |
| 271 | 271 | |
@@ -284,162 +284,162 @@ discard block |
||
| 284 | 284 | form.submit(); |
| 285 | 285 | }); |
| 286 | 286 | JS |
| 287 | - ); |
|
| 288 | - |
|
| 289 | - $this->setTemplate('mfa/enableU2FEnroll.tpl'); |
|
| 290 | - |
|
| 291 | - return; |
|
| 292 | - } |
|
| 293 | - else { |
|
| 294 | - SessionAlert::error('Error enabling TOTP - invalid credentials.'); |
|
| 295 | - $this->redirect('multiFactor'); |
|
| 296 | - |
|
| 297 | - return; |
|
| 298 | - } |
|
| 299 | - } |
|
| 300 | - |
|
| 301 | - if ($stage === "enroll") { |
|
| 302 | - // we *must* have a defined credential already here, |
|
| 303 | - if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) { |
|
| 304 | - |
|
| 305 | - $request = json_decode(WebRequest::postString('u2fRequest')); |
|
| 306 | - $u2fData = json_decode(WebRequest::postString('u2fData')); |
|
| 307 | - |
|
| 308 | - $otpCredentialProvider->enable($currentUser, $request, $u2fData); |
|
| 309 | - |
|
| 310 | - SessionAlert::success('Enabled U2F.'); |
|
| 311 | - |
|
| 312 | - $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 313 | - if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 314 | - $scratchProvider->setCredential($currentUser, 2, null); |
|
| 315 | - $tokens = $scratchProvider->getTokens(); |
|
| 316 | - $this->assign('tokens', $tokens); |
|
| 317 | - $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 318 | - return; |
|
| 319 | - } |
|
| 320 | - |
|
| 321 | - $this->redirect('multiFactor'); |
|
| 322 | - return; |
|
| 323 | - } |
|
| 324 | - else { |
|
| 325 | - SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.'); |
|
| 326 | - $this->redirect('multiFactor'); |
|
| 327 | - |
|
| 328 | - return; |
|
| 329 | - } |
|
| 330 | - } |
|
| 331 | - |
|
| 332 | - // urgh, dunno what happened, but it's not something expected. |
|
| 333 | - throw new ApplicationLogicException(); |
|
| 334 | - } |
|
| 335 | - else { |
|
| 336 | - if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 337 | - // user is not enrolled, we shouldn't have got here. |
|
| 338 | - throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism'); |
|
| 339 | - } |
|
| 340 | - |
|
| 341 | - $this->assignCSRFToken(); |
|
| 342 | - |
|
| 343 | - $this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.'); |
|
| 344 | - $this->assign('alertheader', 'Provide credentials'); |
|
| 345 | - $this->assign('continueText', 'Verify password'); |
|
| 346 | - $this->setTemplate('mfa/enableAuth.tpl'); |
|
| 347 | - } |
|
| 348 | - } |
|
| 349 | - |
|
| 350 | - protected function disableU2F() { |
|
| 351 | - $database = $this->getDatabase(); |
|
| 352 | - $currentUser = User::getCurrent($database); |
|
| 353 | - |
|
| 354 | - $otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 355 | - |
|
| 356 | - $factorType = 'U2F'; |
|
| 357 | - |
|
| 358 | - $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType); |
|
| 359 | - } |
|
| 360 | - |
|
| 361 | - protected function scratch() |
|
| 362 | - { |
|
| 363 | - $database = $this->getDatabase(); |
|
| 364 | - $currentUser = User::getCurrent($database); |
|
| 365 | - |
|
| 366 | - if (WebRequest::wasPosted()) { |
|
| 367 | - $this->validateCSRFToken(); |
|
| 368 | - |
|
| 369 | - $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 370 | - $this->getSiteConfiguration()); |
|
| 371 | - |
|
| 372 | - $otpCredentialProvider = new ScratchTokenCredentialProvider($database, |
|
| 373 | - $this->getSiteConfiguration()); |
|
| 374 | - |
|
| 375 | - $password = WebRequest::postString('password'); |
|
| 376 | - |
|
| 377 | - $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 378 | - |
|
| 379 | - if ($result) { |
|
| 380 | - $otpCredentialProvider->setCredential($currentUser, 2, null); |
|
| 381 | - $tokens = $otpCredentialProvider->getTokens(); |
|
| 382 | - $this->assign('tokens', $tokens); |
|
| 383 | - $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 384 | - } |
|
| 385 | - else { |
|
| 386 | - SessionAlert::error('Error refreshing scratch tokens - invalid credentials.'); |
|
| 387 | - $this->redirect('multiFactor'); |
|
| 388 | - } |
|
| 389 | - } |
|
| 390 | - else { |
|
| 391 | - $this->assignCSRFToken(); |
|
| 392 | - |
|
| 393 | - $this->assign('alertmessage', 'To regenerate your emergency scratch tokens, please prove you are who you say you are by providing the information below. Note that continuing will invalidate all remaining scratch tokens, and provide a set of new ones.'); |
|
| 394 | - $this->assign('alertheader', 'Re-generate scratch tokens'); |
|
| 395 | - $this->assign('continueText', 'Regenerate Scratch Tokens'); |
|
| 396 | - |
|
| 397 | - $this->setTemplate('mfa/enableAuth.tpl'); |
|
| 398 | - } |
|
| 399 | - } |
|
| 400 | - |
|
| 401 | - /** |
|
| 402 | - * @param PdoDatabase $database |
|
| 403 | - * @param User $currentUser |
|
| 404 | - * @param ICredentialProvider $otpCredentialProvider |
|
| 405 | - * @param string $factorType |
|
| 406 | - * |
|
| 407 | - * @throws ApplicationLogicException |
|
| 408 | - */ |
|
| 409 | - private function deleteCredential( |
|
| 410 | - PdoDatabase $database, |
|
| 411 | - User $currentUser, |
|
| 412 | - ICredentialProvider $otpCredentialProvider, |
|
| 413 | - $factorType |
|
| 414 | - ) { |
|
| 415 | - if (WebRequest::wasPosted()) { |
|
| 416 | - $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 417 | - $this->getSiteConfiguration()); |
|
| 418 | - |
|
| 419 | - $this->validateCSRFToken(); |
|
| 420 | - |
|
| 421 | - $password = WebRequest::postString('password'); |
|
| 422 | - $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 423 | - |
|
| 424 | - if ($result) { |
|
| 425 | - $otpCredentialProvider->deleteCredential($currentUser); |
|
| 426 | - SessionAlert::success('Disabled ' . $factorType . '.'); |
|
| 427 | - $this->redirect('multiFactor'); |
|
| 428 | - } |
|
| 429 | - else { |
|
| 430 | - SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.'); |
|
| 431 | - $this->redirect('multiFactor'); |
|
| 432 | - } |
|
| 433 | - } |
|
| 434 | - else { |
|
| 435 | - if (!$otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 436 | - // user is not enrolled, we shouldn't have got here. |
|
| 437 | - throw new ApplicationLogicException('User is not enrolled in the selected MFA mechanism'); |
|
| 438 | - } |
|
| 439 | - |
|
| 440 | - $this->assignCSRFToken(); |
|
| 441 | - $this->assign('otpType', $factorType); |
|
| 442 | - $this->setTemplate('mfa/disableOtp.tpl'); |
|
| 443 | - } |
|
| 444 | - } |
|
| 287 | + ); |
|
| 288 | + |
|
| 289 | + $this->setTemplate('mfa/enableU2FEnroll.tpl'); |
|
| 290 | + |
|
| 291 | + return; |
|
| 292 | + } |
|
| 293 | + else { |
|
| 294 | + SessionAlert::error('Error enabling TOTP - invalid credentials.'); |
|
| 295 | + $this->redirect('multiFactor'); |
|
| 296 | + |
|
| 297 | + return; |
|
| 298 | + } |
|
| 299 | + } |
|
| 300 | + |
|
| 301 | + if ($stage === "enroll") { |
|
| 302 | + // we *must* have a defined credential already here, |
|
| 303 | + if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) { |
|
| 304 | + |
|
| 305 | + $request = json_decode(WebRequest::postString('u2fRequest')); |
|
| 306 | + $u2fData = json_decode(WebRequest::postString('u2fData')); |
|
| 307 | + |
|
| 308 | + $otpCredentialProvider->enable($currentUser, $request, $u2fData); |
|
| 309 | + |
|
| 310 | + SessionAlert::success('Enabled U2F.'); |
|
| 311 | + |
|
| 312 | + $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 313 | + if($scratchProvider->getRemaining($currentUser->getId()) < 3) { |
|
| 314 | + $scratchProvider->setCredential($currentUser, 2, null); |
|
| 315 | + $tokens = $scratchProvider->getTokens(); |
|
| 316 | + $this->assign('tokens', $tokens); |
|
| 317 | + $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 318 | + return; |
|
| 319 | + } |
|
| 320 | + |
|
| 321 | + $this->redirect('multiFactor'); |
|
| 322 | + return; |
|
| 323 | + } |
|
| 324 | + else { |
|
| 325 | + SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.'); |
|
| 326 | + $this->redirect('multiFactor'); |
|
| 327 | + |
|
| 328 | + return; |
|
| 329 | + } |
|
| 330 | + } |
|
| 331 | + |
|
| 332 | + // urgh, dunno what happened, but it's not something expected. |
|
| 333 | + throw new ApplicationLogicException(); |
|
| 334 | + } |
|
| 335 | + else { |
|
| 336 | + if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 337 | + // user is not enrolled, we shouldn't have got here. |
|
| 338 | + throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism'); |
|
| 339 | + } |
|
| 340 | + |
|
| 341 | + $this->assignCSRFToken(); |
|
| 342 | + |
|
| 343 | + $this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing the information below.'); |
|
| 344 | + $this->assign('alertheader', 'Provide credentials'); |
|
| 345 | + $this->assign('continueText', 'Verify password'); |
|
| 346 | + $this->setTemplate('mfa/enableAuth.tpl'); |
|
| 347 | + } |
|
| 348 | + } |
|
| 349 | + |
|
| 350 | + protected function disableU2F() { |
|
| 351 | + $database = $this->getDatabase(); |
|
| 352 | + $currentUser = User::getCurrent($database); |
|
| 353 | + |
|
| 354 | + $otpCredentialProvider = new U2FCredentialProvider($database, $this->getSiteConfiguration()); |
|
| 355 | + |
|
| 356 | + $factorType = 'U2F'; |
|
| 357 | + |
|
| 358 | + $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType); |
|
| 359 | + } |
|
| 360 | + |
|
| 361 | + protected function scratch() |
|
| 362 | + { |
|
| 363 | + $database = $this->getDatabase(); |
|
| 364 | + $currentUser = User::getCurrent($database); |
|
| 365 | + |
|
| 366 | + if (WebRequest::wasPosted()) { |
|
| 367 | + $this->validateCSRFToken(); |
|
| 368 | + |
|
| 369 | + $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 370 | + $this->getSiteConfiguration()); |
|
| 371 | + |
|
| 372 | + $otpCredentialProvider = new ScratchTokenCredentialProvider($database, |
|
| 373 | + $this->getSiteConfiguration()); |
|
| 374 | + |
|
| 375 | + $password = WebRequest::postString('password'); |
|
| 376 | + |
|
| 377 | + $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 378 | + |
|
| 379 | + if ($result) { |
|
| 380 | + $otpCredentialProvider->setCredential($currentUser, 2, null); |
|
| 381 | + $tokens = $otpCredentialProvider->getTokens(); |
|
| 382 | + $this->assign('tokens', $tokens); |
|
| 383 | + $this->setTemplate('mfa/regenScratchTokens.tpl'); |
|
| 384 | + } |
|
| 385 | + else { |
|
| 386 | + SessionAlert::error('Error refreshing scratch tokens - invalid credentials.'); |
|
| 387 | + $this->redirect('multiFactor'); |
|
| 388 | + } |
|
| 389 | + } |
|
| 390 | + else { |
|
| 391 | + $this->assignCSRFToken(); |
|
| 392 | + |
|
| 393 | + $this->assign('alertmessage', 'To regenerate your emergency scratch tokens, please prove you are who you say you are by providing the information below. Note that continuing will invalidate all remaining scratch tokens, and provide a set of new ones.'); |
|
| 394 | + $this->assign('alertheader', 'Re-generate scratch tokens'); |
|
| 395 | + $this->assign('continueText', 'Regenerate Scratch Tokens'); |
|
| 396 | + |
|
| 397 | + $this->setTemplate('mfa/enableAuth.tpl'); |
|
| 398 | + } |
|
| 399 | + } |
|
| 400 | + |
|
| 401 | + /** |
|
| 402 | + * @param PdoDatabase $database |
|
| 403 | + * @param User $currentUser |
|
| 404 | + * @param ICredentialProvider $otpCredentialProvider |
|
| 405 | + * @param string $factorType |
|
| 406 | + * |
|
| 407 | + * @throws ApplicationLogicException |
|
| 408 | + */ |
|
| 409 | + private function deleteCredential( |
|
| 410 | + PdoDatabase $database, |
|
| 411 | + User $currentUser, |
|
| 412 | + ICredentialProvider $otpCredentialProvider, |
|
| 413 | + $factorType |
|
| 414 | + ) { |
|
| 415 | + if (WebRequest::wasPosted()) { |
|
| 416 | + $passwordCredentialProvider = new PasswordCredentialProvider($database, |
|
| 417 | + $this->getSiteConfiguration()); |
|
| 418 | + |
|
| 419 | + $this->validateCSRFToken(); |
|
| 420 | + |
|
| 421 | + $password = WebRequest::postString('password'); |
|
| 422 | + $result = $passwordCredentialProvider->authenticate($currentUser, $password); |
|
| 423 | + |
|
| 424 | + if ($result) { |
|
| 425 | + $otpCredentialProvider->deleteCredential($currentUser); |
|
| 426 | + SessionAlert::success('Disabled ' . $factorType . '.'); |
|
| 427 | + $this->redirect('multiFactor'); |
|
| 428 | + } |
|
| 429 | + else { |
|
| 430 | + SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.'); |
|
| 431 | + $this->redirect('multiFactor'); |
|
| 432 | + } |
|
| 433 | + } |
|
| 434 | + else { |
|
| 435 | + if (!$otpCredentialProvider->userIsEnrolled($currentUser->getId())) { |
|
| 436 | + // user is not enrolled, we shouldn't have got here. |
|
| 437 | + throw new ApplicationLogicException('User is not enrolled in the selected MFA mechanism'); |
|
| 438 | + } |
|
| 439 | + |
|
| 440 | + $this->assignCSRFToken(); |
|
| 441 | + $this->assign('otpType', $factorType); |
|
| 442 | + $this->setTemplate('mfa/disableOtp.tpl'); |
|
| 443 | + } |
|
| 444 | + } |
|
| 445 | 445 | } |
@@ -14,20 +14,20 @@ discard block |
||
| 14 | 14 | |
| 15 | 15 | class PageU2FLogin extends LoginCredentialPageBase |
| 16 | 16 | { |
| 17 | - protected function providerSpecificSetup() |
|
| 18 | - { |
|
| 19 | - $this->assign('showSignIn', false); |
|
| 20 | - $this->setTemplate('login/u2f.tpl'); |
|
| 17 | + protected function providerSpecificSetup() |
|
| 18 | + { |
|
| 19 | + $this->assign('showSignIn', false); |
|
| 20 | + $this->setTemplate('login/u2f.tpl'); |
|
| 21 | 21 | |
| 22 | - if ($this->partialUser === null) { |
|
| 23 | - throw new ApplicationLogicException("U2F cannot be first-stage authentication"); |
|
| 24 | - } |
|
| 22 | + if ($this->partialUser === null) { |
|
| 23 | + throw new ApplicationLogicException("U2F cannot be first-stage authentication"); |
|
| 24 | + } |
|
| 25 | 25 | |
| 26 | - $u2f = new U2FCredentialProvider($this->getDatabase(), $this->getSiteConfiguration()); |
|
| 27 | - $authData = json_encode($u2f->getAuthenticationData($this->partialUser)); |
|
| 26 | + $u2f = new U2FCredentialProvider($this->getDatabase(), $this->getSiteConfiguration()); |
|
| 27 | + $authData = json_encode($u2f->getAuthenticationData($this->partialUser)); |
|
| 28 | 28 | |
| 29 | - $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js'); |
|
| 30 | - $this->setTailScript($this->getCspManager()->getNonce(), <<<JS |
|
| 29 | + $this->addJs('/vendor/yubico/u2flib-server/examples/assets/u2f-api.js'); |
|
| 30 | + $this->setTailScript($this->getCspManager()->getNonce(), <<<JS |
|
| 31 | 31 | var request = {$authData}; |
| 32 | 32 | u2f.sign(request, function(data) { |
| 33 | 33 | document.getElementById('authenticate').value=JSON.stringify(data); |
@@ -35,19 +35,19 @@ discard block |
||
| 35 | 35 | document.getElementById('loginForm').submit(); |
| 36 | 36 | }); |
| 37 | 37 | JS |
| 38 | - ); |
|
| 38 | + ); |
|
| 39 | 39 | |
| 40 | - } |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - protected function getProviderCredentials() |
|
| 43 | - { |
|
| 44 | - $authenticate = WebRequest::postString("authenticate"); |
|
| 45 | - $request = WebRequest::postString("request"); |
|
| 42 | + protected function getProviderCredentials() |
|
| 43 | + { |
|
| 44 | + $authenticate = WebRequest::postString("authenticate"); |
|
| 45 | + $request = WebRequest::postString("request"); |
|
| 46 | 46 | |
| 47 | - if ($authenticate === null || $authenticate === "" || $request === null || $request === "") { |
|
| 48 | - throw new ApplicationLogicException("No authentication specified"); |
|
| 49 | - } |
|
| 47 | + if ($authenticate === null || $authenticate === "" || $request === null || $request === "") { |
|
| 48 | + throw new ApplicationLogicException("No authentication specified"); |
|
| 49 | + } |
|
| 50 | 50 | |
| 51 | - return array(json_decode($authenticate), json_decode($request), 'u2f'); |
|
| 52 | - } |
|
| 51 | + return array(json_decode($authenticate), json_decode($request), 'u2f'); |
|
| 52 | + } |
|
| 53 | 53 | } |
@@ -20,60 +20,60 @@ discard block |
||
| 20 | 20 | |
| 21 | 21 | class PageMain extends InternalPageBase |
| 22 | 22 | { |
| 23 | - /** |
|
| 24 | - * Main function for this page, when no actions are called. |
|
| 25 | - */ |
|
| 26 | - protected function main() |
|
| 27 | - { |
|
| 28 | - $this->assignCSRFToken(); |
|
| 29 | - |
|
| 30 | - $config = $this->getSiteConfiguration(); |
|
| 31 | - $database = $this->getDatabase(); |
|
| 32 | - $currentUser = User::getCurrent($database); |
|
| 33 | - |
|
| 34 | - // general template configuration |
|
| 35 | - $this->assign('defaultRequestState', $config->getDefaultRequestStateKey()); |
|
| 36 | - $this->assign('requestLimitShowOnly', $config->getMiserModeLimit()); |
|
| 37 | - |
|
| 38 | - // Get map of possible usernames |
|
| 39 | - $userList = UserSearchHelper::get($database)->withReservedRequest(); |
|
| 40 | - $this->assign('userList', $userList); |
|
| 41 | - |
|
| 42 | - $seeAllRequests = $this->barrierTest('seeAllRequests', $currentUser, PageViewRequest::class); |
|
| 43 | - |
|
| 44 | - // Fetch request data |
|
| 45 | - $requestSectionData = array(); |
|
| 46 | - if ($seeAllRequests) { |
|
| 47 | - $this->setupStatusSections($database, $config, $requestSectionData); |
|
| 48 | - $this->setupHospitalQueue($database, $config, $requestSectionData); |
|
| 49 | - $this->setupJobQueue($database, $config, $requestSectionData); |
|
| 50 | - } |
|
| 51 | - $this->setupLastFiveClosedData($database, $seeAllRequests); |
|
| 52 | - |
|
| 53 | - // Assign data to template |
|
| 54 | - $this->assign('requestSectionData', $requestSectionData); |
|
| 55 | - |
|
| 56 | - // Extra rights |
|
| 57 | - $this->assign('canBan', $this->barrierTest('set', $currentUser, PageBan::class)); |
|
| 58 | - $this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class)); |
|
| 59 | - |
|
| 60 | - $this->setTemplate('mainpage/mainpage.tpl'); |
|
| 61 | - } |
|
| 62 | - |
|
| 63 | - /** |
|
| 64 | - * @param PdoDatabase $database |
|
| 65 | - * @param bool $seeAllRequests |
|
| 66 | - * |
|
| 67 | - * @internal param User $currentUser |
|
| 68 | - */ |
|
| 69 | - private function setupLastFiveClosedData(PdoDatabase $database, $seeAllRequests) |
|
| 70 | - { |
|
| 71 | - $this->assign('showLastFive', $seeAllRequests); |
|
| 72 | - if (!$seeAllRequests) { |
|
| 73 | - return; |
|
| 74 | - } |
|
| 75 | - |
|
| 76 | - $query = <<<SQL |
|
| 23 | + /** |
|
| 24 | + * Main function for this page, when no actions are called. |
|
| 25 | + */ |
|
| 26 | + protected function main() |
|
| 27 | + { |
|
| 28 | + $this->assignCSRFToken(); |
|
| 29 | + |
|
| 30 | + $config = $this->getSiteConfiguration(); |
|
| 31 | + $database = $this->getDatabase(); |
|
| 32 | + $currentUser = User::getCurrent($database); |
|
| 33 | + |
|
| 34 | + // general template configuration |
|
| 35 | + $this->assign('defaultRequestState', $config->getDefaultRequestStateKey()); |
|
| 36 | + $this->assign('requestLimitShowOnly', $config->getMiserModeLimit()); |
|
| 37 | + |
|
| 38 | + // Get map of possible usernames |
|
| 39 | + $userList = UserSearchHelper::get($database)->withReservedRequest(); |
|
| 40 | + $this->assign('userList', $userList); |
|
| 41 | + |
|
| 42 | + $seeAllRequests = $this->barrierTest('seeAllRequests', $currentUser, PageViewRequest::class); |
|
| 43 | + |
|
| 44 | + // Fetch request data |
|
| 45 | + $requestSectionData = array(); |
|
| 46 | + if ($seeAllRequests) { |
|
| 47 | + $this->setupStatusSections($database, $config, $requestSectionData); |
|
| 48 | + $this->setupHospitalQueue($database, $config, $requestSectionData); |
|
| 49 | + $this->setupJobQueue($database, $config, $requestSectionData); |
|
| 50 | + } |
|
| 51 | + $this->setupLastFiveClosedData($database, $seeAllRequests); |
|
| 52 | + |
|
| 53 | + // Assign data to template |
|
| 54 | + $this->assign('requestSectionData', $requestSectionData); |
|
| 55 | + |
|
| 56 | + // Extra rights |
|
| 57 | + $this->assign('canBan', $this->barrierTest('set', $currentUser, PageBan::class)); |
|
| 58 | + $this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class)); |
|
| 59 | + |
|
| 60 | + $this->setTemplate('mainpage/mainpage.tpl'); |
|
| 61 | + } |
|
| 62 | + |
|
| 63 | + /** |
|
| 64 | + * @param PdoDatabase $database |
|
| 65 | + * @param bool $seeAllRequests |
|
| 66 | + * |
|
| 67 | + * @internal param User $currentUser |
|
| 68 | + */ |
|
| 69 | + private function setupLastFiveClosedData(PdoDatabase $database, $seeAllRequests) |
|
| 70 | + { |
|
| 71 | + $this->assign('showLastFive', $seeAllRequests); |
|
| 72 | + if (!$seeAllRequests) { |
|
| 73 | + return; |
|
| 74 | + } |
|
| 75 | + |
|
| 76 | + $query = <<<SQL |
|
| 77 | 77 | SELECT request.id, request.name, request.updateversion |
| 78 | 78 | FROM request /* PageMain::main() */ |
| 79 | 79 | JOIN log ON log.objectid = request.id AND log.objecttype = 'Request' |
@@ -82,107 +82,107 @@ discard block |
||
| 82 | 82 | LIMIT 5; |
| 83 | 83 | SQL; |
| 84 | 84 | |
| 85 | - $statement = $database->prepare($query); |
|
| 86 | - $statement->execute(); |
|
| 87 | - |
|
| 88 | - $last5result = $statement->fetchAll(PDO::FETCH_ASSOC); |
|
| 89 | - |
|
| 90 | - $this->assign('lastFive', $last5result); |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - /** |
|
| 94 | - * @param PdoDatabase $database |
|
| 95 | - * @param SiteConfiguration $config |
|
| 96 | - * @param $requestSectionData |
|
| 97 | - */ |
|
| 98 | - private function setupHospitalQueue( |
|
| 99 | - PdoDatabase $database, |
|
| 100 | - SiteConfiguration $config, |
|
| 101 | - &$requestSectionData |
|
| 102 | - ) { |
|
| 103 | - $search = RequestSearchHelper::get($database) |
|
| 104 | - ->limit($config->getMiserModeLimit()) |
|
| 105 | - ->excludingStatus('Closed') |
|
| 106 | - ->isHospitalised(); |
|
| 107 | - |
|
| 108 | - if ($config->getEmailConfirmationEnabled()) { |
|
| 109 | - $search->withConfirmedEmail(); |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - $results = $search->getRecordCount($requestCount)->fetch(); |
|
| 113 | - |
|
| 114 | - if($requestCount > 0) { |
|
| 115 | - $requestSectionData['Hospital - Requests failed auto-creation'] = array( |
|
| 116 | - 'requests' => $results, |
|
| 117 | - 'total' => $requestCount, |
|
| 118 | - 'api' => 'hospital', |
|
| 119 | - 'type' => 'hospital', |
|
| 120 | - 'special' => 'Job Queue', |
|
| 121 | - 'help' => 'This queue lists all the requests which have been attempted to be created in the background, but for which this has failed for one reason or another. Check the job queue to find the error. Requests here may need to be created manually, or it may be possible to re-queue the request for auto-creation by the tool, or it may have been created already. Use your own technical discretion here.' |
|
| 122 | - ); |
|
| 123 | - } |
|
| 124 | - } |
|
| 125 | - |
|
| 126 | - /** |
|
| 127 | - * @param PdoDatabase $database |
|
| 128 | - * @param SiteConfiguration $config |
|
| 129 | - * @param $requestSectionData |
|
| 130 | - */ |
|
| 131 | - private function setupJobQueue( |
|
| 132 | - PdoDatabase $database, |
|
| 133 | - SiteConfiguration $config, |
|
| 134 | - &$requestSectionData |
|
| 135 | - ) { |
|
| 136 | - $search = RequestSearchHelper::get($database) |
|
| 137 | - ->limit($config->getMiserModeLimit()) |
|
| 138 | - ->byStatus(RequestStatus::JOBQUEUE); |
|
| 139 | - |
|
| 140 | - if ($config->getEmailConfirmationEnabled()) { |
|
| 141 | - $search->withConfirmedEmail(); |
|
| 142 | - } |
|
| 143 | - |
|
| 144 | - $results = $search->getRecordCount($requestCount)->fetch(); |
|
| 145 | - |
|
| 146 | - if($requestCount > 0) { |
|
| 147 | - $requestSectionData['Requests queued in the Job Queue'] = array( |
|
| 148 | - 'requests' => $results, |
|
| 149 | - 'total' => $requestCount, |
|
| 150 | - 'api' => 'JobQueue', |
|
| 151 | - 'type' => 'JobQueue', |
|
| 152 | - 'special' => 'Job Queue', |
|
| 153 | - 'help' => 'This section lists all the requests which are currently waiting to be created by the tool. Requests should automatically disappear from here within a few minutes.' |
|
| 154 | - ); |
|
| 155 | - } |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - /** |
|
| 159 | - * @param PdoDatabase $database |
|
| 160 | - * @param SiteConfiguration $config |
|
| 161 | - * @param $requestSectionData |
|
| 162 | - */ |
|
| 163 | - private function setupStatusSections( |
|
| 164 | - PdoDatabase $database, |
|
| 165 | - SiteConfiguration $config, |
|
| 166 | - &$requestSectionData |
|
| 167 | - ) { |
|
| 168 | - $search = RequestSearchHelper::get($database)->limit($config->getMiserModeLimit())->notHospitalised(); |
|
| 169 | - |
|
| 170 | - if ($config->getEmailConfirmationEnabled()) { |
|
| 171 | - $search->withConfirmedEmail(); |
|
| 172 | - } |
|
| 173 | - |
|
| 174 | - $requestStates = $config->getRequestStates(); |
|
| 175 | - $requestsByStatus = $search->fetchByStatus(array_keys($requestStates)); |
|
| 176 | - |
|
| 177 | - foreach ($requestStates as $type => $v) { |
|
| 178 | - $requestSectionData[$v['header']] = array( |
|
| 179 | - 'requests' => $requestsByStatus[$type]['data'], |
|
| 180 | - 'total' => $requestsByStatus[$type]['count'], |
|
| 181 | - 'api' => $v['api'], |
|
| 182 | - 'type' => $type, |
|
| 183 | - 'special' => null, |
|
| 184 | - 'help' => $v['queuehelp'], |
|
| 185 | - ); |
|
| 186 | - } |
|
| 187 | - } |
|
| 85 | + $statement = $database->prepare($query); |
|
| 86 | + $statement->execute(); |
|
| 87 | + |
|
| 88 | + $last5result = $statement->fetchAll(PDO::FETCH_ASSOC); |
|
| 89 | + |
|
| 90 | + $this->assign('lastFive', $last5result); |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + /** |
|
| 94 | + * @param PdoDatabase $database |
|
| 95 | + * @param SiteConfiguration $config |
|
| 96 | + * @param $requestSectionData |
|
| 97 | + */ |
|
| 98 | + private function setupHospitalQueue( |
|
| 99 | + PdoDatabase $database, |
|
| 100 | + SiteConfiguration $config, |
|
| 101 | + &$requestSectionData |
|
| 102 | + ) { |
|
| 103 | + $search = RequestSearchHelper::get($database) |
|
| 104 | + ->limit($config->getMiserModeLimit()) |
|
| 105 | + ->excludingStatus('Closed') |
|
| 106 | + ->isHospitalised(); |
|
| 107 | + |
|
| 108 | + if ($config->getEmailConfirmationEnabled()) { |
|
| 109 | + $search->withConfirmedEmail(); |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + $results = $search->getRecordCount($requestCount)->fetch(); |
|
| 113 | + |
|
| 114 | + if($requestCount > 0) { |
|
| 115 | + $requestSectionData['Hospital - Requests failed auto-creation'] = array( |
|
| 116 | + 'requests' => $results, |
|
| 117 | + 'total' => $requestCount, |
|
| 118 | + 'api' => 'hospital', |
|
| 119 | + 'type' => 'hospital', |
|
| 120 | + 'special' => 'Job Queue', |
|
| 121 | + 'help' => 'This queue lists all the requests which have been attempted to be created in the background, but for which this has failed for one reason or another. Check the job queue to find the error. Requests here may need to be created manually, or it may be possible to re-queue the request for auto-creation by the tool, or it may have been created already. Use your own technical discretion here.' |
|
| 122 | + ); |
|
| 123 | + } |
|
| 124 | + } |
|
| 125 | + |
|
| 126 | + /** |
|
| 127 | + * @param PdoDatabase $database |
|
| 128 | + * @param SiteConfiguration $config |
|
| 129 | + * @param $requestSectionData |
|
| 130 | + */ |
|
| 131 | + private function setupJobQueue( |
|
| 132 | + PdoDatabase $database, |
|
| 133 | + SiteConfiguration $config, |
|
| 134 | + &$requestSectionData |
|
| 135 | + ) { |
|
| 136 | + $search = RequestSearchHelper::get($database) |
|
| 137 | + ->limit($config->getMiserModeLimit()) |
|
| 138 | + ->byStatus(RequestStatus::JOBQUEUE); |
|
| 139 | + |
|
| 140 | + if ($config->getEmailConfirmationEnabled()) { |
|
| 141 | + $search->withConfirmedEmail(); |
|
| 142 | + } |
|
| 143 | + |
|
| 144 | + $results = $search->getRecordCount($requestCount)->fetch(); |
|
| 145 | + |
|
| 146 | + if($requestCount > 0) { |
|
| 147 | + $requestSectionData['Requests queued in the Job Queue'] = array( |
|
| 148 | + 'requests' => $results, |
|
| 149 | + 'total' => $requestCount, |
|
| 150 | + 'api' => 'JobQueue', |
|
| 151 | + 'type' => 'JobQueue', |
|
| 152 | + 'special' => 'Job Queue', |
|
| 153 | + 'help' => 'This section lists all the requests which are currently waiting to be created by the tool. Requests should automatically disappear from here within a few minutes.' |
|
| 154 | + ); |
|
| 155 | + } |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + /** |
|
| 159 | + * @param PdoDatabase $database |
|
| 160 | + * @param SiteConfiguration $config |
|
| 161 | + * @param $requestSectionData |
|
| 162 | + */ |
|
| 163 | + private function setupStatusSections( |
|
| 164 | + PdoDatabase $database, |
|
| 165 | + SiteConfiguration $config, |
|
| 166 | + &$requestSectionData |
|
| 167 | + ) { |
|
| 168 | + $search = RequestSearchHelper::get($database)->limit($config->getMiserModeLimit())->notHospitalised(); |
|
| 169 | + |
|
| 170 | + if ($config->getEmailConfirmationEnabled()) { |
|
| 171 | + $search->withConfirmedEmail(); |
|
| 172 | + } |
|
| 173 | + |
|
| 174 | + $requestStates = $config->getRequestStates(); |
|
| 175 | + $requestsByStatus = $search->fetchByStatus(array_keys($requestStates)); |
|
| 176 | + |
|
| 177 | + foreach ($requestStates as $type => $v) { |
|
| 178 | + $requestSectionData[$v['header']] = array( |
|
| 179 | + 'requests' => $requestsByStatus[$type]['data'], |
|
| 180 | + 'total' => $requestsByStatus[$type]['count'], |
|
| 181 | + 'api' => $v['api'], |
|
| 182 | + 'type' => $type, |
|
| 183 | + 'special' => null, |
|
| 184 | + 'help' => $v['queuehelp'], |
|
| 185 | + ); |
|
| 186 | + } |
|
| 187 | + } |
|
| 188 | 188 | } |
@@ -249,7 +249,7 @@ discard block |
||
| 249 | 249 | $targetScriptName = $currentScriptName; |
| 250 | 250 | } |
| 251 | 251 | else { |
| 252 | - $targetScriptName = $this->getSiteConfiguration()->getBaseUrl() . '/' . $script; |
|
| 252 | + $targetScriptName = $this->getSiteConfiguration()->getBaseUrl().'/'.$script; |
|
| 253 | 253 | } |
| 254 | 254 | |
| 255 | 255 | $pathInfo = array($targetScriptName); |
@@ -263,7 +263,7 @@ discard block |
||
| 263 | 263 | $url = implode('/', $pathInfo); |
| 264 | 264 | |
| 265 | 265 | if (is_array($parameters) && count($parameters) > 0) { |
| 266 | - $url .= '?' . http_build_query($parameters); |
|
| 266 | + $url .= '?'.http_build_query($parameters); |
|
| 267 | 267 | } |
| 268 | 268 | |
| 269 | 269 | $this->redirectUrl($url); |
@@ -307,8 +307,8 @@ discard block |
||
| 307 | 307 | * |
| 308 | 308 | * @param string $path The path (relative to the application root) of the file |
| 309 | 309 | */ |
| 310 | - final protected function addJs($path){ |
|
| 311 | - if(in_array($path, $this->extraJs)){ |
|
| 310 | + final protected function addJs($path) { |
|
| 311 | + if (in_array($path, $this->extraJs)) { |
|
| 312 | 312 | // nothing to do |
| 313 | 313 | return; |
| 314 | 314 | } |
@@ -331,7 +331,7 @@ discard block |
||
| 331 | 331 | */ |
| 332 | 332 | final protected function setHtmlTitle($title) |
| 333 | 333 | { |
| 334 | - $this->htmlTitle = $this->smarty->fetch('string:' . $title); |
|
| 334 | + $this->htmlTitle = $this->smarty->fetch('string:'.$title); |
|
| 335 | 335 | } |
| 336 | 336 | |
| 337 | 337 | public function execute() |
@@ -307,8 +307,9 @@ |
||
| 307 | 307 | * |
| 308 | 308 | * @param string $path The path (relative to the application root) of the file |
| 309 | 309 | */ |
| 310 | - final protected function addJs($path){ |
|
| 311 | - if(in_array($path, $this->extraJs)){ |
|
| 310 | + final protected function addJs($path) |
|
| 311 | + { |
|
| 312 | + if(in_array($path, $this->extraJs)) { |
|
| 312 | 313 | // nothing to do |
| 313 | 314 | return; |
| 314 | 315 | } |
@@ -23,357 +23,357 @@ |
||
| 23 | 23 | |
| 24 | 24 | abstract class PageBase extends TaskBase implements IRoutedTask |
| 25 | 25 | { |
| 26 | - use TemplateOutput; |
|
| 27 | - /** @var string Smarty template to display */ |
|
| 28 | - protected $template = "base.tpl"; |
|
| 29 | - /** @var string HTML title. Currently unused. */ |
|
| 30 | - protected $htmlTitle; |
|
| 31 | - /** @var bool Determines if the page is a redirect or not */ |
|
| 32 | - protected $isRedirecting = false; |
|
| 33 | - /** @var array Queue of headers to be sent on successful completion */ |
|
| 34 | - protected $headerQueue = array(); |
|
| 35 | - /** @var string The name of the route to use, as determined by the request router. */ |
|
| 36 | - private $routeName = null; |
|
| 37 | - /** @var TokenManager */ |
|
| 38 | - protected $tokenManager; |
|
| 39 | - /** @var ContentSecurityPolicyManager */ |
|
| 40 | - private $cspManager; |
|
| 41 | - /** @var string[] Extra JS files to include */ |
|
| 42 | - private $extraJs = array(); |
|
| 43 | - |
|
| 44 | - /** |
|
| 45 | - * Sets the route the request will take. Only should be called from the request router or barrier test. |
|
| 46 | - * |
|
| 47 | - * @param string $routeName The name of the route |
|
| 48 | - * @param bool $skipCallableTest Don't use this unless you know what you're doing, and what the implications are. |
|
| 49 | - * |
|
| 50 | - * @throws Exception |
|
| 51 | - * @category Security-Critical |
|
| 52 | - */ |
|
| 53 | - final public function setRoute($routeName, $skipCallableTest = false) |
|
| 54 | - { |
|
| 55 | - // Test the new route is callable before adopting it. |
|
| 56 | - if (!$skipCallableTest && !is_callable(array($this, $routeName))) { |
|
| 57 | - throw new Exception("Proposed route '$routeName' is not callable."); |
|
| 58 | - } |
|
| 59 | - |
|
| 60 | - // Adopt the new route |
|
| 61 | - $this->routeName = $routeName; |
|
| 62 | - } |
|
| 63 | - |
|
| 64 | - /** |
|
| 65 | - * Gets the name of the route that has been passed from the request router. |
|
| 66 | - * @return string |
|
| 67 | - */ |
|
| 68 | - final public function getRouteName() |
|
| 69 | - { |
|
| 70 | - return $this->routeName; |
|
| 71 | - } |
|
| 72 | - |
|
| 73 | - /** |
|
| 74 | - * Performs generic page setup actions |
|
| 75 | - */ |
|
| 76 | - final protected function setupPage() |
|
| 77 | - { |
|
| 78 | - $this->setUpSmarty(); |
|
| 79 | - |
|
| 80 | - $currentUser = User::getCurrent($this->getDatabase()); |
|
| 81 | - $this->assign('currentUser', $currentUser); |
|
| 82 | - $this->assign('loggedIn', (!$currentUser->isCommunityUser())); |
|
| 83 | - } |
|
| 84 | - |
|
| 85 | - /** |
|
| 86 | - * Runs the page logic as routed by the RequestRouter |
|
| 87 | - * |
|
| 88 | - * Only should be called after a security barrier! That means only from execute(). |
|
| 89 | - */ |
|
| 90 | - final protected function runPage() |
|
| 91 | - { |
|
| 92 | - $database = $this->getDatabase(); |
|
| 93 | - |
|
| 94 | - // initialise a database transaction |
|
| 95 | - if (!$database->beginTransaction()) { |
|
| 96 | - throw new Exception('Failed to start transaction on primary database.'); |
|
| 97 | - } |
|
| 98 | - |
|
| 99 | - try { |
|
| 100 | - // run the page code |
|
| 101 | - $this->{$this->getRouteName()}(); |
|
| 102 | - |
|
| 103 | - $database->commit(); |
|
| 104 | - } |
|
| 105 | - catch (ApplicationLogicException $ex) { |
|
| 106 | - // it's an application logic exception, so nothing went seriously wrong with the site. We can use the |
|
| 107 | - // standard templating system for this. |
|
| 108 | - |
|
| 109 | - // Firstly, let's undo anything that happened to the database. |
|
| 110 | - $database->rollBack(); |
|
| 111 | - |
|
| 112 | - // Reset smarty |
|
| 113 | - $this->setupPage(); |
|
| 114 | - |
|
| 115 | - // Set the template |
|
| 116 | - $this->setTemplate('exception/application-logic.tpl'); |
|
| 117 | - $this->assign('message', $ex->getMessage()); |
|
| 118 | - |
|
| 119 | - // Force this back to false |
|
| 120 | - $this->isRedirecting = false; |
|
| 121 | - $this->headerQueue = array(); |
|
| 122 | - } |
|
| 123 | - catch (OptimisticLockFailedException $ex) { |
|
| 124 | - // it's an optimistic lock failure exception, so nothing went seriously wrong with the site. We can use the |
|
| 125 | - // standard templating system for this. |
|
| 126 | - |
|
| 127 | - // Firstly, let's undo anything that happened to the database. |
|
| 128 | - $database->rollBack(); |
|
| 129 | - |
|
| 130 | - // Reset smarty |
|
| 131 | - $this->setupPage(); |
|
| 132 | - |
|
| 133 | - // Set the template |
|
| 134 | - $this->setTemplate('exception/optimistic-lock-failure.tpl'); |
|
| 135 | - $this->assign('message', $ex->getMessage()); |
|
| 136 | - |
|
| 137 | - $this->assign('debugTrace', false); |
|
| 138 | - |
|
| 139 | - if ($this->getSiteConfiguration()->getDebuggingTraceEnabled()) { |
|
| 140 | - ob_start(); |
|
| 141 | - var_dump(ExceptionHandler::getExceptionData($ex)); |
|
| 142 | - $textErrorData = ob_get_contents(); |
|
| 143 | - ob_end_clean(); |
|
| 144 | - |
|
| 145 | - $this->assign('exceptionData', $textErrorData); |
|
| 146 | - $this->assign('debugTrace', true); |
|
| 147 | - } |
|
| 148 | - |
|
| 149 | - // Force this back to false |
|
| 150 | - $this->isRedirecting = false; |
|
| 151 | - $this->headerQueue = array(); |
|
| 152 | - } |
|
| 153 | - finally { |
|
| 154 | - // Catch any hanging on transactions |
|
| 155 | - if ($database->hasActiveTransaction()) { |
|
| 156 | - $database->rollBack(); |
|
| 157 | - } |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - // run any finalisation code needed before we send the output to the browser. |
|
| 161 | - $this->finalisePage(); |
|
| 162 | - |
|
| 163 | - // Send the headers |
|
| 164 | - $this->sendResponseHeaders(); |
|
| 165 | - |
|
| 166 | - // Check we have a template to use! |
|
| 167 | - if ($this->template !== null) { |
|
| 168 | - $content = $this->fetchTemplate($this->template); |
|
| 169 | - ob_clean(); |
|
| 170 | - print($content); |
|
| 171 | - ob_flush(); |
|
| 172 | - |
|
| 173 | - return; |
|
| 174 | - } |
|
| 175 | - } |
|
| 176 | - |
|
| 177 | - /** |
|
| 178 | - * Performs final tasks needed before rendering the page. |
|
| 179 | - */ |
|
| 180 | - protected function finalisePage() |
|
| 181 | - { |
|
| 182 | - if ($this->isRedirecting) { |
|
| 183 | - $this->template = null; |
|
| 184 | - |
|
| 185 | - return; |
|
| 186 | - } |
|
| 187 | - |
|
| 188 | - $this->assign('extraJs', $this->extraJs); |
|
| 189 | - |
|
| 190 | - // If we're actually displaying content, we want to add the session alerts here! |
|
| 191 | - $this->assign('alerts', SessionAlert::getAlerts()); |
|
| 192 | - SessionAlert::clearAlerts(); |
|
| 193 | - |
|
| 194 | - $this->assign('htmlTitle', $this->htmlTitle); |
|
| 195 | - } |
|
| 196 | - |
|
| 197 | - /** |
|
| 198 | - * @return TokenManager |
|
| 199 | - */ |
|
| 200 | - public function getTokenManager() |
|
| 201 | - { |
|
| 202 | - return $this->tokenManager; |
|
| 203 | - } |
|
| 204 | - |
|
| 205 | - /** |
|
| 206 | - * @param TokenManager $tokenManager |
|
| 207 | - */ |
|
| 208 | - public function setTokenManager($tokenManager) |
|
| 209 | - { |
|
| 210 | - $this->tokenManager = $tokenManager; |
|
| 211 | - } |
|
| 212 | - |
|
| 213 | - /** |
|
| 214 | - * @return ContentSecurityPolicyManager |
|
| 215 | - */ |
|
| 216 | - public function getCspManager(): ContentSecurityPolicyManager |
|
| 217 | - { |
|
| 218 | - return $this->cspManager; |
|
| 219 | - } |
|
| 220 | - |
|
| 221 | - /** |
|
| 222 | - * @param ContentSecurityPolicyManager $cspManager |
|
| 223 | - */ |
|
| 224 | - public function setCspManager(ContentSecurityPolicyManager $cspManager): void |
|
| 225 | - { |
|
| 226 | - $this->cspManager = $cspManager; |
|
| 227 | - } |
|
| 228 | - |
|
| 229 | - /** |
|
| 230 | - * Sends the redirect headers to perform a GET at the destination page. |
|
| 231 | - * |
|
| 232 | - * Also nullifies the set template so Smarty does not render it. |
|
| 233 | - * |
|
| 234 | - * @param string $page The page to redirect requests to (as used in the UR) |
|
| 235 | - * @param null|string $action The action to use on the page. |
|
| 236 | - * @param null|array $parameters |
|
| 237 | - * @param null|string $script The script (relative to index.php) to redirect to |
|
| 238 | - */ |
|
| 239 | - final protected function redirect($page = '', $action = null, $parameters = null, $script = null) |
|
| 240 | - { |
|
| 241 | - $currentScriptName = WebRequest::scriptName(); |
|
| 242 | - |
|
| 243 | - // Are we changing script? |
|
| 244 | - if ($script === null || substr($currentScriptName, -1 * count($script)) === $script) { |
|
| 245 | - $targetScriptName = $currentScriptName; |
|
| 246 | - } |
|
| 247 | - else { |
|
| 248 | - $targetScriptName = $this->getSiteConfiguration()->getBaseUrl() . '/' . $script; |
|
| 249 | - } |
|
| 250 | - |
|
| 251 | - $pathInfo = array($targetScriptName); |
|
| 252 | - |
|
| 253 | - $pathInfo[1] = $page; |
|
| 254 | - |
|
| 255 | - if ($action !== null) { |
|
| 256 | - $pathInfo[2] = $action; |
|
| 257 | - } |
|
| 258 | - |
|
| 259 | - $url = implode('/', $pathInfo); |
|
| 260 | - |
|
| 261 | - if (is_array($parameters) && count($parameters) > 0) { |
|
| 262 | - $url .= '?' . http_build_query($parameters); |
|
| 263 | - } |
|
| 264 | - |
|
| 265 | - $this->redirectUrl($url); |
|
| 266 | - } |
|
| 267 | - |
|
| 268 | - /** |
|
| 269 | - * Sends the redirect headers to perform a GET at the new address. |
|
| 270 | - * |
|
| 271 | - * Also nullifies the set template so Smarty does not render it. |
|
| 272 | - * |
|
| 273 | - * @param string $path URL to redirect to |
|
| 274 | - */ |
|
| 275 | - final protected function redirectUrl($path) |
|
| 276 | - { |
|
| 277 | - // 303 See Other = re-request at new address with a GET. |
|
| 278 | - $this->headerQueue[] = 'HTTP/1.1 303 See Other'; |
|
| 279 | - $this->headerQueue[] = "Location: $path"; |
|
| 280 | - |
|
| 281 | - $this->setTemplate(null); |
|
| 282 | - $this->isRedirecting = true; |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - /** |
|
| 286 | - * Sets the name of the template this page should display. |
|
| 287 | - * |
|
| 288 | - * @param string $name |
|
| 289 | - * |
|
| 290 | - * @throws Exception |
|
| 291 | - */ |
|
| 292 | - final protected function setTemplate($name) |
|
| 293 | - { |
|
| 294 | - if ($this->isRedirecting) { |
|
| 295 | - throw new Exception('This page has been set as a redirect, no template can be displayed!'); |
|
| 296 | - } |
|
| 297 | - |
|
| 298 | - $this->template = $name; |
|
| 299 | - } |
|
| 300 | - |
|
| 301 | - /** |
|
| 302 | - * Adds an extra JS file to to the page |
|
| 303 | - * |
|
| 304 | - * @param string $path The path (relative to the application root) of the file |
|
| 305 | - */ |
|
| 306 | - final protected function addJs($path){ |
|
| 307 | - if(in_array($path, $this->extraJs)){ |
|
| 308 | - // nothing to do |
|
| 309 | - return; |
|
| 310 | - } |
|
| 311 | - |
|
| 312 | - $this->extraJs[] = $path; |
|
| 313 | - } |
|
| 314 | - |
|
| 315 | - /** |
|
| 316 | - * Main function for this page, when no specific actions are called. |
|
| 317 | - * @return void |
|
| 318 | - */ |
|
| 319 | - abstract protected function main(); |
|
| 320 | - |
|
| 321 | - /** |
|
| 322 | - * Takes a smarty template string and sets the HTML title to that value |
|
| 323 | - * |
|
| 324 | - * @param string $title |
|
| 325 | - * |
|
| 326 | - * @throws SmartyException |
|
| 327 | - */ |
|
| 328 | - final protected function setHtmlTitle($title) |
|
| 329 | - { |
|
| 330 | - $this->htmlTitle = $this->smarty->fetch('string:' . $title); |
|
| 331 | - } |
|
| 332 | - |
|
| 333 | - public function execute() |
|
| 334 | - { |
|
| 335 | - if ($this->getRouteName() === null) { |
|
| 336 | - throw new Exception('Request is unrouted.'); |
|
| 337 | - } |
|
| 338 | - |
|
| 339 | - if ($this->getSiteConfiguration() === null) { |
|
| 340 | - throw new Exception('Page has no configuration!'); |
|
| 341 | - } |
|
| 342 | - |
|
| 343 | - $this->setupPage(); |
|
| 344 | - |
|
| 345 | - $this->runPage(); |
|
| 346 | - } |
|
| 347 | - |
|
| 348 | - public function assignCSRFToken() |
|
| 349 | - { |
|
| 350 | - $token = $this->tokenManager->getNewToken(); |
|
| 351 | - $this->assign('csrfTokenData', $token->getTokenData()); |
|
| 352 | - } |
|
| 353 | - |
|
| 354 | - public function validateCSRFToken() |
|
| 355 | - { |
|
| 356 | - if (!$this->tokenManager->validateToken(WebRequest::postString('csrfTokenData'))) { |
|
| 357 | - throw new ApplicationLogicException('Form token is not valid, please reload and try again'); |
|
| 358 | - } |
|
| 359 | - } |
|
| 360 | - |
|
| 361 | - protected function sendResponseHeaders() |
|
| 362 | - { |
|
| 363 | - if (headers_sent()) { |
|
| 364 | - throw new ApplicationLogicException('Headers have already been sent! This is likely a bug in the application.'); |
|
| 365 | - } |
|
| 366 | - |
|
| 367 | - // send the CSP headers now |
|
| 368 | - header($this->getCspManager()->getHeader()); |
|
| 369 | - |
|
| 370 | - foreach ($this->headerQueue as $item) { |
|
| 371 | - if (mb_strpos($item, "\r") !== false || mb_strpos($item, "\n") !== false) { |
|
| 372 | - // Oops. We're not allowed to do this. |
|
| 373 | - throw new Exception('Unable to split header'); |
|
| 374 | - } |
|
| 375 | - |
|
| 376 | - header($item); |
|
| 377 | - } |
|
| 378 | - } |
|
| 26 | + use TemplateOutput; |
|
| 27 | + /** @var string Smarty template to display */ |
|
| 28 | + protected $template = "base.tpl"; |
|
| 29 | + /** @var string HTML title. Currently unused. */ |
|
| 30 | + protected $htmlTitle; |
|
| 31 | + /** @var bool Determines if the page is a redirect or not */ |
|
| 32 | + protected $isRedirecting = false; |
|
| 33 | + /** @var array Queue of headers to be sent on successful completion */ |
|
| 34 | + protected $headerQueue = array(); |
|
| 35 | + /** @var string The name of the route to use, as determined by the request router. */ |
|
| 36 | + private $routeName = null; |
|
| 37 | + /** @var TokenManager */ |
|
| 38 | + protected $tokenManager; |
|
| 39 | + /** @var ContentSecurityPolicyManager */ |
|
| 40 | + private $cspManager; |
|
| 41 | + /** @var string[] Extra JS files to include */ |
|
| 42 | + private $extraJs = array(); |
|
| 43 | + |
|
| 44 | + /** |
|
| 45 | + * Sets the route the request will take. Only should be called from the request router or barrier test. |
|
| 46 | + * |
|
| 47 | + * @param string $routeName The name of the route |
|
| 48 | + * @param bool $skipCallableTest Don't use this unless you know what you're doing, and what the implications are. |
|
| 49 | + * |
|
| 50 | + * @throws Exception |
|
| 51 | + * @category Security-Critical |
|
| 52 | + */ |
|
| 53 | + final public function setRoute($routeName, $skipCallableTest = false) |
|
| 54 | + { |
|
| 55 | + // Test the new route is callable before adopting it. |
|
| 56 | + if (!$skipCallableTest && !is_callable(array($this, $routeName))) { |
|
| 57 | + throw new Exception("Proposed route '$routeName' is not callable."); |
|
| 58 | + } |
|
| 59 | + |
|
| 60 | + // Adopt the new route |
|
| 61 | + $this->routeName = $routeName; |
|
| 62 | + } |
|
| 63 | + |
|
| 64 | + /** |
|
| 65 | + * Gets the name of the route that has been passed from the request router. |
|
| 66 | + * @return string |
|
| 67 | + */ |
|
| 68 | + final public function getRouteName() |
|
| 69 | + { |
|
| 70 | + return $this->routeName; |
|
| 71 | + } |
|
| 72 | + |
|
| 73 | + /** |
|
| 74 | + * Performs generic page setup actions |
|
| 75 | + */ |
|
| 76 | + final protected function setupPage() |
|
| 77 | + { |
|
| 78 | + $this->setUpSmarty(); |
|
| 79 | + |
|
| 80 | + $currentUser = User::getCurrent($this->getDatabase()); |
|
| 81 | + $this->assign('currentUser', $currentUser); |
|
| 82 | + $this->assign('loggedIn', (!$currentUser->isCommunityUser())); |
|
| 83 | + } |
|
| 84 | + |
|
| 85 | + /** |
|
| 86 | + * Runs the page logic as routed by the RequestRouter |
|
| 87 | + * |
|
| 88 | + * Only should be called after a security barrier! That means only from execute(). |
|
| 89 | + */ |
|
| 90 | + final protected function runPage() |
|
| 91 | + { |
|
| 92 | + $database = $this->getDatabase(); |
|
| 93 | + |
|
| 94 | + // initialise a database transaction |
|
| 95 | + if (!$database->beginTransaction()) { |
|
| 96 | + throw new Exception('Failed to start transaction on primary database.'); |
|
| 97 | + } |
|
| 98 | + |
|
| 99 | + try { |
|
| 100 | + // run the page code |
|
| 101 | + $this->{$this->getRouteName()}(); |
|
| 102 | + |
|
| 103 | + $database->commit(); |
|
| 104 | + } |
|
| 105 | + catch (ApplicationLogicException $ex) { |
|
| 106 | + // it's an application logic exception, so nothing went seriously wrong with the site. We can use the |
|
| 107 | + // standard templating system for this. |
|
| 108 | + |
|
| 109 | + // Firstly, let's undo anything that happened to the database. |
|
| 110 | + $database->rollBack(); |
|
| 111 | + |
|
| 112 | + // Reset smarty |
|
| 113 | + $this->setupPage(); |
|
| 114 | + |
|
| 115 | + // Set the template |
|
| 116 | + $this->setTemplate('exception/application-logic.tpl'); |
|
| 117 | + $this->assign('message', $ex->getMessage()); |
|
| 118 | + |
|
| 119 | + // Force this back to false |
|
| 120 | + $this->isRedirecting = false; |
|
| 121 | + $this->headerQueue = array(); |
|
| 122 | + } |
|
| 123 | + catch (OptimisticLockFailedException $ex) { |
|
| 124 | + // it's an optimistic lock failure exception, so nothing went seriously wrong with the site. We can use the |
|
| 125 | + // standard templating system for this. |
|
| 126 | + |
|
| 127 | + // Firstly, let's undo anything that happened to the database. |
|
| 128 | + $database->rollBack(); |
|
| 129 | + |
|
| 130 | + // Reset smarty |
|
| 131 | + $this->setupPage(); |
|
| 132 | + |
|
| 133 | + // Set the template |
|
| 134 | + $this->setTemplate('exception/optimistic-lock-failure.tpl'); |
|
| 135 | + $this->assign('message', $ex->getMessage()); |
|
| 136 | + |
|
| 137 | + $this->assign('debugTrace', false); |
|
| 138 | + |
|
| 139 | + if ($this->getSiteConfiguration()->getDebuggingTraceEnabled()) { |
|
| 140 | + ob_start(); |
|
| 141 | + var_dump(ExceptionHandler::getExceptionData($ex)); |
|
| 142 | + $textErrorData = ob_get_contents(); |
|
| 143 | + ob_end_clean(); |
|
| 144 | + |
|
| 145 | + $this->assign('exceptionData', $textErrorData); |
|
| 146 | + $this->assign('debugTrace', true); |
|
| 147 | + } |
|
| 148 | + |
|
| 149 | + // Force this back to false |
|
| 150 | + $this->isRedirecting = false; |
|
| 151 | + $this->headerQueue = array(); |
|
| 152 | + } |
|
| 153 | + finally { |
|
| 154 | + // Catch any hanging on transactions |
|
| 155 | + if ($database->hasActiveTransaction()) { |
|
| 156 | + $database->rollBack(); |
|
| 157 | + } |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + // run any finalisation code needed before we send the output to the browser. |
|
| 161 | + $this->finalisePage(); |
|
| 162 | + |
|
| 163 | + // Send the headers |
|
| 164 | + $this->sendResponseHeaders(); |
|
| 165 | + |
|
| 166 | + // Check we have a template to use! |
|
| 167 | + if ($this->template !== null) { |
|
| 168 | + $content = $this->fetchTemplate($this->template); |
|
| 169 | + ob_clean(); |
|
| 170 | + print($content); |
|
| 171 | + ob_flush(); |
|
| 172 | + |
|
| 173 | + return; |
|
| 174 | + } |
|
| 175 | + } |
|
| 176 | + |
|
| 177 | + /** |
|
| 178 | + * Performs final tasks needed before rendering the page. |
|
| 179 | + */ |
|
| 180 | + protected function finalisePage() |
|
| 181 | + { |
|
| 182 | + if ($this->isRedirecting) { |
|
| 183 | + $this->template = null; |
|
| 184 | + |
|
| 185 | + return; |
|
| 186 | + } |
|
| 187 | + |
|
| 188 | + $this->assign('extraJs', $this->extraJs); |
|
| 189 | + |
|
| 190 | + // If we're actually displaying content, we want to add the session alerts here! |
|
| 191 | + $this->assign('alerts', SessionAlert::getAlerts()); |
|
| 192 | + SessionAlert::clearAlerts(); |
|
| 193 | + |
|
| 194 | + $this->assign('htmlTitle', $this->htmlTitle); |
|
| 195 | + } |
|
| 196 | + |
|
| 197 | + /** |
|
| 198 | + * @return TokenManager |
|
| 199 | + */ |
|
| 200 | + public function getTokenManager() |
|
| 201 | + { |
|
| 202 | + return $this->tokenManager; |
|
| 203 | + } |
|
| 204 | + |
|
| 205 | + /** |
|
| 206 | + * @param TokenManager $tokenManager |
|
| 207 | + */ |
|
| 208 | + public function setTokenManager($tokenManager) |
|
| 209 | + { |
|
| 210 | + $this->tokenManager = $tokenManager; |
|
| 211 | + } |
|
| 212 | + |
|
| 213 | + /** |
|
| 214 | + * @return ContentSecurityPolicyManager |
|
| 215 | + */ |
|
| 216 | + public function getCspManager(): ContentSecurityPolicyManager |
|
| 217 | + { |
|
| 218 | + return $this->cspManager; |
|
| 219 | + } |
|
| 220 | + |
|
| 221 | + /** |
|
| 222 | + * @param ContentSecurityPolicyManager $cspManager |
|
| 223 | + */ |
|
| 224 | + public function setCspManager(ContentSecurityPolicyManager $cspManager): void |
|
| 225 | + { |
|
| 226 | + $this->cspManager = $cspManager; |
|
| 227 | + } |
|
| 228 | + |
|
| 229 | + /** |
|
| 230 | + * Sends the redirect headers to perform a GET at the destination page. |
|
| 231 | + * |
|
| 232 | + * Also nullifies the set template so Smarty does not render it. |
|
| 233 | + * |
|
| 234 | + * @param string $page The page to redirect requests to (as used in the UR) |
|
| 235 | + * @param null|string $action The action to use on the page. |
|
| 236 | + * @param null|array $parameters |
|
| 237 | + * @param null|string $script The script (relative to index.php) to redirect to |
|
| 238 | + */ |
|
| 239 | + final protected function redirect($page = '', $action = null, $parameters = null, $script = null) |
|
| 240 | + { |
|
| 241 | + $currentScriptName = WebRequest::scriptName(); |
|
| 242 | + |
|
| 243 | + // Are we changing script? |
|
| 244 | + if ($script === null || substr($currentScriptName, -1 * count($script)) === $script) { |
|
| 245 | + $targetScriptName = $currentScriptName; |
|
| 246 | + } |
|
| 247 | + else { |
|
| 248 | + $targetScriptName = $this->getSiteConfiguration()->getBaseUrl() . '/' . $script; |
|
| 249 | + } |
|
| 250 | + |
|
| 251 | + $pathInfo = array($targetScriptName); |
|
| 252 | + |
|
| 253 | + $pathInfo[1] = $page; |
|
| 254 | + |
|
| 255 | + if ($action !== null) { |
|
| 256 | + $pathInfo[2] = $action; |
|
| 257 | + } |
|
| 258 | + |
|
| 259 | + $url = implode('/', $pathInfo); |
|
| 260 | + |
|
| 261 | + if (is_array($parameters) && count($parameters) > 0) { |
|
| 262 | + $url .= '?' . http_build_query($parameters); |
|
| 263 | + } |
|
| 264 | + |
|
| 265 | + $this->redirectUrl($url); |
|
| 266 | + } |
|
| 267 | + |
|
| 268 | + /** |
|
| 269 | + * Sends the redirect headers to perform a GET at the new address. |
|
| 270 | + * |
|
| 271 | + * Also nullifies the set template so Smarty does not render it. |
|
| 272 | + * |
|
| 273 | + * @param string $path URL to redirect to |
|
| 274 | + */ |
|
| 275 | + final protected function redirectUrl($path) |
|
| 276 | + { |
|
| 277 | + // 303 See Other = re-request at new address with a GET. |
|
| 278 | + $this->headerQueue[] = 'HTTP/1.1 303 See Other'; |
|
| 279 | + $this->headerQueue[] = "Location: $path"; |
|
| 280 | + |
|
| 281 | + $this->setTemplate(null); |
|
| 282 | + $this->isRedirecting = true; |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + /** |
|
| 286 | + * Sets the name of the template this page should display. |
|
| 287 | + * |
|
| 288 | + * @param string $name |
|
| 289 | + * |
|
| 290 | + * @throws Exception |
|
| 291 | + */ |
|
| 292 | + final protected function setTemplate($name) |
|
| 293 | + { |
|
| 294 | + if ($this->isRedirecting) { |
|
| 295 | + throw new Exception('This page has been set as a redirect, no template can be displayed!'); |
|
| 296 | + } |
|
| 297 | + |
|
| 298 | + $this->template = $name; |
|
| 299 | + } |
|
| 300 | + |
|
| 301 | + /** |
|
| 302 | + * Adds an extra JS file to to the page |
|
| 303 | + * |
|
| 304 | + * @param string $path The path (relative to the application root) of the file |
|
| 305 | + */ |
|
| 306 | + final protected function addJs($path){ |
|
| 307 | + if(in_array($path, $this->extraJs)){ |
|
| 308 | + // nothing to do |
|
| 309 | + return; |
|
| 310 | + } |
|
| 311 | + |
|
| 312 | + $this->extraJs[] = $path; |
|
| 313 | + } |
|
| 314 | + |
|
| 315 | + /** |
|
| 316 | + * Main function for this page, when no specific actions are called. |
|
| 317 | + * @return void |
|
| 318 | + */ |
|
| 319 | + abstract protected function main(); |
|
| 320 | + |
|
| 321 | + /** |
|
| 322 | + * Takes a smarty template string and sets the HTML title to that value |
|
| 323 | + * |
|
| 324 | + * @param string $title |
|
| 325 | + * |
|
| 326 | + * @throws SmartyException |
|
| 327 | + */ |
|
| 328 | + final protected function setHtmlTitle($title) |
|
| 329 | + { |
|
| 330 | + $this->htmlTitle = $this->smarty->fetch('string:' . $title); |
|
| 331 | + } |
|
| 332 | + |
|
| 333 | + public function execute() |
|
| 334 | + { |
|
| 335 | + if ($this->getRouteName() === null) { |
|
| 336 | + throw new Exception('Request is unrouted.'); |
|
| 337 | + } |
|
| 338 | + |
|
| 339 | + if ($this->getSiteConfiguration() === null) { |
|
| 340 | + throw new Exception('Page has no configuration!'); |
|
| 341 | + } |
|
| 342 | + |
|
| 343 | + $this->setupPage(); |
|
| 344 | + |
|
| 345 | + $this->runPage(); |
|
| 346 | + } |
|
| 347 | + |
|
| 348 | + public function assignCSRFToken() |
|
| 349 | + { |
|
| 350 | + $token = $this->tokenManager->getNewToken(); |
|
| 351 | + $this->assign('csrfTokenData', $token->getTokenData()); |
|
| 352 | + } |
|
| 353 | + |
|
| 354 | + public function validateCSRFToken() |
|
| 355 | + { |
|
| 356 | + if (!$this->tokenManager->validateToken(WebRequest::postString('csrfTokenData'))) { |
|
| 357 | + throw new ApplicationLogicException('Form token is not valid, please reload and try again'); |
|
| 358 | + } |
|
| 359 | + } |
|
| 360 | + |
|
| 361 | + protected function sendResponseHeaders() |
|
| 362 | + { |
|
| 363 | + if (headers_sent()) { |
|
| 364 | + throw new ApplicationLogicException('Headers have already been sent! This is likely a bug in the application.'); |
|
| 365 | + } |
|
| 366 | + |
|
| 367 | + // send the CSP headers now |
|
| 368 | + header($this->getCspManager()->getHeader()); |
|
| 369 | + |
|
| 370 | + foreach ($this->headerQueue as $item) { |
|
| 371 | + if (mb_strpos($item, "\r") !== false || mb_strpos($item, "\n") !== false) { |
|
| 372 | + // Oops. We're not allowed to do this. |
|
| 373 | + throw new Exception('Unable to split header'); |
|
| 374 | + } |
|
| 375 | + |
|
| 376 | + header($item); |
|
| 377 | + } |
|
| 378 | + } |
|
| 379 | 379 | } |
@@ -15,93 +15,93 @@ |
||
| 15 | 15 | |
| 16 | 16 | trait TemplateOutput |
| 17 | 17 | { |
| 18 | - /** @var Smarty */ |
|
| 19 | - private $smarty; |
|
| 20 | - /** @var string Extra JavaScript to include at the end of the page's execution */ |
|
| 21 | - private $tailScript; |
|
| 22 | - /** @var string */ |
|
| 23 | - private $tailScriptNonce; |
|
| 18 | + /** @var Smarty */ |
|
| 19 | + private $smarty; |
|
| 20 | + /** @var string Extra JavaScript to include at the end of the page's execution */ |
|
| 21 | + private $tailScript; |
|
| 22 | + /** @var string */ |
|
| 23 | + private $tailScriptNonce; |
|
| 24 | 24 | |
| 25 | - /** |
|
| 26 | - * @return SiteConfiguration |
|
| 27 | - */ |
|
| 28 | - protected abstract function getSiteConfiguration(); |
|
| 25 | + /** |
|
| 26 | + * @return SiteConfiguration |
|
| 27 | + */ |
|
| 28 | + protected abstract function getSiteConfiguration(); |
|
| 29 | 29 | |
| 30 | - /** |
|
| 31 | - * Include extra JavaScript at the end of the page's execution |
|
| 32 | - * |
|
| 33 | - * @param $nonce string CSP Nonce generated by ContentSecurityPolicyManager::getNonce() |
|
| 34 | - * @param $script string JavaScript to include at the end of the page |
|
| 35 | - */ |
|
| 36 | - final protected function setTailScript($nonce, $script) |
|
| 37 | - { |
|
| 38 | - $this->tailScriptNonce = $nonce; |
|
| 39 | - $this->tailScript = $script; |
|
| 40 | - } |
|
| 30 | + /** |
|
| 31 | + * Include extra JavaScript at the end of the page's execution |
|
| 32 | + * |
|
| 33 | + * @param $nonce string CSP Nonce generated by ContentSecurityPolicyManager::getNonce() |
|
| 34 | + * @param $script string JavaScript to include at the end of the page |
|
| 35 | + */ |
|
| 36 | + final protected function setTailScript($nonce, $script) |
|
| 37 | + { |
|
| 38 | + $this->tailScriptNonce = $nonce; |
|
| 39 | + $this->tailScript = $script; |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * Assigns a Smarty variable |
|
| 44 | - * |
|
| 45 | - * @param array|string $name the template variable name(s) |
|
| 46 | - * @param mixed $value the value to assign |
|
| 47 | - */ |
|
| 48 | - final protected function assign($name, $value) |
|
| 49 | - { |
|
| 50 | - $this->smarty->assign($name, $value); |
|
| 51 | - } |
|
| 42 | + /** |
|
| 43 | + * Assigns a Smarty variable |
|
| 44 | + * |
|
| 45 | + * @param array|string $name the template variable name(s) |
|
| 46 | + * @param mixed $value the value to assign |
|
| 47 | + */ |
|
| 48 | + final protected function assign($name, $value) |
|
| 49 | + { |
|
| 50 | + $this->smarty->assign($name, $value); |
|
| 51 | + } |
|
| 52 | 52 | |
| 53 | - /** |
|
| 54 | - * Sets up the variables used by the main Smarty base template. |
|
| 55 | - * |
|
| 56 | - * This list is getting kinda long. |
|
| 57 | - */ |
|
| 58 | - final protected function setUpSmarty() |
|
| 59 | - { |
|
| 60 | - $this->smarty = new Smarty(); |
|
| 61 | - $this->smarty->addPluginsDir($this->getSiteConfiguration()->getFilePath() . '/smarty-plugins'); |
|
| 53 | + /** |
|
| 54 | + * Sets up the variables used by the main Smarty base template. |
|
| 55 | + * |
|
| 56 | + * This list is getting kinda long. |
|
| 57 | + */ |
|
| 58 | + final protected function setUpSmarty() |
|
| 59 | + { |
|
| 60 | + $this->smarty = new Smarty(); |
|
| 61 | + $this->smarty->addPluginsDir($this->getSiteConfiguration()->getFilePath() . '/smarty-plugins'); |
|
| 62 | 62 | |
| 63 | - $this->assign('currentUser', User::getCommunity()); |
|
| 64 | - $this->assign('loggedIn', false); |
|
| 65 | - $this->assign('baseurl', $this->getSiteConfiguration()->getBaseUrl()); |
|
| 66 | - $this->assign('mediawikiScriptPath', $this->getSiteConfiguration()->getMediawikiScriptPath()); |
|
| 63 | + $this->assign('currentUser', User::getCommunity()); |
|
| 64 | + $this->assign('loggedIn', false); |
|
| 65 | + $this->assign('baseurl', $this->getSiteConfiguration()->getBaseUrl()); |
|
| 66 | + $this->assign('mediawikiScriptPath', $this->getSiteConfiguration()->getMediawikiScriptPath()); |
|
| 67 | 67 | |
| 68 | - $this->assign('siteNoticeText', ''); |
|
| 69 | - $this->assign('toolversion', Environment::getToolVersion()); |
|
| 68 | + $this->assign('siteNoticeText', ''); |
|
| 69 | + $this->assign('toolversion', Environment::getToolVersion()); |
|
| 70 | 70 | |
| 71 | - // default these |
|
| 72 | - $this->assign('onlineusers', array()); |
|
| 73 | - $this->assign('typeAheadBlock', ''); |
|
| 74 | - $this->assign('extraJs', array()); |
|
| 71 | + // default these |
|
| 72 | + $this->assign('onlineusers', array()); |
|
| 73 | + $this->assign('typeAheadBlock', ''); |
|
| 74 | + $this->assign('extraJs', array()); |
|
| 75 | 75 | |
| 76 | - // nav menu access control |
|
| 77 | - $this->assign('nav__canRequests', false); |
|
| 78 | - $this->assign('nav__canLogs', false); |
|
| 79 | - $this->assign('nav__canUsers', false); |
|
| 80 | - $this->assign('nav__canSearch', false); |
|
| 81 | - $this->assign('nav__canStats', false); |
|
| 82 | - $this->assign('nav__canBan', false); |
|
| 83 | - $this->assign('nav__canEmailMgmt', false); |
|
| 84 | - $this->assign('nav__canWelcomeMgmt', false); |
|
| 85 | - $this->assign('nav__canSiteNoticeMgmt', false); |
|
| 86 | - $this->assign('nav__canUserMgmt', false); |
|
| 87 | - $this->assign('nav__canViewRequest', false); |
|
| 88 | - $this->assign('nav__canJobQueue', false); |
|
| 76 | + // nav menu access control |
|
| 77 | + $this->assign('nav__canRequests', false); |
|
| 78 | + $this->assign('nav__canLogs', false); |
|
| 79 | + $this->assign('nav__canUsers', false); |
|
| 80 | + $this->assign('nav__canSearch', false); |
|
| 81 | + $this->assign('nav__canStats', false); |
|
| 82 | + $this->assign('nav__canBan', false); |
|
| 83 | + $this->assign('nav__canEmailMgmt', false); |
|
| 84 | + $this->assign('nav__canWelcomeMgmt', false); |
|
| 85 | + $this->assign('nav__canSiteNoticeMgmt', false); |
|
| 86 | + $this->assign('nav__canUserMgmt', false); |
|
| 87 | + $this->assign('nav__canViewRequest', false); |
|
| 88 | + $this->assign('nav__canJobQueue', false); |
|
| 89 | 89 | |
| 90 | - $this->assign('page', $this); |
|
| 91 | - } |
|
| 90 | + $this->assign('page', $this); |
|
| 91 | + } |
|
| 92 | 92 | |
| 93 | - /** |
|
| 94 | - * Fetches a rendered Smarty template |
|
| 95 | - * |
|
| 96 | - * @param $template string Template file path, relative to /templates/ |
|
| 97 | - * |
|
| 98 | - * @return string Templated HTML |
|
| 99 | - */ |
|
| 100 | - final protected function fetchTemplate($template) |
|
| 101 | - { |
|
| 102 | - $this->assign('tailScript', $this->tailScript); |
|
| 103 | - $this->assign('tailScriptNonce', $this->tailScriptNonce); |
|
| 93 | + /** |
|
| 94 | + * Fetches a rendered Smarty template |
|
| 95 | + * |
|
| 96 | + * @param $template string Template file path, relative to /templates/ |
|
| 97 | + * |
|
| 98 | + * @return string Templated HTML |
|
| 99 | + */ |
|
| 100 | + final protected function fetchTemplate($template) |
|
| 101 | + { |
|
| 102 | + $this->assign('tailScript', $this->tailScript); |
|
| 103 | + $this->assign('tailScriptNonce', $this->tailScriptNonce); |
|
| 104 | 104 | |
| 105 | - return $this->smarty->fetch($template); |
|
| 106 | - } |
|
| 105 | + return $this->smarty->fetch($template); |
|
| 106 | + } |
|
| 107 | 107 | } |
@@ -16,73 +16,73 @@ |
||
| 16 | 16 | */ |
| 17 | 17 | function smarty_modifier_relativedate($input) |
| 18 | 18 | { |
| 19 | - $now = new DateTime(); |
|
| 19 | + $now = new DateTime(); |
|
| 20 | 20 | |
| 21 | - if (gettype($input) === 'object' |
|
| 22 | - && (get_class($input) === DateTime::class || get_class($input) === DateTimeImmutable::class) |
|
| 23 | - ) { |
|
| 24 | - $then = $input; |
|
| 25 | - } |
|
| 26 | - else { |
|
| 27 | - try { |
|
| 28 | - $then = new DateTime($input); |
|
| 29 | - } |
|
| 30 | - catch(Exception $ex) { |
|
| 31 | - return $input; |
|
| 32 | - } |
|
| 33 | - } |
|
| 21 | + if (gettype($input) === 'object' |
|
| 22 | + && (get_class($input) === DateTime::class || get_class($input) === DateTimeImmutable::class) |
|
| 23 | + ) { |
|
| 24 | + $then = $input; |
|
| 25 | + } |
|
| 26 | + else { |
|
| 27 | + try { |
|
| 28 | + $then = new DateTime($input); |
|
| 29 | + } |
|
| 30 | + catch(Exception $ex) { |
|
| 31 | + return $input; |
|
| 32 | + } |
|
| 33 | + } |
|
| 34 | 34 | |
| 35 | - $secs = $now->getTimestamp() - $then->getTimestamp(); |
|
| 35 | + $secs = $now->getTimestamp() - $then->getTimestamp(); |
|
| 36 | 36 | |
| 37 | - $second = 1; |
|
| 38 | - $minute = 60 * $second; |
|
| 39 | - $minuteCut = 60 * $second; |
|
| 40 | - $hour = 60 * $minute; |
|
| 41 | - $hourCut = 90 * $minute; |
|
| 42 | - $day = 24 * $hour; |
|
| 43 | - $dayCut = 48 * $hour; |
|
| 44 | - $week = 7 * $day; |
|
| 45 | - $weekCut = 14 * $day; |
|
| 46 | - $month = 30 * $day; |
|
| 47 | - $monthCut = 60 * $day; |
|
| 48 | - $year = 365 * $day; |
|
| 49 | - $yearCut = $year * 2; |
|
| 37 | + $second = 1; |
|
| 38 | + $minute = 60 * $second; |
|
| 39 | + $minuteCut = 60 * $second; |
|
| 40 | + $hour = 60 * $minute; |
|
| 41 | + $hourCut = 90 * $minute; |
|
| 42 | + $day = 24 * $hour; |
|
| 43 | + $dayCut = 48 * $hour; |
|
| 44 | + $week = 7 * $day; |
|
| 45 | + $weekCut = 14 * $day; |
|
| 46 | + $month = 30 * $day; |
|
| 47 | + $monthCut = 60 * $day; |
|
| 48 | + $year = 365 * $day; |
|
| 49 | + $yearCut = $year * 2; |
|
| 50 | 50 | |
| 51 | - $pluralise = true; |
|
| 51 | + $pluralise = true; |
|
| 52 | 52 | |
| 53 | - if ($secs <= 10) { |
|
| 54 | - $output = "just now"; |
|
| 55 | - $pluralise = false; |
|
| 56 | - } |
|
| 57 | - elseif ($secs > 10 && $secs < $minuteCut) { |
|
| 58 | - $output = round($secs / $second) . " second"; |
|
| 59 | - } |
|
| 60 | - elseif ($secs >= $minuteCut && $secs < $hourCut) { |
|
| 61 | - $output = round($secs / $minute) . " minute"; |
|
| 62 | - } |
|
| 63 | - elseif ($secs >= $hourCut && $secs < $dayCut) { |
|
| 64 | - $output = round($secs / $hour) . " hour"; |
|
| 65 | - } |
|
| 66 | - elseif ($secs >= $dayCut && $secs < $weekCut) { |
|
| 67 | - $output = round($secs / $day) . " day"; |
|
| 68 | - } |
|
| 69 | - elseif ($secs >= $weekCut && $secs < $monthCut) { |
|
| 70 | - $output = round($secs / $week) . " week"; |
|
| 71 | - } |
|
| 72 | - elseif ($secs >= $monthCut && $secs < $yearCut) { |
|
| 73 | - $output = round($secs / $month) . " month"; |
|
| 74 | - } |
|
| 75 | - elseif ($secs >= $yearCut && $secs < $year * 10) { |
|
| 76 | - $output = round($secs / $year) . " year"; |
|
| 77 | - } |
|
| 78 | - else { |
|
| 79 | - $output = "a long time ago"; |
|
| 80 | - $pluralise = false; |
|
| 81 | - } |
|
| 53 | + if ($secs <= 10) { |
|
| 54 | + $output = "just now"; |
|
| 55 | + $pluralise = false; |
|
| 56 | + } |
|
| 57 | + elseif ($secs > 10 && $secs < $minuteCut) { |
|
| 58 | + $output = round($secs / $second) . " second"; |
|
| 59 | + } |
|
| 60 | + elseif ($secs >= $minuteCut && $secs < $hourCut) { |
|
| 61 | + $output = round($secs / $minute) . " minute"; |
|
| 62 | + } |
|
| 63 | + elseif ($secs >= $hourCut && $secs < $dayCut) { |
|
| 64 | + $output = round($secs / $hour) . " hour"; |
|
| 65 | + } |
|
| 66 | + elseif ($secs >= $dayCut && $secs < $weekCut) { |
|
| 67 | + $output = round($secs / $day) . " day"; |
|
| 68 | + } |
|
| 69 | + elseif ($secs >= $weekCut && $secs < $monthCut) { |
|
| 70 | + $output = round($secs / $week) . " week"; |
|
| 71 | + } |
|
| 72 | + elseif ($secs >= $monthCut && $secs < $yearCut) { |
|
| 73 | + $output = round($secs / $month) . " month"; |
|
| 74 | + } |
|
| 75 | + elseif ($secs >= $yearCut && $secs < $year * 10) { |
|
| 76 | + $output = round($secs / $year) . " year"; |
|
| 77 | + } |
|
| 78 | + else { |
|
| 79 | + $output = "a long time ago"; |
|
| 80 | + $pluralise = false; |
|
| 81 | + } |
|
| 82 | 82 | |
| 83 | - if ($pluralise) { |
|
| 84 | - $output = (substr($output, 0, 2) <> "1 ") ? $output . "s ago" : $output . " ago"; |
|
| 85 | - } |
|
| 83 | + if ($pluralise) { |
|
| 84 | + $output = (substr($output, 0, 2) <> "1 ") ? $output . "s ago" : $output . " ago"; |
|
| 85 | + } |
|
| 86 | 86 | |
| 87 | - return $output; |
|
| 87 | + return $output; |
|
| 88 | 88 | } |
@@ -27,7 +27,7 @@ discard block |
||
| 27 | 27 | try { |
| 28 | 28 | $then = new DateTime($input); |
| 29 | 29 | } |
| 30 | - catch(Exception $ex) { |
|
| 30 | + catch (Exception $ex) { |
|
| 31 | 31 | return $input; |
| 32 | 32 | } |
| 33 | 33 | } |
@@ -55,25 +55,25 @@ discard block |
||
| 55 | 55 | $pluralise = false; |
| 56 | 56 | } |
| 57 | 57 | elseif ($secs > 10 && $secs < $minuteCut) { |
| 58 | - $output = round($secs / $second) . " second"; |
|
| 58 | + $output = round($secs / $second)." second"; |
|
| 59 | 59 | } |
| 60 | 60 | elseif ($secs >= $minuteCut && $secs < $hourCut) { |
| 61 | - $output = round($secs / $minute) . " minute"; |
|
| 61 | + $output = round($secs / $minute)." minute"; |
|
| 62 | 62 | } |
| 63 | 63 | elseif ($secs >= $hourCut && $secs < $dayCut) { |
| 64 | - $output = round($secs / $hour) . " hour"; |
|
| 64 | + $output = round($secs / $hour)." hour"; |
|
| 65 | 65 | } |
| 66 | 66 | elseif ($secs >= $dayCut && $secs < $weekCut) { |
| 67 | - $output = round($secs / $day) . " day"; |
|
| 67 | + $output = round($secs / $day)." day"; |
|
| 68 | 68 | } |
| 69 | 69 | elseif ($secs >= $weekCut && $secs < $monthCut) { |
| 70 | - $output = round($secs / $week) . " week"; |
|
| 70 | + $output = round($secs / $week)." week"; |
|
| 71 | 71 | } |
| 72 | 72 | elseif ($secs >= $monthCut && $secs < $yearCut) { |
| 73 | - $output = round($secs / $month) . " month"; |
|
| 73 | + $output = round($secs / $month)." month"; |
|
| 74 | 74 | } |
| 75 | 75 | elseif ($secs >= $yearCut && $secs < $year * 10) { |
| 76 | - $output = round($secs / $year) . " year"; |
|
| 76 | + $output = round($secs / $year)." year"; |
|
| 77 | 77 | } |
| 78 | 78 | else { |
| 79 | 79 | $output = "a long time ago"; |
@@ -81,7 +81,7 @@ discard block |
||
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | if ($pluralise) { |
| 84 | - $output = (substr($output, 0, 2) <> "1 ") ? $output . "s ago" : $output . " ago"; |
|
| 84 | + $output = (substr($output, 0, 2) <> "1 ") ? $output."s ago" : $output." ago"; |
|
| 85 | 85 | } |
| 86 | 86 | |
| 87 | 87 | return $output; |
@@ -21,160 +21,160 @@ discard block |
||
| 21 | 21 | */ |
| 22 | 22 | class User extends DataObject |
| 23 | 23 | { |
| 24 | - const STATUS_ACTIVE = 'Active'; |
|
| 25 | - const STATUS_SUSPENDED = 'Suspended'; |
|
| 26 | - const STATUS_DECLINED = 'Declined'; |
|
| 27 | - const STATUS_NEW = 'New'; |
|
| 28 | - const CREATION_MANUAL = 0; |
|
| 29 | - const CREATION_OAUTH = 1; |
|
| 30 | - const CREATION_BOT = 2; |
|
| 31 | - private $username; |
|
| 32 | - private $email; |
|
| 33 | - private $status = self::STATUS_NEW; |
|
| 34 | - private $onwikiname; |
|
| 35 | - private $welcome_sig = ""; |
|
| 36 | - private $lastactive = "0000-00-00 00:00:00"; |
|
| 37 | - private $forcelogout = 0; |
|
| 38 | - private $forceidentified = null; |
|
| 39 | - private $welcome_template = 0; |
|
| 40 | - private $abortpref = 0; |
|
| 41 | - private $confirmationdiff = 0; |
|
| 42 | - private $emailsig = ""; |
|
| 43 | - private $creationmode = 0; |
|
| 44 | - private $skin = "main"; |
|
| 45 | - /** @var User Cache variable of the current user - it's never going to change in the middle of a request. */ |
|
| 46 | - private static $currentUser; |
|
| 47 | - #region Object load methods |
|
| 48 | - |
|
| 49 | - /** |
|
| 50 | - * Gets the currently logged in user |
|
| 51 | - * |
|
| 52 | - * @param PdoDatabase $database |
|
| 53 | - * |
|
| 54 | - * @return User|CommunityUser |
|
| 55 | - */ |
|
| 56 | - public static function getCurrent(PdoDatabase $database) |
|
| 57 | - { |
|
| 58 | - if (self::$currentUser === null) { |
|
| 59 | - $sessionId = WebRequest::getSessionUserId(); |
|
| 60 | - |
|
| 61 | - if ($sessionId !== null) { |
|
| 62 | - /** @var User $user */ |
|
| 63 | - $user = self::getById($sessionId, $database); |
|
| 64 | - |
|
| 65 | - if ($user === false) { |
|
| 66 | - self::$currentUser = new CommunityUser(); |
|
| 67 | - } |
|
| 68 | - else { |
|
| 69 | - self::$currentUser = $user; |
|
| 70 | - } |
|
| 71 | - } |
|
| 72 | - else { |
|
| 73 | - $anonymousCoward = new CommunityUser(); |
|
| 74 | - |
|
| 75 | - self::$currentUser = $anonymousCoward; |
|
| 76 | - } |
|
| 77 | - } |
|
| 78 | - |
|
| 79 | - return self::$currentUser; |
|
| 80 | - } |
|
| 81 | - |
|
| 82 | - /** |
|
| 83 | - * Gets a user by their user ID |
|
| 84 | - * |
|
| 85 | - * Pass -1 to get the community user. |
|
| 86 | - * |
|
| 87 | - * @param int|null $id |
|
| 88 | - * @param PdoDatabase $database |
|
| 89 | - * |
|
| 90 | - * @return User|false |
|
| 91 | - */ |
|
| 92 | - public static function getById($id, PdoDatabase $database) |
|
| 93 | - { |
|
| 94 | - if ($id === null || $id == -1) { |
|
| 95 | - return new CommunityUser(); |
|
| 96 | - } |
|
| 97 | - |
|
| 98 | - /** @var User|false $user */ |
|
| 99 | - $user = parent::getById($id, $database); |
|
| 100 | - |
|
| 101 | - return $user; |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | - /** |
|
| 105 | - * @return CommunityUser |
|
| 106 | - */ |
|
| 107 | - public static function getCommunity() |
|
| 108 | - { |
|
| 109 | - return new CommunityUser(); |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - /** |
|
| 113 | - * Gets a user by their username |
|
| 114 | - * |
|
| 115 | - * @param string $username |
|
| 116 | - * @param PdoDatabase $database |
|
| 117 | - * |
|
| 118 | - * @return CommunityUser|User|false |
|
| 119 | - */ |
|
| 120 | - public static function getByUsername($username, PdoDatabase $database) |
|
| 121 | - { |
|
| 122 | - global $communityUsername; |
|
| 123 | - if ($username == $communityUsername) { |
|
| 124 | - return new CommunityUser(); |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - $statement = $database->prepare("SELECT * FROM user WHERE username = :id LIMIT 1;"); |
|
| 128 | - $statement->bindValue(":id", $username); |
|
| 129 | - |
|
| 130 | - $statement->execute(); |
|
| 131 | - |
|
| 132 | - $resultObject = $statement->fetchObject(get_called_class()); |
|
| 133 | - |
|
| 134 | - if ($resultObject != false) { |
|
| 135 | - $resultObject->setDatabase($database); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - return $resultObject; |
|
| 139 | - } |
|
| 140 | - |
|
| 141 | - /** |
|
| 142 | - * Gets a user by their on-wiki username. |
|
| 143 | - * |
|
| 144 | - * @param string $username |
|
| 145 | - * @param PdoDatabase $database |
|
| 146 | - * |
|
| 147 | - * @return User|false |
|
| 148 | - */ |
|
| 149 | - public static function getByOnWikiUsername($username, PdoDatabase $database) |
|
| 150 | - { |
|
| 151 | - $statement = $database->prepare("SELECT * FROM user WHERE onwikiname = :id LIMIT 1;"); |
|
| 152 | - $statement->bindValue(":id", $username); |
|
| 153 | - $statement->execute(); |
|
| 154 | - |
|
| 155 | - $resultObject = $statement->fetchObject(get_called_class()); |
|
| 156 | - |
|
| 157 | - if ($resultObject != false) { |
|
| 158 | - $resultObject->setDatabase($database); |
|
| 159 | - |
|
| 160 | - return $resultObject; |
|
| 161 | - } |
|
| 162 | - |
|
| 163 | - return false; |
|
| 164 | - } |
|
| 165 | - |
|
| 166 | - #endregion |
|
| 167 | - |
|
| 168 | - /** |
|
| 169 | - * Saves the current object |
|
| 170 | - * |
|
| 171 | - * @throws Exception |
|
| 172 | - */ |
|
| 173 | - public function save() |
|
| 174 | - { |
|
| 175 | - if ($this->isNew()) { |
|
| 176 | - // insert |
|
| 177 | - $statement = $this->dbObject->prepare(<<<SQL |
|
| 24 | + const STATUS_ACTIVE = 'Active'; |
|
| 25 | + const STATUS_SUSPENDED = 'Suspended'; |
|
| 26 | + const STATUS_DECLINED = 'Declined'; |
|
| 27 | + const STATUS_NEW = 'New'; |
|
| 28 | + const CREATION_MANUAL = 0; |
|
| 29 | + const CREATION_OAUTH = 1; |
|
| 30 | + const CREATION_BOT = 2; |
|
| 31 | + private $username; |
|
| 32 | + private $email; |
|
| 33 | + private $status = self::STATUS_NEW; |
|
| 34 | + private $onwikiname; |
|
| 35 | + private $welcome_sig = ""; |
|
| 36 | + private $lastactive = "0000-00-00 00:00:00"; |
|
| 37 | + private $forcelogout = 0; |
|
| 38 | + private $forceidentified = null; |
|
| 39 | + private $welcome_template = 0; |
|
| 40 | + private $abortpref = 0; |
|
| 41 | + private $confirmationdiff = 0; |
|
| 42 | + private $emailsig = ""; |
|
| 43 | + private $creationmode = 0; |
|
| 44 | + private $skin = "main"; |
|
| 45 | + /** @var User Cache variable of the current user - it's never going to change in the middle of a request. */ |
|
| 46 | + private static $currentUser; |
|
| 47 | + #region Object load methods |
|
| 48 | + |
|
| 49 | + /** |
|
| 50 | + * Gets the currently logged in user |
|
| 51 | + * |
|
| 52 | + * @param PdoDatabase $database |
|
| 53 | + * |
|
| 54 | + * @return User|CommunityUser |
|
| 55 | + */ |
|
| 56 | + public static function getCurrent(PdoDatabase $database) |
|
| 57 | + { |
|
| 58 | + if (self::$currentUser === null) { |
|
| 59 | + $sessionId = WebRequest::getSessionUserId(); |
|
| 60 | + |
|
| 61 | + if ($sessionId !== null) { |
|
| 62 | + /** @var User $user */ |
|
| 63 | + $user = self::getById($sessionId, $database); |
|
| 64 | + |
|
| 65 | + if ($user === false) { |
|
| 66 | + self::$currentUser = new CommunityUser(); |
|
| 67 | + } |
|
| 68 | + else { |
|
| 69 | + self::$currentUser = $user; |
|
| 70 | + } |
|
| 71 | + } |
|
| 72 | + else { |
|
| 73 | + $anonymousCoward = new CommunityUser(); |
|
| 74 | + |
|
| 75 | + self::$currentUser = $anonymousCoward; |
|
| 76 | + } |
|
| 77 | + } |
|
| 78 | + |
|
| 79 | + return self::$currentUser; |
|
| 80 | + } |
|
| 81 | + |
|
| 82 | + /** |
|
| 83 | + * Gets a user by their user ID |
|
| 84 | + * |
|
| 85 | + * Pass -1 to get the community user. |
|
| 86 | + * |
|
| 87 | + * @param int|null $id |
|
| 88 | + * @param PdoDatabase $database |
|
| 89 | + * |
|
| 90 | + * @return User|false |
|
| 91 | + */ |
|
| 92 | + public static function getById($id, PdoDatabase $database) |
|
| 93 | + { |
|
| 94 | + if ($id === null || $id == -1) { |
|
| 95 | + return new CommunityUser(); |
|
| 96 | + } |
|
| 97 | + |
|
| 98 | + /** @var User|false $user */ |
|
| 99 | + $user = parent::getById($id, $database); |
|
| 100 | + |
|
| 101 | + return $user; |
|
| 102 | + } |
|
| 103 | + |
|
| 104 | + /** |
|
| 105 | + * @return CommunityUser |
|
| 106 | + */ |
|
| 107 | + public static function getCommunity() |
|
| 108 | + { |
|
| 109 | + return new CommunityUser(); |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + /** |
|
| 113 | + * Gets a user by their username |
|
| 114 | + * |
|
| 115 | + * @param string $username |
|
| 116 | + * @param PdoDatabase $database |
|
| 117 | + * |
|
| 118 | + * @return CommunityUser|User|false |
|
| 119 | + */ |
|
| 120 | + public static function getByUsername($username, PdoDatabase $database) |
|
| 121 | + { |
|
| 122 | + global $communityUsername; |
|
| 123 | + if ($username == $communityUsername) { |
|
| 124 | + return new CommunityUser(); |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + $statement = $database->prepare("SELECT * FROM user WHERE username = :id LIMIT 1;"); |
|
| 128 | + $statement->bindValue(":id", $username); |
|
| 129 | + |
|
| 130 | + $statement->execute(); |
|
| 131 | + |
|
| 132 | + $resultObject = $statement->fetchObject(get_called_class()); |
|
| 133 | + |
|
| 134 | + if ($resultObject != false) { |
|
| 135 | + $resultObject->setDatabase($database); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + return $resultObject; |
|
| 139 | + } |
|
| 140 | + |
|
| 141 | + /** |
|
| 142 | + * Gets a user by their on-wiki username. |
|
| 143 | + * |
|
| 144 | + * @param string $username |
|
| 145 | + * @param PdoDatabase $database |
|
| 146 | + * |
|
| 147 | + * @return User|false |
|
| 148 | + */ |
|
| 149 | + public static function getByOnWikiUsername($username, PdoDatabase $database) |
|
| 150 | + { |
|
| 151 | + $statement = $database->prepare("SELECT * FROM user WHERE onwikiname = :id LIMIT 1;"); |
|
| 152 | + $statement->bindValue(":id", $username); |
|
| 153 | + $statement->execute(); |
|
| 154 | + |
|
| 155 | + $resultObject = $statement->fetchObject(get_called_class()); |
|
| 156 | + |
|
| 157 | + if ($resultObject != false) { |
|
| 158 | + $resultObject->setDatabase($database); |
|
| 159 | + |
|
| 160 | + return $resultObject; |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + return false; |
|
| 164 | + } |
|
| 165 | + |
|
| 166 | + #endregion |
|
| 167 | + |
|
| 168 | + /** |
|
| 169 | + * Saves the current object |
|
| 170 | + * |
|
| 171 | + * @throws Exception |
|
| 172 | + */ |
|
| 173 | + public function save() |
|
| 174 | + { |
|
| 175 | + if ($this->isNew()) { |
|
| 176 | + // insert |
|
| 177 | + $statement = $this->dbObject->prepare(<<<SQL |
|
| 178 | 178 | INSERT INTO `user` ( |
| 179 | 179 | username, email, status, onwikiname, welcome_sig, |
| 180 | 180 | lastactive, forcelogout, forceidentified, |
@@ -185,32 +185,32 @@ discard block |
||
| 185 | 185 | :welcome_template, :abortpref, :confirmationdiff, :emailsig, :creationmode, :skin |
| 186 | 186 | ); |
| 187 | 187 | SQL |
| 188 | - ); |
|
| 189 | - $statement->bindValue(":username", $this->username); |
|
| 190 | - $statement->bindValue(":email", $this->email); |
|
| 191 | - $statement->bindValue(":status", $this->status); |
|
| 192 | - $statement->bindValue(":onwikiname", $this->onwikiname); |
|
| 193 | - $statement->bindValue(":welcome_sig", $this->welcome_sig); |
|
| 194 | - $statement->bindValue(":lastactive", $this->lastactive); |
|
| 195 | - $statement->bindValue(":forcelogout", $this->forcelogout); |
|
| 196 | - $statement->bindValue(":forceidentified", $this->forceidentified); |
|
| 197 | - $statement->bindValue(":welcome_template", $this->welcome_template); |
|
| 198 | - $statement->bindValue(":abortpref", $this->abortpref); |
|
| 199 | - $statement->bindValue(":confirmationdiff", $this->confirmationdiff); |
|
| 200 | - $statement->bindValue(":emailsig", $this->emailsig); |
|
| 201 | - $statement->bindValue(":creationmode", $this->creationmode); |
|
| 202 | - $statement->bindValue(":skin", $this->skin); |
|
| 203 | - |
|
| 204 | - if ($statement->execute()) { |
|
| 205 | - $this->id = (int)$this->dbObject->lastInsertId(); |
|
| 206 | - } |
|
| 207 | - else { |
|
| 208 | - throw new Exception($statement->errorInfo()); |
|
| 209 | - } |
|
| 210 | - } |
|
| 211 | - else { |
|
| 212 | - // update |
|
| 213 | - $statement = $this->dbObject->prepare(<<<SQL |
|
| 188 | + ); |
|
| 189 | + $statement->bindValue(":username", $this->username); |
|
| 190 | + $statement->bindValue(":email", $this->email); |
|
| 191 | + $statement->bindValue(":status", $this->status); |
|
| 192 | + $statement->bindValue(":onwikiname", $this->onwikiname); |
|
| 193 | + $statement->bindValue(":welcome_sig", $this->welcome_sig); |
|
| 194 | + $statement->bindValue(":lastactive", $this->lastactive); |
|
| 195 | + $statement->bindValue(":forcelogout", $this->forcelogout); |
|
| 196 | + $statement->bindValue(":forceidentified", $this->forceidentified); |
|
| 197 | + $statement->bindValue(":welcome_template", $this->welcome_template); |
|
| 198 | + $statement->bindValue(":abortpref", $this->abortpref); |
|
| 199 | + $statement->bindValue(":confirmationdiff", $this->confirmationdiff); |
|
| 200 | + $statement->bindValue(":emailsig", $this->emailsig); |
|
| 201 | + $statement->bindValue(":creationmode", $this->creationmode); |
|
| 202 | + $statement->bindValue(":skin", $this->skin); |
|
| 203 | + |
|
| 204 | + if ($statement->execute()) { |
|
| 205 | + $this->id = (int)$this->dbObject->lastInsertId(); |
|
| 206 | + } |
|
| 207 | + else { |
|
| 208 | + throw new Exception($statement->errorInfo()); |
|
| 209 | + } |
|
| 210 | + } |
|
| 211 | + else { |
|
| 212 | + // update |
|
| 213 | + $statement = $this->dbObject->prepare(<<<SQL |
|
| 214 | 214 | UPDATE `user` SET |
| 215 | 215 | username = :username, email = :email, |
| 216 | 216 | status = :status, |
@@ -223,387 +223,387 @@ discard block |
||
| 223 | 223 | updateversion = updateversion + 1 |
| 224 | 224 | WHERE id = :id AND updateversion = :updateversion; |
| 225 | 225 | SQL |
| 226 | - ); |
|
| 227 | - $statement->bindValue(":forceidentified", $this->forceidentified); |
|
| 228 | - |
|
| 229 | - $statement->bindValue(':id', $this->id); |
|
| 230 | - $statement->bindValue(':updateversion', $this->updateversion); |
|
| 231 | - |
|
| 232 | - $statement->bindValue(':username', $this->username); |
|
| 233 | - $statement->bindValue(':email', $this->email); |
|
| 234 | - $statement->bindValue(':status', $this->status); |
|
| 235 | - $statement->bindValue(':onwikiname', $this->onwikiname); |
|
| 236 | - $statement->bindValue(':welcome_sig', $this->welcome_sig); |
|
| 237 | - $statement->bindValue(':lastactive', $this->lastactive); |
|
| 238 | - $statement->bindValue(':forcelogout', $this->forcelogout); |
|
| 239 | - $statement->bindValue(':forceidentified', $this->forceidentified); |
|
| 240 | - $statement->bindValue(':welcome_template', $this->welcome_template); |
|
| 241 | - $statement->bindValue(':abortpref', $this->abortpref); |
|
| 242 | - $statement->bindValue(':confirmationdiff', $this->confirmationdiff); |
|
| 243 | - $statement->bindValue(':emailsig', $this->emailsig); |
|
| 244 | - $statement->bindValue(':creationmode', $this->creationmode); |
|
| 245 | - $statement->bindValue(':skin', $this->skin); |
|
| 246 | - |
|
| 247 | - if (!$statement->execute()) { |
|
| 248 | - throw new Exception($statement->errorInfo()); |
|
| 249 | - } |
|
| 250 | - |
|
| 251 | - if ($statement->rowCount() !== 1) { |
|
| 252 | - throw new OptimisticLockFailedException(); |
|
| 253 | - } |
|
| 254 | - |
|
| 255 | - $this->updateversion++; |
|
| 256 | - } |
|
| 257 | - } |
|
| 258 | - |
|
| 259 | - #region properties |
|
| 260 | - |
|
| 261 | - /** |
|
| 262 | - * Gets the tool username |
|
| 263 | - * @return string |
|
| 264 | - */ |
|
| 265 | - public function getUsername() |
|
| 266 | - { |
|
| 267 | - return $this->username; |
|
| 268 | - } |
|
| 269 | - |
|
| 270 | - /** |
|
| 271 | - * Sets the tool username |
|
| 272 | - * |
|
| 273 | - * @param string $username |
|
| 274 | - */ |
|
| 275 | - public function setUsername($username) |
|
| 276 | - { |
|
| 277 | - $this->username = $username; |
|
| 278 | - |
|
| 279 | - // If this isn't a brand new user, then it's a rename, force the logout |
|
| 280 | - if (!$this->isNew()) { |
|
| 281 | - $this->forcelogout = 1; |
|
| 282 | - } |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - /** |
|
| 286 | - * Gets the user's email address |
|
| 287 | - * @return string |
|
| 288 | - */ |
|
| 289 | - public function getEmail() |
|
| 290 | - { |
|
| 291 | - return $this->email; |
|
| 292 | - } |
|
| 293 | - |
|
| 294 | - /** |
|
| 295 | - * Sets the user's email address |
|
| 296 | - * |
|
| 297 | - * @param string $email |
|
| 298 | - */ |
|
| 299 | - public function setEmail($email) |
|
| 300 | - { |
|
| 301 | - $this->email = $email; |
|
| 302 | - } |
|
| 303 | - |
|
| 304 | - /** |
|
| 305 | - * Gets the status (User, Admin, Suspended, etc - excludes checkuser) of the user. |
|
| 306 | - * @return string |
|
| 307 | - */ |
|
| 308 | - public function getStatus() |
|
| 309 | - { |
|
| 310 | - return $this->status; |
|
| 311 | - } |
|
| 312 | - |
|
| 313 | - /** |
|
| 314 | - * @param string $status |
|
| 315 | - */ |
|
| 316 | - public function setStatus($status) |
|
| 317 | - { |
|
| 318 | - $this->status = $status; |
|
| 319 | - } |
|
| 320 | - |
|
| 321 | - /** |
|
| 322 | - * Gets the user's on-wiki name |
|
| 323 | - * @return string |
|
| 324 | - */ |
|
| 325 | - public function getOnWikiName() |
|
| 326 | - { |
|
| 327 | - return $this->onwikiname; |
|
| 328 | - } |
|
| 329 | - |
|
| 330 | - /** |
|
| 331 | - * Sets the user's on-wiki name |
|
| 332 | - * |
|
| 333 | - * This can have interesting side-effects with OAuth. |
|
| 334 | - * |
|
| 335 | - * @param string $onWikiName |
|
| 336 | - */ |
|
| 337 | - public function setOnWikiName($onWikiName) |
|
| 338 | - { |
|
| 339 | - $this->onwikiname = $onWikiName; |
|
| 340 | - } |
|
| 341 | - |
|
| 342 | - /** |
|
| 343 | - * Gets the welcome signature |
|
| 344 | - * @return string |
|
| 345 | - */ |
|
| 346 | - public function getWelcomeSig() |
|
| 347 | - { |
|
| 348 | - return $this->welcome_sig; |
|
| 349 | - } |
|
| 350 | - |
|
| 351 | - /** |
|
| 352 | - * Sets the welcome signature |
|
| 353 | - * |
|
| 354 | - * @param string $welcomeSig |
|
| 355 | - */ |
|
| 356 | - public function setWelcomeSig($welcomeSig) |
|
| 357 | - { |
|
| 358 | - $this->welcome_sig = $welcomeSig; |
|
| 359 | - } |
|
| 360 | - |
|
| 361 | - /** |
|
| 362 | - * Gets the last activity date for the user |
|
| 363 | - * |
|
| 364 | - * @return string |
|
| 365 | - * @todo This should probably return an instance of DateTime |
|
| 366 | - */ |
|
| 367 | - public function getLastActive() |
|
| 368 | - { |
|
| 369 | - return $this->lastactive; |
|
| 370 | - } |
|
| 371 | - |
|
| 372 | - /** |
|
| 373 | - * Gets the user's forced logout status |
|
| 374 | - * |
|
| 375 | - * @return bool |
|
| 376 | - */ |
|
| 377 | - public function getForceLogout() |
|
| 378 | - { |
|
| 379 | - return $this->forcelogout == 1; |
|
| 380 | - } |
|
| 381 | - |
|
| 382 | - /** |
|
| 383 | - * Sets the user's forced logout status |
|
| 384 | - * |
|
| 385 | - * @param bool $forceLogout |
|
| 386 | - */ |
|
| 387 | - public function setForceLogout($forceLogout) |
|
| 388 | - { |
|
| 389 | - $this->forcelogout = $forceLogout ? 1 : 0; |
|
| 390 | - } |
|
| 391 | - |
|
| 392 | - /** |
|
| 393 | - * Returns the ID of the welcome template used. |
|
| 394 | - * @return int |
|
| 395 | - */ |
|
| 396 | - public function getWelcomeTemplate() |
|
| 397 | - { |
|
| 398 | - return $this->welcome_template; |
|
| 399 | - } |
|
| 400 | - |
|
| 401 | - /** |
|
| 402 | - * Sets the ID of the welcome template used. |
|
| 403 | - * |
|
| 404 | - * @param int $welcomeTemplate |
|
| 405 | - */ |
|
| 406 | - public function setWelcomeTemplate($welcomeTemplate) |
|
| 407 | - { |
|
| 408 | - $this->welcome_template = $welcomeTemplate; |
|
| 409 | - } |
|
| 410 | - |
|
| 411 | - /** |
|
| 412 | - * Gets the user's abort preference |
|
| 413 | - * @todo this is badly named too! Also a bool that's actually an int. |
|
| 414 | - * @return int |
|
| 415 | - */ |
|
| 416 | - public function getAbortPref() |
|
| 417 | - { |
|
| 418 | - return $this->abortpref; |
|
| 419 | - } |
|
| 420 | - |
|
| 421 | - /** |
|
| 422 | - * Sets the user's abort preference |
|
| 423 | - * @todo rename, retype, and re-comment. |
|
| 424 | - * |
|
| 425 | - * @param int $abortPreference |
|
| 426 | - */ |
|
| 427 | - public function setAbortPref($abortPreference) |
|
| 428 | - { |
|
| 429 | - $this->abortpref = $abortPreference; |
|
| 430 | - } |
|
| 431 | - |
|
| 432 | - /** |
|
| 433 | - * Gets the user's confirmation diff. Unused if OAuth is in use. |
|
| 434 | - * @return int the diff ID |
|
| 435 | - */ |
|
| 436 | - public function getConfirmationDiff() |
|
| 437 | - { |
|
| 438 | - return $this->confirmationdiff; |
|
| 439 | - } |
|
| 440 | - |
|
| 441 | - /** |
|
| 442 | - * Sets the user's confirmation diff. |
|
| 443 | - * |
|
| 444 | - * @param int $confirmationDiff |
|
| 445 | - */ |
|
| 446 | - public function setConfirmationDiff($confirmationDiff) |
|
| 447 | - { |
|
| 448 | - $this->confirmationdiff = $confirmationDiff; |
|
| 449 | - } |
|
| 450 | - |
|
| 451 | - /** |
|
| 452 | - * Gets the users' email signature used on outbound mail. |
|
| 453 | - * @todo rename me! |
|
| 454 | - * @return string |
|
| 455 | - */ |
|
| 456 | - public function getEmailSig() |
|
| 457 | - { |
|
| 458 | - return $this->emailsig; |
|
| 459 | - } |
|
| 460 | - |
|
| 461 | - /** |
|
| 462 | - * Sets the user's email signature for outbound mail. |
|
| 463 | - * |
|
| 464 | - * @param string $emailSignature |
|
| 465 | - */ |
|
| 466 | - public function setEmailSig($emailSignature) |
|
| 467 | - { |
|
| 468 | - $this->emailsig = $emailSignature; |
|
| 469 | - } |
|
| 470 | - |
|
| 471 | - /** |
|
| 472 | - * @return int |
|
| 473 | - */ |
|
| 474 | - public function getCreationMode() |
|
| 475 | - { |
|
| 476 | - return $this->creationmode; |
|
| 477 | - } |
|
| 478 | - |
|
| 479 | - /** |
|
| 480 | - * @param $creationMode int |
|
| 481 | - */ |
|
| 482 | - public function setCreationMode($creationMode) |
|
| 483 | - { |
|
| 484 | - $this->creationmode = $creationMode; |
|
| 485 | - } |
|
| 486 | - |
|
| 487 | - /** |
|
| 488 | - * @return boolean |
|
| 489 | - */ |
|
| 490 | - public function getUseAlternateSkin() |
|
| 491 | - { |
|
| 492 | - return $this->skin === 'alt'; |
|
| 493 | - } |
|
| 494 | - |
|
| 495 | - /** |
|
| 496 | - * @return string |
|
| 497 | - */ |
|
| 498 | - public function getSkin() |
|
| 499 | - { |
|
| 500 | - return $this->skin; |
|
| 501 | - } |
|
| 502 | - |
|
| 503 | - /** |
|
| 504 | - * @param $skin string |
|
| 505 | - */ |
|
| 506 | - public function setSkin($skin) |
|
| 507 | - { |
|
| 508 | - $this->skin = $skin; |
|
| 509 | - } |
|
| 510 | - |
|
| 511 | - #endregion |
|
| 512 | - |
|
| 513 | - #region user access checks |
|
| 514 | - |
|
| 515 | - public function isActive() |
|
| 516 | - { |
|
| 517 | - return $this->status == self::STATUS_ACTIVE; |
|
| 518 | - } |
|
| 519 | - |
|
| 520 | - /** |
|
| 521 | - * Tests if the user is identified |
|
| 522 | - * |
|
| 523 | - * @param IdentificationVerifier $iv |
|
| 524 | - * |
|
| 525 | - * @return bool |
|
| 526 | - * @todo Figure out what on earth is going on with PDO's typecasting here. Apparently, it returns string("0") for |
|
| 527 | - * the force-unidentified case, and int(1) for the identified case?! This is quite ugly, but probably needed |
|
| 528 | - * to play it safe for now. |
|
| 529 | - * @category Security-Critical |
|
| 530 | - */ |
|
| 531 | - public function isIdentified(IdentificationVerifier $iv) |
|
| 532 | - { |
|
| 533 | - if ($this->forceidentified === 0 || $this->forceidentified === "0") { |
|
| 534 | - // User forced to unidentified in the database. |
|
| 535 | - return false; |
|
| 536 | - } |
|
| 537 | - elseif ($this->forceidentified === 1 || $this->forceidentified === "1") { |
|
| 538 | - // User forced to identified in the database. |
|
| 539 | - return true; |
|
| 540 | - } |
|
| 541 | - else { |
|
| 542 | - // User not forced to any particular identified status; consult IdentificationVerifier |
|
| 543 | - return $iv->isUserIdentified($this->getOnWikiName()); |
|
| 544 | - } |
|
| 545 | - } |
|
| 546 | - |
|
| 547 | - /** |
|
| 548 | - * DO NOT USE FOR TESTING IDENTIFICATION STATUS. |
|
| 549 | - * |
|
| 550 | - * @return bool|null |
|
| 551 | - */ |
|
| 552 | - public function getForceIdentified() { |
|
| 553 | - return $this->forceidentified; |
|
| 554 | - } |
|
| 555 | - |
|
| 556 | - /** |
|
| 557 | - * Tests if the user is suspended |
|
| 558 | - * @return bool |
|
| 559 | - * @category Security-Critical |
|
| 560 | - */ |
|
| 561 | - public function isSuspended() |
|
| 562 | - { |
|
| 563 | - return $this->status == self::STATUS_SUSPENDED; |
|
| 564 | - } |
|
| 565 | - |
|
| 566 | - /** |
|
| 567 | - * Tests if the user is new |
|
| 568 | - * @return bool |
|
| 569 | - * @category Security-Critical |
|
| 570 | - */ |
|
| 571 | - public function isNewUser() |
|
| 572 | - { |
|
| 573 | - return $this->status == self::STATUS_NEW; |
|
| 574 | - } |
|
| 575 | - |
|
| 576 | - /** |
|
| 577 | - * Tests if the user has been declined access to the tool |
|
| 578 | - * @return bool |
|
| 579 | - * @category Security-Critical |
|
| 580 | - */ |
|
| 581 | - public function isDeclined() |
|
| 582 | - { |
|
| 583 | - return $this->status == self::STATUS_DECLINED; |
|
| 584 | - } |
|
| 585 | - |
|
| 586 | - /** |
|
| 587 | - * Tests if the user is the community user |
|
| 588 | - * |
|
| 589 | - * @todo decide if this means logged out. I think it usually does. |
|
| 590 | - * @return bool |
|
| 591 | - * @category Security-Critical |
|
| 592 | - */ |
|
| 593 | - public function isCommunityUser() |
|
| 594 | - { |
|
| 595 | - return false; |
|
| 596 | - } |
|
| 597 | - |
|
| 598 | - #endregion |
|
| 599 | - |
|
| 600 | - /** |
|
| 601 | - * Gets the approval date of the user |
|
| 602 | - * @return DateTime|false |
|
| 603 | - */ |
|
| 604 | - public function getApprovalDate() |
|
| 605 | - { |
|
| 606 | - $query = $this->dbObject->prepare(<<<SQL |
|
| 226 | + ); |
|
| 227 | + $statement->bindValue(":forceidentified", $this->forceidentified); |
|
| 228 | + |
|
| 229 | + $statement->bindValue(':id', $this->id); |
|
| 230 | + $statement->bindValue(':updateversion', $this->updateversion); |
|
| 231 | + |
|
| 232 | + $statement->bindValue(':username', $this->username); |
|
| 233 | + $statement->bindValue(':email', $this->email); |
|
| 234 | + $statement->bindValue(':status', $this->status); |
|
| 235 | + $statement->bindValue(':onwikiname', $this->onwikiname); |
|
| 236 | + $statement->bindValue(':welcome_sig', $this->welcome_sig); |
|
| 237 | + $statement->bindValue(':lastactive', $this->lastactive); |
|
| 238 | + $statement->bindValue(':forcelogout', $this->forcelogout); |
|
| 239 | + $statement->bindValue(':forceidentified', $this->forceidentified); |
|
| 240 | + $statement->bindValue(':welcome_template', $this->welcome_template); |
|
| 241 | + $statement->bindValue(':abortpref', $this->abortpref); |
|
| 242 | + $statement->bindValue(':confirmationdiff', $this->confirmationdiff); |
|
| 243 | + $statement->bindValue(':emailsig', $this->emailsig); |
|
| 244 | + $statement->bindValue(':creationmode', $this->creationmode); |
|
| 245 | + $statement->bindValue(':skin', $this->skin); |
|
| 246 | + |
|
| 247 | + if (!$statement->execute()) { |
|
| 248 | + throw new Exception($statement->errorInfo()); |
|
| 249 | + } |
|
| 250 | + |
|
| 251 | + if ($statement->rowCount() !== 1) { |
|
| 252 | + throw new OptimisticLockFailedException(); |
|
| 253 | + } |
|
| 254 | + |
|
| 255 | + $this->updateversion++; |
|
| 256 | + } |
|
| 257 | + } |
|
| 258 | + |
|
| 259 | + #region properties |
|
| 260 | + |
|
| 261 | + /** |
|
| 262 | + * Gets the tool username |
|
| 263 | + * @return string |
|
| 264 | + */ |
|
| 265 | + public function getUsername() |
|
| 266 | + { |
|
| 267 | + return $this->username; |
|
| 268 | + } |
|
| 269 | + |
|
| 270 | + /** |
|
| 271 | + * Sets the tool username |
|
| 272 | + * |
|
| 273 | + * @param string $username |
|
| 274 | + */ |
|
| 275 | + public function setUsername($username) |
|
| 276 | + { |
|
| 277 | + $this->username = $username; |
|
| 278 | + |
|
| 279 | + // If this isn't a brand new user, then it's a rename, force the logout |
|
| 280 | + if (!$this->isNew()) { |
|
| 281 | + $this->forcelogout = 1; |
|
| 282 | + } |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + /** |
|
| 286 | + * Gets the user's email address |
|
| 287 | + * @return string |
|
| 288 | + */ |
|
| 289 | + public function getEmail() |
|
| 290 | + { |
|
| 291 | + return $this->email; |
|
| 292 | + } |
|
| 293 | + |
|
| 294 | + /** |
|
| 295 | + * Sets the user's email address |
|
| 296 | + * |
|
| 297 | + * @param string $email |
|
| 298 | + */ |
|
| 299 | + public function setEmail($email) |
|
| 300 | + { |
|
| 301 | + $this->email = $email; |
|
| 302 | + } |
|
| 303 | + |
|
| 304 | + /** |
|
| 305 | + * Gets the status (User, Admin, Suspended, etc - excludes checkuser) of the user. |
|
| 306 | + * @return string |
|
| 307 | + */ |
|
| 308 | + public function getStatus() |
|
| 309 | + { |
|
| 310 | + return $this->status; |
|
| 311 | + } |
|
| 312 | + |
|
| 313 | + /** |
|
| 314 | + * @param string $status |
|
| 315 | + */ |
|
| 316 | + public function setStatus($status) |
|
| 317 | + { |
|
| 318 | + $this->status = $status; |
|
| 319 | + } |
|
| 320 | + |
|
| 321 | + /** |
|
| 322 | + * Gets the user's on-wiki name |
|
| 323 | + * @return string |
|
| 324 | + */ |
|
| 325 | + public function getOnWikiName() |
|
| 326 | + { |
|
| 327 | + return $this->onwikiname; |
|
| 328 | + } |
|
| 329 | + |
|
| 330 | + /** |
|
| 331 | + * Sets the user's on-wiki name |
|
| 332 | + * |
|
| 333 | + * This can have interesting side-effects with OAuth. |
|
| 334 | + * |
|
| 335 | + * @param string $onWikiName |
|
| 336 | + */ |
|
| 337 | + public function setOnWikiName($onWikiName) |
|
| 338 | + { |
|
| 339 | + $this->onwikiname = $onWikiName; |
|
| 340 | + } |
|
| 341 | + |
|
| 342 | + /** |
|
| 343 | + * Gets the welcome signature |
|
| 344 | + * @return string |
|
| 345 | + */ |
|
| 346 | + public function getWelcomeSig() |
|
| 347 | + { |
|
| 348 | + return $this->welcome_sig; |
|
| 349 | + } |
|
| 350 | + |
|
| 351 | + /** |
|
| 352 | + * Sets the welcome signature |
|
| 353 | + * |
|
| 354 | + * @param string $welcomeSig |
|
| 355 | + */ |
|
| 356 | + public function setWelcomeSig($welcomeSig) |
|
| 357 | + { |
|
| 358 | + $this->welcome_sig = $welcomeSig; |
|
| 359 | + } |
|
| 360 | + |
|
| 361 | + /** |
|
| 362 | + * Gets the last activity date for the user |
|
| 363 | + * |
|
| 364 | + * @return string |
|
| 365 | + * @todo This should probably return an instance of DateTime |
|
| 366 | + */ |
|
| 367 | + public function getLastActive() |
|
| 368 | + { |
|
| 369 | + return $this->lastactive; |
|
| 370 | + } |
|
| 371 | + |
|
| 372 | + /** |
|
| 373 | + * Gets the user's forced logout status |
|
| 374 | + * |
|
| 375 | + * @return bool |
|
| 376 | + */ |
|
| 377 | + public function getForceLogout() |
|
| 378 | + { |
|
| 379 | + return $this->forcelogout == 1; |
|
| 380 | + } |
|
| 381 | + |
|
| 382 | + /** |
|
| 383 | + * Sets the user's forced logout status |
|
| 384 | + * |
|
| 385 | + * @param bool $forceLogout |
|
| 386 | + */ |
|
| 387 | + public function setForceLogout($forceLogout) |
|
| 388 | + { |
|
| 389 | + $this->forcelogout = $forceLogout ? 1 : 0; |
|
| 390 | + } |
|
| 391 | + |
|
| 392 | + /** |
|
| 393 | + * Returns the ID of the welcome template used. |
|
| 394 | + * @return int |
|
| 395 | + */ |
|
| 396 | + public function getWelcomeTemplate() |
|
| 397 | + { |
|
| 398 | + return $this->welcome_template; |
|
| 399 | + } |
|
| 400 | + |
|
| 401 | + /** |
|
| 402 | + * Sets the ID of the welcome template used. |
|
| 403 | + * |
|
| 404 | + * @param int $welcomeTemplate |
|
| 405 | + */ |
|
| 406 | + public function setWelcomeTemplate($welcomeTemplate) |
|
| 407 | + { |
|
| 408 | + $this->welcome_template = $welcomeTemplate; |
|
| 409 | + } |
|
| 410 | + |
|
| 411 | + /** |
|
| 412 | + * Gets the user's abort preference |
|
| 413 | + * @todo this is badly named too! Also a bool that's actually an int. |
|
| 414 | + * @return int |
|
| 415 | + */ |
|
| 416 | + public function getAbortPref() |
|
| 417 | + { |
|
| 418 | + return $this->abortpref; |
|
| 419 | + } |
|
| 420 | + |
|
| 421 | + /** |
|
| 422 | + * Sets the user's abort preference |
|
| 423 | + * @todo rename, retype, and re-comment. |
|
| 424 | + * |
|
| 425 | + * @param int $abortPreference |
|
| 426 | + */ |
|
| 427 | + public function setAbortPref($abortPreference) |
|
| 428 | + { |
|
| 429 | + $this->abortpref = $abortPreference; |
|
| 430 | + } |
|
| 431 | + |
|
| 432 | + /** |
|
| 433 | + * Gets the user's confirmation diff. Unused if OAuth is in use. |
|
| 434 | + * @return int the diff ID |
|
| 435 | + */ |
|
| 436 | + public function getConfirmationDiff() |
|
| 437 | + { |
|
| 438 | + return $this->confirmationdiff; |
|
| 439 | + } |
|
| 440 | + |
|
| 441 | + /** |
|
| 442 | + * Sets the user's confirmation diff. |
|
| 443 | + * |
|
| 444 | + * @param int $confirmationDiff |
|
| 445 | + */ |
|
| 446 | + public function setConfirmationDiff($confirmationDiff) |
|
| 447 | + { |
|
| 448 | + $this->confirmationdiff = $confirmationDiff; |
|
| 449 | + } |
|
| 450 | + |
|
| 451 | + /** |
|
| 452 | + * Gets the users' email signature used on outbound mail. |
|
| 453 | + * @todo rename me! |
|
| 454 | + * @return string |
|
| 455 | + */ |
|
| 456 | + public function getEmailSig() |
|
| 457 | + { |
|
| 458 | + return $this->emailsig; |
|
| 459 | + } |
|
| 460 | + |
|
| 461 | + /** |
|
| 462 | + * Sets the user's email signature for outbound mail. |
|
| 463 | + * |
|
| 464 | + * @param string $emailSignature |
|
| 465 | + */ |
|
| 466 | + public function setEmailSig($emailSignature) |
|
| 467 | + { |
|
| 468 | + $this->emailsig = $emailSignature; |
|
| 469 | + } |
|
| 470 | + |
|
| 471 | + /** |
|
| 472 | + * @return int |
|
| 473 | + */ |
|
| 474 | + public function getCreationMode() |
|
| 475 | + { |
|
| 476 | + return $this->creationmode; |
|
| 477 | + } |
|
| 478 | + |
|
| 479 | + /** |
|
| 480 | + * @param $creationMode int |
|
| 481 | + */ |
|
| 482 | + public function setCreationMode($creationMode) |
|
| 483 | + { |
|
| 484 | + $this->creationmode = $creationMode; |
|
| 485 | + } |
|
| 486 | + |
|
| 487 | + /** |
|
| 488 | + * @return boolean |
|
| 489 | + */ |
|
| 490 | + public function getUseAlternateSkin() |
|
| 491 | + { |
|
| 492 | + return $this->skin === 'alt'; |
|
| 493 | + } |
|
| 494 | + |
|
| 495 | + /** |
|
| 496 | + * @return string |
|
| 497 | + */ |
|
| 498 | + public function getSkin() |
|
| 499 | + { |
|
| 500 | + return $this->skin; |
|
| 501 | + } |
|
| 502 | + |
|
| 503 | + /** |
|
| 504 | + * @param $skin string |
|
| 505 | + */ |
|
| 506 | + public function setSkin($skin) |
|
| 507 | + { |
|
| 508 | + $this->skin = $skin; |
|
| 509 | + } |
|
| 510 | + |
|
| 511 | + #endregion |
|
| 512 | + |
|
| 513 | + #region user access checks |
|
| 514 | + |
|
| 515 | + public function isActive() |
|
| 516 | + { |
|
| 517 | + return $this->status == self::STATUS_ACTIVE; |
|
| 518 | + } |
|
| 519 | + |
|
| 520 | + /** |
|
| 521 | + * Tests if the user is identified |
|
| 522 | + * |
|
| 523 | + * @param IdentificationVerifier $iv |
|
| 524 | + * |
|
| 525 | + * @return bool |
|
| 526 | + * @todo Figure out what on earth is going on with PDO's typecasting here. Apparently, it returns string("0") for |
|
| 527 | + * the force-unidentified case, and int(1) for the identified case?! This is quite ugly, but probably needed |
|
| 528 | + * to play it safe for now. |
|
| 529 | + * @category Security-Critical |
|
| 530 | + */ |
|
| 531 | + public function isIdentified(IdentificationVerifier $iv) |
|
| 532 | + { |
|
| 533 | + if ($this->forceidentified === 0 || $this->forceidentified === "0") { |
|
| 534 | + // User forced to unidentified in the database. |
|
| 535 | + return false; |
|
| 536 | + } |
|
| 537 | + elseif ($this->forceidentified === 1 || $this->forceidentified === "1") { |
|
| 538 | + // User forced to identified in the database. |
|
| 539 | + return true; |
|
| 540 | + } |
|
| 541 | + else { |
|
| 542 | + // User not forced to any particular identified status; consult IdentificationVerifier |
|
| 543 | + return $iv->isUserIdentified($this->getOnWikiName()); |
|
| 544 | + } |
|
| 545 | + } |
|
| 546 | + |
|
| 547 | + /** |
|
| 548 | + * DO NOT USE FOR TESTING IDENTIFICATION STATUS. |
|
| 549 | + * |
|
| 550 | + * @return bool|null |
|
| 551 | + */ |
|
| 552 | + public function getForceIdentified() { |
|
| 553 | + return $this->forceidentified; |
|
| 554 | + } |
|
| 555 | + |
|
| 556 | + /** |
|
| 557 | + * Tests if the user is suspended |
|
| 558 | + * @return bool |
|
| 559 | + * @category Security-Critical |
|
| 560 | + */ |
|
| 561 | + public function isSuspended() |
|
| 562 | + { |
|
| 563 | + return $this->status == self::STATUS_SUSPENDED; |
|
| 564 | + } |
|
| 565 | + |
|
| 566 | + /** |
|
| 567 | + * Tests if the user is new |
|
| 568 | + * @return bool |
|
| 569 | + * @category Security-Critical |
|
| 570 | + */ |
|
| 571 | + public function isNewUser() |
|
| 572 | + { |
|
| 573 | + return $this->status == self::STATUS_NEW; |
|
| 574 | + } |
|
| 575 | + |
|
| 576 | + /** |
|
| 577 | + * Tests if the user has been declined access to the tool |
|
| 578 | + * @return bool |
|
| 579 | + * @category Security-Critical |
|
| 580 | + */ |
|
| 581 | + public function isDeclined() |
|
| 582 | + { |
|
| 583 | + return $this->status == self::STATUS_DECLINED; |
|
| 584 | + } |
|
| 585 | + |
|
| 586 | + /** |
|
| 587 | + * Tests if the user is the community user |
|
| 588 | + * |
|
| 589 | + * @todo decide if this means logged out. I think it usually does. |
|
| 590 | + * @return bool |
|
| 591 | + * @category Security-Critical |
|
| 592 | + */ |
|
| 593 | + public function isCommunityUser() |
|
| 594 | + { |
|
| 595 | + return false; |
|
| 596 | + } |
|
| 597 | + |
|
| 598 | + #endregion |
|
| 599 | + |
|
| 600 | + /** |
|
| 601 | + * Gets the approval date of the user |
|
| 602 | + * @return DateTime|false |
|
| 603 | + */ |
|
| 604 | + public function getApprovalDate() |
|
| 605 | + { |
|
| 606 | + $query = $this->dbObject->prepare(<<<SQL |
|
| 607 | 607 | SELECT timestamp |
| 608 | 608 | FROM log |
| 609 | 609 | WHERE objectid = :userid |
@@ -612,12 +612,12 @@ discard block |
||
| 612 | 612 | ORDER BY id DESC |
| 613 | 613 | LIMIT 1; |
| 614 | 614 | SQL |
| 615 | - ); |
|
| 616 | - $query->execute(array(":userid" => $this->id)); |
|
| 615 | + ); |
|
| 616 | + $query->execute(array(":userid" => $this->id)); |
|
| 617 | 617 | |
| 618 | - $data = DateTime::createFromFormat("Y-m-d H:i:s", $query->fetchColumn()); |
|
| 619 | - $query->closeCursor(); |
|
| 618 | + $data = DateTime::createFromFormat("Y-m-d H:i:s", $query->fetchColumn()); |
|
| 619 | + $query->closeCursor(); |
|
| 620 | 620 | |
| 621 | - return $data; |
|
| 622 | - } |
|
| 621 | + return $data; |
|
| 622 | + } |
|
| 623 | 623 | } |
@@ -549,7 +549,8 @@ |
||
| 549 | 549 | * |
| 550 | 550 | * @return bool|null |
| 551 | 551 | */ |
| 552 | - public function getForceIdentified() { |
|
| 552 | + public function getForceIdentified() |
|
| 553 | + { |
|
| 553 | 554 | return $this->forceidentified; |
| 554 | 555 | } |
| 555 | 556 | |
@@ -23,267 +23,267 @@ |
||
| 23 | 23 | |
| 24 | 24 | abstract class BackgroundTaskBase |
| 25 | 25 | { |
| 26 | - /** @var JobQueue */ |
|
| 27 | - private $job; |
|
| 28 | - /** @var PdoDatabase */ |
|
| 29 | - private $database; |
|
| 30 | - /** @var IOAuthProtocolHelper */ |
|
| 31 | - private $oauthProtocolHelper; |
|
| 32 | - /** @var SiteConfiguration */ |
|
| 33 | - private $siteConfiguration; |
|
| 34 | - /** @var IEmailHelper */ |
|
| 35 | - private $emailHelper; |
|
| 36 | - /** @var HttpHelper */ |
|
| 37 | - private $httpHelper; |
|
| 38 | - /** @var IrcNotificationHelper */ |
|
| 39 | - private $notificationHelper; |
|
| 40 | - /** @var User */ |
|
| 41 | - private $triggerUser; |
|
| 42 | - /** @var Request */ |
|
| 43 | - private $request; |
|
| 44 | - /** @var EmailTemplate */ |
|
| 45 | - private $emailTemplate = null; |
|
| 46 | - /** @var mixed */ |
|
| 47 | - private $parameters; |
|
| 48 | - |
|
| 49 | - /** |
|
| 50 | - * @return JobQueue |
|
| 51 | - */ |
|
| 52 | - public function getJob() |
|
| 53 | - { |
|
| 54 | - return $this->job; |
|
| 55 | - } |
|
| 56 | - |
|
| 57 | - /** |
|
| 58 | - * @param JobQueue $job |
|
| 59 | - */ |
|
| 60 | - public function setJob(JobQueue $job) |
|
| 61 | - { |
|
| 62 | - $this->job = $job; |
|
| 63 | - } |
|
| 64 | - |
|
| 65 | - /** |
|
| 66 | - * @return PdoDatabase |
|
| 67 | - */ |
|
| 68 | - public function getDatabase() |
|
| 69 | - { |
|
| 70 | - return $this->database; |
|
| 71 | - } |
|
| 72 | - |
|
| 73 | - /** |
|
| 74 | - * @param PdoDatabase $database |
|
| 75 | - */ |
|
| 76 | - public function setDatabase(PdoDatabase $database) |
|
| 77 | - { |
|
| 78 | - $this->database = $database; |
|
| 79 | - } |
|
| 80 | - |
|
| 81 | - /** |
|
| 82 | - * @return IOAuthProtocolHelper |
|
| 83 | - */ |
|
| 84 | - public function getOauthProtocolHelper() |
|
| 85 | - { |
|
| 86 | - return $this->oauthProtocolHelper; |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - /** |
|
| 90 | - * @param IOAuthProtocolHelper $oauthProtocolHelper |
|
| 91 | - */ |
|
| 92 | - public function setOauthProtocolHelper(IOAuthProtocolHelper $oauthProtocolHelper) |
|
| 93 | - { |
|
| 94 | - $this->oauthProtocolHelper = $oauthProtocolHelper; |
|
| 95 | - } |
|
| 96 | - |
|
| 97 | - /** |
|
| 98 | - * @return SiteConfiguration |
|
| 99 | - */ |
|
| 100 | - public function getSiteConfiguration() |
|
| 101 | - { |
|
| 102 | - return $this->siteConfiguration; |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - /** |
|
| 106 | - * @param SiteConfiguration $siteConfiguration |
|
| 107 | - */ |
|
| 108 | - public function setSiteConfiguration(SiteConfiguration $siteConfiguration) |
|
| 109 | - { |
|
| 110 | - $this->siteConfiguration = $siteConfiguration; |
|
| 111 | - } |
|
| 112 | - |
|
| 113 | - /** |
|
| 114 | - * @return HttpHelper |
|
| 115 | - */ |
|
| 116 | - public function getHttpHelper() |
|
| 117 | - { |
|
| 118 | - return $this->httpHelper; |
|
| 119 | - } |
|
| 120 | - |
|
| 121 | - /** |
|
| 122 | - * @param HttpHelper $httpHelper |
|
| 123 | - */ |
|
| 124 | - public function setHttpHelper(HttpHelper $httpHelper) |
|
| 125 | - { |
|
| 126 | - $this->httpHelper = $httpHelper; |
|
| 127 | - } |
|
| 128 | - |
|
| 129 | - /** |
|
| 130 | - * @return IEmailHelper |
|
| 131 | - */ |
|
| 132 | - public function getEmailHelper() |
|
| 133 | - { |
|
| 134 | - return $this->emailHelper; |
|
| 135 | - } |
|
| 136 | - |
|
| 137 | - /** |
|
| 138 | - * @param IEmailHelper $emailHelper |
|
| 139 | - */ |
|
| 140 | - public function setEmailHelper(IEmailHelper $emailHelper) |
|
| 141 | - { |
|
| 142 | - $this->emailHelper = $emailHelper; |
|
| 143 | - } |
|
| 144 | - |
|
| 145 | - /** |
|
| 146 | - * @return IrcNotificationHelper |
|
| 147 | - */ |
|
| 148 | - public function getNotificationHelper() |
|
| 149 | - { |
|
| 150 | - return $this->notificationHelper; |
|
| 151 | - } |
|
| 152 | - |
|
| 153 | - /** |
|
| 154 | - * @param IrcNotificationHelper $notificationHelper |
|
| 155 | - */ |
|
| 156 | - public function setNotificationHelper($notificationHelper) |
|
| 157 | - { |
|
| 158 | - $this->notificationHelper = $notificationHelper; |
|
| 159 | - } |
|
| 160 | - |
|
| 161 | - /** |
|
| 162 | - * @return void |
|
| 163 | - */ |
|
| 164 | - protected abstract function execute(); |
|
| 165 | - |
|
| 166 | - public function run() |
|
| 167 | - { |
|
| 168 | - $this->triggerUser = User::getById($this->job->getTriggerUserId(), $this->getDatabase()); |
|
| 169 | - |
|
| 170 | - if ($this->triggerUser === false) { |
|
| 171 | - throw new ApplicationLogicException('Cannot locate trigger user'); |
|
| 172 | - } |
|
| 173 | - |
|
| 174 | - $this->request = Request::getById($this->job->getRequest(), $this->getDatabase()); |
|
| 175 | - |
|
| 176 | - if ($this->request === false) { |
|
| 177 | - throw new ApplicationLogicException('Cannot locate request'); |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - if($this->job->getEmailTemplate() !== null){ |
|
| 181 | - $this->emailTemplate = EmailTemplate::getById($this->job->getEmailTemplate(), $this->getDatabase()); |
|
| 182 | - |
|
| 183 | - if ($this->emailTemplate === false) { |
|
| 184 | - throw new ApplicationLogicException('Cannot locate email template'); |
|
| 185 | - } |
|
| 186 | - } |
|
| 187 | - |
|
| 188 | - if($this->job->getParameters() !== null) { |
|
| 189 | - $this->parameters = json_decode($this->job->getParameters()); |
|
| 190 | - |
|
| 191 | - if (json_last_error() !== JSON_ERROR_NONE) { |
|
| 192 | - throw new ApplicationLogicException('JSON decode: ' . json_last_error_msg()); |
|
| 193 | - } |
|
| 194 | - } |
|
| 195 | - |
|
| 196 | - // Should we wait for a parent job? |
|
| 197 | - if($this->job->getParent() !== null) { |
|
| 198 | - /** @var JobQueue $parentJob */ |
|
| 199 | - $parentJob = JobQueue::getById($this->job->getParent(), $this->getDatabase()); |
|
| 200 | - |
|
| 201 | - if($parentJob === false) { |
|
| 202 | - $this->markFailed("Parent job could not be found"); |
|
| 203 | - return; |
|
| 204 | - } |
|
| 205 | - |
|
| 206 | - switch ($parentJob->getStatus()) { |
|
| 207 | - case JobQueue::STATUS_CANCELLED: |
|
| 208 | - case JobQueue::STATUS_FAILED: |
|
| 209 | - $this->markCancelled('Parent job failed/cancelled'); |
|
| 210 | - return; |
|
| 211 | - case JobQueue::STATUS_WAITING: |
|
| 212 | - case JobQueue::STATUS_READY: |
|
| 213 | - case JobQueue::STATUS_RUNNING: |
|
| 214 | - case JobQueue::STATUS_HELD: |
|
| 215 | - // Defer to next execution |
|
| 216 | - $this->job->setStatus(JobQueue::STATUS_READY); |
|
| 217 | - $this->job->save(); |
|
| 218 | - return; |
|
| 219 | - case JobQueue::STATUS_COMPLETE: |
|
| 220 | - // do nothing |
|
| 221 | - break; |
|
| 222 | - } |
|
| 223 | - } |
|
| 224 | - |
|
| 225 | - $this->execute(); |
|
| 226 | - } |
|
| 227 | - |
|
| 228 | - protected function markComplete() |
|
| 229 | - { |
|
| 230 | - $this->job->setStatus(JobQueue::STATUS_COMPLETE); |
|
| 231 | - $this->job->setError(null); |
|
| 232 | - $this->job->setAcknowledged(null); |
|
| 233 | - $this->job->save(); |
|
| 234 | - |
|
| 235 | - Logger::backgroundJobComplete($this->getDatabase(), $this->getJob()); |
|
| 236 | - } |
|
| 237 | - |
|
| 238 | - protected function markCancelled($reason = null) |
|
| 239 | - { |
|
| 240 | - $this->job->setStatus(JobQueue::STATUS_CANCELLED); |
|
| 241 | - $this->job->setError($reason); |
|
| 242 | - $this->job->setAcknowledged(null); |
|
| 243 | - $this->job->save(); |
|
| 244 | - |
|
| 245 | - Logger::backgroundJobIssue($this->getDatabase(), $this->getJob()); |
|
| 246 | - } |
|
| 247 | - |
|
| 248 | - protected function markFailed($reason = null) |
|
| 249 | - { |
|
| 250 | - $this->job->setStatus(JobQueue::STATUS_FAILED); |
|
| 251 | - $this->job->setError($reason); |
|
| 252 | - $this->job->setAcknowledged(0); |
|
| 253 | - $this->job->save(); |
|
| 254 | - |
|
| 255 | - Logger::backgroundJobIssue($this->getDatabase(), $this->getJob()); |
|
| 256 | - } |
|
| 257 | - |
|
| 258 | - /** |
|
| 259 | - * @return User |
|
| 260 | - */ |
|
| 261 | - public function getTriggerUser() |
|
| 262 | - { |
|
| 263 | - return $this->triggerUser; |
|
| 264 | - } |
|
| 265 | - |
|
| 266 | - /** |
|
| 267 | - * @return Request |
|
| 268 | - */ |
|
| 269 | - public function getRequest() |
|
| 270 | - { |
|
| 271 | - return $this->request; |
|
| 272 | - } |
|
| 273 | - |
|
| 274 | - /** |
|
| 275 | - * @return EmailTemplate |
|
| 276 | - */ |
|
| 277 | - public function getEmailTemplate() |
|
| 278 | - { |
|
| 279 | - return $this->emailTemplate; |
|
| 280 | - } |
|
| 281 | - |
|
| 282 | - /** |
|
| 283 | - * @return mixed |
|
| 284 | - */ |
|
| 285 | - public function getParameters() |
|
| 286 | - { |
|
| 287 | - return $this->parameters; |
|
| 288 | - } |
|
| 26 | + /** @var JobQueue */ |
|
| 27 | + private $job; |
|
| 28 | + /** @var PdoDatabase */ |
|
| 29 | + private $database; |
|
| 30 | + /** @var IOAuthProtocolHelper */ |
|
| 31 | + private $oauthProtocolHelper; |
|
| 32 | + /** @var SiteConfiguration */ |
|
| 33 | + private $siteConfiguration; |
|
| 34 | + /** @var IEmailHelper */ |
|
| 35 | + private $emailHelper; |
|
| 36 | + /** @var HttpHelper */ |
|
| 37 | + private $httpHelper; |
|
| 38 | + /** @var IrcNotificationHelper */ |
|
| 39 | + private $notificationHelper; |
|
| 40 | + /** @var User */ |
|
| 41 | + private $triggerUser; |
|
| 42 | + /** @var Request */ |
|
| 43 | + private $request; |
|
| 44 | + /** @var EmailTemplate */ |
|
| 45 | + private $emailTemplate = null; |
|
| 46 | + /** @var mixed */ |
|
| 47 | + private $parameters; |
|
| 48 | + |
|
| 49 | + /** |
|
| 50 | + * @return JobQueue |
|
| 51 | + */ |
|
| 52 | + public function getJob() |
|
| 53 | + { |
|
| 54 | + return $this->job; |
|
| 55 | + } |
|
| 56 | + |
|
| 57 | + /** |
|
| 58 | + * @param JobQueue $job |
|
| 59 | + */ |
|
| 60 | + public function setJob(JobQueue $job) |
|
| 61 | + { |
|
| 62 | + $this->job = $job; |
|
| 63 | + } |
|
| 64 | + |
|
| 65 | + /** |
|
| 66 | + * @return PdoDatabase |
|
| 67 | + */ |
|
| 68 | + public function getDatabase() |
|
| 69 | + { |
|
| 70 | + return $this->database; |
|
| 71 | + } |
|
| 72 | + |
|
| 73 | + /** |
|
| 74 | + * @param PdoDatabase $database |
|
| 75 | + */ |
|
| 76 | + public function setDatabase(PdoDatabase $database) |
|
| 77 | + { |
|
| 78 | + $this->database = $database; |
|
| 79 | + } |
|
| 80 | + |
|
| 81 | + /** |
|
| 82 | + * @return IOAuthProtocolHelper |
|
| 83 | + */ |
|
| 84 | + public function getOauthProtocolHelper() |
|
| 85 | + { |
|
| 86 | + return $this->oauthProtocolHelper; |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + /** |
|
| 90 | + * @param IOAuthProtocolHelper $oauthProtocolHelper |
|
| 91 | + */ |
|
| 92 | + public function setOauthProtocolHelper(IOAuthProtocolHelper $oauthProtocolHelper) |
|
| 93 | + { |
|
| 94 | + $this->oauthProtocolHelper = $oauthProtocolHelper; |
|
| 95 | + } |
|
| 96 | + |
|
| 97 | + /** |
|
| 98 | + * @return SiteConfiguration |
|
| 99 | + */ |
|
| 100 | + public function getSiteConfiguration() |
|
| 101 | + { |
|
| 102 | + return $this->siteConfiguration; |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + /** |
|
| 106 | + * @param SiteConfiguration $siteConfiguration |
|
| 107 | + */ |
|
| 108 | + public function setSiteConfiguration(SiteConfiguration $siteConfiguration) |
|
| 109 | + { |
|
| 110 | + $this->siteConfiguration = $siteConfiguration; |
|
| 111 | + } |
|
| 112 | + |
|
| 113 | + /** |
|
| 114 | + * @return HttpHelper |
|
| 115 | + */ |
|
| 116 | + public function getHttpHelper() |
|
| 117 | + { |
|
| 118 | + return $this->httpHelper; |
|
| 119 | + } |
|
| 120 | + |
|
| 121 | + /** |
|
| 122 | + * @param HttpHelper $httpHelper |
|
| 123 | + */ |
|
| 124 | + public function setHttpHelper(HttpHelper $httpHelper) |
|
| 125 | + { |
|
| 126 | + $this->httpHelper = $httpHelper; |
|
| 127 | + } |
|
| 128 | + |
|
| 129 | + /** |
|
| 130 | + * @return IEmailHelper |
|
| 131 | + */ |
|
| 132 | + public function getEmailHelper() |
|
| 133 | + { |
|
| 134 | + return $this->emailHelper; |
|
| 135 | + } |
|
| 136 | + |
|
| 137 | + /** |
|
| 138 | + * @param IEmailHelper $emailHelper |
|
| 139 | + */ |
|
| 140 | + public function setEmailHelper(IEmailHelper $emailHelper) |
|
| 141 | + { |
|
| 142 | + $this->emailHelper = $emailHelper; |
|
| 143 | + } |
|
| 144 | + |
|
| 145 | + /** |
|
| 146 | + * @return IrcNotificationHelper |
|
| 147 | + */ |
|
| 148 | + public function getNotificationHelper() |
|
| 149 | + { |
|
| 150 | + return $this->notificationHelper; |
|
| 151 | + } |
|
| 152 | + |
|
| 153 | + /** |
|
| 154 | + * @param IrcNotificationHelper $notificationHelper |
|
| 155 | + */ |
|
| 156 | + public function setNotificationHelper($notificationHelper) |
|
| 157 | + { |
|
| 158 | + $this->notificationHelper = $notificationHelper; |
|
| 159 | + } |
|
| 160 | + |
|
| 161 | + /** |
|
| 162 | + * @return void |
|
| 163 | + */ |
|
| 164 | + protected abstract function execute(); |
|
| 165 | + |
|
| 166 | + public function run() |
|
| 167 | + { |
|
| 168 | + $this->triggerUser = User::getById($this->job->getTriggerUserId(), $this->getDatabase()); |
|
| 169 | + |
|
| 170 | + if ($this->triggerUser === false) { |
|
| 171 | + throw new ApplicationLogicException('Cannot locate trigger user'); |
|
| 172 | + } |
|
| 173 | + |
|
| 174 | + $this->request = Request::getById($this->job->getRequest(), $this->getDatabase()); |
|
| 175 | + |
|
| 176 | + if ($this->request === false) { |
|
| 177 | + throw new ApplicationLogicException('Cannot locate request'); |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + if($this->job->getEmailTemplate() !== null){ |
|
| 181 | + $this->emailTemplate = EmailTemplate::getById($this->job->getEmailTemplate(), $this->getDatabase()); |
|
| 182 | + |
|
| 183 | + if ($this->emailTemplate === false) { |
|
| 184 | + throw new ApplicationLogicException('Cannot locate email template'); |
|
| 185 | + } |
|
| 186 | + } |
|
| 187 | + |
|
| 188 | + if($this->job->getParameters() !== null) { |
|
| 189 | + $this->parameters = json_decode($this->job->getParameters()); |
|
| 190 | + |
|
| 191 | + if (json_last_error() !== JSON_ERROR_NONE) { |
|
| 192 | + throw new ApplicationLogicException('JSON decode: ' . json_last_error_msg()); |
|
| 193 | + } |
|
| 194 | + } |
|
| 195 | + |
|
| 196 | + // Should we wait for a parent job? |
|
| 197 | + if($this->job->getParent() !== null) { |
|
| 198 | + /** @var JobQueue $parentJob */ |
|
| 199 | + $parentJob = JobQueue::getById($this->job->getParent(), $this->getDatabase()); |
|
| 200 | + |
|
| 201 | + if($parentJob === false) { |
|
| 202 | + $this->markFailed("Parent job could not be found"); |
|
| 203 | + return; |
|
| 204 | + } |
|
| 205 | + |
|
| 206 | + switch ($parentJob->getStatus()) { |
|
| 207 | + case JobQueue::STATUS_CANCELLED: |
|
| 208 | + case JobQueue::STATUS_FAILED: |
|
| 209 | + $this->markCancelled('Parent job failed/cancelled'); |
|
| 210 | + return; |
|
| 211 | + case JobQueue::STATUS_WAITING: |
|
| 212 | + case JobQueue::STATUS_READY: |
|
| 213 | + case JobQueue::STATUS_RUNNING: |
|
| 214 | + case JobQueue::STATUS_HELD: |
|
| 215 | + // Defer to next execution |
|
| 216 | + $this->job->setStatus(JobQueue::STATUS_READY); |
|
| 217 | + $this->job->save(); |
|
| 218 | + return; |
|
| 219 | + case JobQueue::STATUS_COMPLETE: |
|
| 220 | + // do nothing |
|
| 221 | + break; |
|
| 222 | + } |
|
| 223 | + } |
|
| 224 | + |
|
| 225 | + $this->execute(); |
|
| 226 | + } |
|
| 227 | + |
|
| 228 | + protected function markComplete() |
|
| 229 | + { |
|
| 230 | + $this->job->setStatus(JobQueue::STATUS_COMPLETE); |
|
| 231 | + $this->job->setError(null); |
|
| 232 | + $this->job->setAcknowledged(null); |
|
| 233 | + $this->job->save(); |
|
| 234 | + |
|
| 235 | + Logger::backgroundJobComplete($this->getDatabase(), $this->getJob()); |
|
| 236 | + } |
|
| 237 | + |
|
| 238 | + protected function markCancelled($reason = null) |
|
| 239 | + { |
|
| 240 | + $this->job->setStatus(JobQueue::STATUS_CANCELLED); |
|
| 241 | + $this->job->setError($reason); |
|
| 242 | + $this->job->setAcknowledged(null); |
|
| 243 | + $this->job->save(); |
|
| 244 | + |
|
| 245 | + Logger::backgroundJobIssue($this->getDatabase(), $this->getJob()); |
|
| 246 | + } |
|
| 247 | + |
|
| 248 | + protected function markFailed($reason = null) |
|
| 249 | + { |
|
| 250 | + $this->job->setStatus(JobQueue::STATUS_FAILED); |
|
| 251 | + $this->job->setError($reason); |
|
| 252 | + $this->job->setAcknowledged(0); |
|
| 253 | + $this->job->save(); |
|
| 254 | + |
|
| 255 | + Logger::backgroundJobIssue($this->getDatabase(), $this->getJob()); |
|
| 256 | + } |
|
| 257 | + |
|
| 258 | + /** |
|
| 259 | + * @return User |
|
| 260 | + */ |
|
| 261 | + public function getTriggerUser() |
|
| 262 | + { |
|
| 263 | + return $this->triggerUser; |
|
| 264 | + } |
|
| 265 | + |
|
| 266 | + /** |
|
| 267 | + * @return Request |
|
| 268 | + */ |
|
| 269 | + public function getRequest() |
|
| 270 | + { |
|
| 271 | + return $this->request; |
|
| 272 | + } |
|
| 273 | + |
|
| 274 | + /** |
|
| 275 | + * @return EmailTemplate |
|
| 276 | + */ |
|
| 277 | + public function getEmailTemplate() |
|
| 278 | + { |
|
| 279 | + return $this->emailTemplate; |
|
| 280 | + } |
|
| 281 | + |
|
| 282 | + /** |
|
| 283 | + * @return mixed |
|
| 284 | + */ |
|
| 285 | + public function getParameters() |
|
| 286 | + { |
|
| 287 | + return $this->parameters; |
|
| 288 | + } |
|
| 289 | 289 | } |
@@ -177,7 +177,7 @@ discard block |
||
| 177 | 177 | throw new ApplicationLogicException('Cannot locate request'); |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | - if($this->job->getEmailTemplate() !== null){ |
|
| 180 | + if ($this->job->getEmailTemplate() !== null) { |
|
| 181 | 181 | $this->emailTemplate = EmailTemplate::getById($this->job->getEmailTemplate(), $this->getDatabase()); |
| 182 | 182 | |
| 183 | 183 | if ($this->emailTemplate === false) { |
@@ -185,20 +185,20 @@ discard block |
||
| 185 | 185 | } |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | - if($this->job->getParameters() !== null) { |
|
| 188 | + if ($this->job->getParameters() !== null) { |
|
| 189 | 189 | $this->parameters = json_decode($this->job->getParameters()); |
| 190 | 190 | |
| 191 | 191 | if (json_last_error() !== JSON_ERROR_NONE) { |
| 192 | - throw new ApplicationLogicException('JSON decode: ' . json_last_error_msg()); |
|
| 192 | + throw new ApplicationLogicException('JSON decode: '.json_last_error_msg()); |
|
| 193 | 193 | } |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | 196 | // Should we wait for a parent job? |
| 197 | - if($this->job->getParent() !== null) { |
|
| 197 | + if ($this->job->getParent() !== null) { |
|
| 198 | 198 | /** @var JobQueue $parentJob */ |
| 199 | 199 | $parentJob = JobQueue::getById($this->job->getParent(), $this->getDatabase()); |
| 200 | 200 | |
| 201 | - if($parentJob === false) { |
|
| 201 | + if ($parentJob === false) { |
|
| 202 | 202 | $this->markFailed("Parent job could not be found"); |
| 203 | 203 | return; |
| 204 | 204 | } |
@@ -23,13 +23,13 @@ discard block |
||
| 23 | 23 | |
| 24 | 24 | class StatsUsers extends InternalPageBase |
| 25 | 25 | { |
| 26 | - public function main() |
|
| 27 | - { |
|
| 28 | - $this->setHtmlTitle('Users :: Statistics'); |
|
| 26 | + public function main() |
|
| 27 | + { |
|
| 28 | + $this->setHtmlTitle('Users :: Statistics'); |
|
| 29 | 29 | |
| 30 | - $database = $this->getDatabase(); |
|
| 30 | + $database = $this->getDatabase(); |
|
| 31 | 31 | |
| 32 | - $query = <<<SQL |
|
| 32 | + $query = <<<SQL |
|
| 33 | 33 | SELECT |
| 34 | 34 | u.id |
| 35 | 35 | , u.username |
@@ -45,34 +45,34 @@ discard block |
||
| 45 | 45 | WHERE u.status = 'Active' |
| 46 | 46 | SQL; |
| 47 | 47 | |
| 48 | - $users = $database->query($query)->fetchAll(PDO::FETCH_ASSOC); |
|
| 49 | - $this->assign('users', $users); |
|
| 48 | + $users = $database->query($query)->fetchAll(PDO::FETCH_ASSOC); |
|
| 49 | + $this->assign('users', $users); |
|
| 50 | 50 | |
| 51 | - $this->assign('statsPageTitle', 'Account Creation Tool users'); |
|
| 52 | - $this->setTemplate("statistics/users.tpl"); |
|
| 53 | - } |
|
| 51 | + $this->assign('statsPageTitle', 'Account Creation Tool users'); |
|
| 52 | + $this->setTemplate("statistics/users.tpl"); |
|
| 53 | + } |
|
| 54 | 54 | |
| 55 | - /** |
|
| 56 | - * Entry point for the detail action. |
|
| 57 | - * |
|
| 58 | - * @throws ApplicationLogicException |
|
| 59 | - */ |
|
| 60 | - protected function detail() |
|
| 61 | - { |
|
| 62 | - $userId = WebRequest::getInt('user'); |
|
| 63 | - if ($userId === null) { |
|
| 64 | - throw new ApplicationLogicException("User not found"); |
|
| 65 | - } |
|
| 55 | + /** |
|
| 56 | + * Entry point for the detail action. |
|
| 57 | + * |
|
| 58 | + * @throws ApplicationLogicException |
|
| 59 | + */ |
|
| 60 | + protected function detail() |
|
| 61 | + { |
|
| 62 | + $userId = WebRequest::getInt('user'); |
|
| 63 | + if ($userId === null) { |
|
| 64 | + throw new ApplicationLogicException("User not found"); |
|
| 65 | + } |
|
| 66 | 66 | |
| 67 | - $database = $this->getDatabase(); |
|
| 67 | + $database = $this->getDatabase(); |
|
| 68 | 68 | |
| 69 | - $user = User::getById($userId, $database); |
|
| 70 | - if ($user == false) { |
|
| 71 | - throw new ApplicationLogicException('User not found'); |
|
| 72 | - } |
|
| 69 | + $user = User::getById($userId, $database); |
|
| 70 | + if ($user == false) { |
|
| 71 | + throw new ApplicationLogicException('User not found'); |
|
| 72 | + } |
|
| 73 | 73 | |
| 74 | 74 | |
| 75 | - $activitySummary = $database->prepare(<<<SQL |
|
| 75 | + $activitySummary = $database->prepare(<<<SQL |
|
| 76 | 76 | SELECT COALESCE(closes.mail_desc, log.action) AS action, COUNT(*) AS count |
| 77 | 77 | FROM log |
| 78 | 78 | INNER JOIN user ON log.user = user.id |
@@ -80,14 +80,14 @@ discard block |
||
| 80 | 80 | WHERE user.username = :username |
| 81 | 81 | GROUP BY action; |
| 82 | 82 | SQL |
| 83 | - ); |
|
| 84 | - $activitySummary->execute(array(":username" => $user->getUsername())); |
|
| 85 | - $activitySummaryData = $activitySummary->fetchAll(PDO::FETCH_ASSOC); |
|
| 83 | + ); |
|
| 84 | + $activitySummary->execute(array(":username" => $user->getUsername())); |
|
| 85 | + $activitySummaryData = $activitySummary->fetchAll(PDO::FETCH_ASSOC); |
|
| 86 | 86 | |
| 87 | - $this->assign("user", $user); |
|
| 88 | - $this->assign("activity", $activitySummaryData); |
|
| 87 | + $this->assign("user", $user); |
|
| 88 | + $this->assign("activity", $activitySummaryData); |
|
| 89 | 89 | |
| 90 | - $usersCreatedQuery = $database->prepare(<<<SQL |
|
| 90 | + $usersCreatedQuery = $database->prepare(<<<SQL |
|
| 91 | 91 | SELECT log.timestamp time, request.name name, request.id id |
| 92 | 92 | FROM log |
| 93 | 93 | INNER JOIN request ON (request.id = log.objectid AND log.objecttype = 'Request') |
@@ -98,12 +98,12 @@ discard block |
||
| 98 | 98 | AND (emailtemplate.oncreated = '1' OR log.action = 'Closed custom-y') |
| 99 | 99 | ORDER BY log.timestamp; |
| 100 | 100 | SQL |
| 101 | - ); |
|
| 102 | - $usersCreatedQuery->execute(array(":username" => $user->getUsername())); |
|
| 103 | - $usersCreated = $usersCreatedQuery->fetchAll(PDO::FETCH_ASSOC); |
|
| 104 | - $this->assign("created", $usersCreated); |
|
| 101 | + ); |
|
| 102 | + $usersCreatedQuery->execute(array(":username" => $user->getUsername())); |
|
| 103 | + $usersCreated = $usersCreatedQuery->fetchAll(PDO::FETCH_ASSOC); |
|
| 104 | + $this->assign("created", $usersCreated); |
|
| 105 | 105 | |
| 106 | - $usersNotCreatedQuery = $database->prepare(<<<SQL |
|
| 106 | + $usersNotCreatedQuery = $database->prepare(<<<SQL |
|
| 107 | 107 | SELECT log.timestamp time, request.name name, request.id id |
| 108 | 108 | FROM log |
| 109 | 109 | JOIN request ON request.id = log.objectid AND log.objecttype = 'Request' |
@@ -114,54 +114,54 @@ discard block |
||
| 114 | 114 | AND (emailtemplate.oncreated = '0' OR log.action = 'Closed custom-n' OR log.action = 'Closed 0') |
| 115 | 115 | ORDER BY log.timestamp; |
| 116 | 116 | SQL |
| 117 | - ); |
|
| 118 | - $usersNotCreatedQuery->execute(array(":username" => $user->getUsername())); |
|
| 119 | - $usersNotCreated = $usersNotCreatedQuery->fetchAll(PDO::FETCH_ASSOC); |
|
| 120 | - $this->assign("notcreated", $usersNotCreated); |
|
| 121 | - |
|
| 122 | - /** @var Log[] $logs */ |
|
| 123 | - $logs = LogSearchHelper::get($database) |
|
| 124 | - ->byObjectType('User') |
|
| 125 | - ->byObjectId($user->getId()) |
|
| 126 | - ->getRecordCount($logCount) |
|
| 127 | - ->fetch(); |
|
| 128 | - |
|
| 129 | - if ($logCount === 0) { |
|
| 130 | - $this->assign('accountlog', array()); |
|
| 131 | - } |
|
| 132 | - else { |
|
| 133 | - list($users, $logData) = LogHelper::prepareLogsForTemplate($logs, $database, $this->getSiteConfiguration()); |
|
| 134 | - |
|
| 135 | - $this->assign("accountlog", $logData); |
|
| 136 | - $this->assign("users", $users); |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - $currentUser = User::getCurrent($database); |
|
| 140 | - $this->assign('canApprove', $this->barrierTest('approve', $currentUser, PageUserManagement::class)); |
|
| 141 | - $this->assign('canDecline', $this->barrierTest('decline', $currentUser, PageUserManagement::class)); |
|
| 142 | - $this->assign('canRename', $this->barrierTest('rename', $currentUser, PageUserManagement::class)); |
|
| 143 | - $this->assign('canEditUser', $this->barrierTest('editUser', $currentUser, PageUserManagement::class)); |
|
| 144 | - $this->assign('canSuspend', $this->barrierTest('suspend', $currentUser, PageUserManagement::class)); |
|
| 145 | - $this->assign('canEditRoles', $this->barrierTest('editRoles', $currentUser, PageUserManagement::class)); |
|
| 146 | - |
|
| 147 | - $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration()); |
|
| 148 | - $this->assign('oauth', $oauth); |
|
| 149 | - |
|
| 150 | - if($user->getForceIdentified() === null) { |
|
| 151 | - $idVerifier = new IdentificationVerifier($this->getHttpHelper(), $this->getSiteConfiguration(), $this->getDatabase()); |
|
| 152 | - $this->assign('identificationStatus', $idVerifier->isUserIdentified($user->getOnWikiName()) ? 'detected' : 'missing'); |
|
| 153 | - } else { |
|
| 154 | - $this->assign('identificationStatus', $user->getForceIdentified() == 1 ? 'forced-on' : 'forced-off'); |
|
| 155 | - } |
|
| 156 | - |
|
| 157 | - if ($oauth->isFullyLinked()) { |
|
| 158 | - $this->assign('identity', $oauth->getIdentity(true)); |
|
| 159 | - $this->assign('identityExpired', $oauth->identityExpired()); |
|
| 160 | - } |
|
| 161 | - |
|
| 162 | - $this->assign('statsPageTitle', 'Account Creation Tool users'); |
|
| 163 | - |
|
| 164 | - $this->setHtmlTitle('{$user->getUsername()|escape} :: Users :: Statistics'); |
|
| 165 | - $this->setTemplate("statistics/userdetail.tpl"); |
|
| 166 | - } |
|
| 117 | + ); |
|
| 118 | + $usersNotCreatedQuery->execute(array(":username" => $user->getUsername())); |
|
| 119 | + $usersNotCreated = $usersNotCreatedQuery->fetchAll(PDO::FETCH_ASSOC); |
|
| 120 | + $this->assign("notcreated", $usersNotCreated); |
|
| 121 | + |
|
| 122 | + /** @var Log[] $logs */ |
|
| 123 | + $logs = LogSearchHelper::get($database) |
|
| 124 | + ->byObjectType('User') |
|
| 125 | + ->byObjectId($user->getId()) |
|
| 126 | + ->getRecordCount($logCount) |
|
| 127 | + ->fetch(); |
|
| 128 | + |
|
| 129 | + if ($logCount === 0) { |
|
| 130 | + $this->assign('accountlog', array()); |
|
| 131 | + } |
|
| 132 | + else { |
|
| 133 | + list($users, $logData) = LogHelper::prepareLogsForTemplate($logs, $database, $this->getSiteConfiguration()); |
|
| 134 | + |
|
| 135 | + $this->assign("accountlog", $logData); |
|
| 136 | + $this->assign("users", $users); |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + $currentUser = User::getCurrent($database); |
|
| 140 | + $this->assign('canApprove', $this->barrierTest('approve', $currentUser, PageUserManagement::class)); |
|
| 141 | + $this->assign('canDecline', $this->barrierTest('decline', $currentUser, PageUserManagement::class)); |
|
| 142 | + $this->assign('canRename', $this->barrierTest('rename', $currentUser, PageUserManagement::class)); |
|
| 143 | + $this->assign('canEditUser', $this->barrierTest('editUser', $currentUser, PageUserManagement::class)); |
|
| 144 | + $this->assign('canSuspend', $this->barrierTest('suspend', $currentUser, PageUserManagement::class)); |
|
| 145 | + $this->assign('canEditRoles', $this->barrierTest('editRoles', $currentUser, PageUserManagement::class)); |
|
| 146 | + |
|
| 147 | + $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration()); |
|
| 148 | + $this->assign('oauth', $oauth); |
|
| 149 | + |
|
| 150 | + if($user->getForceIdentified() === null) { |
|
| 151 | + $idVerifier = new IdentificationVerifier($this->getHttpHelper(), $this->getSiteConfiguration(), $this->getDatabase()); |
|
| 152 | + $this->assign('identificationStatus', $idVerifier->isUserIdentified($user->getOnWikiName()) ? 'detected' : 'missing'); |
|
| 153 | + } else { |
|
| 154 | + $this->assign('identificationStatus', $user->getForceIdentified() == 1 ? 'forced-on' : 'forced-off'); |
|
| 155 | + } |
|
| 156 | + |
|
| 157 | + if ($oauth->isFullyLinked()) { |
|
| 158 | + $this->assign('identity', $oauth->getIdentity(true)); |
|
| 159 | + $this->assign('identityExpired', $oauth->identityExpired()); |
|
| 160 | + } |
|
| 161 | + |
|
| 162 | + $this->assign('statsPageTitle', 'Account Creation Tool users'); |
|
| 163 | + |
|
| 164 | + $this->setHtmlTitle('{$user->getUsername()|escape} :: Users :: Statistics'); |
|
| 165 | + $this->setTemplate("statistics/userdetail.tpl"); |
|
| 166 | + } |
|
| 167 | 167 | } |
@@ -147,7 +147,7 @@ |
||
| 147 | 147 | $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration()); |
| 148 | 148 | $this->assign('oauth', $oauth); |
| 149 | 149 | |
| 150 | - if($user->getForceIdentified() === null) { |
|
| 150 | + if ($user->getForceIdentified() === null) { |
|
| 151 | 151 | $idVerifier = new IdentificationVerifier($this->getHttpHelper(), $this->getSiteConfiguration(), $this->getDatabase()); |
| 152 | 152 | $this->assign('identificationStatus', $idVerifier->isUserIdentified($user->getOnWikiName()) ? 'detected' : 'missing'); |
| 153 | 153 | } else { |
@@ -150,7 +150,8 @@ |
||
| 150 | 150 | if($user->getForceIdentified() === null) { |
| 151 | 151 | $idVerifier = new IdentificationVerifier($this->getHttpHelper(), $this->getSiteConfiguration(), $this->getDatabase()); |
| 152 | 152 | $this->assign('identificationStatus', $idVerifier->isUserIdentified($user->getOnWikiName()) ? 'detected' : 'missing'); |
| 153 | - } else { |
|
| 153 | + } |
|
| 154 | + else { |
|
| 154 | 155 | $this->assign('identificationStatus', $user->getForceIdentified() == 1 ? 'forced-on' : 'forced-off'); |
| 155 | 156 | } |
| 156 | 157 | |