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
25 changes: 14 additions & 11 deletions backend/controllers/referral.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,20 +394,21 @@ async function rejectReferral(req, res, next) {
// Get single referral by ID
async function getReferralById(req, res, next) {
try {
const referral = await JobReferral.findById(req.params.id)
.populate('postedBy', 'name email alumnus_bio type referralPostingSuspended referralPostingSuspendedReason')
.populate('applicants.user', 'name email alumnus_bio');

const { referral, access } = await getReferralAccess(req.params.id, req.user.id);

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

const currentUser = req.user?.id ? await getCurrentUserSummary(req.user.id) : null;
const isOwner = referral.postedBy?._id?.toString() === req.user?.id;
if (isReferralHidden(referral) && currentUser?.type !== 'admin' && !isOwner) {
if (!access) {
// Do not leak referral existence.
return res.status(404).json({ message: 'Referral not found' });
}

// Keep response structure consistent with prior implementation.
await referral.populate('postedBy', 'name email alumnus_bio type referralPostingSuspended referralPostingSuspendedReason');
await referral.populate('applicants.user', 'name email alumnus_bio');

res.json(referral);
} catch (err) {
next(err);
Expand All @@ -416,14 +417,14 @@ async function getReferralById(req, res, next) {

async function getReferralTimeline(req, res, next) {
try {
const referral = await JobReferral.findById(req.params.id).select('timeline moderation postedBy');
const { referral, access } = await getReferralAccess(req.params.id, req.user.id);

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

const currentUser = req.user?.id ? await getCurrentUserSummary(req.user.id) : null;
const isOwner = referral.postedBy?.toString() === req.user?.id;
if (isReferralHidden(referral) && currentUser?.type !== 'admin' && !isOwner) {
if (!access) {
// Do not leak referral existence.
return res.status(404).json({ message: 'Referral not found' });
}

Expand All @@ -437,7 +438,9 @@ async function getReferralTimeline(req, res, next) {
}
}


async function closeReferral(req, res, next) {

try {
const { id } = req.params;
const currentUser = await getCurrentUserSummary(req.user.id);
Expand Down
15 changes: 8 additions & 7 deletions frontend/src/components/ReferralDetail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,15 @@ const ReferralDetail = () => {
return;
}

if (isOwner && applicants.length > 0 && !selectedRecipientId) {
setSelectedRecipientId(getDocId(applicants[0].user));
if (isOwner) {
if (applicants.length > 0 && !selectedRecipientId) {
setSelectedRecipientId(getDocId(applicants[0].user));
}
return;
}

if (!isOwner) {
setSelectedRecipientId(getDocId(referral.postedBy));
}
}, [referral, applicants, isOwner, selectedRecipientId]);
setSelectedRecipientId(getDocId(referral.postedBy));
}, [referral, applicants, isOwner]);

const fetchReferral = async () => {
try {
Expand Down Expand Up @@ -487,7 +488,7 @@ const ReferralDetail = () => {

<button
type="submit"
disabled={sendingMessage}
disabled={sendingMessage || (isOwner && !selectedRecipientId)}
className="inline-flex items-center justify-center rounded-xl bg-blue-600 px-5 py-3 font-semibold text-white shadow-lg transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50"
>
{sendingMessage ? 'Sending...' : 'Send Message'}
Expand Down
Loading