Background: Login works perfectly, the data is organized like [![this][1]][1]
[1]: https://i.stack.imgur.com/f9Cjq.png
Anytime I log into one of the 2 accounts I made and go to the settings page, it only shows one specific user's info. Lastly, under the .collection("userInfo"), I added .doc(user.uid) and it said that the forEach function was invalid.
Here's the code. Can anyone tell me what I'm doing wrong?
var auth = firebase.auth().currentUser;
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
db = firebase.firestore()
db
.collection("userInfo")
.get()
.then(function (querySnapshot) {
querySnapshot.forEach(function (doc) {
// console.log(user.uid, " => ", doc.data());
console.log(user.uid)
var email = doc.data().email;
var bio = doc.data().bio;
var downloadURL = doc.data().downloadURL;
document.getElementById("email").placeholder = email;
document.getElementById("bio").placeholder = bio;
myimg.src = downloadURL;
}
})
var auth = firebase.auth().currentUser;
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
db = firebase.firestore();
db.collection("userInfo").doc(user.uid).get()
.then(function (doc) {
if(doc.exists) {
var email = doc.data().email;
var bio = doc.data().bio;
var downloadURL = doc.data().downloadURL;
document.getElementById("email").placeholder = email;
document.getElementById("bio").placeholder = bio;
myimg.src = downloadURL;
}
});
}
});
Related
I have firebase function(javascript node.js) in flutter app. This function is creating the firebase collection of "timelineLocal" using the data based on "post" collection and "user" collection.
What I want is calling all the post from all the user and locate at the timelineLocal, but my function only calls the new post, not the old one. What am I missing? any help?
users -> userID -> data field user
timelineLocal-> userID -> "timelinePosts" -> data field
posts-> userID-> "userPosts" -> posted -> data field
Here are the code
const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp();
exports.onCreateDistance = functions.firestore.document("/users/{userId}")
.onCreate(async (snapshot, context) => {
console.log("Follower Created", snapshot.id);
const userId = context.params.userId;
// 1) Create users posts ref
const userPostsRef = admin
.firestore()
.collection("posts")
.doc(userId)
.collection("userPosts");
// 2) Create user's timeline ref
const timelinePostsLocalRef = admin
.firestore()
.collection("timelineLocal")
.doc(userId)
.collection("timelinePosts");
// 3) Get users posts
const querySnapshotLocal = await userPostsRef.get();
// 4) Add each user post to user's timeline
querySnapshotLocal.forEach(doc => {
if (doc.exists) {
const postId = doc.id;
const postData = doc.data();
timelinePostsLocalRef.doc(postId).set(postData);
}
});
});
exports.onDeleteDistance = functions.firestore.document("/users/{userId}")
.onDelete(async (snapshot, context) => {
console.log("Follower Deleted", snapshot.id);
const userId = context.params.userId;
const timelinePostsLocalRef = admin
.firestore()
.collection("timelineLocal")
.doc(userId)
.collection("timelinePosts");
const querySnapshotLocal = await timelinePostsLocalRef.get();
querySnapshotLocal.forEach(doc => {
if (doc.exists) {
doc.ref.delete();
}
});
});
exports.onCreatePostLocal = functions.firestore.document('/posts/{userId}/userPosts/{postId}')
.onCreate(async (snapshot, context) => {
const postCreated = snapshot.data();
const userId = context.params.userId;
const postId = context.params.postId;
//1) get all the user who made the post
const usersRef = admin.firestore().collection('users');
const querySnapshotLocal = await usersRef.get();
//2) Add new post to each user's timeline
querySnapshotLocal.forEach(doc => {
const userId = doc.id;
admin.firestore().collection('timelineLocal').doc(userId).collection('timelinePosts').doc(postId).set(postCreated);
});
});
exports.onUpdatePostLocal = functions.firestore.document('/posts/{userId}/userPosts/{postId}').onUpdate(
async (change, context) => {
const postUpdated = change.after.data();
const userId = context.params.userId;
const postId = context.params.postId;
//1) get all the user who made the post
const usersRef = admin.firestore().collection('users');
const querySnapshotLocal = await usersRef.get();
//2) update new post to each user's timeline
querySnapshotLocal.forEach(doc => {
const userId = doc.id;
admin.firestore().collection('timeline').doc(userId).collection('timelinePosts').doc(postId).get().then(doc => {
if (doc.exists) {
doc.ref.update(postUpdated);
}
});
});
});
exports.onDeletePostLocal = functions.firestore.document('/posts/{userId}/userPosts/{postId}').onDelete(
async (change, context) => {
const userId = context.params.userId;
const postId = context.params.postId;
const usersRef = admin.firestore().collection('users');
const querySnapshotLocal = await usersRef.get();
//2) delete new post to each user's timeline
querySnapshotLocal.forEach(doc => {
const userId = doc.id;
admin.firestore().collection('timeline').doc(userId).collection('timelinePosts').doc(postId).get().then(doc => {
if (doc.exists) {
doc.ref.delete();
}
});
});
});
I want the code to behave such that it creates specific data when user is signed in but doesn't create it if already present in the firebase real-time database.
I have used the following code through which i check if the child is already present or not and if not then creates the child in firebase database, but somehow the code isn't behaving as it should.
Whenev the user logins again the complete data part is rewritten.
Snippet I need help in
if (!(checkdata(user.uid))) {
writeUserData(user.uid,user.displayName,user.email,user.photoURL)
}
var database = firebase.database();
function checkdata(userid){
var ref = firebase.database().ref("users");
ref.once("value")
.then(function(snapshot) {
var datapresent = snapshot.hasChild(userid); // true
return datapresent
});
}
function writeUserData(userId, name, email, imageUrl) {
firebase.database().ref('users/' + userId).set({
username: name,
email: email,
profile_picture : imageUrl,
cropdata : []
});
}
Complete JS file
const signInBtn = document.getElementById('signinbtn');
const signOutBtn = document.getElementById('signoutbtn');
const userDetails = document.getElementById('username');
const auth = firebase.auth();
const provider = new firebase.auth.GoogleAuthProvider();
signInBtn.onclick = () => auth.signInWithPopup(provider);
signOutBtn.onclick = () => auth.signOut();
function toggle(className, displayState){
var elements = document.getElementsByClassName(className)
for (var i = 0; i < elements.length; i++){
elements[i].style.display = displayState;
}
}
auth.onAuthStateChanged(function(user) {
if (user) {
// signed in
toggle('userishere', 'block');
toggle('usernothere', 'none');
//userDetails.innerHTML = `<h3>Hello ${user.displayName}!</h3> <p>User ID: ${user.uid}</p>`;
userDetails.innerHTML = `Hello ${user.displayName}!`
console.log(user)
if (!(checkdata(user.uid))) {
writeUserData(user.uid,user.displayName,user.email,user.photoURL)
}
} else {
// not signed in
toggle('userishere', 'none');
toggle('usernothere', 'block');
userDetails.innerHTML = '';
}
});
var database = firebase.database();
function checkdata(userid){
var ref = firebase.database().ref("users");
ref.once("value")
.then(function(snapshot) {
var datapresent = snapshot.hasChild(userid); // true
return datapresent
});
}
function writeUserData(userId, name, email, imageUrl) {
firebase.database().ref('users/' + userId).set({
username: name,
email: email,
profile_picture : imageUrl,
cropdata : []
});
}
I just found the solution, the asynchronous code wasn't waiting for my firebase response and just checeked if datapresent was true or not, so with a async definition before function and await before ref.once(value) does the trick and my problem is solve. Working code below :
const signInBtn = document.getElementById('signinbtn');
const signOutBtn = document.getElementById('signoutbtn');
const userDetails = document.getElementById('username');
var database = firebase.database();
const auth = firebase.auth();
const provider = new firebase.auth.GoogleAuthProvider();
signInBtn.onclick = () => auth.signInWithPopup(provider);
signOutBtn.onclick = () => auth.signOut();
async function checkdata(user){
let ref = firebase.database().ref("users");
let snapshot = await ref.once('value');
if (!snapshot.hasChild(user.uid)){
console.log(user)
writeUserData(user.uid,user.displayName,user.email,user.photoURL)
console.log("write done")
}
else{
console.log("did not write")
}
}
function writeUserData(userId, name, email, imageUrl) {
firebase.database().ref('users/' + userId).set({
username: name,
email: email,
profile_picture: imageUrl,
cropdata: []
});
}
function toggle(className, displayState) {
var elements = document.getElementsByClassName(className)
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = displayState;
}
}
auth.onAuthStateChanged(function (user) {
if (user) {
// signed in
toggle('userishere', 'block');
toggle('usernothere', 'none');
//userDetails.innerHTML = `<h3>Hello ${user.displayName}!</h3> <p>User ID: ${user.uid}</p>`;
userDetails.innerHTML = `Hello ${user.displayName}!`
console.log(user)
checkdata(user)
}
else {
toggle('userishere', 'none');
toggle('usernothere', 'block');
userDetails.innerHTML = '';
}
})
in my app I am getting the uid of the current user by:
also I get the username from :
console.log gives me the right name.
But when I try to write to my db via:
https://movieapp-8a157.firebaseio.com/users/${username}/${authUser}/posts.json?auth=${token}
It doesnt work. If I remove the ${username} it will write in the correct path. Any ideas? I edited my post for more clearness.
export const postJob = data => {
return async (dispatch, getState) => {
const randomColors = ["#f3a683"];
const colorNumber = Math.floor(Math.random() * 20) + 1;
const bgColor = randomColors[colorNumber];
const val = getState();
const userId = val.auth.userId;
const rules = {
description: "required|min:2"
};
const messages = {
required: field => `${field} is required`,
"description.min": "job description is too short"
};
try {
await validateAll(data, rules, messages);
const token = await firebase
.auth()
.currentUser.getIdToken(true)
.then(function(idToken) {
return idToken;
});
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
// ...
} else {
// User is signed out.
// ...
}
});
var user = firebase.auth().currentUser;
const authUser = user.uid;
const username = await firebase
.database()
.ref("users/" + authUser + "/name")
.once("value", function(snapshot) {
console.log("################", snapshot.val());
});
//console.log("#####################", authUser);
const response = await fetch(
`https://movieapp-8a157.firebaseio.com/users/${username}/${authUser}/posts.json?auth=${token}`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
titel: data.titel,
fname: data.fname,
description: data.description,
cover: data.cover,
friend: data.friend,
ownerId: userId,
bgColor: bgColor
})
}
);
const resData = await response.json();
Your code that's getting the UID isn't working the way you exepct. The auth state listener is asynchronous and is triggering after the line of code that accessesfirebase.auth().currentUser. That line of code is actually giving you the current user before the sign-in completes. That means it's going to be undefined.
You're then using that undefined value to build a reference to a location in the database. This is causing the actual reference to be something other than what you expect. You should add debug logging to see this yourself.
You should be using the callback to determine when exactly the user is signed in, and only read and write that user's location. This means that you should probably move the lines of code that write the database into the callback, when you know that user is correct, and use user.uid to build the database reference for reading and writing.
The following function works well when tested with shell, and data are created in firestore.
When pushed in prod, it returns Function execution took 60002 ms, finished with status: 'timeout'
Any input?
exports.synchronizeAzavista = functions.auth.user().onCreate(event => {
console.log('New User Created');
const user = event.data;
const email = user.email;
const uid = user.uid;
return admin.database().ref(`/delegates`)
.orderByChild(`email`)
.equalTo(email)
.once("child_added").then(snap => {
const fbUserRef = snap.key;
return admin.firestore().collection(`/users`).doc(`${fbUserRef}`).set({
email: email,
uid: uid
}).then(() => console.log("User Created"));
});
});
Edit
I've update my code with the following, but I still getting Function returned undefined, expected Promise or value but I can't identify where my function return undefined. Why my getUser() function does not return anything?
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.synchronizeAzavista = functions.auth.user().onCreate(event => {
console.log('New User Created');//This log
const user = event.data;
const email = user.email;
const uid = user.uid;
console.log('Const are set');//This log
getUser(email).then(snap => {
console.log("User Key is " + snap.key);//No log
const fbUserRef = snap.key;
return admin.firestore().collection(`/users`).doc(`${fbUserRef}`).set({
email: email,
uid: uid
});
}).then(() => console.log("User Data transferred in Firestore"));
});
function getUser(email) {
console.log("Start GetUser for " + email);//This log
const snapKey = admin.database().ref(`/delegates`).orderByChild(`email`).equalTo(email).once("child_added").then(snap => {
console.log(snap.key);//No Log here
return snap;
});
return snapKey;
}
You're not returning a promise from your write to Firestore.
exports.synchronizeAzavista = functions.auth.user().onCreate(event => {
const user = event.data;
const email = user.email;
const uid = user.uid;
return admin.database().ref(`/delegates`)
.orderByChild(`email`)
.equalTo(email)
.once("child_added").then(snap => {
const fbUserRef = snap.key;
return admin.firestore().collection(`/users`).doc(`${fbUserRef}`).set({
email: email,
uid: uid
});
});
});
I've built a website where users can log in through Facebook, Google, or Twitter, and then their email, name, and profile picture URL will be saved to a Firebase database. Now, I'm trying to obtain the currently logged in user's profile picture URL from the Firebase database, but I have no idea where to start. I've read Firebase's accessing data documentation, but didn't understand it enough to make it work.
This is the function that checks if the user is logged in and then checks if they're an admin. I need to grab the currently logged in user's profile image on the line labeled "RIGHT HERE".
$(document).ready(function() {
var ref = new Firebase("https://mpacares.firebaseio.com/");
ref.onAuth(function (auth) {
if (auth) {
var userRef = ref.child('users').child(auth.uid);
userRef.on('value', function (snap) {
var user = snap.val();
if (user) {
// RIGHT HERE: set the user image src to user.picture
} else {
// TODO: hide the user image
}
}, function (error) {
console.log(error);
});
var adminRef = ref.child('admins').child(auth.uid);
adminRef.on('value', function (snap) {
var user = snap.val();
if (user) {
console.log("You're an admin!");
// enable admin button
} else {
console.log("Sorry, no access for you.");
// disable admin button
}
}, function (error) {
console.log(error);
});
} else {
// logged out
}
});
});
Additionally, you can view my current Firebase app on https://mpacares.firebaseapp.com/.
Here's what worked for me in the end:
$(document).ready(function() {
var ref = new Firebase("https://mpacares.firebaseio.com/");
ref.onAuth(function (auth) {
if (auth) {
var userRef = ref.child('users').child(auth.uid);
userRef.on('value', function (snap) {
var user = snap.val();
if (user) {
$(document).ready(function() {
var ref = new Firebase("https://mpacares.firebaseio.com/");
var user = ref.getAuth();
console.log(user);
var userRef = ref.child('users').child(user.uid);
userRef.once("value", function(snap) {
var user = snap.val();
console.log(user);
console.log(user.name);
console.log(user.picture);
console.log(user.email);
var userName = user.name;
var userPicURL = user.picture;
var userEmail = user.email;
document.getElementById("account-txt").innerHTML = user.name;
$(".account-img").attr("src", userPicURL);
});
});
} else {
$(".account-txt").hide();
$(".account-img").hide();
}
}, function (error) {
console.log(error);
});