how to stop duplication in firebase database - javascript

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.

Related

how to import file html using javascript

Javascript / Node.js importing html file
I'm making a node.js server which sends emails on demand. The variable "output" is what I want to send via email. When I use inline html it works fine, however I want to import a complete html file instead.
const { EmailClient } = require("#azure/communication-email");
const connectionString = "<ACS_CONNECTION_STRING>";
const sender = "<SENDER_EMAIL>";
const toRecipients = {
to: [
{ email: "<alice#contoso.com>", displayName: "Alice" },
],
};
const client = new EmailClient(connectionString);
const emailContent = {
subject: "Send email plain text - JS sample",
plainText: "",
// html: "<h3>Hi, this works</h3>", // WORKS
// html: "<object type="text/html" data="file.html"></object>", // // Doesn't work
html: "<link href="file.html" rel="import" />", // // Doesn't work
};
async function main() {
try {
const emailMessage = {
sender: sender,
content: emailContent,
importance: 'low',
recipients: toRecipients,
};
const sendResult = await client.send(emailMessage);
if (sendResult && sendResult.messageId) {
const messageId = sendResult.messageId;
if (messageId === null || messageId === undefined) {
console.log("Message Id not found.");
return;
}
console.log("Send email success, MessageId :", messageId);
let counter = 0;
const statusInterval = setInterval(async function () {
counter++;
try {
const sendStatusResult = await client.getSendStatus(messageId);
if (sendStatusResult) {
console.log(`Email status for {${messageId}} : [${sendStatusResult.status}]`);
if (sendStatusResult.status.toLowerCase() !== "queued" || counter > 12) {
clearInterval(statusInterval);
}
}
} catch (e) {
console.log("Error in checking send mail status: ",e);
}
}, 5000);
} else {
console.error("Something went wrong when trying to send this email: ", sendResult);
}
} catch (e) {
console.log("################### Exception occurred while sending email #####################", e);
}
}
main();
Help is much appreciated.
You can use fs.readFileSync to import your HTML file as a string.
const emailContent = {
...
html: fs.readFileSync('./file.html', 'utf8'),
...
}

How do I make it so it does not just like the newest post and it will like the post that they clicked the like button on?

How do I make it so it does not just like the newest post and it will like the post that they clicked the like button on?
code:
postSearch.addEventListener("input", (ev) => {
async function findPosts() {
const postsRef = collection(firestore, "posts")
const q = query(postsRef, orderBy("createdAt"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((post) => {
// doc.data() is never undefined for query doc snapshots
if (post.data().likes == undefined) {
post.data().likes = 0
}
function epicTest() {
let postData = {
description: post.data().description,
display_name: post.data().display_name,
createdAt: post.data().createdAt,
uid: post.data().uid,
title: post.data().title,
likes: post.data().likes + 1
}
console.log(post.id)
console.log(postData)
setDoc(doc(postsRef, post.id), postData)
console.log("this feature hasn't been added yet")
}
let items = querySnapshot.docs.map(post => {
if (post.data().title.includes(ev.target.value) || post.data().description.includes(ev.target.value)) {
return `<div id="postBox">
<h4 id="postName">${post.data().display_name}</h4>
<h1 id="postTitle">${post.data().title}</h1>
<h3 id="postDescription">${post.data().description}</h3>
<div id="likeContainer"><ion-icon name="thumbs-up-outline" id="likeBtn" onclick="epicTest()"></ion-icon><h3 id="likeCount">${post.data().likes}</h3></div>
</div>`
}
});
items.reverse()
postList.innerHTML = items.join('');
if (postList.innerText == "") {
postList.innerText = "no results found"
}
let likeBtn = document.querySelectorAll("#likeBtn")
likeBtn.forEach(item => {
item.addEventListener("click", (ev) => {
let postData = {
description: post.data().description,
display_name: post.data().display_name,
createdAt: post.data().createdAt,
uid: post.data().uid,
title: post.data().title,
likes: post.data().likes + 1
}
console.log(post.id)
console.log(postData)
setDoc(doc(postsRef, post.id), postData)
console.log("this feature hasn't been added yet")
})
})
});
}
findPosts()
})
The following example shows how you can use the function to run whenever a 'Like' button is clicked, check the below sample:
var postRef = new Firebase(firebaseURL + id);
postRef.child('like-count').once('value', function(snapshot) {
var currentLikes = snapshot.val() ? snapshot.val() : 0;
postRef.update({
'postID': id,
'like-count': currentLikes + 1
}, function(error) {
if (error) {
console.log('Data could not be saved:' + error);
} else {
console.log('Data saved successfully');
}
});
getLikeCount(id);
});
}
The basic idea behind this is to pass the post id as a parameter to the function that is called when clicking the like button.
Also check the following examples for similar implementations:
Like/Dislike function for Firebase
Creating like button using firestore and useeffect
Like-Dislike system using Firebase Database
How to implement like button concept
Like button functionality

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

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

Firebase push don't work inside value event

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.

Categories

Resources