Skip to content

Commit f6d49ca

Browse files
🚚 refactor: migrate GET uploads logic to new search route
Refactored the uploads fetching logic by removing the GET function from `uploads/route.ts` and implementing a new POST request handler in `uploads/search/route.ts` - Centralizes upload search functionality in a dedicated file for clarity and maintainability. - Introduces validation of request bodies using Zod, improving the robustness of the API by ensuring only valid requests are processed. - Supports advanced filtering by project ID and author IDs, allowing for more granular access to upload data.
1 parent ae5db6e commit f6d49ca

2 files changed

Lines changed: 84 additions & 59 deletions

File tree

‎apps/web/app/api/uploads/route.ts‎

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -131,62 +131,3 @@ export async function POST(req: NextRequest, res: NextApiResponse) {
131131
});
132132
}
133133
}
134-
135-
// Handles GET requests for fetching user uploads with pagination support
136-
export async function GET(req: NextRequest, res: NextApiResponse) {
137-
try {
138-
const user = await getUser();
139-
// @ts-ignore
140-
// If user retrieval fails, respond with an Unauthorized error
141-
if (!user.id) return NextResponse.json({ error: "Unauthorized" }, {
142-
status: 401
143-
})
144-
145-
// Extracting offset and limit from the query parameters
146-
const { searchParams } = new URL(req.url, baseUrl); // Ensure baseUrl is defined appropriately
147-
const limit = parseInt(searchParams.get('limit') || '10', 10);
148-
const offset = parseInt(searchParams.get('offset') || '0', 10);
149-
150-
// Fetch a paginated list of uploads for the current user
151-
const uploads = await prisma.upload.findMany({
152-
where: {
153-
// @ts-ignore
154-
userId: user?.id,
155-
},
156-
orderBy: {
157-
createdAt: 'desc',
158-
},
159-
take: limit,
160-
skip: offset,
161-
});
162-
163-
// Fetching the total count of uploads for pagination
164-
const totalCount = await prisma.upload.count({
165-
where: {
166-
// @ts-ignore
167-
userId: user.id,
168-
},
169-
});
170-
171-
if (!uploads) {
172-
return NextResponse.json({ error: 'No uploads found' }, {
173-
status: 404
174-
});
175-
}
176-
// Respond with the list of uploads and the total count for pagination
177-
return NextResponse.json({ uploads, total: totalCount });
178-
} catch (error: any) {
179-
console.error(error);
180-
captureException(new Error(`Fetching Uploads: ${error?.message}`), {
181-
data: {
182-
error,
183-
},
184-
});
185-
return NextResponse.json({
186-
status: 500,
187-
body: {
188-
error: error?.message || 'Failed to fetch uploads',
189-
}
190-
});
191-
}
192-
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { NextApiResponse, NextApiRequest } from 'next';
2+
import { prisma } from '@/app/utils';
3+
import { getUser } from '../../utils';
4+
import { captureException } from '@sentry/nextjs';
5+
import { NextResponse } from 'next/server';
6+
import { z } from 'zod'; // Import Zod
7+
import { Role } from '@prisma/client';
8+
9+
// Define the request body schema using Zod
10+
const requestBodySchema = z.object({
11+
offset: z.number().optional(),
12+
limit: z.number().optional(),
13+
projectId: z.string(), // projectId is required
14+
authorIds: z.array(z.string()).optional(), // authorIds are optional
15+
});
16+
17+
// Handles POST requests for fetching user uploads with pagination and filtering support
18+
export async function POST(req: NextApiRequest, res: NextApiResponse) {
19+
try {
20+
// console.log(req.body)
21+
const body = await new Response(req.body).json();
22+
// const body = await
23+
// Validate the request body against the schema
24+
const validatedBody = requestBodySchema.safeParse(body);
25+
if (!validatedBody.success) {
26+
// Extract and format Zod error messages
27+
const errorMessages = validatedBody.error.errors.map(error => `${error.path.join('.')}: ${error.message}`).join(', ');
28+
return NextResponse.json({ error: "Validation failed", details: errorMessages }, {
29+
status: 400
30+
});
31+
}
32+
33+
const user = await getUser();
34+
// @ts-ignore
35+
const userId = user?.id;
36+
if (!userId) return res.status(401).json({ error: "Unauthorized" });
37+
38+
const { offset = 0, limit = 10, projectId, authorIds } = validatedBody.data;
39+
40+
// Check if the user is an owner of the project
41+
const projectUserRole = await prisma.projectUsers.findUnique({
42+
where: {
43+
userId_projectId: {
44+
userId,
45+
projectId: projectId,
46+
},
47+
},
48+
});
49+
50+
if (projectUserRole?.role !== Role.owner && authorIds && authorIds.some(authorId => authorId !== userId)) {
51+
return NextResponse.json({ error: "Forbidden: User is not an owner of the project" }, { status: 403 })
52+
}
53+
54+
// Construct the where clause for filtering uploads
55+
const whereClause = {
56+
projectId,
57+
userId: authorIds?.length ? { in: authorIds } : userId,
58+
};
59+
60+
// Fetch a paginated list of uploads based on the request body parameters
61+
const uploads = await prisma.upload.findMany({
62+
where: whereClause,
63+
orderBy: { createdAt: 'desc' },
64+
take: limit,
65+
skip: offset,
66+
});
67+
68+
// Fetching the total count of uploads for pagination
69+
const totalCount = await prisma.upload.count({ where: whereClause });
70+
71+
if (!uploads.length) return NextResponse.json({ uploads: [], total: 0 });
72+
73+
// Respond with the list of uploads and the total count for pagination
74+
return NextResponse.json({ uploads, total: totalCount });
75+
} catch (error: any) {
76+
// Handle Zod validation errors
77+
if (error instanceof z.ZodError) {
78+
return NextResponse.json({ error: error.flatten() }, { status: 400 });
79+
}
80+
console.error(error);
81+
captureException(new Error(`Fetching Uploads: ${error?.message}`), { data: { error: error?.message } });
82+
return NextResponse.json({ error: error?.message }, { status: 500 });
83+
}
84+
}

0 commit comments

Comments
 (0)