This commit is contained in:
omkieit 2024-09-07 19:28:47 +05:30
parent d040974f3f
commit a6d1abee9c
8 changed files with 181 additions and 66 deletions

View File

@ -39,10 +39,11 @@ export const signup = async (req, res) => {
result.tokens.push({ token });
// Save the user
await result.save();
// 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
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
export const signin = async (req, res) => {
const { email, password } = req.body;

View File

@ -9,6 +9,7 @@ const userSchema = new mongoose.Schema({
password: { type: String, required: true },
termsconditions:{type: String,},
userType:{ type: String, required: true },
verified: { type: Boolean, default: false },
tokens:[
{
token:{

View File

@ -1,10 +1,11 @@
import express from "express";
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("/signup", signup);
router.get('/:id/verify/:token/', verifyUser);
router.get('/:id', showUser);

41
ef-api/utils/sendEmail.js Normal file
View File

@ -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

View File

@ -27,7 +27,7 @@
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css">
<!-- 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">
<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">
</head>

View File

@ -25,7 +25,17 @@ const Register = () => {
const [formValue, setFormValue] = useState(initialState);
const [isFormValid, setIsFormValid] = useState(false); // New state variable
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 navigate = useNavigate();
@ -47,7 +57,17 @@ const Register = () => {
userType !== ""; // Validate userType selection
setIsFormValid(isValid);
}, [title, email, password, firstName, middleName, lastName, confirmPassword, termsconditions, userType]);
}, [
title,
email,
password,
firstName,
middleName,
lastName,
confirmPassword,
termsconditions,
userType,
]);
const handleSubmit = (e) => {
e.preventDefault();
@ -107,8 +127,6 @@ const Register = () => {
>
<div className="container-fluid px-0">
<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">
{/* <i
className="fa fa-dollar"
@ -139,7 +157,6 @@ const Register = () => {
</div> */}
</div>
<div className="col-12 col-md-6 col-xl-5">
<div
className="card border-0 rounded-4 shadow-lg"
@ -153,50 +170,49 @@ const Register = () => {
<h3 style={{ color: "red" }}>
All fields are mandatory to enable "Sign up"
</h3>
<hr />
</div>
</div>
</div>
<form onSubmit={handleSubmit}>
<div className="row gy-3 overflow-hidden">
{/* Radio buttons for Lender and Borrower */}
<div className="col-12">
<div className="form-floating mb-3">
<label className="form-label">Please select the role <br /><br /></label>
<div className="form-check form-check-inline">
<input
className="form-check-input"
type="radio"
name="userType"
value="Lender"
checked={userType === "Lender"}
onChange={handleUserTypeChange}
required
/>
<label className="form-check-label">Lender</label>
</div>
<div className="form-check form-check-inline">
<input
className="form-check-input"
type="radio"
name="userType"
value="Borrower"
checked={userType === "Borrower"}
onChange={handleUserTypeChange}
required
/>
<label className="form-check-label">Borrower </label>
<br /><br /><br />
</div>
</div>
</div>
{/* Radio buttons for Lender and Borrower */}
<div className="col-12">
<div className="form-floating mb-3">
<label className="form-label">
Please select the role. <br />
<br />
</label>
<div className="form-check form-check-inline">
<input
className="form-check-input"
type="radio"
name="userType"
value="Lender"
checked={userType === "Lender"}
onChange={handleUserTypeChange}
required
/>
<label className="form-check-label">Lender</label>
</div>
<div className="form-check form-check-inline">
<input
className="form-check-input"
type="radio"
name="userType"
value="Borrower"
checked={userType === "Borrower"}
onChange={handleUserTypeChange}
required
/>
<label className="form-check-label">
Borrower{" "}
</label>
<br />
<br />
</div>
</div>
</div>
<div className="col-12">
<select
@ -367,7 +383,6 @@ const Register = () => {
{loading && <LoadingIcons.Bars />}
Sign up
</button>
</div>
</div>
</div>

View File

@ -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({
name: "user",
initialState: {
@ -36,6 +48,22 @@ const userSlice = createSlice({
.addCase(showUser.rejected, (state, action) => {
state.loading = false;
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;
});