From 4a72442fdba69fe9c66f140d7b61e04f8e6a3065 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Fri, 17 Aug 2018 17:03:38 +0800 Subject: [PATCH] Add a option for requiring player name when register --- app/Http/Controllers/AdminController.php | 1 + app/Http/Controllers/AuthController.php | 42 ++++++--- config/options.php | 1 + .../assets/src/components/auth/Register.vue | 37 +++++++- resources/assets/src/js/polyfill.js | 1 + .../tests/components/auth/Register.test.js | 41 +++++++++ resources/lang/en/front-end.yml | 3 + resources/lang/en/options.yml | 3 + resources/lang/zh_CN/front-end.yml | 3 + resources/lang/zh_CN/options.yml | 3 + resources/views/auth/register.tpl | 10 +++ tests/AuthControllerTest.php | 88 +++++++++++++++++-- 12 files changed, 214 insertions(+), 19 deletions(-) diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 346332b5..3d2f9c05 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -172,6 +172,7 @@ class AdminController extends Controller }); $form->checkbox('user_can_register')->label(); + $form->checkbox('register_with_player_name')->label(); $form->checkbox('require_verification')->label(); $form->text('regs_per_ip'); diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 6e1ac4ed..ae568978 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -11,6 +11,7 @@ use Cache; use Session; use App\Events; use App\Models\User; +use App\Models\Player; use App\Mail\ForgotPassword; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -91,23 +92,33 @@ class AuthController extends Controller public function handleRegister(Request $request) { - $data = $this->validate($request, [ - 'email' => 'required|email|unique:users', - 'password' => 'required|min:8|max:32', - 'nickname' => 'required|no_special_chars|max:255', - 'captcha' => 'required'.(app()->environment('testing') ? '' : '|captcha') - ]); - if (! option('user_can_register')) { return json(trans('auth.register.close'), 7); } + $rule = option('register_with_player_name') ? + ['player_name' => 'required|player_name|min:'.option('player_name_length_min').'|max:'.option('player_name_length_max')] : + ['nickname' => 'required|no_special_chars|max:255']; + $data = $this->validate($request, array_merge([ + 'email' => 'required|email|unique:users', + 'password' => 'required|min:8|max:32', + 'captcha' => 'required'.(app()->environment('testing') ? '' : '|captcha') + ], $rule)); + + if (option('register_with_player_name')) { + event(new Events\CheckPlayerExists($request->get('player_name'))); + + if (Player::where('player_name', $request->get('player_name'))->first()) { + return json(trans('user.player.add.repeated'), 2); + } + } + // If amount of registered accounts of IP is more than allowed amounts, // reject the registration. if (User::where('ip', Utils::getClientIp())->count() < option('regs_per_ip')) { $user = new User; $user->email = $data['email']; - $user->nickname = $data['nickname']; + $user->nickname = $data[option('register_with_player_name') ? 'player_name' : 'nickname']; $user->score = option('user_initial_score'); $user->avatar = 0; $user->password = User::getEncryptedPwdFromEvent($data['password'], $user) @@ -121,11 +132,22 @@ class AuthController extends Controller event(new Events\UserRegistered($user)); + if (option('register_with_player_name')) { + $player = new Player; + $player->uid = $user->uid; + $player->player_name = $request->get('player_name'); + $player->preference = 'default'; + $player->last_modified = Utils::getTimeFormatted(); + $player->save(); + + event(new Events\PlayerWasAdded($player)); + } + Auth::login($user); return json([ - 'errno' => 0, - 'msg' => trans('auth.register.success') + 'errno' => 0, + 'msg' => trans('auth.register.success') ]); } else { diff --git a/config/options.php b/config/options.php index dccfc3b6..72ea224a 100644 --- a/config/options.php +++ b/config/options.php @@ -5,6 +5,7 @@ return [ 'site_name' => 'Blessing Skin', 'site_description' => 'Open-source PHP Minecraft Skin Hosting Service', 'user_can_register' => 'true', + 'register_with_player_name' => 'true', 'require_verification' => 'false', 'regs_per_ip' => '3', 'ip_get_method' => '0', diff --git a/resources/assets/src/components/auth/Register.vue b/resources/assets/src/components/auth/Register.vue index e35394b2..75a7e2c8 100644 --- a/resources/assets/src/components/auth/Register.vue +++ b/resources/assets/src/components/auth/Register.vue @@ -32,6 +32,23 @@
+ + +
+
{ jest.spyOn(Date, 'now'); const wrapper = mount(Register); @@ -12,6 +14,16 @@ test('click to refresh captcha', () => { expect(Date.now).toHaveBeenCalledTimes(2); }); +test('require player name', () => { + window.__bs_data__ = { player: true }; + + const wrapper = mount(Register); + expect(wrapper.findAll('[type="text"]').at(0).attributes()) + .toHaveProperty('placeholder', 'auth.player-name'); + + window.__bs_data__ = { player: false }; +}); + test('register', async () => { jest.spyOn(Date, 'now'); Vue.prototype.$http.post @@ -81,3 +93,32 @@ test('register', async () => { jest.runAllTimers(); expect(swal).toBeCalledWith({ type: 'success', text: 'ok' }); }); + +test('register with player name', async () => { + window.__bs_data__ = { player: true }; + Vue.prototype.$http.post.mockResolvedValue({ errno: 0, msg: 'ok' }); + const wrapper = mount(Register); + const button = wrapper.find('button'); + const info = wrapper.find('.callout-info'); + wrapper.find('[type="email"]').setValue('a@b.c'); + wrapper.findAll('[type="password"]').at(0).setValue('12345678'); + wrapper.findAll('[type="password"]').at(1).setValue('12345678'); + wrapper.findAll('[type="text"]').at(1).setValue('captcha'); + + button.trigger('click'); + expect(Vue.prototype.$http.post).not.toBeCalled(); + expect(info.text()).toBe('auth.emptyPlayerName'); + + wrapper.findAll('[type="text"]').at(0).setValue('abc'); + button.trigger('click'); + await wrapper.vm.$nextTick(); + expect(Vue.prototype.$http.post).toBeCalledWith( + '/auth/register', + { + email: 'a@b.c', + password: '12345678', + player_name: 'abc', + captcha: 'captcha' + } + ); +}); diff --git a/resources/lang/en/front-end.yml b/resources/lang/en/front-end.yml index bad54087..aabfd20a 100644 --- a/resources/lang/en/front-end.yml +++ b/resources/lang/en/front-end.yml @@ -11,6 +11,7 @@ auth: emptyConfirmPwd: Empty confirming password. invalidConfirmPwd: Confirming password is not equal with password. emptyNickname: Empty nickname. + emptyPlayerName: Empty player name. register: Register registering: Registering send: Send @@ -18,6 +19,7 @@ auth: reset: Reset resetting: Resetting nickname: Nickname + player-name: Minecraft player name email: Email identification: Email or player name password: Password @@ -28,6 +30,7 @@ auth: keep: Remember me repeat-pwd: Repeat your password nickname-intro: Whatever you like expect special characters + player-name-intro: Player name in Minecraft, can be changed later register-button: Register forgot: login-link: I do remember it diff --git a/resources/lang/en/options.yml b/resources/lang/en/options.yml index e797b0eb..faa63bc0 100644 --- a/resources/lang/en/options.yml +++ b/resources/lang/en/options.yml @@ -75,6 +75,9 @@ general: user_can_register: title: Open Registration label: Everyone is allowed to register. + register_with_player_name: + title: Register with Player Name + label: Require Minecraft's player name when user register require_verification: title: Account Verification label: Users must verify their email address first. diff --git a/resources/lang/zh_CN/front-end.yml b/resources/lang/zh_CN/front-end.yml index 551d8bf7..fc54efdf 100644 --- a/resources/lang/zh_CN/front-end.yml +++ b/resources/lang/zh_CN/front-end.yml @@ -11,6 +11,7 @@ auth: emptyConfirmPwd: 确认密码不能为空 invalidConfirmPwd: 密码和确认的密码不一样诶? emptyNickname: 你还没有填写昵称哦 + emptyPlayerName: 你还没有填写角色名哦 register: 注册 registering: 注册中 send: 发送 @@ -19,6 +20,7 @@ auth: resetting: 重置中 nickname: 昵称 email: Email + player-name: 游戏内角色名 identification: Email 或角色名 password: 密码 captcha: 请输入验证码 @@ -28,6 +30,7 @@ auth: keep: 记住我 repeat-pwd: 重复密码 nickname-intro: 昵称可使用汉字,不可包含特殊字符 + player-name-intro: 游戏内的角色名,注册后可修改 register-button: 注册 forgot: login-link: 我又想起来了 diff --git a/resources/lang/zh_CN/options.yml b/resources/lang/zh_CN/options.yml index ea62b69c..d5050405 100644 --- a/resources/lang/zh_CN/options.yml +++ b/resources/lang/zh_CN/options.yml @@ -75,6 +75,9 @@ general: user_can_register: title: 开放注册 label: 任何人都可以注册 + register_with_player_name: + title: 使用角色名注册 + label: 注册时要求填写游戏内角色名 require_verification: title: 邮箱验证 label: 用户必须验证邮箱后才能使用皮肤托管等功能 diff --git a/resources/views/auth/register.tpl b/resources/views/auth/register.tpl index a0dae36d..a5ab95eb 100644 --- a/resources/views/auth/register.tpl +++ b/resources/views/auth/register.tpl @@ -18,4 +18,14 @@
+ @endsection diff --git a/tests/AuthControllerTest.php b/tests/AuthControllerTest.php index 16593d64..f7cd5712 100644 --- a/tests/AuthControllerTest.php +++ b/tests/AuthControllerTest.php @@ -247,19 +247,82 @@ class AuthControllerTest extends TestCase [ 'email' => 'a@b.c', 'password' => str_random(33) - ], - ['X-Requested-With' => 'XMLHttpRequest'] + ] )->assertJson([ 'errno' => 1, 'msg' => trans('validation.max.string', ['attribute' => 'password', 'max' => 32]) ]); + // The register_with_player_name option is set to true by default. + // Should return a warning if `player_name` is empty + $this->postJson( + '/auth/register', + [ + 'email' => 'a@b.c', + 'password' => '12345678', + 'captcha' => 'a' + ] + )->assertJson([ + 'errno' => 1, + 'msg' => trans('validation.required', ['attribute' => 'Player Name']) + ]); + + // Should return a warning if `player_name` is invalid + option(['player_name_rule' => 'official']); + $this->postJson( + '/auth/register', + [ + 'email' => 'a@b.c', + 'password' => '12345678', + 'player_name' => '角色名', + 'captcha' => 'a' + ] + )->assertJson([ + 'errno' => 1, + 'msg' => trans('validation.player_name', ['attribute' => 'Player Name']) + ]); + + // Should return a warning if `player_name` is too long + $this->postJson( + '/auth/register', + [ + 'email' => 'a@b.c', + 'password' => '12345678', + 'player_name' => str_random(option('player_name_length_max') + 10), + 'captcha' => 'a' + ] + )->assertJson([ + 'errno' => 1, + 'msg' => trans('validation.max.string', [ + 'attribute' => 'Player Name', + 'max' => option('player_name_length_max') + ]) + ]); + + // Existed player + $player = factory(Player::class)->create(); + $this->postJson( + '/auth/register', + [ + 'email' => 'a@b.c', + 'password' => '12345678', + 'player_name' => $player->player_name, + 'captcha' => 'a' + ] + )->assertJson([ + 'errno' => 2, + 'msg' => trans('user.player.add.repeated') + ]); + + option(['register_with_player_name' => false]); + // Should return a warning if `nickname` is empty $this->postJson( '/auth/register', [ 'email' => 'a@b.c', - 'password' => '12345678' + 'password' => '12345678', + 'captcha' => 'a' ], ['X-Requested-With' => 'XMLHttpRequest'] )->assertJson([ @@ -273,7 +336,8 @@ class AuthControllerTest extends TestCase [ 'email' => 'a@b.c', 'password' => '12345678', - 'nickname' => '\\' + 'nickname' => '\\', + 'captcha' => 'a' ], ['X-Requested-With' => 'XMLHttpRequest'] )->assertJson([ @@ -287,7 +351,8 @@ class AuthControllerTest extends TestCase [ 'email' => 'a@b.c', 'password' => '12345678', - 'nickname' => str_random(256) + 'nickname' => str_random(256), + 'captcha' => 'a' ], ['X-Requested-With' => 'XMLHttpRequest'] )->assertJson([ @@ -370,6 +435,19 @@ class AuthControllerTest extends TestCase 'permission' => User::NORMAL ]); $this->assertAuthenticated(); + + // Require player name + option(['register_with_player_name' => false]); + $this->postJson( + '/auth/register', + [ + 'email' => 'a@b.c', + 'password' => '12345678', + 'player_name' => 'name', + 'captcha' => 'a' + ] + ); + $this->assertNotNull(Player::where('player_name', 'name')); } public function testForgot()