104 lines
2.9 KiB
TypeScript
104 lines
2.9 KiB
TypeScript
import type { Actions, PageServerLoad } from '$types';
|
|
import { type inquiryTokenPayload, Sender } from '$lib/types/inquiries';
|
|
import jwt from 'jsonwebtoken';
|
|
import { error } from '@sveltejs/kit';
|
|
import sql from '$lib/db/db.server';
|
|
import { getRequiredFormString } from '$lib/shared';
|
|
import { sendInquiryMessageEmail } from '$lib/email/sender.server';
|
|
import type { Item } from '$lib/types/item';
|
|
|
|
export const load: PageServerLoad = async ({ url, locals, params }) => {
|
|
const token: string | undefined = url.searchParams.get('token');
|
|
const inquiryId: string = params.inquiryId;
|
|
|
|
if (token) {
|
|
try {
|
|
jwt.verify(token, process.env.JWT_SECRET!);
|
|
} catch {
|
|
throw error(403, 'Your response token does not match this inquiry!');
|
|
}
|
|
} else if (!locals || !locals.user) {
|
|
throw error(
|
|
403,
|
|
'You must be either signed in, or have a respond token to access this inquiry!'
|
|
);
|
|
}
|
|
|
|
const [item]: Item[] = await sql`
|
|
SELECT
|
|
i.*,
|
|
json_agg(
|
|
jsonb_build_object(
|
|
'id', t.id,
|
|
'item_id', t.item_id,
|
|
'created_at', t.created_at,
|
|
'messages', m.messages
|
|
)
|
|
) FILTER ( WHERE t.id = ${inquiryId} ) AS threads
|
|
FROM items i
|
|
LEFT JOIN inquiry_threads t
|
|
ON t.item_id = i.id
|
|
LEFT JOIN LATERAL (
|
|
SELECT
|
|
json_agg(im.* ORDER BY im.created_at) AS messages
|
|
FROM inquiry_messages im
|
|
WHERE im.thread_id = t.id
|
|
) m ON TRUE
|
|
WHERE i.id = (SELECT item_id FROM inquiry_threads WHERE id = ${inquiryId})
|
|
GROUP BY i.id;`;
|
|
|
|
console.log(item);
|
|
|
|
return { item };
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
reply: async ({ request, url, locals, params }) => {
|
|
const token: string | undefined = url.searchParams.get('token');
|
|
const inquiryId: number = params.inquiryId;
|
|
|
|
let sender: Sender | undefined;
|
|
|
|
if (locals && locals.user) {
|
|
sender = Sender.ADMIN;
|
|
} else if (token) {
|
|
let decoded: inquiryTokenPayload;
|
|
try {
|
|
decoded = jwt.verify(token, process.env.JWT_SECRET!) as inquiryTokenPayload;
|
|
sender = decoded.sender;
|
|
} catch {
|
|
throw error(403, 'Your response token does not match this inquiry!');
|
|
}
|
|
|
|
if (decoded.threadId.toString() !== inquiryId.toString()) {
|
|
throw error(403, 'Your response token does not match this inquiry!');
|
|
}
|
|
} else {
|
|
throw error(
|
|
403,
|
|
'You must be either signed in, or have a respond token to access this inquiry!'
|
|
);
|
|
}
|
|
|
|
const data = await request.formData();
|
|
|
|
const body = getRequiredFormString(data, 'message');
|
|
|
|
const response = await sql`
|
|
INSERT INTO inquiry_messages (thread_id, sender, body)
|
|
VALUES (${inquiryId}, ${sender}, ${body})
|
|
RETURNING id;
|
|
`;
|
|
|
|
let nextReplySender: Sender;
|
|
if (sender === Sender.ADMIN || sender === Sender.FINDER) {
|
|
nextReplySender = Sender.INQUIRER;
|
|
} else {
|
|
nextReplySender = Sender.FINDER;
|
|
}
|
|
await sendInquiryMessageEmail(inquiryId, nextReplySender);
|
|
|
|
return { success: true };
|
|
}
|
|
} satisfies Actions;
|