forked from rohit/spurrin-backend
234 lines
12 KiB
JavaScript
234 lines
12 KiB
JavaScript
const db = require('../config/database');
|
|
const nodemailer = require('nodemailer');
|
|
|
|
const sender_mail = process.env.mail;
|
|
const sender_app_password = process.env.apppassword;
|
|
const back_url = process.env.BACK_URL;
|
|
const jwt = require("jsonwebtoken");
|
|
|
|
const bcrypt = require('bcrypt');
|
|
|
|
|
|
const transporter = nodemailer.createTransport({
|
|
host: "smtp.zoho.com",
|
|
port: 465,
|
|
secure: true,
|
|
auth: {
|
|
user: "no-reply@spurrin.com", // Your Zoho email address
|
|
pass: "8TFvKswgH69Y", // Your Zoho App Password (not your account password)
|
|
},
|
|
// tls: {
|
|
// rejectUnauthorized: false, // Allow self-signed certificates
|
|
// minVersion: "TLSv1.2"
|
|
// }
|
|
});
|
|
|
|
// Create a new record
|
|
exports.createExcelEntry = async (req, res) => {
|
|
try {
|
|
const requestorRole = req.user.role;
|
|
const uploaded_by = req.user.id;
|
|
const { hospital_id, hospital_code } = req.user;
|
|
|
|
|
|
|
|
if (!['Superadmin', 'Admin', 8, 7].includes(requestorRole)) {
|
|
return res.status(403).json({ error: 'Access denied. Only Superadmin and Admin can do this action.' });
|
|
}
|
|
|
|
const hospitalUsersQuery = `
|
|
SELECT *
|
|
FROM hospital_users
|
|
WHERE hospital_id = ?
|
|
`;
|
|
const hospitalUserResult = await db.query(hospitalUsersQuery, [hospital_id]);
|
|
|
|
if (!hospitalUserResult || hospitalUserResult.length === 0) {
|
|
return res.status(404).json({ error: 'Hospital not found for the given hospital_id' });
|
|
}
|
|
|
|
// Ensure the request body is an array
|
|
if (!Array.isArray(req.body)) {
|
|
return res.status(400).json({ error: "Invalid data format. Expected an array." });
|
|
}
|
|
|
|
const hospitalQuery = `
|
|
SELECT *
|
|
FROM hospitals
|
|
WHERE hospital_code = ?
|
|
`;
|
|
const hospitalResult = await db.query(hospitalQuery, [hospital_code]);
|
|
|
|
sendEmails(req.body, hospitalResult, back_url);
|
|
|
|
|
|
|
|
|
|
const query = `
|
|
INSERT INTO hospital_users
|
|
(hospital_code, hospital_id, email, hash_password, role_id, is_default_admin, requires_onboarding, password_reset_required, profile_photo_url, phone_number, bio, status, name, department, location, mobile_number)
|
|
VALUES ?
|
|
`;
|
|
|
|
// insert into hospital_users
|
|
const values_hospital_users = await Promise.all(req.body.map(async (item) => {
|
|
const hashedPassword = await bcrypt.hash(item.password, 10); // Hash the password
|
|
|
|
return [
|
|
hospital_code,
|
|
hospital_id,
|
|
item.email,
|
|
hashedPassword, // Use the hashed password here
|
|
item.role,
|
|
0,
|
|
hospitalUserResult[0].requires_onboarding,
|
|
hospitalUserResult[0].password_reset_required,
|
|
hospitalUserResult[0].profile_photo_url,
|
|
item.phonenumber,
|
|
hospitalUserResult[0].bio,
|
|
hospitalUserResult[0].status,
|
|
item.name,
|
|
item.department,
|
|
item.location,
|
|
item.phonenumber
|
|
];
|
|
}));
|
|
|
|
const result = await db.query(query, [values_hospital_users]);
|
|
console.log("result---", result)
|
|
|
|
// Generate and update refresh tokens for each inserted user
|
|
// Get the first inserted ID and calculate subsequent IDs
|
|
const firstInsertedId = result.insertId;
|
|
const numberOfInsertedRows = result.affectedRows;
|
|
|
|
await Promise.all(
|
|
req.body.map(async (item, index) => {
|
|
const insertedUserId = firstInsertedId + index; // Calculate user ID
|
|
|
|
const refreshTokenPayload = {
|
|
id: insertedUserId,
|
|
email: item.email,
|
|
role: item.role,
|
|
};
|
|
|
|
const refreshToken = jwt.sign(
|
|
refreshTokenPayload,
|
|
process.env.JWT_REFRESH_TOKEN_SECRET
|
|
);
|
|
|
|
const updateRefreshTokenQuery = `UPDATE hospital_users SET refresh_token = ? WHERE id = ?`;
|
|
await db.query(updateRefreshTokenQuery, [refreshToken, insertedUserId]);
|
|
})
|
|
);
|
|
// Constructing bulk insert query keeping a copy of uploaded users
|
|
|
|
|
|
res.status(201).json({ message: "Records added successfully!" });
|
|
|
|
} catch (error) {
|
|
console.error("Error inserting data:", error.message);
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// Retrieve all records
|
|
|
|
async function sendEmails(users, hospitalResult, back_url) {
|
|
|
|
for (const user of users) {
|
|
const mailOptions = {
|
|
from: "no-reply@spurrin.com", // Sender's email
|
|
to: user.email, // Unique recipient email
|
|
subject: 'Spurrinai Login Credentials', // Email subject
|
|
html: `<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Welcome to Spurrinai</title>
|
|
<style>
|
|
@media only screen and (max-width: 600px) {
|
|
.container { width: 100% !important; padding-block: 60px; }
|
|
.header-image { height: 150px !important; background-color: #F2F2F7; }
|
|
.content { padding: 20px !important; }
|
|
.credentials-table { font-size: 14px !important; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body style="margin: 0; padding: 0; font-family: Inter, sans-serif; background-color: #f4f4f4;">
|
|
<table role="presentation" style="width: 100%; border-collapse: collapse; display: flex; justify-content: center; align-items: center; height: 100vh;">
|
|
<tr>
|
|
<td align="center" style="padding: 0;">
|
|
<table role="presentation" class="container" style="width: 680px; margin: 0 auto; background-color: #F2F2F7; box-shadow: 0 0 10px rgba(0,0,0,0.1); border-radius: 12px;">
|
|
<tr>
|
|
<td style="padding: 0;">
|
|
<table role="presentation" style="width: 100%; border-collapse: collapse;">
|
|
<tr>
|
|
<td style="padding: 20px 25px; background-color: #F2F2F7;">
|
|
<h1 style="margin: 0; font-size: 24px; color: #333333;">Spurrinai</h1>
|
|
</td>
|
|
</tr>
|
|
<tr style="padding: 0px 0px; display: grid; width: 93%; margin: auto;">
|
|
<td class="header-image" style="height: 200px; background-color: #b5e8e0; background-image: url(${back_url}'public/images/email-banner.png'); background-size: cover; background-position: right bottom; border-radius: 8px;">
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="content" style="padding: 20px 25px;">
|
|
<h2 style="margin: 0 0 20px; font-size: 28px; color: #333333;">Greetings, ${user.name},</h2>
|
|
<p style="margin: 0 0 20px; font-size: 16px; line-height: 1.5; color: #666666;">
|
|
Congratulations! Your hospital, <span style="color: #4F5A68; font-weight: 600;">${hospitalResult[0].name_hospital}</span>, has been successfully onboarded to <span style="color: #4F5A68; font-weight: 600;">Spurrinai</span>. We are excited to have you on board and look forward to supporting your hospital's needs.
|
|
</p>
|
|
<p style="margin: 0 0 20px; font-size: 16px; line-height: 1.5; color: #4F5A68;">
|
|
<strong style="font-weight: 600; color: #4F5A68;">Please find your hospital's login credentials below:</strong>
|
|
</p>
|
|
<table role="presentation" class="credentials-table rounded-table" style="width: 100%; border-collapse: collapse; margin-bottom: 20px;">
|
|
<tbody style="border: 1px solid #dddddd; border-radius: 8px; display: list-item; list-style-type: none; background-color: #fff;">
|
|
<tr style="display: flex; list-style: none;">
|
|
<td style="width: 100%; color: #1B1B1B; padding: 10px; background-color: #F1fffe; border: 1px solid #dddddd; font-weight: 600;">Hospital Name</td>
|
|
<td style="width: 100%; padding: 10px; color: #151515; font-weight: 300; border: 1px solid #dddddd;">${hospitalResult[0].name_hospital}</td>
|
|
</tr>
|
|
<tr style="display: flex; list-style: none;">
|
|
<td style="width: 100%; color: #1B1B1B; padding: 10px; background-color: #F1fffe; border: 1px solid #dddddd; font-weight: 600;">Domain</td>
|
|
<td style="width: 100%; padding: 10px; color: #151515; font-weight: 300; border: 1px solid #dddddd;">${hospitalResult[0].subdomain}</td>
|
|
</tr>
|
|
<tr style="display: flex; list-style: none;">
|
|
<td style="width: 100%; color: #1B1B1B; padding: 10px; background-color: #F1fffe; border: 1px solid #dddddd; font-weight: 600;">Username</td>
|
|
<td style="width: 100%; padding: 10px; color: #151515; font-weight: 300; border: 1px solid #dddddd;">${user.email}</td>
|
|
</tr>
|
|
<tr style="display: flex; list-style: none;">
|
|
<td style="width: 100%; color: #1B1B1B; padding: 10px; background-color: #F1fffe; border: 1px solid #dddddd; font-weight: 600;">Temporary Password</td>
|
|
<td style="width: 100%; padding: 10px; color: #151515; font-weight: 300; border: 1px solid #dddddd;">${user.password}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p style="margin: 0 0 20px; font-size: 16px; line-height: 1.5; color: #525660;">
|
|
For security reasons, we recommend changing your password immediately after logging in.
|
|
</p>
|
|
<table role="presentation" style="width: 100%;">
|
|
<tr>
|
|
<td align="left">
|
|
<a href="https://${hospitalResult[0].subdomain}user" style="display: inline-block; padding: 12px 24px; background-color: #4F5A68; color: #fff; text-decoration: none; border-radius: 4px; font-weight: bold;">Log In and Change Password</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>`
|
|
};
|
|
|
|
try {
|
|
await transporter.sendMail(mailOptions);
|
|
} catch (error) {
|
|
console.error(`Error sending email to ${user.email_id}:`, error);
|
|
}
|
|
}
|
|
} |