feat: implement email case-insensitive queries (fix #318)

This commit is contained in:
xboard
2026-03-28 07:07:57 +08:00
parent a6c37bb112
commit 7fbd1bb92d
9 changed files with 64 additions and 11 deletions

View File

@@ -43,7 +43,7 @@ class ResetPassword extends Command
public function handle()
{
$password = $this->argument('password') ;
$user = User::where('email', $this->argument('email'))->first();
$user = User::byEmail($this->argument('email'))->first();
if (!$user) abort(500, '邮箱不存在');
$password = $password ?? Helper::guid(false);
$user->password = password_hash($password, PASSWORD_DEFAULT);

View File

@@ -29,7 +29,7 @@ class CommController extends Controller
// 检查白名单后缀限制
if ((int) admin_setting('email_whitelist_enable', 0)) {
$isRegisteredEmail = User::where('email', $email)->exists();
$isRegisteredEmail = User::byEmail($email)->exists();
if (!$isRegisteredEmail) {
$allowedSuffixes = Helper::getEmailSuffix();
$emailSuffix = substr(strrchr($email, '@'), 1);

View File

@@ -199,7 +199,7 @@ class OrderController extends Controller
public function assign(OrderAssign $request)
{
$plan = Plan::find($request->input('plan_id'));
$user = User::where('email', $request->input('email'))->first();
$user = User::byEmail($request->input('email'))->first();
if (!$user) {
return $this->fail([400202, '该用户不存在']);

View File

@@ -220,7 +220,7 @@ class UserController extends Controller
return $this->fail([400202, '用户不存在']);
}
if (isset($params['email'])) {
if (User::where('email', $params['email'])->first() && $user->email !== $params['email']) {
if (User::byEmail($params['email'])->first() && $user->email !== $params['email']) {
return $this->fail([400201, '邮箱已被使用']);
}
}
@@ -240,7 +240,7 @@ class UserController extends Controller
$params['group_id'] = $plan->group_id;
}
// 处理邀请用户
if ($request->input('invite_user_email') && $inviteUser = User::where('email', $request->input('invite_user_email'))->first()) {
if ($request->input('invite_user_email') && $inviteUser = User::byEmail($request->input('invite_user_email'))->first()) {
$params['invite_user_id'] = $inviteUser->id;
} else {
$params['invite_user_id'] = null;
@@ -365,7 +365,7 @@ class UserController extends Controller
if ($request->input('email_prefix')) {
$email = $request->input('email_prefix') . '@' . $request->input('email_suffix');
if (User::where('email', $email)->exists()) {
if (User::byEmail($email)->exists()) {
return $this->fail([400201, '邮箱已存在于系统中']);
}

View File

@@ -3,6 +3,8 @@
namespace App\Models;
use App\Utils\Helper;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -81,6 +83,20 @@ class User extends Authenticatable
public const COMMISSION_TYPE_SYSTEM = 0;
public const COMMISSION_TYPE_PERIOD = 1;
public const COMMISSION_TYPE_ONETIME = 2;
protected function email(): Attribute
{
return Attribute::make(
set: fn (string $value) => strtolower(trim($value)),
);
}
/**
* 按邮箱查询(大小写不敏感,兼容所有数据库)
*/
public function scopeByEmail(Builder $query, string $email): Builder
{
return $query->where('email', strtolower(trim($email)));
}
// 获取邀请人信息
public function invite_user(): BelongsTo

View File

@@ -36,7 +36,7 @@ class LoginService
}
// 查找用户
$user = User::where('email', $email)->first();
$user = User::byEmail($email)->first();
if (!$user) {
return [false, [400, __('Incorrect email or password')]];
}
@@ -99,7 +99,7 @@ class LoginService
}
// 查找用户
$user = User::where('email', $email)->first();
$user = User::byEmail($email)->first();
if (!$user) {
return [false, [400, __('This email is not registered in the system')]];
}

View File

@@ -27,7 +27,7 @@ class MailLinkService
return [false, [429, __('Sending frequently, please try again later')]];
}
$user = User::where('email', $email)->first();
$user = User::byEmail($email)->first();
if (!$user) {
return [true, true]; // 成功但用户不存在,保护用户隐私
}

View File

@@ -91,8 +91,7 @@ class RegisterService
}
// 检查邮箱是否存在
$email = $request->input('email');
$exist = User::where('email', $email)->first();
$exist = User::byEmail($request->input('email'))->first();
if ($exist) {
return [false, [400201, __('Email already exists')]];
}

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// 统计需要转换的记录数
$count = DB::table('v2_user')
->whereNotNull('email')
->whereRaw('email != LOWER(email)')
->count();
if ($count > 0) {
Log::info("Converting {$count} email(s) to lowercase");
DB::table('v2_user')
->whereNotNull('email')
->whereRaw('email != LOWER(email)')
->update(['email' => DB::raw('LOWER(email)')]);
Log::info("Email lowercase conversion completed");
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// 无法恢复原始大小写
}
};