Security with DB
Unanswered
Masai Lion posted this in #help-forum
Masai LionOP
Let´s say we need to handle database sorting through an API endpoint, like localhost:3000/api/products?sortBy=price&order=ASC&category=, and we need to always ensure it's done safely while I have to prioritize security. What would be your opinions on handling like this?
49 Replies
Masai LionOP
@DirtyCajunRice | AppDir
Basically I first create a db client from
/db/config.ts, then, I made and API that fetches and queries the data based on params src/app/api/products/route.ts, and from that I make a request from a page to get the products and display themBasically
DB > API > PAGEOn the API I handle the query with
const { searchParams } = new URL(request.url);
const sortBy = (searchParams.get('sortBy') as ValidColumn) || 'price';
const order = searchParams.get('order') || 'ASC';
const category = searchParams.get('category') || '';
const keyword = searchParams.get('keyword') || '';My question is, how "safe" is it to handle the query like this?
and make requests like this:
useEffect(() => {
async function fetchProducts() {
const res = await fetch(`/api/products?sortBy=${sortBy}&order=${order}&category=${category}`);
const sortedProducts = await res.json();
setFilteredProducts(sortedProducts);
}
fetchProducts();
}, [sortBy, order, category]);@Masai Lion <@184479429404262410>
got hyper focused. looking now
1. request.nextUrl.searchParams
2. i would personally convert those search params into an object and have zod parse it
3. i NEVER suggest fetching in a useEffect. use a tanstack query
@DirtyCajunRice | AppDir 1. request.nextUrl.searchParams
Masai LionOP
i dont understand...
you mean from the searchParams object?
the new URL(request.url)?
@Masai Lion i dont understand...
const { searchParams } = new URL(request.url);to
const { searchParams } = request.nextUrlno need to reinvent the wheel. its already done for you
@DirtyCajunRice | AppDir js
const { searchParams } = new URL(request.url);
to
js
const { searchParams } = request.nextUrl
Masai LionOP
but i defined request as Request from 'next/server';
@Masai Lion but i defined request as Request from 'next/server';
Need to change it to NextRequest. Thats what it really is.
@DirtyCajunRice | AppDir Need to change it to NextRequest. Thats what it really is.
Masai LionOP
alr so i made my zod thingy like this:
const querySchema = z.object({
sortBy: z.enum(['price', 'name', 'createdAt']).default('price'),
order: z.enum(['ASC', 'DESC']).default('ASC'),
category: z.string().optional(),
keyword: z.string().optional()
});
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const result = querySchema.safeParse(Object.fromEntries(searchParams.entries()));
}i need to see
how to change searchParams definition
meanwhile it can stay like it is for a while
@Masai Lion how to change searchParams definition
i literally linked it
Masai LionOP
yay i did it
@DirtyCajunRice | AppDir i literally linked it
Masai LionOP
ye i saw
@DirtyCajunRice | AppDir 3. i NEVER suggest fetching in a useEffect. use a tanstack query
Masai LionOP
now for this... mmm havent used it much, but let me do something from what i remember
@Masai Lion ye i saw
also its generally not smart to do what you did with entries
as params can be entered multiple times and it may come back as a comma list
you should .get each value
@DirtyCajunRice | AppDir you should .get each value
Masai LionOP
with zod entries?
const params = ParamsSchema.parse({
tags: searchParams.get('tags'),
period: searchParams.get('period'),
posts: searchParams.get('posts'),
}); if the user can break it, the user WILL break it
leave nothing to chance
@DirtyCajunRice | AppDir ts
const params = ParamsSchema.parse({
tags: searchParams.get('tags'),
period: searchParams.get('period'),
posts: searchParams.get('posts'),
});
Masai LionOP
const querySchema = z.object({
sortBy: z.enum(['price', 'name', 'createdAt']).default('price'),
order: z.enum(['ASC', 'DESC']).default('ASC'),
category: z.string().optional(),
keyword: z.string().optional()
});
export async function GET(request: NextRequest) {
const url = request.nextUrl.searchParams
const searchParams = url.searchParams;
const params = querySchema.parse({
sortBy: searchParams.get('sortBy') || undefined,
order: searchParams.get('order') || undefined,
category: searchParams.get('category') || undefined,
keyword: searchParams.get('keyword') || undefined,
});
const { sortBy, order, category, keyword } = params;
}this is what i did
you dont need undefined
you can deal with that in the schema
@DirtyCajunRice | AppDir you dont need undefined
Masai LionOP
so queryschema should be deleted
and we stay with params?
wait
… what
Masai LionOP
mmm
i understood now
hold up
ye got it
Masai LionOP
@DirtyCajunRice | AppDir
basically what i did now is uhhh on the client
im still fetching but using tanstack query, never used it before btw so not sure if its correctly implemented
basically what i did now is uhhh on the client
const [sortBy, setSortBy] = useState<keyof IProduct>('price');
const [order, setOrder] = useState<'ASC' | 'DESC'>('ASC');
const router = useRouter();
const fetchProducts = async () => {
const res = await fetch(`/api/products?sortBy=${sortBy}&order=${order}&category=${category}`);
return res.json();
};
const { data: filteredProducts = [] } = useQuery({
queryKey: ['products', sortBy, order, category],
queryFn: fetchProducts,
});im still fetching but using tanstack query, never used it before btw so not sure if its correctly implemented
import { z } from 'zod';
const querySchema = z.object({
sortBy: z.enum(['price', 'name', 'createdAt']).default('price'),
order: z.enum(['ASC', 'DESC']).default('ASC'),
category: z.string().optional(),
keyword: z.string().optional()
});
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams
const sortBy = searchParams.get('sortBy') || 'price';
const order = searchParams.get('order') || 'ASC';
const category = searchParams.get('category') || '';
const keyword = searchParams.get('keyword') || '';
const result = querySchema.safeParse({ sortBy, order, category, keyword });for zod parse I cant make the zod interface inside my db schema cuz it isnt part of it at all, this are just params that have nothing to do with the object. then I get the search params and then I do safeParse to pase the four params.
not sure what else is missing or what might be wrong...