File: //proc/thread-self/root/home/arjun/projects/good-life-be/api/Auth/service.js
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import BadRequest from '../../helper/exception/badRequest.js';
import Login from '../../models/Login.js';
import User from '../../models/User.js';
import sendEmails from '../../helper/sendEmail.js';
export const loginSevice = async (body) => {
const { email, password } = body;
const { JWT_SECRET } = process.env;
// Find login by email
const login = await Login.findOne({
where: { email },
include: { model: User, where: { is_deleted: false } },
raw: true,
});
if (!login) throw new BadRequest('No User found with this email or password');
if (!login['user.is_verified']) {
throw new BadRequest('Please verify your email before logging in.');
}
if (login['user.status'] === 'blocked') {
throw new BadRequest(
'Your Account has been blocked.Please contact Admin for further assistance.'
);
}
// Compare passwords
const isPasswordValid = await bcrypt.compare(password, login.password);
if (!isPasswordValid) {
throw new BadRequest('Invalid email or password.');
}
// Generate JWT token
const token = jwt.sign(
{
id: login.id,
email: login.email,
},
JWT_SECRET,
{ expiresIn: '30d' } // Token expiration time set to 30 days
);
return {
token,
userId: login['user.id'],
role: login['user.role'],
};
};
export const signUpService = async (body) => {
const { email, password, firstName, secondName } = body;
const role = 'user';
// Check if the email already exists
const existingLogin = await Login.findOne({
where: { email },
include: { model: User, where: { is_deleted: false, status: 'active' } },
});
if (existingLogin) {
throw new BadRequest('Email is already registered.');
}
// Create a new User
const newUser = await User.create({
first_name: firstName,
second_name: secondName,
role,
});
// Create a Login record associated with the User
await Login.create({
email,
password,
user_id: newUser.id,
});
// ----------------->>>> Email <<<<---------------------
const { MAILER_NAME, MAILER_AUTH_USER, WEB_DOMAIN } = process.env;
const token = newUser.verification_token;
const verificationLink = `${WEB_DOMAIN}/verify-email?token=${token}`;
const mailOptions = {
from: `${MAILER_NAME} ${MAILER_AUTH_USER}`,
to: email,
subject: 'New Registration Verification',
};
const contentVarialbles = {
name: `${newUser.first_name} ${newUser.second_name}`,
verificationLink,
};
const fileName = 'registerationNotify.ejs';
sendEmails({ mailOptions, fileName, contentVarialbles });
};
export const verifyEmail = async (query) => {
const { token } = query;
// Find user with the verification token
const user = await User.findOne({
where: { verification_token: token },
});
if (!user) {
throw new BadRequest('User is already verified');
}
const login = await Login.findOne({
where: { user_id: user?.id },
attributes: ['email'],
});
// Update the user's verification status
user.is_verified = true;
user.verification_token = null; // Token is no longer needed after verification
user.status = 'active';
await user.save();
// ----------------->>>> Email <<<<---------------------
const { MAILER_NAME, MAILER_AUTH_USER, WEB_DOMAIN } = process.env;
const mailOptions = {
from: `${MAILER_NAME} ${MAILER_AUTH_USER}`,
to: login.email,
subject: 'Welcome to Balance Calendar',
};
const contentVarialbles = {
name: `${user.first_name} ${user.second_name}`,
feUrl: WEB_DOMAIN,
};
const fileName = 'welcome.ejs';
sendEmails({ mailOptions, fileName, contentVarialbles });
};
export async function forgotPassword(email) {
const { JWT_SECRET, MAILER_NAME, MAILER_AUTH_USER } = process.env;
const existingUser = await Login.findOne({
where: { email },
include: {
model: User,
where: { is_deleted: false, status: 'active' },
attributes: ['first_name', 'second_name', 'role'],
},
});
if (!existingUser) {
throw new BadRequest('No account is related to this email.');
}
// if (existingUser.user?.role !== 'admin') {
// throw new BadRequest('Only admins can access this functionality.');
// }
const token = jwt.sign({ email: email.toLowerCase() }, JWT_SECRET, {
expiresIn: '1h',
});
const mailOptions = {
from: `${MAILER_NAME} ${MAILER_AUTH_USER}`,
to: email.toLowerCase(),
subject: 'Reset Your Password',
};
const contentVarialbles = {
url: `${existingUser.user.role === 'user' ? process.env.WEB_DOMAIN : process.env.WEB_DOMAIN_ADMIN}/reset-password/${token}`,
name: `${existingUser.user?.first_name} ${existingUser.user?.second_name}`,
};
const fileName = 'forgotPassword.ejs';
sendEmails({ mailOptions, fileName, contentVarialbles });
return { token };
}
export async function resetPasswordService(token, newPassword) {
const { JWT_SECRET } = process.env;
let hashedNewPassword;
let decoded;
let isSamePassword;
// Verify the tokentry{}
try {
decoded = jwt?.verify(token, JWT_SECRET);
console.log('decoded', decoded);
} catch (error) {
throw new BadRequest('Link Expired', 400);
}
if (!decoded.email) {
throw new BadRequest('Invalid token or token expired', 400);
}
// Fetch the user by email
const existingUser = await Login.findOne({
where: { email: decoded.email },
});
if (!existingUser) {
throw new BadRequest('User not found', 404);
}
console.log('newPassword', newPassword);
if (newPassword !== undefined) {
isSamePassword = await bcrypt.compare(newPassword, existingUser.password);
if (isSamePassword) {
throw new BadRequest(
'New password cannot be the same as the previous password.'
);
}
hashedNewPassword = await bcrypt.hash(newPassword, 10);
await Login.update(
{
password: hashedNewPassword,
},
{ where: { email: decoded.email } }
);
}
// Check if the new password is the same as the current password
// Update the user's password
}