Skip to content
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
1 change: 0 additions & 1 deletion src/config/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import mongoose from 'mongoose';
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI);
console.log('MongoDB connected');
} catch (error) {
console.error('DB connection failed', error);
process.exit(1);
Expand Down
11 changes: 10 additions & 1 deletion src/controllers/authcontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const login = async (req, res) => {
const user = await User.findOne({
email: { $regex: new RegExp(`^${email}$`, 'i') },
role: { $regex: new RegExp(`^${role}$`, 'i') },
}).select('email role status password');
}).select('email role status password, mustchangepassword');
if (!user) {
return res.status(401).json({ success: false, message: 'Invalid role or email' });
}
Expand All @@ -35,6 +35,15 @@ export const login = async (req, res) => {
return res.status(403).json({ success: false, message: "Your account is currently inactive. Kindly reach out to the admin for support." });
}

if (user.mustchangepassword) {
return res.status(200).json({
success: true,
reuirePasswordChange: true,
message: "You are required to change your password before proceeding.",
email: user.email,
});
}

const token = jwt.sign(
{ id: user._id, role: user.role, email: user.email },
process.env.JWT_SECRET,
Expand Down
14 changes: 13 additions & 1 deletion src/controllers/patient.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import Patient from '../models/patient.js';
import { createPatientPortalAccount } from '../services/patientPortal.service.js';

const createPatient = async (req, res, next) => {
try {
const patient = new Patient(req.body);
await patient.save();
res.status(201).json(patient);

const { email, paymentMethod } = req.body;

if (paymentMethod === "online" && email) {
await createPatientPortalAccount(email);
}

res.status(201).json({
success: true,
patient
});

} catch (err) {
next(err);
}
Expand Down
12 changes: 11 additions & 1 deletion src/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,25 @@ const userSchema = new mongoose.Schema({
match: /.+@.+\..+/
},

patientId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Patient"
},

password: {
type: String,
required: true
},

mustChangePassword: {
type: Boolean,
default: false
},

role: {
type: String,
required: true,
enum: ['admin', 'doctor','receptionist','billing']
enum: ['admin', 'doctor','receptionist','billing','patient']
},

name: { type: String },
Expand Down
5 changes: 5 additions & 0 deletions src/models/patient.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ status:{
default:'active',
required:true
},
paymentMethod: {
type: String,
enum: ['cash', 'online'],
default: 'cash'
},
bg:{
type: String,
enum:['A+','A-','B+','B-','AB+','AB-','O+','O-']
Expand Down
8 changes: 4 additions & 4 deletions src/routes/patient.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import * as patientController from '../controllers/patient.js';
const router = express.Router();


router.get('/', protect, authorize('admin', 'doctor'), patientController.getPatients);
router.get('/', protect, authorize('admin', 'doctor','receptionist'), patientController.getPatients);

router.post('/', protect, authorize('admin', 'doctor'), patientController.createPatient);
router.post('/', protect, authorize('admin', 'doctor','receptionist'), patientController.createPatient);

router.put('/:id', protect, authorize('admin', 'doctor'), patientController.updatePatient);
router.put('/:id', protect, authorize('admin', 'doctor','receptionist'), patientController.updatePatient);

router.delete('/:id', protect, authorize('admin'), patientController.deletePatient);
router.delete('/:id', protect, authorize('admin','receptionist'), patientController.deletePatient);

export default router;
29 changes: 29 additions & 0 deletions src/services/email.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,33 @@ export const sendOTPEmail = async (email, otp) => {
</div>
`
});
};

export const sendCredentialsEmail = async (email, password) => {
await transporter.sendMail({
from: `"HMS Team" <${process.env.GMAIL_EMAIL}>`,
to: email,
subject: "Your HMS Patient Portal Login Credentials",

html: `
<div style="font-family: Arial; padding:20px;">
<h2>Welcome to HMS Portal</h2>

<p>Your account has been created successfully.</p>

<p><b>Email:</b> ${email}</p>
<p><b>Password:</b> ${password}</p>

<p>Please login and change your password immediately.</p>

<p>Login Link: <a href="https://hms-app/login">Login</a></p>

<hr/>

<p style="font-size:12px;color:#888;">
This email was generated automatically.
</p>
</div>
`
});
};
32 changes: 32 additions & 0 deletions src/services/patientPortal.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import bcrypt from 'bcrypt';
import User from '../models/User.js';
import { generateRandomPassword } from '../utils/password.utils.js';
import { sendCredentialsEmail } from './email.service.js';

export const createPatientPortalAccount = async (email) => {

try {const existingUser = await User.findOne({ email });

if (existingUser) {
return;
}

const rawPassword = generateRandomPassword(10);

const hashedPassword = await bcrypt.hash(rawPassword, 10);

const user = new User({
email,
password: hashedPassword,
role: "patient",
status: "Active",
mustChangePassword: true
});

await user.save();

await sendCredentialsEmail(email, rawPassword);
} catch (err) {
console.error("Patient pirtal account creation failed:", err);
}
};
8 changes: 8 additions & 0 deletions src/utils/password.utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import crypto from 'crypto';

export const generateRandomPassword = (length = 10) => {
return crypto
.randomBytes(length)
.toString('base64')
.slice(0, length);
};
Loading