#[SOLVED] Create Appwrite function to add username when OAuth signup

1 messages · Page 1 of 1 (latest)

tall crest
#

I have a NextJS app with users that have unique usernames (stored in a 'user' collection). Thus, during registration, they choose their user name among the other inputs of the form. But when you register/login via OAuth, it is impossible to set this username. How to deals with ? The only way that ive found to solve the problem is when u login, there is a check if user.username exists. If not, a modal open to let the user add his username. But it's a bit "handmade" isn't it?

atomic rampart
tall crest
#

Well I think I just realized that apps that require unique usernames don't use OAuth precisely because of that

#

Mhh for example soundcloud, when u signup with Google, soundcloud choose a username considering ur name

#

I guess there is no function trigger event when someone logs with OAuth?

#

Twitter too do that like create a default username

atomic rampart
tall crest
tall crest
#

Well I try to create a function which for the moment only check if a document with the userId of the user just created exist :

const sdk = require("node-appwrite");

module.exports = async function (req, res) {
  const client = new sdk.Client();

  const account = new sdk.Account(client);
  const avatars = new sdk.Avatars(client);
  const database = new sdk.Databases(client);
  const functions = new sdk.Functions(client);
  const health = new sdk.Health(client);
  const locale = new sdk.Locale(client);
  const storage = new sdk.Storage(client);
  const teams = new sdk.Teams(client);
  const users = new sdk.Users(client);
  const query = new sdk.Query();

  if (
    !req.variables['APPWRITE_FUNCTION_ENDPOINT'] ||
    !req.variables['APPWRITE_FUNCTION_API_KEY']
  ) {
    console.warn("Environment variables are not set. Function cannot use Appwrite SDK.");
  } else {
    client
      .setEndpoint(req.variables['APPWRITE_FUNCTION_ENDPOINT'])
      .setProject(req.variables['APPWRITE_FUNCTION_PROJECT_ID'])
      .setKey(req.variables['APPWRITE_FUNCTION_API_KEY'])
      .setSelfSigned(true);
  }

  const user = JSON.parse(req.variables['APPWRITE_FUNCTION_DATA'])

  async function checkSignupType(id, databaseId, collectionId) {
    try {
      await database.getDocument(req.variables["APPWRITE_FUNCTION_DATABASE_ID"], req.variables["APPWRITE_FUNCTION_COLLECTION_ID"], id);
      return true
    } catch (error) {
      console.error("Error checking signup type:", error);
      return false;
    }
  }

  // const userDocuments = await database.getDocument(req.variables["APPWRITE_FUNCTION_DATABASE_ID"], req.variables["APPWRITE_FUNCTION_COLLECTION_ID"], user.$id);

  const userDocuments = await checkSignupType(user.$id);

  console.log("userDocuments", userDocuments)

};
#

But Ive got a function error : An internal curl error has occurred within the executor! Error Msg: Operation timed out
But if I replace this line:
const userDocuments = await checkSignupType(user.$id);
By :
const userDocuments = await database.getDocument(req.variables["APPWRITE_FUNCTION_DATABASE_ID"]
Ive this output :
Error: Document with the requested ID could not be found. But without the console.log

atomic rampart
tall crest
atomic rampart
tall crest
# atomic rampart No. The function needs to complete successfully for you to see the logs

That weird because Ive this :

async function checkSignupType(id) {
    try {
      await database.getDocument(req.variables["APPWRITE_FUNCTION_DATABASE_ID"], req.variables["APPWRITE_FUNCTION_COLLECTION_ID"], id);
      console.log('Email')
      res.json()
      return false
    } catch (error) {
      console.log('OAuth')
      res.json()
      return true;
    }
  }

  const isOAuth = await checkSignupType(user.$id);

  console.log("isOAuth", isOAuth)

And in the function logs I can see the console.log('OAuth') and the console.log('Email') but not the last one

#

Create Appwrite function to add username when OAuth signup

tall crest
#

wait when signup with OAuth the user.*.create isnt triggered ?

atomic rampart
tall crest
tall crest
#

Well I success to make username generator function for OAuth signups, based on username; there is the code appwriterocket :

const sdk = require("node-appwrite");

module.exports = async function (req, res) {
  const client = new sdk.Client();

  const database = new sdk.Databases(client);

  if (
    !req.variables['APPWRITE_FUNCTION_ENDPOINT'] ||
    !req.variables['APPWRITE_FUNCTION_API_KEY']
  ) {
    console.warn("Environment variables are not set. Function cannot use Appwrite SDK.");
  } else {
    client
      .setEndpoint(req.variables['APPWRITE_FUNCTION_ENDPOINT'])
      .setProject(req.variables['APPWRITE_FUNCTION_PROJECT_ID'])
      .setKey(req.variables['APPWRITE_FUNCTION_API_KEY'])
      .setSelfSigned(true);
  }
  const user = JSON.parse(req.variables['APPWRITE_FUNCTION_EVENT_DATA'])

  async function handleIsOAuth(id) {
    try {
      await database.getDocument(req.variables["APPWRITE_FUNCTION_DATABASE_ID"], req.variables["APPWRITE_FUNCTION_COLLECTION_ID"], id);
      console.log('User already has a username')
      res.json({ message: 'User already has a username' })
      return false
    } catch (error) {
      console.log('User has no username')
      return true
    }
  }

  async function generateUniqueUsername(name, id, attempt = 1) {
    if (attempt > 5) {
      console.log('Unable to generate a unique username.')
      return id
    }

    let username = name.toLowerCase().replace(/[^A-Za-z0-9_]/g, "");
    username = username.slice(0, 11)
    username += Math.floor(Math.random() * Math.pow(10, (15 - username.length)));

    const checkUsernameAvailability = await database.listDocuments(req.variables["APPWRITE_FUNCTION_DATABASE_ID"], req.variables["APPWRITE_FUNCTION_COLLECTION_ID"], [
      sdk.Query.equal('username', username)
    ]);

    if (checkUsernameAvailability.documents.length > 0) {
      console.log('Username is already in use, generating a new one.')
      return generateUniqueUsername(name, id, attempt + 1);
    }

    return username;
  }

  await handleIsOAuth(user.$id);

  const username = await generateUniqueUsername(user.name, user.$id)

  try {
    await database.createDocument(req.variables["APPWRITE_FUNCTION_DATABASE_ID"], req.variables["APPWRITE_FUNCTION_COLLECTION_ID"], user.$id, {
      "userId": user.$id,
      "username": username
    })
    res.json({ message: 'Username @' + username +' has been created successfully.'})
    return
  } catch (error) {
    res.json({ error: 'Error creating user', error: error })
    return
  }
};
#

But for now I can't use it until the user.*.create event is triggered when creating a user via OAuth

atomic rampart
tall crest
#

Well with the event user.*.sessions.*.create we dont have a the user Name

atomic rampart
tall crest