import { createClient } from '@supabase/supabase-js' import type { NextApiRequest, NextApiResponse } from 'next' import z from 'zod' import { DASHBOARD_LOG_BUCKET } from '@/components/interfaces/Support/dashboard-logs' import apiWrapper from '@/lib/api/apiWrapper' import { getUserClaims } from '@/lib/gotrue' export const maxDuration = 120 const GenerateAttachmentUrlSchema = z.object({ filenames: z.array(z.string()), bucket: z .enum(['support-attachments', 'feedback-attachments', DASHBOARD_LOG_BUCKET]) .default('support-attachments'), }) async function handlePost(req: NextApiRequest, res: NextApiResponse) { const { claims, error: userClaimsError } = await getUserClaims(req.headers.authorization!) if (userClaimsError || !claims) { return res.status(401).json({ error: { message: 'Unauthorized' } }) } const userId = claims.sub const json = JSON.parse(req.body) const parseResult = GenerateAttachmentUrlSchema.safeParse(json) if (!parseResult.success) { return res.status(400).json({ error: { message: 'Invalid request body' } }) } const filenames = parseResult.data.filenames const requestedPrefixes = [...new Set(filenames.map((filename) => filename.split('/')[0]))] if (requestedPrefixes.some((prefix) => prefix !== userId)) { return res .status(403) .json({ error: { message: 'Forbidden: Users can only access their own resources' } }) } const adminBriven = createClient( process.env.NEXT_PUBLIC_SUPPORT_API_URL!, process.env.SUPPORT_BRIVEN_SECRET_KEY!, { auth: { persistSession: false, autoRefreshToken: false, // @ts-expect-error multiTab: false, detectSessionInUrl: false, localStorage: { getItem: (_key: string) => undefined, setItem: (_key: string, _value: string) => {}, removeItem: (_key: string) => {}, }, }, } ) const bucket = parseResult.data.bucket // Create signed URLs for 10 years const { data, error: signedUrlError } = await adminBriven.storage .from(bucket) .createSignedUrls(filenames, 10 * 365 * 24 * 60 * 60) if (signedUrlError) { console.error('Failed to sign URLs for attachments', signedUrlError) return res.status(500).json({ error: { message: 'Failed to sign URLs for attachments' } }) } return res.status(200).json(data ? data.map((file) => file.signedUrl) : []) } async function handler(req: NextApiRequest, res: NextApiResponse) { const { method } = req switch (method) { case 'POST': return handlePost(req, res) default: res.setHeader('Allow', ['POST']) res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` }, }) } } const wrapper = (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler, { withAuth: true }) export default wrapper