feat: secure convex admin flows with real metrics\n\nCo-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>

This commit is contained in:
esdrasrenan 2025-10-05 19:59:24 -03:00
parent 0ec5b49e8a
commit 29a647f6c6
43 changed files with 4992 additions and 363 deletions

View file

@ -15,7 +15,45 @@ export const ensureUser = mutation({
.query("users")
.withIndex("by_tenant_email", (q) => q.eq("tenantId", args.tenantId).eq("email", args.email))
.first();
if (existing) return existing;
const reconcile = async (record: typeof existing) => {
if (!record) return null;
const shouldPatch =
record.tenantId !== args.tenantId ||
(args.role && record.role !== args.role) ||
(args.avatarUrl && record.avatarUrl !== args.avatarUrl) ||
record.name !== args.name ||
(args.teams && JSON.stringify(args.teams) !== JSON.stringify(record.teams ?? []));
if (shouldPatch) {
await ctx.db.patch(record._id, {
tenantId: args.tenantId,
role: args.role ?? record.role,
avatarUrl: args.avatarUrl ?? record.avatarUrl,
name: args.name,
teams: args.teams ?? record.teams,
});
const updated = await ctx.db.get(record._id);
if (updated) {
return updated;
}
}
return record;
};
if (existing) {
const reconciled = await reconcile(existing);
if (reconciled) {
return reconciled;
}
} else {
const anyTenant = (await ctx.db.query("users").collect()).find((user) => user.email === args.email);
if (anyTenant) {
const reconciled = await reconcile(anyTenant);
if (reconciled) {
return reconciled;
}
}
}
const id = await ctx.db.insert("users", {
tenantId: args.tenantId,
email: args.email,