How to obtain the current user's profile image URL from Firebase - javascript

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);
});

Related

How to create user specific data when user logs in for the first time in realtime firebase database?

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 = '';
}
})

Why isn't firestore showing the logged in user's info?

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;
}
});
}
});

Firebase writing data with variable via REST

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.

Removing one item from array results in removing all items at first?

I'm creating a simple to-do list app with angular and cannot seem to figure out this strange bug. When the page loads initially, if I add tasks to my to-do list, then try to delete one the whole list disappears. However, if I don't refresh and add more task, they will delete individually afterwards. Can someone help me figure out what I'm missing?
Factory:
//Save user in local storage
AccountFactory.saveUser = function (user) {
var users = getUsers();
var index = this.getUser(user.email, 'index');
users[index] = user;
localStorage.setItem('Users', JSON.stringify(users));
return { status: 200, message: 'User saved', data: user };
};
AccountFactory.setCurrentUser = function (user) {
localStorage.setItem('currentUser', JSON.stringify(user));
return { status: 200, message: 'Current user set', data: user };
};
//Delete Task
AccountFactory.removeTask = function (user, task) {
var index = user.tasks.indexOf(task);
user.tasks.splice(index, 1);
return this.saveUser(user);
}
//Get all users function
function getUsers() {
var users = JSON.parse(localStorage.getItem('Users')) || [];
return users;
}
//Get user function
AccountFactory.getUser = function (email, type) {
var users = getUsers();
var account,
index;
for (var i = 0, user; user = users[i]; i++) {
if (user.email.toLowerCase() === email.toLowerCase()) {
account = user;
index = i;
break;
}
}
if (type === 'account') return account;
if (type === 'index') return index;
};
Controller:
function saveUser(user) {
var response = AccountFactory.saveUser(user);
if (response.status === 200) {
var newUser = new User(response.data);
AccountFactory.setCurrentUser(user);
$scope.user = user;
console.log(response.message);
}
}
$scope.removeTask = function (task) {
var response = AccountFactory.removeTask($scope.user, task);
saveUser(user);
}

How to Implement $child method in new AngularFire v0.8.0?

A user is logged in to the website and tries to create a post. Whenever a new post is created, this post gets associated with the user who created the post.
Referring to a thinkster.io Tutorial, which uses older API of AngularFire.
When using AngularFire API v0.8.0, this line of code which adds the post breaks:
user.$child('posts').$child(postId).$set(postId);
The Post Factory (post.js) with the method for creating post is:
app.factory('Post',
function ($firebase, FIREBASE_URL, User) {
var ref = new Firebase(FIREBASE_URL + 'posts');
var posts = $firebase(ref).$asArray();
var Post = {
all: posts,
//Starting of create function
create: function (post) {
if (User.signedIn()) {
var user = User.getCurrent(); //Gets the current logged in user
post.owner = user.username;
return posts.$add(post).then(function (ref) {
var postId = ref.name();
user.$child('posts').$child(postId).$set(postId);
//user.$getRecord('posts').$getRecord(postId).$set(postId);
return postId;
});
}
},
//End of create function
Changelog for AngularFire states that
$child() no longer exists. The data already exists in the parent object and creating additional synchronized children is not efficient and discouraged. Use data transformations, flatten your data, or drop down to the Firebase SDK and use its child() method.
I am confused as to how to change the code to work with the update in the API.
After Edit
This is the getCurrent method:
getCurrent: function(){ // retrieves current user
return $rootScope.currentUser;
},
Which belongs to user.js Factory:
'use strict';
app.factory('User', function ($firebase, FIREBASE_URL, Auth, $rootScope) {
var ref = new Firebase(FIREBASE_URL + 'users');
var users = $firebase(ref);
var usersdiv = $firebase(ref).$asArray();
var User = {
create: function (authUser, username) {
users[username] = {
md5_hash: authUser.md5_hash,
username: username
};
users.$update(username, {
md5_hash: authUser.md5_hash,
username: username
}).then(function (dataRef) {
dataRef.setPriority(authUser.uid);
setCurrentUser(username);
});
}, // end of create method
findByUsername: function(username){
if(username){
return usersdiv.$getRecord(username);
}
},
getCurrent: function(){ // retrieves current user
return $rootScope.currentUser;
},
signedIn: function(){ //checks if user is signed in
return $rootScope.currentUser !== undefined;
}
}; // end of User
// so that we can pull info about user when logged in
function setCurrentUser (username){
$rootScope.currentUser = User.findByUsername(username);
}
//for logins and refreshes
$rootScope.$on('$firebaseSimpleLogin:login', function(e, authUser){
var queryRef = ref.startAt(authUser.uid).endAt(authUser.uid);
var queryArray = $firebase(queryRef).$asArray();
queryArray.$loaded().then(function() {
setCurrentUser(queryArray.$keyAt(0));
});
});
//logout
$rootScope.$on('$firebaseSimpleLogin:logout', function(){
delete $rootScope.currentUser;
});
return User;
});
You don't need to create a synchronized object locally (what $child used to do) just to set a value in Firebase. You can do this at any time with the Firebase ref you've already created. I can't tell exactly what the data structure of user is since it wasn't included, but something like this:
new Firebase(FIREBASE_URL).child('...path/to/posts').child(postId).set(postId);
Most likely, this belongs on your user object, so that in the Post factory, you can just do something like user.addPost(postId).
I was facing the same problem. As Kato suggested, you will have to use the child function in the Firebase object. I chose to add the post to the user in the Post factory itself.
Adding Post to User
var usersref = new Firebase(FIREBASE_URL + 'users');
usersref.child(post.owner).child('posts').child(postId).set(postId);
The Entire post.js is as below:
'use strict';
app.factory('Post',
function($firebase, FIREBASE_URL, User){
var ref = new Firebase(FIREBASE_URL + 'posts');
var usersref = new Firebase(FIREBASE_URL + 'users');
var posts = $firebase(ref).$asArray();
var Post = {
all : posts,
create : function(post){
if(User.signedIn()){
var user = User.getCurrent();
post.owner = user.username;
return posts.$add(post).then(function(ref){
var postId = ref.name();
usersref.child(post.owner).child('posts').child(postId).set(postId);
return postId;
});
}
},
find: function(postId){
return $firebase(ref.child(postId)).$asObject();
},
delete: function(postId){
if(User.signedIn()){
var postToDel = Post.find(postId);
postToDel.$loaded().then(function(){
var p = posts[postToDel.$id];
posts.$remove(postId).then(function(){
$firebase(usersref.child(p.owner).child('posts')).$asArray().$remove(p.$id);
});
});
}
}
};
return Post;
});
Correct Answer is:
'use strict';
app.factory('Post',
function ($firebase, FIREBASE_URL, User) {
var postsref = new Firebase(FIREBASE_URL + 'posts');
var usersref = new Firebase(FIREBASE_URL + 'users');
var posts = $firebase(postsref).$asArray();
var Post = {
all: posts,
create: function (post) {
if (User.signedIn()) {
var user = User.getCurrent();
post.owner = user.username;
return posts.$add(post).then(function (ref) {
var postId = ref.name();
//a child in user forge should be made with its key as postID
usersref.child(post.owner).child('posts').child(postId).set(postId);
return postId;
});
}
},
find: function (postId) {
return $firebase(postsref.child(postId)).$asObject();
},
delete: function (postId) {
if (User.signedIn()) {
var postToDel = Post.find(postId);
postToDel.$loaded().then(function(){
var p = posts[postToDel.$id];
posts.$remove(postId).then(function(){
$firebase(usersref.child(p.owner).child('posts')).$remove(p.$id);
});
});
}
},
Thus, child can be used at Firebase SDK Level.
Example:
var ref = new Firebase(FIREBASE_URL);
var userArray = $firebase(ref.child('user')).$asArray();
var userObject = $firebase(ref.child('user')).$asObject();

Categories

Resources