Problems with creating new user in firebase

Viewed 50

There's something wrong with this function here, that I'cant find the reason for, I'm trying to add new users to my firebase database, and it doesn't work

exports.createUserWithEmailAndPassword = functions.https.onCall(
    async(data, context) => {
        const { adminEmail, adminPassword, adminNome, role, isActive } = data;

        if (context.auth.token.roles.includes("admin")) {
            const user = await admin.auth().createUser({
                email: adminEmail,
                password: adminPassword,
                displayName: adminNome
            });
            const customClaims = {
                roles: [role],
            };
            await admin.auth().setCustomUserClaims(user.uid, customClaims)
            await db.collection("admin-roles").doc(user.uid).set({
                    uid: user.uid,
                    adminEmail,
                    adminPassword,
                    adminNome,
                    role,
                    isActive: true,
                    registeredAt: Date.now()
                }, { merge: true })
                .then(() => {
                    console.log(
                        `User "${adminNome}" created. Custom claim added: "${customClaims.roles}"`
                    );
                    return {
                        uid,
                        adminEmail,
                        adminPassword,
                        adminNome,
                        role,
                        isActive,
                        registeredAt
                    };
                })
                .catch((error) => {
                    throw new functions.https.HttpsError(
                        "Erro interno",
                        "Erro ao criar usuário",
                        error
                    );
                });
        } else {
            throw new functions.https.HttpsError(
                "unauthenticated",
                "Only admins can create users."
            );
        }
    }
);

it should work with these functions

async signUp({ adminEmail, adminPassword, adminNome, role, isActive}: any): Promise<void> {
this.fns
  .httpsCallable('createUserWithEmailAndPassword')({ adminEmail, adminPassword, adminNome, role, isActive }).subscribe({
    next: response => {
      console.log('Usuário criado com sucesso!');
    },
    error: (err: FirebaseError) => {
      console.log(
        `${err.message}: Erro ao cadastrar usuário. Tente novamente.`
      );
    }
  });

}

signUp() {
    this.adminNovo.adminPassword = ''

    var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    for (var i = 0; i < 9; i++) {
      this.adminNovo.adminPassword += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    console.log(this.adminNovo)
    this.adminService.signUp(this.adminNovo).then(
      (res: any) => console.log(res)
    )

  }

But there's something wrong with my firebase function that is stopping the creation, in the console it calls exactly the first function

error in console

enter image description here

So I've looked in the logs in firebase

error code: Erro interno.
    at new HttpsError (/workspace/node_modules/firebase-functions/lib/common/providers/https.js:69:19)
    at /workspace/index.js:89:19
    at fixedLen (/workspace/node_modules/firebase-functions/lib/providers/https.js:66:41)
    at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:385:32
    at processTicksAndRejections (node:internal/process/task_queues:96:5)


{
insertId: "6329b7680004d257cbcc04fa"
labels: {
execution_id: "xss82uddvcsm"
instance_id: "00c61b117c54f94608670deae52421503ae18f031859611f1e55f4b3ec13c0990192a31900a81fb99db4d03e7cf36203f4726c29cb6acb0f1545"
}
logName: "projects/dev-processo-seletivo/logs/cloudfunctions.googleapis.com%2Fcloud-functions"
receiveTimestamp: "2022-09-20T12:51:52.643048282Z"
resource: {
labels: {3}
type: "cloud_function"
}
severity: "ERROR"
textPayload: "Invalid request, unable to process."
timestamp: "2022-09-20T12:51:52.315991Z"
trace: "projects/dev-processo-seletivo/traces/f3e3336110816f1a5e7dfc609827f649"
}
2 Answers

You don't share any error but there are two thing you should adapt:

  1. Avoid mixing then() with async/await.
  2. Declare registeredAt and user.uid as variables.

Also note that you don't pass any value for isActive when you call the CF from your front-end.


exports.createUserWithEmailAndPassword = functions.https.onCall(
    async (data, context) => {
        try {
            const { adminEmail, adminPassword, adminNome, role, isActive } = data;

            if (context.auth.token.roles.includes("admin")) {
                const user = await admin.auth().createUser({
                    email: adminEmail,
                    password: adminPassword,
                    displayName: adminNome
                });
                const customClaims = {
                    roles: [role],
                };

                const userId = user.uid;

                await admin.auth().setCustomUserClaims(userId, customClaims);

                const registeredAt = Date.now();  // You could use FieldValue.serverTimestamp()  // Add const FieldValue = require('firebase-admin').firestore.FieldValue; at the top of the index.js file

                await db.collection("admin-roles").doc(user.uid).set({
                    uid: userId,
                    adminEmail,
                    adminPassword,
                    adminNome,
                    role,
                    isActive: true,
                    registeredAt
                }, { merge: true });

                console.log(`User "${adminNome}" created. Custom claim added: "${customClaims.roles}"`);

                return {
                    uid: userId,
                    adminEmail,
                    adminPassword,
                    adminNome,
                    role,
                    isActive: true,
                    registeredAt
                };

            } else {
                throw new functions.https.HttpsError(
                    "unauthenticated",
                    "Only admins can create users."
                );
            }
        } catch (error) {
            throw new functions.https.HttpsError(
                "Erro interno",
                "Erro ao criar usuário",
                error
            );
        }

    });

Well we've managed to find the solution, and I think Renaud kind of pointed in that direction and I've must have missed.

Since the data was coming but wasn't passing through the try we made a verification first.

async function verifyUserAdmin(uid) {
    const result = await db.collection('admin-roles').doc(uid).get();
    const user = result.data();
    return user.role.includes("admin");
}

then we inserted into the the try so it would pass the verification

exports.createUserWithEmailAndPassword = functions.https.onCall(
    async (data, context) => {
        try {
            const { adminEmail, adminPassword, adminNome, role, isActive } = data;
            const idUsuario = context.auth.token.uid;
            if (verifyUserAdmin(idUsuario)) {
                const user = await admin.auth().createUser({
                    email: adminEmail,
                    password: adminPassword,
                    displayName: adminNome
                });
                const customClaims = {
                    admin: true
                };
                const userId = user.uid;
                await admin.auth().setCustomUserClaims(userId, customClaims);
                const registeredAt = Date.now();
                await db.collection("admin-roles").doc(user.uid).set({
                    uid: userId,
                    adminEmail,
                    adminPassword,
                    adminNome,
                    role,
                    isActive: true,
                    registeredAt
                }, { merge: true });
                console.log(`User "${adminNome}" created. Custom claim added: "${customClaims.roles}"`);
                return {
                    uid: userId,
                    adminEmail,
                    adminPassword,
                    adminNome,
                    role,
                    isActive: true,
                    registeredAt
                };
            } else {
                throw new functions.https.HttpsError(
                    "unauthenticated",
                    "Only admins can create users."
                );
            }
        } catch (error) {
            throw new functions.https.HttpsError(
                "Erro interno",
                "Erro ao criar usuário",
                error
            );
        }
    });

And now we can finally add users in our database through the app

Related