diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 8b0faa02..7a694e2a 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -233,8 +233,14 @@ class AdminController extends Controller $form->textarea('meta_extras')->rows(6); })->handle(); + $recaptcha = Option::form('recaptcha', 'reCAPTCHA', function ($form) { + $form->text('recaptcha_sitekey', 'sitekey'); + $form->text('recaptcha_secretkey', 'secretkey'); + $form->checkbox('recaptcha_mirror')->label(); + })->handle(); + return view('admin.options') - ->with('forms', compact('general', 'announ', 'meta')); + ->with('forms', compact('general', 'announ', 'meta', 'recaptcha')); } public function resource(Request $request) diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index fe75e91e..ce0de1c3 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -10,6 +10,7 @@ use Session; use App\Events; use App\Models\User; use App\Models\Player; +use App\Rules\Captcha; use App\Mail\ForgotPassword; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -43,7 +44,7 @@ class AuthController extends Controller $loginFails = (int) Cache::get($loginFailsCacheKey, 0); if ($loginFails > 3) { - $this->validate($request, ['captcha' => 'required|captcha']); + $this->validate($request, ['captcha' => ['required', new Captcha]]); } if (! $user) { @@ -83,7 +84,12 @@ class AuthController extends Controller public function register() { if (option('user_can_register')) { - return view('auth.register', ['extra' => ['player' => option('register_with_player_name')]]); + return view('auth.register', [ + 'extra' => [ + 'player' => option('register_with_player_name'), + 'recaptcha' => option('recaptcha_sitekey'), + ] + ]); } else { throw new PrettyPageException(trans('auth.register.close'), 7); } @@ -101,7 +107,7 @@ class AuthController extends Controller $data = $this->validate($request, array_merge([ 'email' => 'required|email|unique:users', 'password' => 'required|min:8|max:32', - 'captcha' => 'required'.(app()->environment('testing') ? '' : '|captcha'), + 'captcha' => ['required', new Captcha], ], $rule)); if (option('register_with_player_name')) { diff --git a/app/Rules/Captcha.php b/app/Rules/Captcha.php new file mode 100644 index 00000000..9a1e4190 --- /dev/null +++ b/app/Rules/Captcha.php @@ -0,0 +1,43 @@ +environment('testing')) { + return true; + } + + $secretkey = option('recaptcha_secretkey'); + if ($secretkey) { + $client = new \GuzzleHttp\Client(); + $url = option('recaptcha_mirror') + ? 'https://www.recaptcha.net/recaptcha/api/siteverify' + : 'https://www.google.com/recaptcha/api/siteverify'; + $response = $client->post($url, [ + 'form_params' => [ + 'secret' => $secretkey, + 'response' => $value, + ] + ]); + if ($response->getStatusCode() == 200) { + $body = json_decode((string) $response->getBody()); + return $body->success; + } + return false; + } + + return captcha_check($value); + } + + public function message() + { + return option('recaptcha_secretkey') + ? trans('validation.recaptcha') + : trans('validation.captcha'); + } +} diff --git a/config/options.php b/config/options.php index ac9c7eb6..a36ff41c 100644 --- a/config/options.php +++ b/config/options.php @@ -50,4 +50,7 @@ return [ 'meta_description' => '', 'meta_extras' => '', 'cdn_address' => '', + 'recaptcha_sitekey' => '', + 'recaptcha_secretkey' => '', + 'recaptcha_mirror' => 'false', ]; diff --git a/package.json b/package.json index a71c57e5..bcecde8b 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "toastr": "^2.1.4", "vue": "^2.6.9", "vue-good-table": "^2.16.3", + "vue-recaptcha": "^1.1.1", "vue-upload-component": "^2.8.19", "vuejs-paginate": "^2.1.0" }, diff --git a/resources/assets/src/components/Captcha.vue b/resources/assets/src/components/Captcha.vue new file mode 100644 index 00000000..18b04eb4 --- /dev/null +++ b/resources/assets/src/components/Captcha.vue @@ -0,0 +1,59 @@ + + + diff --git a/resources/assets/src/components/mixins/updateCaptcha.ts b/resources/assets/src/components/mixins/updateCaptcha.ts new file mode 100644 index 00000000..b74fb54e --- /dev/null +++ b/resources/assets/src/components/mixins/updateCaptcha.ts @@ -0,0 +1,12 @@ +import Vue from 'vue' + +export default Vue.extend({ + data: () => ({ + captcha: '', + }), + methods: { + updateCaptcha(value: string) { + this.captcha = value + }, + }, +}) diff --git a/resources/assets/src/views/auth/Login.vue b/resources/assets/src/views/auth/Login.vue index c4dcf0df..52617def 100644 --- a/resources/assets/src/views/auth/Login.vue +++ b/resources/assets/src/views/auth/Login.vue @@ -21,30 +21,7 @@ -
-
-
- -
-
-
- CAPTCHA -
-
+
{{ infoMsg }}
{{ warningMsg }}
@@ -81,9 +58,17 @@ diff --git a/resources/assets/src/views/auth/Register.vue b/resources/assets/src/views/auth/Register.vue index 20a62648..7dde105b 100644 --- a/resources/assets/src/views/auth/Register.vue +++ b/resources/assets/src/views/auth/Register.vue @@ -64,30 +64,7 @@