ablobwave is there a way to perform

:ablobwave: is there a way to perform arbitrary database updates from a backend? I'm adding convex to an app that already has its own auth solution, and I'm not interested in using auth0 or openID. I just want to manage user documents manually. here's my (incomplete) code, not sure how I can get the DB here
const db = // get convex db somehow

const user = await db
.query("user")
.filter((q) => q.eq(q.field("discordId"), discordUser.id))
.first()

if (!user) {
await db.insert("user", data)
} else {
await db.patch(user._id, data)
}
const db = // get convex db somehow

const user = await db
.query("user")
.filter((q) => q.eq(q.field("discordId"), discordUser.id))
.first()

if (!user) {
await db.insert("user", data)
} else {
await db.patch(user._id, data)
}
I also don't want to make this a mutation(), I want it to only have this logic runnable from the backend
16 Replies
sujayakar
sujayakar3y ago
hi! yeah, this is a limitation with convex right now, since queries can't modify the database. here's some ideas for other patterns -- 1. use a context at the top of your react app (similar to what you would do with an auth0 context) that queries the current user in convex (and maybe talks to your existing auth solution?) and then kicks off a mutation to initialize it if it's not present. it can then provide the user to the rest of your app through the context. 2. if the query is okay with the user not existing (since it's the one initializing it), just use data within the query without writing it to the database, pretending it exists. then, the first mutation called on the user can initialize it properly. would either of those work for your use case?
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
🤔 I guess I phrased my question weirdly. by "arbitrary updates from a backend", I mean outside of a query() or mutation() wrapper. my app is a remix (https://remix.run) app, and the code there would live inside of a regular loader function
// app/routes/auth/callback.tsx
export async function loader() {
// the code which constructs a cookie and such

return new Response(/* send the cookie */)
}
// app/routes/auth/callback.tsx
export async function loader() {
// the code which constructs a cookie and such

return new Response(/* send the cookie */)
}
sujayakar
sujayakar3y ago
ah! no problem. I'm not super familiar with remix, but the idea is that this loader function runs in a backend when server side rendering?
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
correct, yeah
sujayakar
sujayakar3y ago
cool. would it work to make this logic (1) a mutation but then (2) call the mutation using our HTTP client from your remix handler? see https://docs.convex.dev/api/classes/browser.ConvexHttpClient
sujayakar
sujayakar3y ago
that way you're not using the websocket client intended for the browser
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
ah, yeah that should definitely work, thanks! although, this is just a curiosity and not a major concern atm, would a client be able to, theoretically, construct an HTTP/Socket/whatever client, then call the mutation through some browser code modification?
sujayakar
sujayakar3y ago
yeah, exported queries and mutations are your app's backend's public API, and someone could create a client manually and call them directly. convex auth can help with this, since your query or mutation can look at the context's auth (https://docs.convex.dev/generated-api/server#queryctx) and make sure the requestor is who they should be. or, in your case, maybe there'd be some token you can pass up from your auth system that you could validate in your handler to make sure it's legit? also, we'd eventually want to make it really easy to integrate convex auth with your existing auth providers (so all of this is done automatically for you). would be curious how your auth is set up if you're comfortable sharing!
server.js | Convex Developer Hub
These exports are not directly available in the convex package!
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
or, in your case, maybe there'd be some token you can pass up from your auth system that you could validate in your handler to make sure it's legit?
yeah, I think the easiest way here if/when I need that is some CONVEX_ADMIN_SECRET env variable that I can pass along
would be curious how your auth is set up if you're comfortable sharing!
sure! it's handwritten cookie-based Discord oauth. user hits /auth/discord/login, auth with discord, discord goes back to /auth/discord/callback which is where I upsert the user and set the cookie, then each route checks the cookie to see if the user has authorization. it's open source if you want to take a look: https://github.com/itsMapleLeaf/charge-worlds/tree/main/app/routes/auth https://github.com/itsMapleLeaf/charge-worlds/tree/main/app/auth it's an awkward managerie of technologies at the moment (liveblocks, prisma, pusher 😅) and I'm hoping I can replace all of that with just convex another related-ish question: the ConvexHttpClient doesn't appear to be typed like the rest of the library is. is that going to be updated?
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
I tried this and I feel like I'm doing it wrong 😅
No description
sujayakar
sujayakar3y ago
@ballingt was just working on this recently! I'm not on my dev computer now, but I think the right way to do it is to do const client = new ConvexHttpClient<ConvexAPI>(clientConfig) and then the subsequent method calls will be typed.
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
that was my first guess; the class doesn't accept a generic
No description
ballingt
ballingt3y ago
It will tomorrow! I added this on Friday, @void was asking for it too Pretty sure we can do an npm package release tomorrow, I need to fix one more thing first. As a preview, instead of importing ConvexAPI from ./convex/_generated/react it'll be called API and imported from ./convex/_generated/api so that you don't need React types installed.
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
nice! thanks for that ❤️
ballingt
ballingt3y ago
to agree with Sujay you above now that I'm reading this, when I need a quick admin interface and I don't want to build a whole admin system with special admin users etc. I write mutations that require a secret key so they can't be called by anyone else and sometimes editing fields in the dashboard is enough!
MapleLeaf 🍁
MapleLeaf 🍁OP3y ago
actually just hit another issue, but I'll start a new message since it's unrelated

Did you find this page helpful?