done
This commit is contained in:
parent
d040974f3f
commit
a6d1abee9c
|
@ -39,10 +39,11 @@ export const signup = async (req, res) => {
|
||||||
result.tokens.push({ token });
|
result.tokens.push({ token });
|
||||||
// Save the user
|
// Save the user
|
||||||
await result.save();
|
await result.save();
|
||||||
|
|
||||||
|
|
||||||
// console.log("ss", result)
|
// console.log("ss", result)
|
||||||
|
|
||||||
|
const url = `Click on the link ${process.env.RETURN_URL}/users/${result._id}/verify/${token}`;
|
||||||
|
await sendEmail(result.email, "Verify Email", url);
|
||||||
|
|
||||||
// Send the user info and token back to the client
|
// Send the user info and token back to the client
|
||||||
res.status(201).json({ result, token });
|
res.status(201).json({ result, token });
|
||||||
|
|
||||||
|
@ -52,6 +53,34 @@ export const signup = async (req, res) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//This is to verify user
|
||||||
|
|
||||||
|
export const verifyUser = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const user = await UserModal.findOne({ _id: req.params.id });
|
||||||
|
if (!user) return res.status(400).send({ message: "Invalid link" });
|
||||||
|
|
||||||
|
const token = user.tokens.find(
|
||||||
|
(tokenObj) => tokenObj.token === req.params.token
|
||||||
|
);
|
||||||
|
if (!token) return res.status(400).send({ message: "Invalid link" });
|
||||||
|
|
||||||
|
// Update the user's verified status to true
|
||||||
|
user.verified = true;
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Remove the token from the tokens array
|
||||||
|
user.tokens = user.tokens.filter(
|
||||||
|
(tokenObj) => tokenObj.token !== req.params.token
|
||||||
|
);
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
res.status(200).send({ message: "Email verified successfully" });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ message: "Internal Server Errors" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// This is signIn
|
// This is signIn
|
||||||
export const signin = async (req, res) => {
|
export const signin = async (req, res) => {
|
||||||
const { email, password } = req.body;
|
const { email, password } = req.body;
|
||||||
|
|
|
@ -9,6 +9,7 @@ const userSchema = new mongoose.Schema({
|
||||||
password: { type: String, required: true },
|
password: { type: String, required: true },
|
||||||
termsconditions:{type: String,},
|
termsconditions:{type: String,},
|
||||||
userType:{ type: String, required: true },
|
userType:{ type: String, required: true },
|
||||||
|
verified: { type: Boolean, default: false },
|
||||||
tokens:[
|
tokens:[
|
||||||
{
|
{
|
||||||
token:{
|
token:{
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
import { signup, signin,showUser } from "../controllers/user.js";
|
import { signup, signin, verifyUser, showUser } from "../controllers/user.js";
|
||||||
|
|
||||||
router.post("/signin", signin);
|
router.post("/signin", signin);
|
||||||
router.post("/signup", signup);
|
router.post("/signup", signup);
|
||||||
|
router.get('/:id/verify/:token/', verifyUser);
|
||||||
router.get('/:id', showUser);
|
router.get('/:id', showUser);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import nodemailer from "nodemailer";
|
||||||
|
import dotenv from "dotenv";
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
export const sendEmail = async (email, subject, text) => {
|
||||||
|
try {
|
||||||
|
const transporter = nodemailer.createTransport({
|
||||||
|
host: process.env.SMTP_HOST,
|
||||||
|
port: parseInt(process.env.SMTP_PORT),
|
||||||
|
secure: process.env.SMTP_SECURE === "true",
|
||||||
|
socketTimeout: parseInt(process.env.SMTP_SOCKET_TIMEOUT),
|
||||||
|
logger: process.env.SMTP_LOGGER === "true",
|
||||||
|
debug: process.env.SMTP_DEBUG === "true",
|
||||||
|
secureConnection: process.env.SMTP_SECURE_CONNECTION === "true",
|
||||||
|
auth: {
|
||||||
|
user: process.env.SMTP_USER,
|
||||||
|
pass: process.env.SMTP_PASS,
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
rejectUnauthorized: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await transporter.sendMail({
|
||||||
|
from: {
|
||||||
|
name: process.env.SMTP_FROM_NAME,
|
||||||
|
address: process.env.SMTP_FROM,
|
||||||
|
},
|
||||||
|
to: email,
|
||||||
|
subject: subject,
|
||||||
|
text: text,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Email sent successfully");
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Email not sent!");
|
||||||
|
console.error(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because one or more lines are too long
|
@ -27,7 +27,7 @@
|
||||||
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css">
|
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css">
|
||||||
<!-- fonts -->
|
<!-- fonts -->
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;800&family=Sen:wght@400;700;800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;800&family=Sen:wght@400;700;800&display=swap" rel="stylesheet">
|
||||||
<script type="module" crossorigin src="/assets/index-rSI24A6Q.js"></script>
|
<script type="module" crossorigin src="/assets/index-CtE5sUX_.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-CyAHZLBw.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-CyAHZLBw.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,17 @@ const Register = () => {
|
||||||
const [formValue, setFormValue] = useState(initialState);
|
const [formValue, setFormValue] = useState(initialState);
|
||||||
const [isFormValid, setIsFormValid] = useState(false); // New state variable
|
const [isFormValid, setIsFormValid] = useState(false); // New state variable
|
||||||
const { loading, error } = useSelector((state) => ({ ...state.auth }));
|
const { loading, error } = useSelector((state) => ({ ...state.auth }));
|
||||||
const { title, email, password, firstName, middleName, lastName, confirmPassword, termsconditions, userType } = formValue; // include userType
|
const {
|
||||||
|
title,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
firstName,
|
||||||
|
middleName,
|
||||||
|
lastName,
|
||||||
|
confirmPassword,
|
||||||
|
termsconditions,
|
||||||
|
userType,
|
||||||
|
} = formValue; // include userType
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
@ -47,7 +57,17 @@ const Register = () => {
|
||||||
userType !== ""; // Validate userType selection
|
userType !== ""; // Validate userType selection
|
||||||
|
|
||||||
setIsFormValid(isValid);
|
setIsFormValid(isValid);
|
||||||
}, [title, email, password, firstName, middleName, lastName, confirmPassword, termsconditions, userType]);
|
}, [
|
||||||
|
title,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
firstName,
|
||||||
|
middleName,
|
||||||
|
lastName,
|
||||||
|
confirmPassword,
|
||||||
|
termsconditions,
|
||||||
|
userType,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleSubmit = (e) => {
|
const handleSubmit = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -107,8 +127,6 @@ const Register = () => {
|
||||||
>
|
>
|
||||||
<div className="container-fluid px-0">
|
<div className="container-fluid px-0">
|
||||||
<div className="row gy-4 align-items-center justify-content-center">
|
<div className="row gy-4 align-items-center justify-content-center">
|
||||||
|
|
||||||
|
|
||||||
<div className="col-12 col-md-0 col-xl-20 text-center text-md-start">
|
<div className="col-12 col-md-0 col-xl-20 text-center text-md-start">
|
||||||
{/* <i
|
{/* <i
|
||||||
className="fa fa-dollar"
|
className="fa fa-dollar"
|
||||||
|
@ -139,7 +157,6 @@ const Register = () => {
|
||||||
</div> */}
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className="col-12 col-md-6 col-xl-5">
|
<div className="col-12 col-md-6 col-xl-5">
|
||||||
<div
|
<div
|
||||||
className="card border-0 rounded-4 shadow-lg"
|
className="card border-0 rounded-4 shadow-lg"
|
||||||
|
@ -153,50 +170,49 @@ const Register = () => {
|
||||||
<h3 style={{ color: "red" }}>
|
<h3 style={{ color: "red" }}>
|
||||||
All fields are mandatory to enable "Sign up"
|
All fields are mandatory to enable "Sign up"
|
||||||
</h3>
|
</h3>
|
||||||
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className="row gy-3 overflow-hidden">
|
<div className="row gy-3 overflow-hidden">
|
||||||
|
{/* Radio buttons for Lender and Borrower */}
|
||||||
|
<div className="col-12">
|
||||||
{/* Radio buttons for Lender and Borrower */}
|
<div className="form-floating mb-3">
|
||||||
<div className="col-12">
|
<label className="form-label">
|
||||||
|
Please select the role. <br />
|
||||||
<div className="form-floating mb-3">
|
<br />
|
||||||
<label className="form-label">Please select the role <br /><br /></label>
|
</label>
|
||||||
<div className="form-check form-check-inline">
|
<div className="form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
<input
|
type="radio"
|
||||||
className="form-check-input"
|
name="userType"
|
||||||
type="radio"
|
value="Lender"
|
||||||
name="userType"
|
checked={userType === "Lender"}
|
||||||
value="Lender"
|
onChange={handleUserTypeChange}
|
||||||
checked={userType === "Lender"}
|
required
|
||||||
onChange={handleUserTypeChange}
|
/>
|
||||||
required
|
<label className="form-check-label">Lender</label>
|
||||||
/>
|
</div>
|
||||||
<label className="form-check-label">Lender</label>
|
<div className="form-check form-check-inline">
|
||||||
</div>
|
<input
|
||||||
<div className="form-check form-check-inline">
|
className="form-check-input"
|
||||||
<input
|
type="radio"
|
||||||
className="form-check-input"
|
name="userType"
|
||||||
type="radio"
|
value="Borrower"
|
||||||
name="userType"
|
checked={userType === "Borrower"}
|
||||||
value="Borrower"
|
onChange={handleUserTypeChange}
|
||||||
checked={userType === "Borrower"}
|
required
|
||||||
onChange={handleUserTypeChange}
|
/>
|
||||||
required
|
<label className="form-check-label">
|
||||||
/>
|
Borrower{" "}
|
||||||
<label className="form-check-label">Borrower </label>
|
</label>
|
||||||
<br /><br /><br />
|
<br />
|
||||||
</div>
|
<br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<select
|
<select
|
||||||
|
@ -367,7 +383,6 @@ const Register = () => {
|
||||||
{loading && <LoadingIcons.Bars />}
|
{loading && <LoadingIcons.Bars />}
|
||||||
Sign up
|
Sign up
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,6 +14,18 @@ export const showUser = createAsyncThunk(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const verifyEmail = createAsyncThunk(
|
||||||
|
"user/verifyEmail",
|
||||||
|
async ({id, token, data}, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const response = await api.verifyEmail(id, token, data);
|
||||||
|
return response.data.message;
|
||||||
|
} catch (error) {
|
||||||
|
return rejectWithValue("Error verifying email");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const userSlice = createSlice({
|
const userSlice = createSlice({
|
||||||
name: "user",
|
name: "user",
|
||||||
initialState: {
|
initialState: {
|
||||||
|
@ -36,6 +48,22 @@ const userSlice = createSlice({
|
||||||
.addCase(showUser.rejected, (state, action) => {
|
.addCase(showUser.rejected, (state, action) => {
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
state.error = action.payload;
|
state.error = action.payload;
|
||||||
|
})
|
||||||
|
|
||||||
|
.addCase(verifyEmail.pending, (state) => {
|
||||||
|
state.loading = true;
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
|
||||||
|
.addCase(verifyEmail.fulfilled, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.verified = action.payload === "Email verified successfully";
|
||||||
|
// state.verified = true;
|
||||||
|
})
|
||||||
|
|
||||||
|
.addCase(verifyEmail.rejected, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.error = action.error.message;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue