Firebase push don't work inside value event - javascript

I have code like this:
var firebase = new Firebase('https://<MY_APP>.firebaseio.com');
var users = firebase.child('users');
var usersDefer = $.Deferred();
var userName;
if (window.localStorage) {
userName = localStorage.getItem('username');
if (!userName) {
function newUser(users) {
if (userName) return;
var newUserName = prompt('Enter Username:');
if (users.indexOf(newUserName) !== -1) {
alert('Username already taken');
newUser(users);
} else {
localStorage.setItem('username', newUserName);
userName = newUserName;
console.log('push');
// this push don't work
users.push({
name: newUserName
});
console.log('after');
}
}
usersDefer.then(newUser);
}
}
users.once('value', function(snapshot) {
var value = snapshot.val()
if (value) {
var users = Object.values(value).map(function(object) {
return object.name;
});
usersDefer.resolve(users);
} else {
usersDefer.resolve([]);
}
});
and
users.push({
name: newUserName
});
don't work unless I use developer console, anybody have a clue why?
UPDATE:
Same happen if I use this code without jQuery Deferred
users.once('value', function(snapshot) {
function newUser(users) {
if (userName) return;
var newUserName = prompt('Enter your username');
if (users.indexOf(newUserName) !== -1) {
alert('Username already taken');
newUser(users);
} else {
userName = newUserName;
if (window.localStorage) {
localStorage.setItem('username', newUserName);
}
console.log('push');
users.push({
name: userName
});
console.log('after');
}
}
var value = snapshot.val()
var users;
if (value) {
users = Object.values(value).map(function(object) {
return object.name;
});
} else {
users = [];
}
if (window.localStorage) {
userName = localStorage.getItem('username');
if (!userName) {
newUser(users);
}
} else {
newUser(users);
}
});

The problem was that I was using same variable users for firebase reference and list of users.

Related

Code not being executed - Mongoose - Cannot set headers after they are sent to the client

I'm trying to see if the userlookUp in the User.prototype.userExists function is true based on the UserChema.findOne() but for some unknown reason, the block is not being executed if its true. In this case, return this.errors.push('User already exists'), is not being executed.
I have some other error checks in another function, and they work great as they are supposed to (being shown in the browser console) except this one.
Looking for some help.
I appreciate it.
userController.js
const User = require('../models/User');
exports.login = function () {};
exports.logout = function () {};
exports.register = function (req, res) {
let user = new User(req.body);
user.register();
if (user.errors.length) {
res.send(user.errors);
} else {
res.send(user);
res.send('Congrats, there are no errors.');
}
};
exports.home = function (req, res) {
res.send('API up and running!');
};
User.js
const validator = require('validator');
const UserSchema = require('./UserSchema');
const gravatar = require('gravatar');
const bcrypt = require('bcryptjs');
let User = function (data) {
this.data = data;
this.errors = [];
};
User.prototype.cleanUp = function () {
if (typeof this.data.username != 'string') {
this.data.username = '';
}
if (typeof this.data.email != 'string') {
this.data.email = '';
}
if (typeof this.data.password != 'string') {
this.data.password = '';
}
// get rid of any bogus properties
this.data = {
username: this.data.username.trim().toLowerCase(),
email: this.data.email.trim().toLowerCase(),
password: this.data.password,
};
};
User.prototype.validate = function () {
if (this.data.username == '') {
this.errors.push('You must provide a username.');
}
if (
this.data.username != '' &&
!validator.isAlphanumeric(this.data.username)
) {
this.errors.push('Username can only contain letters and numbers.');
}
if (!validator.isEmail(this.data.email)) {
this.errors.push('You must provide a valid email.');
}
if (this.data.password == '') {
this.errors.push('You must provide a password longer than 6 characters.');
}
if (this.data.password.length > 0 && this.data.password.length < 6) {
this.errors.push('The password must be longer than 6 characters.');
}
if (this.data.password.length > 50) {
this.errors.push('The password cannot exceed 50 characters.');
}
if (this.data.username.length < 3 && this.data.username.length > 15) {
this.errors.push('The username must be at least 3 characters.');
}
};
User.prototype.userExists = async function () {
try {
let userLookUp = await UserSchema.findOne({
email: this.data.email,
});
if (userLookUp) {
return this.errors.push('User already exists');
} else {
const avatar = gravatar.url(this.data.email, {
s: '200',
r: 'pg',
d: 'mm',
});
userLookUp = new UserSchema({
username: this.data.username,
email: this.data.email,
password: this.data.password,
avatar: avatar,
});
const salt = await bcrypt.genSalt(10);
userLookUp.password = await bcrypt.hash(this.data.password, salt);
await userLookUp.save();
}
} catch (e) {
console.log('there is a server problem');
}
};
User.prototype.register = function () {
// Step #1: Validate user data
this.cleanUp();
this.validate();
this.userExists();
// Step #2: See if user exists
// Step #3: Get users gravatar
// Step #4: Encrypt the password
// Step #5: Return jsonwebtoken
// Step #6: Only if there are no validation errors
// then save the user data into a database
};
module.exports = User;
In the User.register function you run some functions that are promises (async functions) which are not fulfilled before the User.register function returns.
You can do something like this:
User.prototype.register = async function () {
this.cleanUp();
this.validate();
await this.userExists();
};
...
exports.register = async function (req, res) {
let user = new User(req.body);
await user.register();
if (user.errors.length) {
res.send(user.errors);
} else {
res.send(user);
res.send('Congrats, there are no errors.');
}
};

I want transfer data js to node.js

I don't know how to transfer data from JavaScript to Node.js.
I need to POST the allUsers array and the user.username property.
var allUsers = []
var user = {
username: '',
password: ''
}
var background = document.getElementById("bg")
function verify() {
background.style.display = "inline"
var usrname = document.getElementById("username").value
var pswrd = document.getElementById("password").value
user.username = usrname
user.password = pswrd
axios.get("dbid").then((response) => {
var data = response.data
for (let key in data) {
var body = data[key]
allUsers.push(body.user.username)
}
return verified();
})
}
function verified() {
var inc = allUsers.includes(user.username)
if (user.password.length < 8) {
alert('Şifreniz en az 8 karakter olmalıdır!');
return background.style.display = "none";
} else if (inc) {
alert("Böyle bir mail adresi önceden kaydolmuş! Lütfen başka bir mail adresi deneyim.");
return background.style.display = "none";
} else {
alert("Başarılı, G-mail adresinize bir doğrulama kodu gönderildi...");
axios.post("dbid", {
user: user
})
return background.style.display = "none";
}
}
If you need to post an array of data (in this case allUsers) and a string (username) you need to use the JSON.stringify method to convert the array to a JSON string.
Here is an async function that will post the data you need to send to the server:
const postData = async () => {
try {
await axios.post(<url-to-post>, {
users: JSON.stringify(allUsers),
username: user.username
})
} catch (err) {
// Error posting data
console.log(err)
}
}

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

how to stop duplication in firebase database

I want to authentication in my chat app so when user signedin one time so the data will insert on firbase database but when user just refresh his chrome so one another same data will added again so i want to stop duplication if user already inserted so i tried this code mentioned below but this is not working.
function onStateChanged(user) {
if (user) {
//alert(firebase.auth().currentUser.email + '\n' + firebase.auth().currentUser.displayName);
var userProfile = { email: '', name: '', photoURL: '' };
userProfile.email = firebase.auth().currentUser.email;
userProfile.name = firebase.auth().currentUser.displayName;
userProfile.photoURL = firebase.auth().currentUser.photoURL;
var db = firebase.database().ref('users');
var flag = false;
db.on('value', function (users) {
users.forEach(function (data) {
var user = data.val();
if (user.email === userProfile.email) {
flag = true;
}
});
if (flag === false) {
firebase.database().ref('users').push(userProfile, callback);
}
else {
document.getElementById('imgProfile').src = firebase.auth().currentUser.photoURL;
console.log('elsepart')
document.getElementById('imgProfile').title = firebase.auth().currentUser.displayName;
document.getElementById('lnkSignIn').style = 'display:none';
document.getElementById('lnkSignOut').style = '';
}
});
}
else{
document.getElementById('imgProfile').src = image/profile-image.png;
document.getElementById('imgProfile').title = '';
document.getElementById('linkSignIn').style = '';
document.getElementById('linkSignOut').style = 'display: none';
}
}
let callback = (error)=>{
if(error){
alert(error)
}
else{
document.getElementById('imgProfile').src = firebase.auth().currentUser.photoURL;
document.getElementById('imgProfile').title = firebase.auth().currentUser.displayName;
document.getElementById('linkSignIn').style = 'display: none';
document.getElementById('linkSignOut').style = '';
}
}
///////////
onFirebaseStateChanged();
you can try firebase read and write functions to do this, for reference: link
I have done something kind of similar. Here, I have checked my db for same entries, if that doesn't exist, only then it'll allow you to register.
firebase.database().ref('/login/' + username).once('value').then(function (snapshot) {
if (snapshot.val() === null || snapshot.val() === undefined) {
firebase.database().ref('login/' + username).set({
name: name,
email: username,
password: password
});
_this.setState({
showAlert: true,
alertMessage: "User has been successfully register. Please login",
alertType: 'success'
})
} else {
console.log("in true")
_this.setState({
showAlert: true,
alertMessage: "User already exist",
alertType: 'warning'
})
}
Also, for remaining in the same logged in state even after refresh, creating session storage seems like an easy solution to me.

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

Categories

Resources