diff --git a/src/app/Observers/SignupCodeObserver.php b/src/app/Observers/SignupCodeObserver.php index aaf2783c..55126db1 100644 --- a/src/app/Observers/SignupCodeObserver.php +++ b/src/app/Observers/SignupCodeObserver.php @@ -1,58 +1,38 @@ code)) { - $code->short_code = $this->generateShortCode(); + $code->short_code = SignupCode::generateShortCode(); // FIXME: Replace this with something race-condition free while (true) { $code->code = str_random($code_length); if (!SignupCode::find($code->code)) { break; } } } $code->expires_at = Carbon::now()->addHours($exp_hours); } - - /** - * Generate a short code (for human). - * - * @return string - */ - private function generateShortCode() - { - $code_length = env('SIGNUP_CODE_LENGTH', SignupCode::SHORTCODE_LENGTH); - $code_chars = env('SIGNUP_CODE_CHARS', SignupCode::SHORTCODE_CHARS); - $random = []; - - for ($i = 1; $i <= $code_length; $i++) { - $random[] = $code_chars[rand(0, strlen($code_chars) - 1)]; - } - - shuffle($random); - - return implode('', $random); - } } diff --git a/src/app/SignupCode.php b/src/app/SignupCode.php index 8a71f907..59b56ec5 100644 --- a/src/app/SignupCode.php +++ b/src/app/SignupCode.php @@ -1,80 +1,100 @@ 'array']; /** * The attributes that should be mutated to dates. * * @var array */ protected $dates = ['expires_at']; /** * Check if code is expired. * * @return bool True if code is expired, False otherwise */ public function isExpired() { return $this->expires_at ? Carbon::now()->gte($this->expires_at) : false; } + + /** + * Generate a short code (for human). + * + * @return string + */ + public static function generateShortCode(): string + { + $code_length = env('SIGNUP_CODE_LENGTH', self::SHORTCODE_LENGTH); + $code_chars = env('SIGNUP_CODE_CHARS', self::SHORTCODE_CHARS); + $random = []; + + for ($i = 1; $i <= $code_length; $i++) { + $random[] = $code_chars[rand(0, strlen($code_chars) - 1)]; + } + + shuffle($random); + + return implode('', $random); + } } diff --git a/src/tests/Feature/SignupCodeTest.php b/src/tests/Feature/SignupCodeTest.php new file mode 100644 index 00000000..25af7323 --- /dev/null +++ b/src/tests/Feature/SignupCodeTest.php @@ -0,0 +1,43 @@ + [ + 'email' => 'User@email.org', + 'name' => 'User Name', + ] + ]; + + $now = new \DateTime('now'); + + $code = SignupCode::create($data); + + $this->assertFalse($code->isExpired()); + $this->assertTrue(strlen($code->code) === SignupCode::CODE_LENGTH); + $this->assertTrue(strlen($code->short_code) === SignupCode::SHORTCODE_LENGTH); + $this->assertSame($data['data'], $code->data); + $this->assertInstanceOf(\DateTime::class, $code->expires_at); + $this->assertSame(SignupCode::CODE_EXP_HOURS, $code->expires_at->diff($now)->h + 1); + + $inst = SignupCode::find($code->code); + + $this->assertInstanceOf(SignupCode::class, $inst); + $this->assertSame($inst->code, $code->code); + } +} diff --git a/src/tests/Unit/SignupCodeTest.php b/src/tests/Unit/SignupCodeTest.php new file mode 100644 index 00000000..d12c0cd5 --- /dev/null +++ b/src/tests/Unit/SignupCodeTest.php @@ -0,0 +1,24 @@ +assertTrue(is_string($code)); + $this->assertTrue(strlen($code) === SignupCode::SHORTCODE_LENGTH); + $this->assertTrue(strspn($code, SignupCode::SHORTCODE_CHARS) === strlen($code)); + } +}