0

我使用 Jetstream 和 Inertia 创建了一个新站点。目前,该应用程序将返回“电子邮件已被占用”。如果用户尝试使用现有电子邮件注册,则显示消息。尽管有时间分析,我想保持用户帐户的存在隐私。如果有人使用现有电子邮件注册,有没有办法保持对电子邮件的唯一约束但显示相同的外在行为?理想情况下,我不想创建第二个用户,而是向现有用户发送电子邮件,建议他们重置密码或忽略电子邮件。

4

2 回答 2

0

我同意 Unflux 关于不改变这一点,但如果您需要,您可以修改CreateNewUser.php位于app\Actions\Fortify\CreateNewUser.php并更改验证消息或修改流程。

create()负责创建新用户的方法如下所示:

public function create(array $input)
    {
        //define custom messages
        $customValidationMessages = {
            'email.unique' => 'New Message',
        }


        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], //email validation rules here
            'password' => $this->passwordRules(),
        ], $customValidationMessages)->validate(); //add the variable containing the custom message(s) here

        
        return User::create([
            'name' => $input['name'],
            'email' => $input['email'],
            'password' => Hash::make($input['password']),
            'api_token' => Str::random(60),
        ]);
    }

如果您需要向用户发送电子邮件或进一步自定义,我建议您考虑实施“验证后挂钩”,您可以在此处阅读:https ://laravel.com/docs/8.x/validation#after-验证钩子

于 2021-05-05T18:35:42.457 回答
0

这对我有用:

  1. 在中创建一个新的验证异常app/Exceptions/ExistingUserException.php
namespace App\Exceptions;

use Illuminate\Validation\ValidationException;

class ExistingUserException extends ValidationException
{

}
  1. 将验证分为 2 个步骤,如果表单很好,则app/Actions/Fortify/CreateNewUser.php抛出扩展ValidationException
        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255'],
            'password' => $this->passwordRules(),
            'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
        ])->validate();

        $validator =  Validator::make($input, [
            'email' => ['unique:users'],
        ], ['email.unique'=>'']);

        if ($validator->fails())
        {
            throw new ExistingUserException($validator);
        }
  1. 在中创建一个新的中间件app/Http/Middleware/CatchExistingUser.php
<?php

namespace App\Http\Middleware;

use App\Exceptions\ExistingUserException;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\URL;

class CatchExistingUser
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next, $redirectToRoute = null)
    {
        $response = $next($request);

        if ($response->exception && $response->exception instanceof ExistingUserException)
        {
            return $request->expectsJson()
                    ? abort(403, 'Your email address is not verified.')
                    : Redirect::guest(URL::route($redirectToRoute ?: 'verification.notice'));
        }

        return $response;
    }
}
  1. 通过将中间件注入所有设防路由config/fortify.php
'middleware' => [CatchExistingUser::class, 'web'],
  1. 通过覆盖中的路由从验证页面中删除 auth 中间件routes/web.php
use Illuminate\Http\Request;
use Laravel\Fortify\Contracts\VerifyEmailViewResponse;
...
Route::get('/email/verify', function (Request $request) {
    $user = $request->user();
    if ($user && $user->hasVerifiedEmail())
    {
        return redirect()->intended(config('fortify.home'));
    }
    return app(VerifyEmailViewResponse::class);
})
->name('verification.notice');

自定义异常并不理想,但它似乎比测试存储在 中的验证器更干净ValidatorException,然后如果有多个错误则删除一条消息。我认为这将需要允许验证其他字段,同时不泄露电子邮件的唯一性。

于 2021-05-06T15:00:22.933 回答