Rank 3: Container
Mhh for example soundcloud, when u signup with Google, soundcloud choose a username considering ur name
Votes
0
Replies
24
Participants
Unknown
Messages
25
Rank 3: Container
Mhh for example soundcloud, when u signup with Google, soundcloud choose a username considering ur name
Rank 3: Container
I guess there is no function trigger event when someone logs with OAuth?
Rank 3: Container
Twitter too do that like create a default username
It depends on the app/system. Some apps have usernames, while others rely on email. Appwrite mostly uses emails, especially for oauth
Rank 3: Container
If I make a function triggered by user.*.create
Inside I check if a document in the user collection (where extra user data are) exist with the userId just created. If yes (signup with email), return. If not (signup with OAuth), create a default username based on the Name
Rank 3: Container
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)
};
Rank 3: Container
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
You must call res.json() or res.send() once before returning
Rank 3: Container
Ohh yes mb that work. In Appwrite Function when we made a return even if its true or false, the function stop ? Because the console.log never read so these returns in the checkSignupType function stop the Appwrite function
No. The function needs to complete successfully for you to see the logs
Rank 3: Container
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
Rank 3: Container
Create Appwrite function to add username when OAuth signup
Rank 3: Container
wait when signup with OAuth the user.*.create isnt triggered ?
Known issue: https://github.com/appwrite/appwrite/issues/2406
You should probably call res.json last. You should also be passing an object to it
Rank 3: Container
ohh okay sry
Rank 3: Container
Okay I didn't understand that the function stops when res.json is called. Its working !
Rank 3: Container
Well I success to make username generator function for OAuth signups, based on username; there is the code
:
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
}
};
Rank 3: Container
But for now I can't use it until the user.*.create event is triggered when creating a user via OAuth
You can trigger on create session and check if it's an oauth session and there's no document in your collection
Rank 3: Container
I was thinking of doing this but I don't realize if it will require a lot of server power to check each session. I want to do some less energy intensive things at the server level so ... But if you think it's not a problem I would do that!
Rank 3: Container
Well with the event user.*.sessions.*.create we dont have a the user Name
You can make an API call for the user
Rank 3: Container
Yeah I get all info with sdk.Users
Rank 3: Container
[SOLVED] Create Appwrite function to add username when OAuth signup