Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temp #549

Merged
merged 4 commits into from
Sep 15, 2024
Merged

Temp #549

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 113 additions & 41 deletions backend/controllers/usersControllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,64 +193,136 @@ module.exports.verifyOtpForForgotPassword = async (req, res) => {
res.status(200).json({ message: 'OTP is valid.' });
};

module.exports.login = async (req, res) => {
try {
const { email, password } = req.body;
module.exports.login = async (req, res) => {
try {
const { email, password } = req.body;

if (!email || !password) {
return res.status(400).json({ error: 'Please provide email and password' });
}

let user = await User.findOne({ email });
if (!user) {
user = await UnverifiedUser.findOne({ email });
if (!user) return res.status(404).json({ error: 'User not found' });
return res.status(403).json({ error: 'Email not verified. Please check your email.' });
}

if (!user.isVerified) {
return res.status(403).json({ error: 'Email not verified. Please check your email.' });
}

const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).json({ error: 'Invalid password' });
}

// Generate JWT Access Token
const accessToken = jwt.sign(
{ userId: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '15m' } // Short-lived access token
);

// Generate Refresh Token
const refreshToken = jwt.sign(
{ userId: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '7d' } // Longer-lived refresh token
);
console.log('Generated Token:', accessToken);
console.log('Generated Refresh Token', refreshToken)
// Store refresh token in the database
user.refreshToken = refreshToken;
await user.save();

// Set cookies for tokens
res.cookie('accessToken', accessToken, { httpOnly: true, maxAge: 900000 }); // 15 minutes
res.cookie('refreshToken', refreshToken, { httpOnly: true, maxAge: 604800000 }); // 7 days

res.status(200).json({ user, accessToken, refreshToken, message: 'Login Successful' });
} catch (error) {
console.log("Login Error", error);

if (!email || !password) {
return res.status(400).json({ error: 'Please provide email and password' });
if (error.name === 'ValidationError') {
return res.status(400).json({ error: error.message }); // Validation errors
} else {
return res.status(500).json({ error: 'Internal server error' });
}
}
};

let user = await User.findOne({ email });


if (!user) {
module.exports.logout = async (req, res) => {
const { refreshToken } = req.cookies;

user = UnverifiedUser.findOne({email});
if(!user)
return res.status(404).json({ error: 'User not found' });
else
return res.status(403).json({ error: 'Email not verified. Please check your email.' });

}
if (!refreshToken) {
return res.status(400).json({ error: 'Refresh token required' });
}

if (!user.isVerified) {
return res.status(403).json({ error: 'Email not verified. Please check your email.' });
try {
// Find the user and remove the refresh token
const user = await User.findOne({ refreshToken });
if (user) {
user.refreshToken = null;
await user.save();
}


const isPasswordValid = await bcrypt.compare(password, user.password);
// Clear cookies
res.clearCookie('accessToken');
res.clearCookie('refreshToken');

if (!isPasswordValid) {
return res.status(401).json({ error: 'Invalid password' });
res.status(200).json({ message: 'Logout successful' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
};

module.exports.refreshToken = async (req, res) => {
const { refreshToken } = req.body;

if (!refreshToken) {
return res.status(401).json({ error: 'Refresh token required' });
}

try {
// Verify the refresh token
const decoded = jwt.verify(refreshToken, process.env.JWT_SECRET);

// Check if the refresh token is valid and associated with the user
const user = await User.findOne({ _id: decoded.userId, refreshToken });
if (!user) {
return res.status(403).json({ error: 'Invalid refresh token' });
}

const token = jwt.sign(
// Generate a new access token
const newAccessToken = jwt.sign(
{ userId: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1d' }
{ expiresIn: '15m' }
);

user.verificationToken = token;
res.cookie('token', token, { httpOnly: true, maxAge: 86400000 });
res.status(200).json({ user, token, message: "Login Successful" });

// Optionally, generate a new refresh token
const newRefreshToken = jwt.sign(
{ userId: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);

// Update the refresh token in the database
user.refreshToken = newRefreshToken;
await user.save();

res.cookie('accessToken', newAccessToken, { httpOnly: true, maxAge: 900000 }); // 15 minutes
res.cookie('refreshToken', newRefreshToken, { httpOnly: true, maxAge: 604800000 }); // 7 days

res.status(200).json({ accessToken: newAccessToken, refreshToken: newRefreshToken });
} catch (error) {
if (error.name === 'ValidationError') {
return res.status(400).json({ error: error.message }); // Validation errors
} else {
return res.status(500).json({ error: 'Internal server error' });
}
res.status(403).json({ error: 'Invalid refresh token' });
}
};

module.exports.logout = (req, res) => {

// Clear the JWT token cookie
res.clearCookie('token');
res.json({ message: 'Logout successful' });
};

module.exports.deleteByUser = async(req,res)=>{
module.exports.deleteByUser = async(req,res)=>{
let token;
if (req.cookies && req.cookies['token']) {
token = req.cookies['token'];
Expand Down Expand Up @@ -285,7 +357,7 @@ module.exports.logout = (req, res) => {
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}


module.exports.deleteByAdmin = async(req,res)=>{
Expand Down
23 changes: 11 additions & 12 deletions backend/middleware/authentcatetoken.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
const jwt = require('jsonwebtoken');

const authenticateToken = (req, res, next) => {
// console.log(req.cookies.token);
const token = req.cookies.token || req.headers['authorization'];
const token = req.cookies.token || req.headers['authorization']?.split(' ')[1];
console.log("Token", token)
if (!token) return res.status(401).json({ error: 'No token provided' });

if (!token) {
return res.status(401).json({ error: 'Access denied. No token provided.' });
}

try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
console.error('Token verification error:', err.message);
return res.status(403).json({ error: 'Invalid token' });
}
req.user = user;
next();
} catch (ex) {
res.status(400).json({ error: 'Invalid token.' });
}
});
};

module.exports = authenticateToken;

1 change: 1 addition & 0 deletions backend/models/UserModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const userSchema = new mongoose.Schema({
type: String,
default: null,
},
refreshToken: { type: String, default: null } ,
articles: {
type:Array,
default:[]
Expand Down
6 changes: 5 additions & 1 deletion backend/routes/usersRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ const {
updateReadArticles,
collectMonthlyRecordsForReading,
collectMonthlyRecordsForWriting,
checkOtp
checkOtp,
refreshToken
} = require("../controllers/usersControllers");

const { verifyEmail, sendVerificationEmail, Sendverifymail,resendVerificationEmail } = require('../controllers/emailservice');
Expand All @@ -27,6 +28,9 @@ router.post("/user/register", register);
// Login User Route
router.post("/user/login", login);

// Refresh Token
router.post("/user/refreshToken", refreshToken);

// Get profile
router.get('/user/getprofile',getprofile)
// Follow and Unfollow Routes
Expand Down
Loading
Loading