Skip to content

Instantly share code, notes, and snippets.

@JCervantesB
Last active February 2, 2023 15:45
Show Gist options
  • Save JCervantesB/bea63269c6313d0554ec6ff7f98c4b17 to your computer and use it in GitHub Desktop.
Save JCervantesB/bea63269c6313d0554ec6ff7f98c4b17 to your computer and use it in GitHub Desktop.
Correo de confirmación Laravel > React
public function olvide(OlvideRequest $request)
{
$data = $request->validated();
$user = User::where('email', $data['email'])->first();
if($user) {
$user->recoveryToken = Str::random(30);
$user->save();
Mail::send('emails.recovery', ['token' => $user->recoveryToken, 'nombre' => $user->name], function ($message) use ($user) {
$message->to($user->email)
->subject('Recuperación de Contraseña');
});
}
return [
'message' => 'Se ha enviado un email con las instrucciones para recuperar tu cuenta'
];
}
public function recuperar_cuenta(RecuperarRequest $request)
{
$data = $request->validated();
$user = User::where('recoveryToken', $data['recoveryToken'])->first();
if($user) {
$user->password = bcrypt($data['password']);
$user->recoveryToken = null;
$user->save();
}
return [
'user' => $user
];
}
import { createRef, useState } from "react";
import { Link } from "react-router-dom";
import { useAuth } from "../hooks/useAuth";
import Alerta from "../components/Alerta";
import Mensaje from "../components/Mensaje";
export default function Olvide() {
const emailRef = createRef();
const [errores, setErrores] = useState([]);
const [exito, setExito] = useState(false)
const {olvide} = useAuth({middleware: 'guest', url: '/'});
const handleSubmit = async (e) => {
e.preventDefault();
const datos = {
email: emailRef.current.value,
};
olvide(datos, setErrores, setExito);
}
return (
<>
<h1 className="text-4xl font-black">Recupera tu cuenta</h1>
<p>Recupera el acceso a tu cuenta con tu correo</p>
<div className="bg-white shadow-md rounded-md mt-10 px-5 py-10">
<form
onSubmit={handleSubmit}
noValidate
>
{errores ? errores.map((error, i) => <Alerta key={i}>{error}</Alerta>) : null}
{exito ? <Mensaje>Se ha enviado un correo para reestablecer la contraseña</Mensaje> : null}
<div className="mb-4">
<label
className="text-slate-800"
htmlFor="email"
>Email:</label>
<input
className="mt-2 w-full p-3 bg-gray-50"
type="email"
id="email"
name="email"
placeholder="Tu Email"
ref={emailRef}
/>
</div>
<input
type="submit"
value="Reestablecer contraseña"
className="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-4 rounded-md w-full uppercase"
/>
</form>
</div>
<nav className="flex flex-col mt-5">
<Link to="/auth/registro">
¿No tienes cuenta? Crea una aquí
</Link>
<Link to="/auth/login">
¿Ya tienes cuenta? Inicia sesión aquí
</Link>
</nav>
</>
)
}
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class OlvideRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'email' => ['required', 'email', 'exists:users,email']
];
}
public function messages()
{
return [
'email.required' => 'El email es obligatorio',
'email.email' => 'El email no es válido',
'email.exists' => 'La cuenta no existe'
];
}
}
<!DOCTYPE html>
<html>
<head>
<title>Recuperación de Contraseña</title>
</head>
<body>
<h1>Hola {{$nombre}}!</h1>
<p>Has solicitado reestablecer tu contraseña en FreshCoffee</p>
<p>Para hacerlo, por favor haz clic en el siguiente enlace:</p>
<a href="{{ env('FRONTEND_URL') }}/auth/recuperar?token={{ $token }}">{{ env('FRONTEND_URL') }}/auth/recuperar?token={{ $token }}</a>
<p>Gracias!</p>
</body>
</html>
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class RecoveryMail extends Mailable
{
use Queueable, SerializesModels;
protected $content;
public function __construct($content)
{
$this->content = $content;
}
public function build()
{
return $this->from('hello@example.com')
->subject('Recuperación de contraseña')
->view('view.name')
->with([
'content' => $this->content
])
->text('emails.recovery')
->with([
'content' => $this->content
])
->markdown('emails.recovery')
->with([
'content' => $this->content
])
->to($this->content);
}
}
import { createRef, useState } from "react";
import { Link } from "react-router-dom";
import { useAuth } from "../hooks/useAuth";
import Alerta from "../components/Alerta";
import Mensaje from "../components/Mensaje";
export default function Recuperar() {
// leer la url del navegador y obtener el token
const urlParams = new URLSearchParams(window.location.search);
const passwordRef = createRef();
const recoveryToken = urlParams.get('token');
const [errores, setErrores] = useState([]);
const [exito, setExito] = useState(false)
const {recuperar} = useAuth({middleware: 'guest', url: '/'});
//validar si la url tiene un token y si no redireccionar a login
if(!recoveryToken) {
window.location.href = '/auth/login';
}
const handleSubmit = async (e) => {
e.preventDefault();
const datos = {
recoveryToken,
password: passwordRef.current.value,
};
recuperar(datos, setErrores, setExito);
}
return (
<>
<h1 className="text-4xl font-black">Nueva Contraseña</h1>
<p>Ingresa una nueva contraseña para recuperar tu cuenta</p>
<div className="bg-white shadow-md rounded-md mt-10 px-5 py-10">
<form
onSubmit={handleSubmit}
noValidate
>
{errores ? errores.map((error, i) => <Alerta key={i}>{error}</Alerta>) : null}
{exito ? <Mensaje>Se ha cambiado la constraseña con exito</Mensaje> : null}
<div className={`${exito ? 'hidden' : 'mb-4'}`}>
<label
className="text-slate-800"
htmlFor="password"
>Password:</label>
<input
className="mt-2 w-full p-3 bg-gray-50"
type="password"
id="password"
name="password"
placeholder="Tu Password"
ref={passwordRef}
/>
</div>
<input
type="submit"
value="Cambiar contraseña"
className={`${exito ? 'hidden' : 'bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-4 rounded-md w-full uppercase'}`}
/>
</form>
</div>
<nav className="flex flex-col mt-5">
<Link to="/auth/registro">
¿No tienes cuenta? Crea una aquí
</Link>
<Link to="/auth/login">
¿Ya tienes cuenta? Inicia sesión aquí
</Link>
</nav>
</>
)
}
<?php
namespace App\Http\Requests;
use Illuminate\Validation\Rules\Password as PasswordRules;
use Illuminate\Foundation\Http\FormRequest;
class RecuperarRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
// Recuperar cuenta que contenga el recoveryToken
return [
'email' => 'email|exists:users,email',
'recoveryToken' => 'required|exists:users,recoveryToken',
'password' => [
'required',
PasswordRules::min(8)
->letters()
->numbers()
->symbols()
]
];
}
public function messages()
{
return [
'recoveryToken' => 'El token de recuperación es obligatorio',
'recoveryToken.exists' => 'El token de recuperación no es válido',
'password' => 'El password debe contener al menos 8 caracteres, una letra, un número y un símbolo',
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment