Best way of querying documents when using Clerk
Hello! I'm currently working on a project that uses both Convex and Clerk together. I've been running into some issues with consistency within my backend when it comes to query documents by id and wanted to see if anyone had advice. The problem is that it's easy and convenient to query by a user's Clerk id, but I lose the type safety of the _id prop. It also leads to weird situations when creating relationships between tables. Should I just my
me
query function (returns user info protected by auth RLS) every time I want to query with a user id or is using the clerkId as the primary way of fetching a document a ok practice?
me function
utils
4 Replies
The reason you don't want to rely on a
me
query on the client side is that then you're writing functions that rely on passing in the user id directly and that's not safe: a user could pass in whatever they wanted from the client.
Could you say more about losing type safety of the _id prop? _id isn't much different than any other property, so you can make your own property that refers to a Clerk user id.So in that case I should use
ctx.identity.subject
passed from my RLS and then query the user for their user id? The main thing is it feels a bit weird having two main id fields with the clerkId field allowing my to avoid querying the user for their id.
For example if I have a relationship like this where an entry belongs to a user I could either: one use the _id field of the user but then that means I have to query a user by their clerk id to get their user id, or two use the clerk id as the field for relationship and always query by the clerk id. I feel like either there's something I'm missing or there's a better way.Either one of these is fine: using the clerk id as a foreign key to find entities that belong to a user, or using the clerk id as an indexed field on a Users table where you store other things, including a _id that is the foreign key in your other entities.
If you go with the seperate user record approach, probably I'd do this get this User record in the authRLSQuery wrapper, so instead of or in addition to ctx.identity you add ctx.currentUser or similar
I see that makes sense and thank you for the insight!
as a quick example something like this would be best if I decided to go the seperate user route?