├── .gitignore
├── version.php
├── src
├── DcatAuthGoogle2FaServiceProvider.php
├── Models
│ └── AdminUser.php
└── Http
│ ├── routes.php
│ └── Controllers
│ ├── Actions
│ ├── UnbindRowAction.php
│ └── BindRowAction.php
│ ├── DcatAuthGoogle2FaUserController.php
│ └── DcatAuthGoogle2FaAuthController.php
├── LICENSE
├── resources
├── lang
│ ├── zh-CN
│ │ └── dcat-auth-google-2fa.php
│ ├── zh_CN
│ │ └── dcat-auth-google-2fa.php
│ └── en
│ │ └── dcat-auth-google-2fa.php
└── views
│ └── login.blade.php
├── composer.json
├── updates
└── 2021_08_21_120702_add_google_two_fa_secret_to_admin_users_table.php
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | phpunit.phar
3 | /vendor
4 | composer.phar
5 | composer.lock
6 | *.project
7 | .idea/
--------------------------------------------------------------------------------
/version.php:
--------------------------------------------------------------------------------
1 | [
5 | 'Dcat-Admin 登录 Google 2FA两步验证第一版',
6 | '2021_08_21_120702_add_google_two_fa_secret_to_admin_users_table.php',
7 | ],
8 | ];
9 |
--------------------------------------------------------------------------------
/src/DcatAuthGoogle2FaServiceProvider.php:
--------------------------------------------------------------------------------
1 | '两步验证码',
5 | '2fa_bind' => '绑定两步验证',
6 | '2fa_bind_confirm' => '确认要绑定该用户的两步验证吗?',
7 | '2fa_bind_success' => '绑定操作成功',
8 | '2fa_unbind' => '解绑两步验证',
9 | '2fa_unbind_confirm' => '确认要解绑该用户的两步验证吗?',
10 | '2fa_unbind_success' => '解绑操作成功',
11 | 'check_code_error' => '您输入的验证码不正确',
12 | 'google_2fa' => '两步验证',
13 | 'google_2fa_code' => '两步验证验证码',
14 | 'google_2fa_code_enable_help' => '请输入两步验证码,只有验证通过方可绑定',
15 | 'google_2fa_code_tips' => '请输入验证码(如有设置则必填)',
16 | 'google_2fa_code_disable_button' => '若要解绑两步验证,请将开关关闭',
17 | 'google_2fa_code_disable_help' => '请输入两步验证码,只有验证通过方可解绑',
18 | 'google_2fa_qrcode' => '两步验证二维码',
19 | 'google_2fa_qrcode_help' => '若要绑定两步验证,请扫描二维码',
20 | 'login_code_error' => '登录失败,您输入的验证码不正确',
21 | 'login_need_code' => '登录失败,请输入两步验证验证码',
22 | 'login_status_false' => '登录失败,您的账号已禁用',
23 | 'message' => '提示',
24 | 'status' => '账号状态',
25 | 'qrcode_service_tips' => '您需要安装二维码扩展包方可正常使用,访问网址查看说明。https://github.com/asundust/dcat-auth-google-2fa#%E9%87%8D%E8%A6%81%E8%AF%B4%E6%98%8E',
26 | ];
27 |
--------------------------------------------------------------------------------
/resources/lang/zh_CN/dcat-auth-google-2fa.php:
--------------------------------------------------------------------------------
1 | '两步验证码',
5 | '2fa_bind' => '绑定两步验证',
6 | '2fa_bind_confirm' => '确认要绑定该用户的两步验证吗?',
7 | '2fa_bind_success' => '绑定操作成功',
8 | '2fa_unbind' => '解绑两步验证',
9 | '2fa_unbind_confirm' => '确认要解绑该用户的两步验证吗?',
10 | '2fa_unbind_success' => '解绑操作成功',
11 | 'check_code_error' => '您输入的验证码不正确',
12 | 'google_2fa' => '两步验证',
13 | 'google_2fa_code' => '两步验证验证码',
14 | 'google_2fa_code_enable_help' => '请输入两步验证码,只有验证通过方可绑定',
15 | 'google_2fa_code_tips' => '请输入验证码(如有设置则必填)',
16 | 'google_2fa_code_disable_button' => '若要解绑两步验证,请将开关关闭',
17 | 'google_2fa_code_disable_help' => '请输入两步验证码,只有验证通过方可解绑',
18 | 'google_2fa_qrcode' => '两步验证二维码',
19 | 'google_2fa_qrcode_help' => '若要绑定两步验证,请扫描二维码',
20 | 'login_code_error' => '登录失败,您输入的验证码不正确',
21 | 'login_need_code' => '登录失败,请输入两步验证验证码',
22 | 'login_status_false' => '登录失败,您的账号已禁用',
23 | 'message' => '提示',
24 | 'status' => '账号状态',
25 | 'qrcode_service_tips' => '您需要安装二维码扩展包方可正常使用,访问网址查看说明。https://github.com/asundust/dcat-auth-google-2fa#%E9%87%8D%E8%A6%81%E8%AF%B4%E6%98%8E',
26 | ];
27 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asundust/dcat-auth-google-2fa",
3 | "alias": "Auth Google 2FA两步验证",
4 | "description": "Dcat-Admin auth verification by Google 2FA / Dcat-Admin 登录 Google 2FA两步验证",
5 | "type": "library",
6 | "keywords": [
7 | "dcat-admin",
8 | "extension",
9 | "google",
10 | "auth",
11 | "2fa",
12 | "login",
13 | "captcha"
14 | ],
15 | "homepage": "https://github.com/asundust/dcat-auth-google-2fa",
16 | "license": "MIT",
17 | "authors": [
18 | {
19 | "name": "asundust",
20 | "email": "asundust@qq.com"
21 | }
22 | ],
23 | "require": {
24 | "php": ">=7.1.0",
25 | "dcat/laravel-admin": "~2.0",
26 | "pragmarx/google2fa-qrcode": "^2.0|^3.0"
27 | },
28 | "autoload": {
29 | "psr-4": {
30 | "Asundust\\DcatAuthGoogle2Fa\\": "src/"
31 | }
32 | },
33 | "extra": {
34 | "dcat-admin": "Asundust\\DcatAuthGoogle2Fa\\DcatAuthGoogle2FaServiceProvider",
35 | "laravel": {
36 | "providers": [
37 | "Asundust\\DcatAuthGoogle2Fa\\DcatAuthGoogle2FaServiceProvider"
38 | ]
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Http/Controllers/Actions/UnbindRowAction.php:
--------------------------------------------------------------------------------
1 | where('id', $this->getKey())->update(['google_two_fa_secret' => null, 'google_two_fa_enable' => AdminUser::GOOGLE_TWO_FA_ENABLE_FALSE]);
26 | return $this->response()->success(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_unbind_success'))->refresh();
27 | }
28 |
29 |
30 | /**
31 | * @return string[]
32 | */
33 | public function confirm()
34 | {
35 | return [
36 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.message'),
37 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_unbind_confirm'),
38 | ];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/updates/2021_08_21_120702_add_google_two_fa_secret_to_admin_users_table.php:
--------------------------------------------------------------------------------
1 | config('database.users_table'), function (Blueprint $table) {
22 | if (Schema::hasColumns($this->config('database.users_table'), ['remember_token'])) {
23 | $table->string('google_two_fa_secret', 32)->nullable()->after('remember_token');
24 | } else {
25 | $table->string('google_two_fa_secret', 32)->nullable();
26 | }
27 | $table->boolean('google_two_fa_enable')->default(0)->index()->after('google_two_fa_secret');
28 | $table->boolean('status')->default(1)->index()->after('google_two_fa_enable');
29 | });
30 | }
31 |
32 | /**
33 | * Reverse the migrations.
34 | *
35 | * @return void
36 | */
37 | public function down()
38 | {
39 | Schema::table($this->config('database.users_table'), function (Blueprint $table) {
40 | $table->dropColumn('google_two_fa_secret');
41 | $table->dropColumn('google_two_fa_enable');
42 | $table->dropColumn('status');
43 | });
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Dcat-Admin 登录 Google 2FA两步验证 / Dcat-Admin auth verification by Google 2FA
2 | ======
3 |
4 | 
5 |
6 | Dcat-Admin 登录 Google 2FA两步验证
7 |
8 | 
9 |
10 | ### 重要说明!!!
11 |
12 | - 本包依赖于[pragmarx/google2fa-qrcode](https://packagist.org/packages/pragmarx/google2fa-qrcode),该包的二维码依赖是可选扩展包,默认支持[bacon/bacon-qr-code](https://packagist.org/packages/bacon/bacon-qr-code)、[chillerlan/php-qrcode](https://packagist.org/packages/chillerlan/php-qrcode)扩展,需要手动安装,为了兼容性考虑,请选择下方的其中一个扩展安装即可。
13 | - 以上参见说明:[#3](https://github.com/asundust/dcat-auth-google-2fa/issues/3) [https://github.com/antonioribeiro/google2fa-qrcode#built-in-qrcode-rendering-services](https://github.com/antonioribeiro/google2fa-qrcode#built-in-qrcode-rendering-services)
14 | ```
15 | composer require bacon/bacon-qr-code
16 | ```
17 | ```
18 | composer require chillerlan/php-qrcode
19 | ```
20 |
21 | ### 安装
22 |
23 | ```
24 | composer require asundust/dcat-auth-google-2fa
25 | ```
26 |
27 | ### 说明
28 |
29 | - 本应用暂不支持Dact-Admin`1.*`版本,也不考虑支持。
30 | - Dact-Admin`1.*`版本可以使用[https://github.com/changzhong/extension-google-authenticator](https://github.com/changzhong/extension-google-authenticator)
31 | - 本项目也是因为看到目前插件空缺才补上,代码参考上述项目。
32 |
33 | ### 主要功能
34 |
35 | - 登录页谷歌2FA认证
36 | - 支持自助绑定解绑
37 | - 管理员可以绑定解绑
38 | - 支持简体中文及英语
39 |
40 | ### 支持
41 |
42 | 如果觉得这个项目帮你节约了时间,不妨支持一下呗!
43 |
44 | 
45 | 
46 |
47 | ### License
48 |
49 | [The MIT License (MIT)](https://opensource.org/licenses/MIT)
50 |
--------------------------------------------------------------------------------
/resources/lang/en/dcat-auth-google-2fa.php:
--------------------------------------------------------------------------------
1 | 'Google 2FA Code',
5 | '2fa_bind' => 'Binding Google 2FA',
6 | '2fa_bind_confirm' => 'Are you sure you want to bind the user\'s Google 2FA?',
7 | '2fa_bind_success' => 'The binding operation was successful',
8 | '2fa_unbind' => 'Unbinding Google 2FA',
9 | '2fa_unbind_confirm' => 'Are you sure you want to unbind the user\'s Google 2FA?',
10 | '2fa_unbind_success' => 'The unbinding operation was successful',
11 | 'check_code_error' => 'The Google 2FA code you entered is incorrect',
12 | 'google_2fa' => 'Google 2FA',
13 | 'google_2fa_code' => 'Google 2FA code',
14 | 'google_2fa_code_enable_help' => 'Please enter the Google 2FA code, Only after verification is passed can you bind it',
15 | 'google_2fa_code_disable_button' => 'To unbind Google 2FA, please turn off the switch',
16 | 'google_2fa_code_disable_help' => 'Please enter the Google 2FA code, Only after verification is passed can the binding be unbound',
17 | 'google_2fa_code_tips' => 'Please enter the Google 2FA code (Required if set)',
18 | 'google_2fa_qrcode' => 'Google 2FA of QR code',
19 | 'google_2fa_qrcode_help' => 'To bind Google 2FA, please scan the QR code',
20 | 'login_code_error' => 'Login failed, the Google 2FA code is incorrect',
21 | 'login_need_code' => 'Login failed, please enter the Google 2FA code',
22 | 'login_status_false' => 'Login failed, your account has been disabled',
23 | 'message' => 'Message',
24 | 'status' => 'Account status',
25 | 'qrcode_service_tips' => 'You need to install a QR code service package or assign yourself the service to be used. Visit the website to view instructions. https://github.com/asundust/dcat-auth-google-2fa#%E9%87%8D%E8%A6%81%E8%AF%B4%E6%98%8E',
26 | ];
27 |
--------------------------------------------------------------------------------
/src/Http/Controllers/Actions/BindRowAction.php:
--------------------------------------------------------------------------------
1 | generateSecretKey(32);
34 | /* @var AdminUser $user */
35 | $user = AdminUser::query()->find($this->getKey());
36 | $user->google_two_fa_secret = $secret;
37 | $user->google_two_fa_enable = AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE;
38 | $user->save();
39 | return $this->response()->success(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_bind_success'))->refresh();
40 | }
41 |
42 | /**
43 | * @return string[]
44 | */
45 | public function confirm()
46 | {
47 | return [
48 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.message'),
49 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_bind_confirm'),
50 | ];
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/resources/views/login.blade.php:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 |
31 |
32 | {{ config('admin.name') }}
33 |
34 |
35 |
36 |
{{ __('admin.welcome_back') }}
37 |
38 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
165 |
--------------------------------------------------------------------------------
/src/Http/Controllers/DcatAuthGoogle2FaUserController.php:
--------------------------------------------------------------------------------
1 | column('id', trans('id'))->sortable();
23 | $grid->column('username', trans('admin.username'));
24 | $grid->column('name', trans('admin.name'));
25 |
26 | $grid->column('status', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.status'))
27 | ->bool();
28 | $grid->column('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa'))
29 | ->bool()
30 | ->if(function () {
31 | /* @var AdminUser $this */
32 | return $this->google_two_fa_enable;
33 | })
34 | ->qrcode(function () {
35 | /* @var AdminUser $this */
36 | $google2fa = new Google2FA();
37 | return $google2fa->getQRCodeUrl(config('admin.name'), $this->username, $this->google_two_fa_secret);
38 | }, 200, 200);
39 |
40 | if (config('admin.permission.enable')) {
41 | $grid->column('roles', trans('admin.roles'))->pluck('name')->label('primary', 3);
42 |
43 | $permissionModel = config('admin.database.permissions_model');
44 | $roleModel = config('admin.database.roles_model');
45 | $nodes = (new $permissionModel())->allNodes();
46 | $grid->column('permissions', trans('admin.permission'))
47 | ->if(function () {
48 | return !$this['roles']->isEmpty();
49 | })
50 | ->showTreeInDialog(function (Grid\Displayers\DialogTree $tree) use (&$nodes, $roleModel) {
51 | $tree->nodes($nodes);
52 |
53 | foreach (array_column($this['roles']->toArray(), 'slug') as $slug) {
54 | if ($roleModel::isAdministrator($slug)) {
55 | $tree->checkAll();
56 | }
57 | }
58 | })
59 | ->else()
60 | ->display('');
61 | }
62 |
63 | $grid->column('created_at', trans('admin.created_at'));
64 | $grid->column('updated_at', trans('admin.updated_at'))->sortable();
65 |
66 | $grid->quickSearch(['id', 'name', 'username']);
67 |
68 | $grid->showQuickEditButton();
69 | $grid->enableDialogCreate();
70 | $grid->showColumnSelector();
71 | $grid->disableEditButton();
72 |
73 | $grid->actions(function (Grid\Displayers\Actions $actions) {
74 | if ($actions->getKey() == AdminUser::DEFAULT_ID) {
75 | $actions->disableDelete();
76 | }
77 | if ($actions->row['google_two_fa_enable']) {
78 | $actions->append(new UnbindRowAction());
79 | } else {
80 | $actions->append(new BindRowAction());
81 | }
82 | });
83 | });
84 | }
85 |
86 | protected function detail($id)
87 | {
88 | return Show::make($id, Administrator::with(['roles']), function (Show $show) {
89 | $show->field('id', trans('id'));
90 | $show->field('username', trans('admin.username'));
91 | $show->field('name', trans('admin.name'));
92 |
93 | $show->field('status', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.status'))
94 | ->bool();
95 | $show->field('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa'))
96 | ->bool();
97 |
98 | $show->field('avatar', __('admin.avatar'))->image();
99 |
100 | if (config('admin.permission.enable')) {
101 | $show->field('roles', trans('admin.roles'))->as(function ($roles) {
102 | if (!$roles) {
103 | return [];
104 | }
105 |
106 | return collect($roles)->pluck('name');
107 | })->label();
108 |
109 | $show->field('permissions', trans('admin.permission'))->unescape()->as(function () {
110 | $roles = $this['roles']->toArray();
111 |
112 | $permissionModel = config('admin.database.permissions_model');
113 | $roleModel = config('admin.database.roles_model');
114 | $permissionModel = new $permissionModel();
115 | $nodes = $permissionModel->allNodes();
116 |
117 | $tree = Tree::make($nodes);
118 |
119 | $isAdministrator = false;
120 | foreach (array_column($roles, 'slug') as $slug) {
121 | if ($roleModel::isAdministrator($slug)) {
122 | $tree->checkAll();
123 | $isAdministrator = true;
124 | }
125 | }
126 |
127 | if (!$isAdministrator) {
128 | $keyName = $permissionModel->getKeyName();
129 | $tree->check(
130 | $roleModel::getPermissionId(array_column($roles, $keyName))->flatten()
131 | );
132 | }
133 |
134 | return $tree->render();
135 | });
136 | }
137 |
138 | $show->field('created_at', trans('admin.created_at'));
139 | $show->field('updated_at', trans('admin.updated_at'));
140 | });
141 | }
142 |
143 | public function form()
144 | {
145 | return Form::make(Administrator::with(['roles']), function (Form $form) {
146 | $userTable = config('admin.database.users_table');
147 |
148 | $connection = config('admin.database.connection');
149 |
150 | $id = $form->getKey();
151 |
152 | $form->display('id', 'ID');
153 |
154 | $form->text('username', trans('admin.username'))
155 | ->required()
156 | ->creationRules(['required', "unique:$connection.$userTable"])
157 | ->updateRules(['required', "unique:$connection.$userTable,username,$id"]);
158 | $form->text('name', trans('admin.name'))->required();
159 | $form->image('avatar', trans('admin.avatar'))->autoUpload();
160 | $form->switch('status', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.status'))->default(AdminUser::STATUS_TRUE);
161 | $form->switch('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa'))->default(AdminUser::GOOGLE_TWO_FA_ENABLE_FALSE);
162 |
163 | if ($id) {
164 | $form->password('password', trans('admin.password'))
165 | ->minLength(5)
166 | ->maxLength(20)
167 | ->customFormat(function () {
168 | return '';
169 | });
170 | } else {
171 | $form->password('password', trans('admin.password'))
172 | ->required()
173 | ->minLength(5)
174 | ->maxLength(20);
175 | }
176 |
177 | $form->password('password_confirmation', trans('admin.password_confirmation'))->same('password');
178 |
179 | $form->ignore(['password_confirmation']);
180 |
181 | if (config('admin.permission.enable')) {
182 | $form->multipleSelect('roles', trans('admin.roles'))
183 | ->options(function () {
184 | $roleModel = config('admin.database.roles_model');
185 |
186 | return $roleModel::all()->pluck('name', 'id');
187 | })
188 | ->customFormat(function ($v) {
189 | return array_column($v, 'id');
190 | });
191 | }
192 |
193 | $form->display('created_at', trans('admin.created_at'));
194 | $form->display('updated_at', trans('admin.updated_at'));
195 |
196 | if ($id == AdminUser::DEFAULT_ID) {
197 | $form->disableDeleteButton();
198 | }
199 | })->saving(function (Form $form) {
200 | /* @var Form|AdminUser $form */
201 | if ($form->password && $form->model()->get('password') != $form->password) {
202 | $form->password = bcrypt($form->password);
203 | }
204 |
205 | if (!$form->password) {
206 | $form->deleteInput('password');
207 | }
208 |
209 | if ($form->google_two_fa_enable == AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE) {
210 | $form->google_two_fa_secret = (new Google2FA())->generateSecretKey(32);
211 | } else {
212 | $form->google_two_fa_secret = null;
213 | }
214 | });
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/src/Http/Controllers/DcatAuthGoogle2FaAuthController.php:
--------------------------------------------------------------------------------
1 | view = DcatAuthGoogle2FaServiceProvider::instance()->getName() . '::login';
31 | }
32 |
33 | /**
34 | * @param Request $request
35 | *
36 | * @return JsonResponse|RedirectResponse|Response
37 | * @throws IncompatibleWithGoogleAuthenticatorException
38 | * @throws InvalidCharactersException
39 | * @throws SecretKeyTooShortException
40 | */
41 | public function postLogin(Request $request)
42 | {
43 | $credentials = $request->only([$this->username(), 'password']);
44 | $remember = (bool)$request->input('remember', false);
45 |
46 | /** @var \Illuminate\Validation\Validator $validator */
47 | $validator = Validator::make($credentials, [
48 | $this->username() => 'required',
49 | 'password' => 'required',
50 | ]);
51 |
52 | if ($validator->fails()) {
53 | return $this->validationErrorsResponse($validator);
54 | }
55 |
56 | $validatorCode = Validator::make($request->only(['google_2fa_code']), [
57 | 'google_2fa_code' => 'nullable|numeric|digits:6',
58 | ], [], [
59 | 'google_2fa_code' => DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.2fa_code'),
60 | ]);
61 |
62 | if ($validatorCode->fails()) {
63 | return $this->validationErrorsResponse($validatorCode);
64 | }
65 |
66 | if ($this->guard()->attempt($credentials, $remember)) {
67 | /* @var AdminUser $user */
68 | $user = Admin::user();
69 |
70 | if ($user->status != AdminUser::STATUS_TRUE) {
71 | $this->guard()->logout();
72 | return $this->response()
73 | ->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.login_status_false'))
74 | ->send();
75 | }
76 |
77 | if ($user->google_two_fa_enable == AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE) {
78 | $google2faCode = $request->input('google_2fa_code');
79 | if (!$google2faCode) {
80 | $this->guard()->logout();
81 | return $this
82 | ->response()
83 | ->withValidation(new MessageBag(['google_2fa_code' => [DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.login_need_code')]]))
84 | ->send();
85 | }
86 | if (!(new Google2FA())->verifyKey($user->google_two_fa_secret, $google2faCode)) {
87 | $this->guard()->logout();
88 | return $this
89 | ->response()
90 | ->withValidation(new MessageBag(['google_2fa_code' => [DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.login_code_error')]]))
91 | ->send();
92 | }
93 | }
94 |
95 | return $this->sendLoginResponse($request);
96 | }
97 |
98 | return $this->validationErrorsResponse([
99 | $this->username() => $this->getFailedLoginMessage(),
100 | ]);
101 | }
102 |
103 | /**
104 | * @return Form
105 | */
106 | protected function settingForm()
107 | {
108 | return new Form(new Administrator(), function (Form $form) {
109 | $form->action(admin_url('auth/setting'));
110 |
111 | $form->disableCreatingCheck();
112 | $form->disableEditingCheck();
113 | $form->disableViewCheck();
114 |
115 | $form->tools(function (Form\Tools $tools) {
116 | $tools->disableView();
117 | $tools->disableDelete();
118 | });
119 |
120 | $form->display('username', trans('admin.username'));
121 | $form->text('name', trans('admin.name'))->required();
122 | $form->image('avatar', trans('admin.avatar'))->autoUpload();
123 |
124 | $form->password('old_password', trans('admin.old_password'));
125 |
126 | $form->password('password', trans('admin.password'))
127 | ->minLength(5)
128 | ->maxLength(20)
129 | ->customFormat(function ($v) {
130 | if ($v == $this['password']) {
131 | return '';
132 | }
133 |
134 | return $v;
135 | });
136 | $form->password('password_confirmation', trans('admin.password_confirmation'))->same('password');
137 |
138 | /* @var AdminUser $user */
139 | $user = Admin::user();
140 | if ($user->google_two_fa_enable) {
141 | $form->switch('google_two_fa_enable', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa'))
142 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code_disable_button'));
143 | $form->text('google_2fa_code', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code'))
144 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code_disable_help'));
145 | $form->hidden('google_two_fa_secret');
146 | $form->hidden('current_google_two_fa_enable')->value('enable');
147 | } else {
148 | $google2fa = new \PragmaRX\Google2FAQRCode\Google2FA();
149 | if (!$google2fa->getQrCodeService()) {
150 | throw new MissingQrCodeServiceException(
151 | DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.qrcode_service_tips')
152 | );
153 | }
154 | $googleTwoFaSecret = $google2fa->generateSecretKey(32);
155 | $qrcode = $google2fa->getQRCodeInline(config('admin.name'), $user->username, $googleTwoFaSecret);
156 | $form->display('google_2fa_qrcode', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_qrcode'))
157 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_qrcode_help'))
158 | ->width(4)
159 | ->with(function () use ($qrcode, $google2fa) {
160 | if (strpos($qrcode, ';base64,') !== false) {
161 | return '
';
162 | } else {
163 | return $qrcode;
164 | }
165 | });
166 | $form->text('google_2fa_code', DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code'))
167 | ->help(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.google_2fa_code_enable_help'));
168 | $form->hidden('google_two_fa_secret')->value($googleTwoFaSecret);
169 | $form->hidden('google_two_fa_enable');
170 | $form->hidden('current_google_two_fa_enable')->value('disable');
171 | }
172 |
173 | $form->ignore(['password_confirmation', 'old_password']);
174 |
175 | $form->saving(function (Form $form) {
176 | /* @var Form|AdminUser $form */
177 | /* @var AdminUser $adminUser */
178 | $adminUser = $form->model();
179 | if ($form->password && $adminUser->password != $form->password) {
180 | $form->password = bcrypt($form->password);
181 | }
182 |
183 | if (!$form->password) {
184 | $form->deleteInput('password');
185 | }
186 |
187 | if ($form->input('current_google_two_fa_enable') == 'enable') {
188 | if (!$form->google_two_fa_enable) {
189 | $google2faCode = $form->input('google_2fa_code');
190 | if (!$google2faCode) {
191 | return $form->response()->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.check_code_error'));
192 | }
193 | $google2fa = new Google2FA();
194 | if (!$google2fa->verifyKey($adminUser->google_two_fa_secret, $google2faCode)) {
195 | return $form->response()->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.check_code_error'));
196 | }
197 | $form->google_two_fa_enable = AdminUser::GOOGLE_TWO_FA_ENABLE_FALSE;
198 | $form->google_two_fa_secret = null;
199 | }
200 | } else {
201 | $googleTwoFaSecret = $form->google_two_fa_secret;
202 | $google2faCode = $form->input('google_2fa_code');
203 | if ($googleTwoFaSecret) {
204 | if ($google2faCode) {
205 | $google2fa = new Google2FA();
206 | if (!$google2fa->verifyKey($form->google_two_fa_secret, $google2faCode)) {
207 | return $form->response()->error(DcatAuthGoogle2FaServiceProvider::trans('dcat-auth-google-2fa.check_code_error'));
208 | }
209 | $form->google_two_fa_enable = AdminUser::GOOGLE_TWO_FA_ENABLE_TRUE;
210 | } else {
211 | $form->google_two_fa_secret = null;
212 | }
213 | }
214 | }
215 | $form->deleteInput(['google_2fa_code', 'current_google_two_fa_enable']);
216 | });
217 |
218 | $form->saved(function (Form $form) {
219 | return $form
220 | ->response()
221 | ->success(trans('admin.update_succeeded'))
222 | ->redirect('auth/setting');
223 | });
224 | });
225 | }
226 | }
227 |
--------------------------------------------------------------------------------