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

Fix social logins #127

Merged
merged 1 commit into from
Jun 29, 2024
Merged
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
157 changes: 93 additions & 64 deletions src/controller/userController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { sendCode } from '../emails/mailer';
import jwt from 'jsonwebtoken';
import errorHandler from '../middlewares/errorHandler';


// Assuming dbConnection.getRepository(UserModel) returns a repository instance
const userRepository = dbConnection.getRepository(UserModel);
const roleRepository = dbConnection.getRepository(Role);
Expand All @@ -26,10 +25,9 @@ interface UpdateRrofileRequestBody {
firstName: string;
lastName: string;
email: string;
password:string;
password: string;
}


// Define validation and sanitization rules
const registerUserRules = [
check('firstName').isLength({ min: 1 }).withMessage('First name is required'),
Expand Down Expand Up @@ -80,7 +78,11 @@ export const registerUser = [
);

const confirmLink = `${process.env.APP_URL}/api/v1/confirm?token=${token}`;
process.env.NODE_ENV !== 'test' && await sendEmail('confirm', email, { name: firstName, link: confirmLink });
process.env.NODE_ENV !== 'test' &&
(await sendEmail('confirm', email, {
name: firstName,
link: confirmLink,
}));

res.status(201).json({
message: 'User successfully registered',
Expand Down Expand Up @@ -143,7 +145,7 @@ export const Login = errorHandler(async (req: Request, res: Response) => {
);

const confirmLink = `${process.env.APP_URL}/api/v1/confirm?token=${token}`;
if (process.env.NODE_ENV !== 'test'){
if (process.env.NODE_ENV !== 'test') {
await sendEmail('confirm', user.email, {
name: user.firstName,
link: confirmLink,
Expand All @@ -166,20 +168,21 @@ export const Login = errorHandler(async (req: Request, res: Response) => {
});
}

res
.status(200)
.json({ message: 'Please provide the 2FA code sent to your email.' });
return res.status(200).json({
message: 'Please provide the 2FA code sent to your email.',
user: { id: user.id, email: user.email },
});
} else if (user.userType.name === 'Admin') {
const token = jwt.sign({ user }, process.env.JWT_SECRET as jwt.Secret, {
expiresIn: '1h',
expiresIn: '7d',
});

return res
.status(200)
.json({ token, message: 'Admin Logged in successfully' });
} else {
const token = jwt.sign({ user }, process.env.JWT_SECRET as jwt.Secret, {
expiresIn: '1h',
expiresIn: '7d',
});

return res
Expand All @@ -205,12 +208,11 @@ export const verify2FA = errorHandler(async (req: Request, res: Response) => {
}

const token = jwt.sign({ user }, process.env.JWT_SECRET as jwt.Secret, {
expiresIn: '1d',
expiresIn: '7d',
});
return res.status(200).json({ token });
});


// Delete All Users
export const deleteAllUsers = async (req: Request, res: Response) => {
try {
Expand All @@ -227,80 +229,107 @@ export const deleteAllUsers = async (req: Request, res: Response) => {
// Get All Users
export const getAllUsers = errorHandler(async (req: Request, res: Response) => {
const users = await userRepository.find();
return res.status(200).json({message: 'Users fetched successfully', users});
return res.status(200).json({ message: 'Users fetched successfully', users });
});

export const recoverPassword = errorHandler(async (req: Request, res: Response) => {
const { email } = req.body as { email: string };
export const recoverPassword = errorHandler(
async (req: Request, res: Response) => {
const { email } = req.body as { email: string };

const user = await userRepository.findOne({ where: { email } });
const user = await userRepository.findOne({ where: { email } });

if (!user) {
return res.status(404).json({ message: 'User not found' });
}
if (!user) {
return res.status(404).json({ message: 'User not found' });
}

// Generate a JWT token with the user's email as the payload
const recoverToken = jwt.sign({ email : user.email }, process.env.JWT_SECRET as jwt.Secret, { expiresIn: '1h' });

const confirmLink = `${process.env.APP_URL}/api/v1/user/recover/confirm?recoverToken=${recoverToken}`;

return res.status(200).json({ message: 'Password reset token generated successfully', confirmLink });
// Generate a JWT token with the user's email as the payload
const recoverToken = jwt.sign(
{ email: user.email },
process.env.JWT_SECRET as jwt.Secret,
{ expiresIn: '1h' }
);

});
const confirmLink = `${process.env.APP_URL}/api/v1/user/recover/confirm?recoverToken=${recoverToken}`;

return res.status(200).json({
message: 'Password reset token generated successfully',
confirmLink,
});
}
);

//password Recover Confirmation
export const updateNewPassword = errorHandler(async (req: Request, res: Response) => {
const recoverToken = req.query.recoverToken as string;
const { password } = req.body as { password: string };
export const updateNewPassword = errorHandler(
async (req: Request, res: Response) => {
const recoverToken = req.query.recoverToken as string;
const { password } = req.body as { password: string };

if (!recoverToken) {
return res.status(404).json({ message: 'Invalid or expired token' });
}
if (!recoverToken) {
return res.status(404).json({ message: 'Invalid or expired token' });
}

const decoded = jwt.verify(recoverToken, process.env.JWT_SECRET as jwt.Secret) as {
email : string;
};
const user = await userRepository.findOne({
where: { email: decoded.email },
});
const decoded = jwt.verify(
recoverToken,
process.env.JWT_SECRET as jwt.Secret
) as {
email: string;
};
const user = await userRepository.findOne({
where: { email: decoded.email },
});

if (!user) {
return res.status(404).json({ message: 'User not found' });
}

const hashedPassword : string = await bcrypt.hash(password, 10);
user.password = hashedPassword;
if (!user) {
return res.status(404).json({ message: 'User not found' });
}

await userRepository.save(user);
const hashedPassword: string = await bcrypt.hash(password, 10);
user.password = hashedPassword;

return res.status(200).json({ message: 'Password updated successfully' });
await userRepository.save(user);

});
export const updateProfile = errorHandler(async (req: Request, res: Response) => {
const userId: number = parseInt(req.params.id);
const { firstName, lastName, email } = req.body as UpdateRrofileRequestBody;
return res.status(200).json({ message: 'Password updated successfully' });
}
);
export const updateProfile = errorHandler(
async (req: Request, res: Response) => {
const userId: number = parseInt(req.params.id);
const { firstName, lastName, email } = req.body as UpdateRrofileRequestBody;

const user = await userRepository.findOne({ where: { id: userId } });
const user = await userRepository.findOne({ where: { id: userId } });

if (!user) {
return res.status(404).json({ error: 'User not found' });
}
if (!user) {
return res.status(404).json({ error: 'User not found' });
}

user.firstName = firstName || user.firstName;
user.lastName = lastName || user.lastName;

user.firstName = firstName || user.firstName;
user.lastName = lastName || user.lastName;


const emailExists = await userRepository.findOne({ where: { email } });

if (emailExists) {
return res.status(400).json({ error: 'Email is already taken' });
}

user.email = email;



await userRepository.save(user);
await userRepository.save(user);

return res.status(201).json({ message: 'User updated successfully' });
}
);

export const deleteUser = errorHandler(async (req: Request, res: Response) => {
const userId: number = parseInt(req.params.userId);

const user = await userRepository.findOne({
where: { id: userId },
});

if (!user) {
return res.status(404).json({ message: 'user Not Found' });
}

await userRepository.delete(userId);

return res.status(201).json({ message: 'User updated successfully' });
return res.status(200).json({ message: 'User deleted successfully' });
});
90 changes: 48 additions & 42 deletions src/middlewares/passport-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import GooglePassport from 'passport-google-oauth20';
import FacebookPassport from 'passport-facebook';
import dbConnection from '../database';
import UserModel from '../database/models/userModel';
import { Role } from '../database/models/roleEntity';
import dotenv from 'dotenv';
dotenv.config();

const userRepository = dbConnection.getRepository(UserModel);
const roleRepository = dbConnection.getRepository(Role);

passport.serializeUser((user: any, done) => {
done(null, user.id);
Expand All @@ -30,16 +32,24 @@ passport.use(
async (accessToken: any, refreshToken: any, profile: any, done: any) => {
try {
// check if user is already exit in db
const existUser = await userRepository.findOneBy({
googleId: profile.id,
const existUser = await userRepository.find({
where: [{ googleId: profile.id }, { email: profile.emails[0].value }],
select: {
userType: {
name: true,
},
},
relations: ['userType'],
});

if (existUser) {
if (existUser.length > 0) {
// already have the user
console.log('user already exist in db:', existUser);
done(null, existUser);
// console.log('user already exist in db:', existUser[0]);
done(null, existUser[0]);
} else {
// if not , create a new user in db
const userRole = await roleRepository.findOneBy({ name: 'Buyer' });

const newUser = new UserModel({
firstName: profile.name.givenName,
lastName: profile.name.familyName,
Expand All @@ -48,9 +58,10 @@ passport.use(
picture: profile.photos[0].value,
provider: profile.provider,
isVerified: true,
userType: userRole!,
});

const user = await userRepository.save(newUser);
console.log('User successfully registered');
done(null, user);
}
} catch (error) {
Expand All @@ -72,50 +83,45 @@ passport.use(
},
async (accessToken: any, refreshToken: any, profile: any, done: any) => {
// check if user is already exit in db
const existUser = await userRepository.findOneBy({
facebookId: profile.id,
let email = profile.email || profile.emails[0].value;

const existUser = await userRepository.find({
where: [{ facebookId: profile.id }, { email: email }],
select: {
userType: {
name: true,
},
},
relations: ['userType'],
});

if (existUser) {
if (existUser.length > 0) {
// already have the user
console.log('user already exist in db:', existUser);
done(null, existUser);
done(null, existUser[0]);
} else {
try {
// check if user is already exit in db
const existUser = await userRepository.findOneBy({
googleId: profile.id,
});

if (existUser) {
// already have the user
console.log('user already exist in db:', existUser);
done(null, existUser);
} else {
// if not , create a new user in db

// Here we have to check user email because there is people that register with facebook that never verify their email account and there is people that sign up with a phone number, in both those cases their emails will always be undefined.
let email = profile.email || profile.emails[0].value;

if (!email) {
console.log('this user has no email in his facebook account');
let err = { message: 'this user is missing an email' };
return done(err);
}
const newUser = new UserModel({
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: email,
facebookId: profile.id,
picture: profile.photos[0].value,
provider: profile.provider,
});
const user = await userRepository.save(newUser);

console.log('User successfully registered');
// if not , create a new user in db
const userRole = await roleRepository.findOneBy({ name: 'Buyer' });

done(null, user);
// Here we have to check user email because there is people that register with facebook that never verify their email account and there is people that sign up with a phone number, in both those cases their emails will always be undefined.
if (!email) {
console.log('this user has no email in his facebook account');
let err = { message: 'this user is missing an email' };
return done(err);
}
const newUser = new UserModel({
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: email,
facebookId: profile.id,
picture: profile.photos[0].value,
provider: profile.provider,
isVerified: true,
userType: userRole!,
});
const user = await userRepository.save(newUser);
done(null, user);
} catch (error) {
console.log('An error occurred while registering the user:', error);
}
Expand Down
Loading
Loading