lotteryLocale(); $data = $request->validated(); 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(); $permissionSlugs = $admin->fresh()->adminPermissionSlugs(); return ApiResponse::success([ 'token' => $plainToken, 'token_type' => 'Bearer', 'admin' => [ 'id' => $admin->id, 'username' => $admin->username, 'nickname' => $admin->name, 'email' => $admin->email, 'permissions' => $permissionSlugs, 'navigation' => AdminAuthorizationRegistry::visibleNavigationItems($permissionSlugs), ], ]); } }