277 lines
11 KiB
PHP
277 lines
11 KiB
PHP
<?php
|
||
|
||
namespace App\Admin\Controllers;
|
||
|
||
use Slowlyo\OwlAdmin\Admin;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\Hash;
|
||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||
use Slowlyo\OwlAdmin\Renderers\TextControl;
|
||
use Slowlyo\OwlAdmin\Renderers\ImageControl;
|
||
use Slowlyo\OwlAdmin\Support\Captcha;
|
||
use Slowlyo\OwlAdmin\Models\AdminUser;
|
||
use Illuminate\Support\Facades\Validator;
|
||
use Symfony\Component\HttpFoundation\Response;
|
||
use Illuminate\Support\Arr;
|
||
use Illuminate\Validation\Rule;
|
||
use Slowlyo\OwlAdmin\Controllers\AuthController as AdminAuthController;
|
||
|
||
class AuthController extends AdminAuthController
|
||
{
|
||
public function login(Request $request)
|
||
{
|
||
if (Admin::config('admin.auth.login_captcha')) {
|
||
if (!$request->has('captcha')) {
|
||
return $this->response()->fail(__('admin.required', ['attribute' => __('admin.captcha')]));
|
||
}
|
||
|
||
if (strtolower(admin_decode($request->sys_captcha)) != strtolower($request->captcha)) {
|
||
return $this->response()->fail(__('admin.captcha_error'));
|
||
}
|
||
}
|
||
|
||
try {
|
||
$validator = Validator::make($request->all(), [
|
||
'username' => 'required',
|
||
'password' => 'required',
|
||
], [
|
||
'username' . '.required' => __('admin.required', ['attribute' => __('admin.username')]),
|
||
'password.required' => __('admin.required', ['attribute' => __('admin.password')]),
|
||
]);
|
||
|
||
if ($validator->fails()) {
|
||
abort(Response::HTTP_BAD_REQUEST, $validator->errors()->first());
|
||
}
|
||
$adminModel = Admin::config("admin.auth.model", AdminUser::class);
|
||
$user = $adminModel::query()->where('username', $request->username)->first();
|
||
if($user && $user->lock){
|
||
abort(Response::HTTP_BAD_REQUEST, '您的账号已被锁定,需要联系超级管理员解锁。');
|
||
}else{
|
||
if ($user && Hash::check($request->password, $user->password)) {
|
||
$module = Admin::currentModule(true);
|
||
$prefix = $module ? $module . '.' : '';
|
||
$token = $user->createToken($prefix . 'admin')->plainTextToken;
|
||
$user->update([
|
||
'error_num'=>0,
|
||
'last_error_at' => null
|
||
]);
|
||
|
||
return $this->response()->success(compact('token'), __('admin.login_successful'));
|
||
}else{
|
||
//24小时内连续错3次
|
||
if($user->last_error_at && $user->last_error_at> now()->subHours(24)){
|
||
$user->increment('error_num');
|
||
}else{
|
||
$user->update([
|
||
'error_num'=>1,
|
||
]);
|
||
}
|
||
$user->update([
|
||
'last_error_at' => now()
|
||
]);
|
||
}
|
||
if($user->error_num >= 3){
|
||
$user->update([
|
||
'lock' => 1
|
||
]);
|
||
abort(Response::HTTP_BAD_REQUEST, '您24小时连续输错密码3次,账号已锁定,需要联系超级管理员解锁。');
|
||
}else{
|
||
abort(Response::HTTP_BAD_REQUEST, __('admin.login_failed'));
|
||
}
|
||
}
|
||
} catch (\Exception $e) {
|
||
return $this->response()->fail($e->getMessage());
|
||
}
|
||
}
|
||
|
||
public function loginPage()
|
||
{
|
||
$captcha = null;
|
||
$enableCaptcha = Admin::config('admin.auth.login_captcha');
|
||
|
||
// 验证码
|
||
if ($enableCaptcha) {
|
||
$captcha = amisMake()->InputGroupControl()->body([
|
||
amisMake()->TextControl()->name('captcha')->placeholder(__('admin.captcha'))->required(),
|
||
amisMake()->HiddenControl()->name('sys_captcha'),
|
||
amisMake()->Service()->id('captcha-service')->api('get:' . admin_url('/captcha'))->body(
|
||
amisMake()
|
||
->Image()
|
||
->src('${captcha_img}')
|
||
->height('1.917rem')
|
||
->className('p-0 border captcha-box')
|
||
->set(
|
||
'clickAction',
|
||
['actionType' => 'reload', 'target' => 'captcha-service']
|
||
)
|
||
),
|
||
]);
|
||
}
|
||
|
||
$form = amisMake()->Form()->id('login-form')->title()->api(admin_url('/login'))->body([
|
||
amisMake()->TextControl()->name('username')->placeholder(__('admin.username'))->required(),
|
||
amisMake()
|
||
->TextControl()
|
||
->type('input-password')
|
||
->name('password')
|
||
->placeholder(__('admin.password'))
|
||
->required(),
|
||
$captcha,
|
||
amisMake()->CheckboxControl()->name('remember_me')->option(__('admin.remember_me'))->value(true),
|
||
|
||
// 登录按钮
|
||
amisMake()
|
||
->VanillaAction()
|
||
->actionType('submit')
|
||
->label(__('admin.login'))
|
||
->level('primary')
|
||
->className('w-full'),
|
||
])->actions([]); // 清空默认的提交按钮
|
||
|
||
$failAction = [];
|
||
if ($enableCaptcha) {
|
||
// 登录失败后刷新验证码
|
||
$failAction = [
|
||
// 登录失败事件
|
||
'submitFail' => [
|
||
'actions' => [
|
||
// 刷新验证码外层Service
|
||
['actionType' => 'reload', 'componentId' => 'captcha-service'],
|
||
],
|
||
],
|
||
];
|
||
}
|
||
$form->onEvent(array_merge([
|
||
// 页面初始化事件
|
||
'inited' => [
|
||
'actions' => [
|
||
// 读取本地存储的登录参数
|
||
[
|
||
'actionType' => 'custom',
|
||
'script' => <<<JS
|
||
let loginParams = localStorage.getItem('loginParams')
|
||
if(loginParams){
|
||
loginParams = JSON.parse(loginParams)
|
||
doAction({
|
||
actionType: 'setValue',
|
||
componentId: 'login-form',
|
||
args: { value: loginParams }
|
||
})
|
||
}
|
||
JS
|
||
,
|
||
|
||
],
|
||
],
|
||
],
|
||
// 登录成功事件
|
||
'submitSucc' => [
|
||
'actions' => [
|
||
// 保存登录参数到本地, 并跳转到首页
|
||
[
|
||
'actionType' => 'custom',
|
||
'script' => <<<JS
|
||
let _data = {}
|
||
if(event.data.remember_me){
|
||
_data = { username: event.data.username, password: event.data.password }
|
||
}
|
||
window.\$owl.afterLoginSuccess(_data, event.data.result.data.token)
|
||
JS,
|
||
|
||
],
|
||
],
|
||
],
|
||
], $failAction));
|
||
|
||
$card = amisMake()->Card()->className('w-96 m:w-full')->body([
|
||
amisMake()->Flex()->justify('space-between')->className('px-2.5 pb-2.5')->items([
|
||
amisMake()->Image()->src(url(Admin::config('admin.logo')))->width(40)->height(40),
|
||
amisMake()
|
||
->Tpl()
|
||
->className('font-medium')
|
||
->tpl('<div style="font-size: 24px">' . Admin::config('admin.name') . '</div>'),
|
||
]),
|
||
$form,
|
||
]);
|
||
|
||
return amisMake()->Page()->css([
|
||
'.captcha-box .cxd-Image--thumb' => [
|
||
'padding' => '0',
|
||
'cursor' => 'pointer',
|
||
'border' => 'var(--Form-input-borderWidth) solid var(--Form-input-borderColor)',
|
||
|
||
'border-top-right-radius' => '4px',
|
||
'border-bottom-right-radius' => '4px',
|
||
],
|
||
'.cxd-Image-thumb' => ['width' => 'auto'],
|
||
])->body(
|
||
amisMake()->Wrapper()->className("h-screen w-full flex items-center justify-center")->body($card)
|
||
);
|
||
}
|
||
|
||
public function userSetting(): \Illuminate\Http\JsonResponse|\Illuminate\Http\Resources\Json\JsonResource
|
||
{
|
||
$user = $this->user();
|
||
|
||
$form = Form::make()
|
||
->title()
|
||
->panelClassName('px-48 m:px-0')
|
||
->mode('horizontal')
|
||
->data(Arr::only($user->toArray(), ['avatar', 'name']))
|
||
->api('put:' . admin_url('/user_setting'))
|
||
// ->persistDataKeys(['avatar', 'name'])
|
||
// ->resetAfterSubmit()
|
||
->body([
|
||
ImageControl::make()
|
||
->label(__('admin.admin_user.avatar'))
|
||
->name('avatar')
|
||
->receiver($this->uploadImagePath()),
|
||
TextControl::make()
|
||
->label(__('admin.admin_user.name'))
|
||
->name('name')
|
||
->required(),
|
||
// TextControl::make()
|
||
// ->type('input-password')
|
||
// ->label(__('admin.old_password'))
|
||
// ->name('old_password'),
|
||
TextControl::make()
|
||
->type('input-password')
|
||
->label('新密码')
|
||
->name('password')
|
||
->validations(['minLength' => 6])
|
||
->requiredOn('!!this.old_password'),
|
||
TextControl::make()
|
||
->type('input-password')
|
||
->label(__('admin.confirm_password'))
|
||
->name('confirm_password')
|
||
->validations(['minLength' => 6])
|
||
->requiredOn('!!this.old_password'),
|
||
]);
|
||
|
||
return $this->response()->success(Page::make()->body($form));
|
||
}
|
||
|
||
public function saveUserSetting(): \Illuminate\Http\JsonResponse|\Illuminate\Http\Resources\Json\JsonResource
|
||
{
|
||
$request = request();
|
||
$request->validate([
|
||
// 'old_password' => ['nullable', Rule::requiredIf($request->filled(['password', 'confirm_password']))],
|
||
'password' => "required",
|
||
'confirm_password' => ["required", 'same:password'],
|
||
], [
|
||
'password.required' => '新密码必填',
|
||
'confirm_password.required' => '确认密码必填',
|
||
'confirm_password.same' => __('admin.admin_user.password_confirmation'),
|
||
]);
|
||
$user = $this->user();
|
||
$attributes = $request->only(['avatar', 'name']);
|
||
// if ($request->filled('old_password')) {
|
||
$attributes['password']
|
||
= Hash::make(md5($request->input('password')));
|
||
// }
|
||
$user->update($attributes);
|
||
return $this->response()->successMessage(__('admin.action_success'));
|
||
}
|
||
}
|