#Sign up users from backend

7 messages · Page 1 of 1 (latest)

slim granite
#

I want to create new user accounts from the backend using convex-auth, but I am getting this error:

This expression is not callable.

here is the source code:

`export const createUser = internalAction({
args: {
email: v.string(),
password: v.string(),

 },
handler: async (ctx, args) => {
    
    const createUser = await signIn("password", { email:args.email, password:args.password, flow: "signUp" })
}

})
`

Should I just hash the password string using SCRIPT from LUCIA, then create a user in the users and authAccounts tables?

ref github code:

crypto: { async hashSecret(password: string) { return await new Scrypt().hash(password); }, async verifySecret(password: string, hash: string) { return await new Scrypt().verify(hash, password); }, }, extraProviders: [config.reset, config.verify], ...config, }); }

limber spoke
#

Convex Auth doesn't support programatically creating users directly, I'd recommend Clerk if you want to do that in a fully supported way. Otherwise you could fork Convex Auth and make any changes you need to.

slim granite
#

Gotcha thanks

zinc current
#

Hi, guys! @slim granite have you found a solution to that? Thnx!

zinc current
#

I'm using convex-auth password provider and this is working for me:

convex/users.ts

import { createAccount, getAuthUserId } from "@convex-dev/auth/server";
import { ConvexError, v } from "convex/values";
import { mutation, QueryCtx } from "./_generated/server";
import { Id } from "./_generated/dataModel";

/**
 * Retrieves the internal user role for a given user ID.
 */
async function getInternalUserRole(ctx: QueryCtx, userId: Id<"users">) {
  const user = await ctx.db.get(userId);
  const userRole = await ctx.db
    .query("userRoles")
    .filter((q) => q.eq(q.field("_id"), user?.userRoleId))
    .unique();

  return { role: userRole?.role ?? "user" };
}

/**
 * Admin creates a new user account with specified email, password, and role.
 * @param args - The arguments for creating a user, including:
 *   - email: The email of the new user.
 *   - password: The password for the new user.
 *   - userRoleId: Optional ID for the user's role.
 * @returns The newly created user account.
 */
export const adminCreateUser = mutation({
  args: {
    email: v.string(),
    password: v.string(),
    userRoleId: v.optional(v.id("userRoles")),
  },
  handler: async (
    ctx: any,
    args: { password: string; email: string; userRoleId?: string }
  ) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new ConvexError("Not authenticated");

    const userRole = await getInternalUserRole(ctx, userId);
    if (userRole?.role !== "admin") {
      throw new ConvexError("Not authorized");
    }

    const providerId = "password";
    const secret = args.password;
    const account = {
      id: args.email,
      secret: secret,
    };
    const profile = {
      email: args.email,
      userRoleId: args.userRoleId ?? null,
    };
    const newUser = await createAccount(ctx, {
      provider: providerId,
      account: account,
      profile: profile,
      shouldLinkViaEmail: false,
      shouldLinkViaPhone: false,
    });
    return newUser;
  },
});
frigid tusk
#

Thanks for sharing @zinc current