To create a profile for each user upon registration and ensure they have row-level access to update it, you can use Convex Auth's authentication callbacks and Convex's row-level security (RLS) helpers.
1. Create the Profile on Registration
You should use the createOrUpdateUser or afterUserCreatedOrUpdated callback in your convexAuth config. In this callback, you can insert a new profile document into your profile table, associating it with the user's ID. For example:
import { convexAuth } from "@convex-dev/auth/server";
import { Password } from "@convex-dev/auth/providers/Password";
export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
providers: [Password],
callbacks: {
async afterUserCreatedOrUpdated(ctx, { userId }) {
const existing = await ctx.db
.query("profile")
.withIndex("userId", (q) => q.eq("userId", userId))
.first();
if (!existing) {
await ctx.db.insert("profile", {
userId,
});
}
},
},
});
Use afterUserCreatedOrUpdated if you are not using createOrUpdateUser already. If you need more control, use createOrUpdateUser instead, as it allows you to perform additional writes at user creation time.
Writing additional data during authentication
2. Enforce Row-Level Security
To ensure only the user can update their own profile, use the convex-helpers package's row-level security wrappers. Define RLS rules for your profile table, for example: