diff --git a/lib/Controller/AccountController.php b/lib/Controller/AccountController.php index 663bde760ee071a9224a505dd033342ae7a67909..8f9c849bdeca3fcaa757f7ecf434261f7be3d9ea 100644 --- a/lib/Controller/AccountController.php +++ b/lib/Controller/AccountController.php @@ -30,7 +30,7 @@ class AccountController extends Controller { private $session; private $userSession; private $urlGenerator; - + private const SESSION_USERNAME_CHECK = 'username_check_passed'; private const CAPTCHA_VERIFIED_CHECK = 'captcha_verified'; public function __construct( @@ -99,6 +99,12 @@ class AccountController extends Controller { return $response; } + if (!$this->session->get(self::SESSION_USERNAME_CHECK)) { + $response->setData(['message' => 'Username is already taken.', 'success' => false]); + $response->setStatus(400); + return $response; + } + $inputData = [ 'username' => ['value' => $username, 'maxLength' => 30], 'displayname' => ['value' => $displayname, 'maxLength' => 30], @@ -139,7 +145,15 @@ class AccountController extends Controller { $response->setData(['message' => $e->getMessage(), 'success' => false]); $response->setStatus(500); } + + $this->session->remove(self::SESSION_USERNAME_CHECK); $this->session->remove(self::CAPTCHA_VERIFIED_CHECK); + + try { + $this->userService->addUsernameToCommonDataStore($username); + } catch (Exception $e) { + $this->logger->logException($e, ['app' => Application::APP_ID]); + } return $response; } /** @@ -176,9 +190,21 @@ class AccountController extends Controller { public function checkUsernameAvailable(string $username) : DataResponse { $response = new DataResponse(); $response->setStatus(400); - if (!$this->userService->userExists($username)) { - $response->setStatus(200); + + if (empty($username)) { + return $response; + } + + try { + if (!$this->userService->userExists($username) && !$this->userService->isUsernameTaken($username)) { + $response->setStatus(200); + $this->session->set(self::SESSION_USERNAME_CHECK, true); + } + } catch (Exception $e) { + $this->logger->logException($e, ['app' => Application::APP_ID ]); + $response->setStatus(500); } + return $response; } @@ -208,10 +234,10 @@ class AccountController extends Controller { public function verifyCaptcha(string $captchaInput = '') : DataResponse { $response = new DataResponse(); - $captchaResult = (string)$this->session->get('captcha_result', ''); + $captchaResult = (string) $this->session->get(CaptchaService::CAPTCHA_RESULT_KEY, ''); $response->setStatus(400); if ($captchaResult === $captchaInput) { - $this->session->remove('captcha_result'); + $this->session->remove(CaptchaService::CAPTCHA_RESULT_KEY); $this->session->set(self::CAPTCHA_VERIFIED_CHECK, true); $response->setStatus(200); } diff --git a/lib/Service/CaptchaService.php b/lib/Service/CaptchaService.php index 4bc4245dd51867f16705779c5643762304d51283..1a0ea4b6529162461ffc0d13618cb2a8ad34df4c 100644 --- a/lib/Service/CaptchaService.php +++ b/lib/Service/CaptchaService.php @@ -8,11 +8,12 @@ use OCP\ISession; class CaptchaService { private $session; - public const WIDTH = 80; - public const HEIGHT = 40; - public const NUMBERS = '123456789'; - public const SYMBOLS = '+-'; - public const NOISE_LEVEL = 13; + private const WIDTH = 80; + private const HEIGHT = 40; + private const NUMBERS = '123456789'; + private const SYMBOLS = '+-'; + private const NOISE_LEVEL = 13; + public const CAPTCHA_RESULT_KEY = 'captcha_result'; public function __construct(ISession $session) { $this->session = $session; @@ -195,7 +196,7 @@ class CaptchaService { * @return void */ private function updateSession(float $captchaResult): void { - $this->session->set('captcha_result', $captchaResult); + $this->session->set(self::CAPTCHA_RESULT_KEY, $captchaResult); } diff --git a/lib/Service/CurlService.php b/lib/Service/CurlService.php index d7a477fc51e251c3ff991f4f090f324963c7c812..d3b132d500d7368f85a599708f8c41bbf76d3ca0 100644 --- a/lib/Service/CurlService.php +++ b/lib/Service/CurlService.php @@ -14,6 +14,8 @@ namespace OCA\EcloudAccounts\Service; use Exception; class CurlService { + + private int $lastStatusCode = 0; /** * GET alias for request method * @@ -44,6 +46,14 @@ class CurlService { return $this->request('DELETE', $url, $params, $headers, $userOptions); } + /** + * @return int + */ + + public function getLastStatusCode() : int { + return $this->lastStatusCode; + } + /** * Curl run request @@ -90,6 +100,9 @@ class CurlService { $response = curl_exec($ch); + $this->lastStatusCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); + + if ($errno = curl_errno($ch)) { var_dump($errno); $errorMessage = curl_strerror($errno); diff --git a/lib/Service/UserService.php b/lib/Service/UserService.php index f35b6e6e3d5c59806c85afd844e35908bcc8d07e..dbda65c47ace65ce1a51e215136f085ea952163b 100644 --- a/lib/Service/UserService.php +++ b/lib/Service/UserService.php @@ -393,4 +393,59 @@ class UserService { $quota = strval($quota) . ' MB'; $user->setQuota($quota); } + + public function isUsernameTaken(string $username) : bool { + $commonApiUrl = $this->apiConfig['commonApiUrl']; + $commonApiVersion = $this->apiConfig['commonApiVersion']; + + if (!isset($commonApiUrl) || empty($commonApiUrl)) { + return false; + } + $endpoint = $commonApiVersion . '/users/'; + $url = $commonApiUrl . $endpoint . $username; + + $token = $this->apiConfig['commonServiceToken']; + $headers = [ + "Authorization: Bearer $token" + ]; + + $this->curl->get($url, [], $headers); + + $statusCode = $this->curl->getLastStatusCode(); + if ($statusCode === 404) { + return false; + } + + if ($statusCode === 200) { + return true; + } + + throw new Exception("Error checking if username is taken at common source, status code: " . (string) $statusCode); + } + + public function addUsernameToCommonDataStore(string $username) : void { + $commonApiUrl = $this->apiConfig['commonApiUrl']; + $commonApiVersion = $this->apiConfig['commonApiVersion']; + + if (!isset($commonApiUrl) || empty($commonApiUrl)) { + return; + } + $endpoint = $commonApiVersion . '/users/'; + $url = $commonApiUrl . $endpoint ; + + $params = [ + 'username' => $username + ]; + + $token = $this->apiConfig['commonServiceToken']; + $headers = [ + "Authorization: Bearer $token" + ]; + + $this->curl->post($url, $params, $headers); + + if ($this->curl->getLastStatusCode() !== 200) { + throw new Exception('Error adding username ' . $username . ' to common data store'); + } + } } diff --git a/src/signup/RegistrationForm.vue b/src/signup/RegistrationForm.vue index 3a5f091be282a97fd2f467fa6a1ef26bde636aa8..ff81f3d7da1263e8ab610bd2a27b94a285f35a5f 100644 --- a/src/signup/RegistrationForm.vue +++ b/src/signup/RegistrationForm.vue @@ -289,9 +289,9 @@ export default { } } }, - submitRegistrationForm() { + async submitRegistrationForm() { this.validateForm(['displayname', 'username', 'password', 'repassword', 'termsandservices']) - this.checkUsername() + await this.checkUsername() const isFormValid = Object.values(this.validation).every(value => !value) if (isFormValid) {