lotteryLocale(); /** @var array{account:string,password:string,captcha_key:string,captcha_code:string} $data */ $data = validator($request->all(), [ 'account' => ['required', 'string', 'min:2', 'max:64', 'regex:/^[a-zA-Z0-9._-]+$/u'], 'password' => ['required', 'string', 'max:256'], 'captcha_key' => ['required', 'string', 'uuid'], 'captcha_code' => ['required', 'string', 'max:32'], ], [], [ 'account' => 'account', 'password' => 'password', 'captcha_key' => 'captcha_key', 'captcha_code' => 'captcha_code', ])->validate(); if (! $captcha->verify($data['captcha_key'], $data['captcha_code'])) { return ApiResponse::error( trans('admin.invalid_captcha', [], $locale), ErrorCode::AdminCaptchaInvalid->value, null, 422, ); } $normalizedAccount = Str::lower(trim($data['account'])); /** @var AdminUser|null $admin */ $admin = AdminUser::query()->where('username', $normalizedAccount)->first(); $passwordOk = $admin !== null && Hash::check($data['password'], $admin->password); if (! $passwordOk) { /** 统一措辞,弱化枚举用户 */ return ApiResponse::error( trans('admin.invalid_credentials', [], $locale), ErrorCode::AdminCredentialsInvalid->value, null, 401, ); } if ((int) $admin->status !== 0) { return ApiResponse::error( trans('admin.account_disabled', [], $locale), ErrorCode::AdminAccountDisabled->value, null, 403, ); } $ttlDays = (int) config('lottery.admin_api.token_ttl_days', 7); $plainToken = $admin->createToken( 'admin-api', ['*'], now()->addDays(max(1, $ttlDays)), )->plainTextToken; $admin->forceFill(['last_login_at' => now()])->save(); return ApiResponse::success([ 'token' => $plainToken, 'token_type' => 'Bearer', 'admin' => [ 'id' => $admin->id, 'username' => $admin->username, 'nickname' => $admin->name, 'email' => $admin->email, ], ]); } }