Retrieve document in Firestore and validate against user's entry - javascript

I am able to successfully retrieve a document in Firebase Firestore in JavaScript. But would like to validate that document against a user's entry in order to auth that individual into the page.
Using console log I see that I have retrieved the record but it is not matching it against the text inputted by the end user.
How is this accomplished?
I am using Vuejs. And want to password protect one page.
In jsfiddle: https://jsfiddle.net/oL4bondy/4/
HTML
<div v-if="!isLoggedIn">
<h2>Please log in first.</h2>
<div class="form-group">
<form #submit.prevent="validatePin">
<div class="form-group">
<input v-model="password" type="text" class="form-control" placeholder="Enter password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary text-center">Submit</button>
</div>
</form>
</div>
</div>
JS
export default {
name: "add-post",
data() {
return {
password: "",
isLoggedIn: ""
};
},
methods: {
validatePin() {
const docRef = db.collection("passwords").doc("user");
docRef
.get()
.then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
console.log("No such document!");
}
})
.catch(function(error) {
console.log("Error getting document:", error);
});
let password = this.doc.data;
if (this.userInput === password) {
this.isLoggedIn = true;
}
}
}
};

Use Firebase.auth() for this. In particular, the .onAuthStateChanged method/listener will fire after page load. That's where you want to process user/UI access.

There are a few problems, but mostly it's related to the fact that the document is loaded from Firestore asynchronously. The solution is to move all the code that needs the document into the then() that is called once the document is loaded. So:
validatePin() {
const docRef = db.collection("passwords").doc("user");
docRef
.get()
.then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
let password = this.doc.data;
if (this.userInput === password) {
this.isLoggedIn = true;
// TODO: do whatever needs to happen once the user is logged in
}
} else {
console.log("No such document!");
}
})
.catch(function(error) {
console.log("Error getting document:", error);
});
}

Related

Check if user isLoggedIn MongoDB Realm Web SDK

I wish to check if a user is already logged in through email/password auth via mongodb realm web-sdk. Knowing if the user is logged in will allow me to hide the loggin page from site and instead show a log out button.
So far I've successfully created a user and logged in. Using the code/methods below.
async function registerEmailPassword(email, password) {
try {
const user = await app.emailPasswordAuth.registerUser({ email, password });
return user;
} catch (error) {
console.error("Failed to register", error)
}
}
async function loginEmailPassword(email, password) {
// Create an email/password credential
const credentials = Realm.Credentials.emailPassword(email, password);
try {
// Authenticate the user
const user = await app.logIn(credentials);
// `App.currentUser` updates to match the logged in user
console.assert(user.id === app.currentUser.id);
return user;
} catch (error) {
console.error("Failed to log in", error);
}
}
While going through the mongodb class documentation, I wrote the following function which appears to work.
The code is checking for if their is any user in currentUser, if their is no currentUser, their no account logged in. In the event their is a currentUser, the code then checks using currentUser.isLoggedIn if that user is logged and at the end returns a boolean value.
async function isUserLoggedIn() {
try {
const userStatus = await app.currentUser;
if (userStatus == null) {
return false
} else {
const userStatus = await app.currentUser.isLoggedIn;
return userStatus
}
} catch (error) {
console.log("Failed to fetch user", error);
}
}
// Check if user is logged in
isUserLoggedIn().then((value) => {
console.log(value);
}).catch((error) => {
console.log(error);
});

Retrieve wallet address after connecting Metamask with Web3.js

I got this code off github which allows you to connect to MetaMask using web3.js and also to make payment. I then modified it to
Display a Connect Button when user is not logged in by checking if the content of an element is empty and if it is not empty, the connect button is hidden.
Retrieve the connected wallet address which is in the element that hides the button.
The problem i am facing currently is that
The connected wallet address does not display nor is the connect button hidden until i reload the page manually.
I have tried calling location.reload(); after await ethereum.enable(); which works but in turns hide the #status dialogs from displaying when a user declines making payment as a result of the page reloading instead of displaying the dialogs.
Below is my code
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://unpkg.com/#metamask/legacy-web3#latest/dist/metamask.web3.min.js"></script>
</head>
<body>
<div>
<div id="selected-account"></div>
<button class="pay-button">Pay</button>
<div id="status"></div>
<div id="accTabs"></div>
</div>
<script type="text/javascript">
async function initWeb3() {
if (window.ethereum) {
window.web3 = new Web3(ethereum);
try {
await ethereum.enable();
window.location.reload();
} catch (err) {
$("#status").html("User denied account access", err);
}
} else if (window.web3) {
return (window.web3 = new Web3(web3.currentProvider));
} else {
return $("#status").html("No Metamask (or other Web3 Provider) installed");
}
}
selectedAccount = ethereum.selectedAddress;
document.querySelector("#selected-account").textContent = selectedAccount;
$(".pay-button").click(async () => {
await initWeb3();
// paymentAddress is where funds will be send to
const paymentAddress = "0x192c96bfee59158441f26101b2db1af3b07feb40";
const amountEth = "1";
web3.eth.sendTransaction(
{
to: paymentAddress,
value: web3.toWei(amountEth, 'ether')
},
(err, transactionId) => {
if (err) {
console.log("Payment failed", err);
$("#status").html("Payment failed");
} else {
console.log("Payment successful", transactionId);
$("#status").html("Payment successful");
}
}
);
});
</script>
<script>
if ($('#selected-account').text() == '') {
document.getElementById("accTabs").innerHTML = '<button onclick="initWeb3()">Connect Ethereum</button>';
} else {
}
</script>
</body>
</html>
Let me quickly state that there may be some not well written codes here as a result of my not being very good with Javascript. Still learning.
Thanks for your assistance.
The easiest way to answer would be for you to watch this:
YouTube video explaining exactly that

Firebase onAuthStateChanged() triggering before retrieving name from signup form?

I'm creating a dashboard using vanilla HTML, CSS and JS, with Firebase as my backend. In my signup.html page, I have a form that allows users to input their name along with their email address and password. Upon signup, users are redirected to dashboard.html with their personalized content. Inside the dashboard, it has a spot where it displays their name.
The problem is it is not always getting the name from the form, and if it doesn't get the user's name from the signup form then it just doesn't have their name as I don't have a "add name" function in the dashboard. I suspect this is because of the way I use the onAuthStateChanged() inside signup.html.
The following is my signup page JS code:
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
window.location.replace('dashboard.html')
} else {
return
}
});
document.querySelector('#signup_btn').addEventListener("click", (e) => {
e.preventDefault();
var user_email = document.getElementById('user_email').value;
var user_pass = document.getElementById('user_pass').value;
var user_name = document.getElementById('user_name').value;
// Sign Up
firebase.auth().createUserWithEmailAndPassword(user_email, user_pass)
// Success
.then((userCredentials) => {
userCredentials.user.updateProfile({
displayName: user_name
})
})
// Errors
.catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode == 'auth/weak-password') {
alert('The password is too weak.');
} else {
alert(errorMessage);
}
console.log(error);
});
})
If it helps, here is the form from my signup.html page:
<form>
<h1>Sign Up</h1>
<!-- <h2>Log into your account using your email address</h2> -->
<label for="user_name">Name</label>
<input type="text" name="name" id="user_name">
<label for="user_email">Email Address</label>
<input type="text" name="email" id="user_email">
<label for="user_pass">Password</label>
<input type="password" name="Password" id="user_pass">
<button type="submit" id="signup_btn">Sign Up</button>
<p>Already have an account? Log In</p>
</form>
It seems like your onAuthStateChanged listener is being triggered before the write to the database has completed. This is the expected behavior for the API, but not what you want here.
Since you do want to use the onAuthStateChanged listener to navigate on page reload, the best I can think off is to turn off the listener when the user clicks the sign up button:
// 👇 store the unsubscribe function in a variable
var unsubscribe = firebase.auth().onAuthStateChanged(function (user) {
if (user) {
window.location.replace('dashboard.html')
} else {
return
}
});
document.querySelector('#signup_btn').addEventListener("click", (e) => {
e.preventDefault();
unsubscribe(); // 👈 turn off auth state listener
var user_email = document.getElementById('user_email').value;
var user_pass = document.getElementById('user_pass').value;
var user_name = document.getElementById('user_name').value;
// Sign Up
firebase.auth().createUserWithEmailAndPassword(user_email, user_pass)
// Success
.then((userCredentials) => {
return userCredentials.user.updateProfile({ // 👈 add a return
displayName: user_name
})
})
.then(() => {
window.location.replace('dashboard.html') // 👈 explicitly navigate here
})
As mentioned in the documentation,
onAuthStateChanged adds an observer for changes to the user's sign-in state.
When the user is logged in, it redirects your user to /dashboard before the updateProfile is resolved resulting in termination of that request.
I don't think you'll need an auth state listener on login page so try refactoring the code like this:
window.onload = function () {
if (firebase.auth().currentUser) window.location.replace("dashboard.html")
// Else stay on this page
// button click events here
}

can't update user's email

I am trying to update the email of the current user, I went to documentation and I copied the example code that they are given there,
But nothing worked, this from doc didn't work
var user = firebase.auth().currentUser;
user.updateEmail("newemail#example.com").then(function() {
console.log('success')
}).catch(function(error) {
console.log('failed')
});
I have also tried :
try {
await user.updateEmail('test#test.com').then(function() {
console.log('success')
}).catch(function(error) {
handleErrors(dispatch, error.message);
});
} catch(e) {
handleErrors(dispatch, e.message);
}
could you help to solve this issue?
update :
sorry i didn't include the exact error that come out in the console , here is the error :
This operation is sensitive and requires recent authentication. Log in
again before retrying this request.
2)
I should add that I am using asyncstorage of react native , and I store that Item( profile of user => email , name , ect..) in reduxPersist
that how my login code is :
export const login = ( email, password ) => {
return async (dispatch) => {
dispatch({ type: ATTEMPTING });
try {
await firebase.auth().signInWithEmailAndPassword(email, password)
.then(resp => handleLoginSuccess(dispatch, resp.uid,resp.name,email))
.catch(error => handleErrorLogin(dispatch, error.message));
}catch(e){
handleErrorLogin(dispatch, e.message);
}
};
};
const handleLoginSuccess = async(dispatch , userId,name,email) => {
try{
const profile = { userId, name, email };
await AsyncStorage.setItem('userProfile', JSON.stringify(profile));
dispatch({ type: LOGIN_SUCCESS, payload: profile });
}catch(e){
alert(e.message);
}
}
The error message is telling you that there is no user logged in at the time you call updateEmail. The SDK doesn't know which user you're trying to modify. You'll need to wait until the login is fully complete before calling that method.
Note that all of the Firebase APIs are asynchronous, so you'll need to make use of their returned promises to make sure the order of calls is valid.

Firebase Web (Sign In for Email) not working

I've been struggling to get Firebase Auth to work for my website. I'm using a local server to run the HTML code.
Firebase is signing up users successfully (they show up in my Firebase console), but it's not signing them in.
I am using this code to check if user is signed in. It always shows "User is not signed in."
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log(user);
console.log('User is signed in');
} else {
console.log(user);
console.log('User is not signed in');
}
});
I've gone through the documentation and watched the Firecast videos as well as some other tutorials.
My HTML code:
<div class="login w3-display-middle">
<form class="login-container">
<p><input type="text" placeholder="Email" id="email"></p>
<p><input type="password" placeholder="Password" id="password"></p>
<p><button class="w3-blue" id="signin" style="width:100%">LOG IN </button></p>
<p><button class="w3-blue" id="signup" style="width:100%">SIGN UP </button></p>
<p><button class="w3-red" id="signout" style="width:100%">SIGN OUT </button></p>
</form>
</div>
Javascript (included right below the HTML code, before the body tag is closed:
<script src="https://www.gstatic.com/firebasejs/4.5.2/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: <I have included my apiKey>,
authDomain: <I have included my authDomain>,
databaseURL: <Included my database URL>,
projectId: <Used my project ID>,
storageBucket: <Used this as well>,
messagingSenderId: <And this too>
};
firebase.initializeApp(config);
</script>
<script>
const txtEmail = document.getElementById("email");
const txtPassword = document.getElementById("password");
signin.addEventListener('click', e => {
//Get email and password
const email = txtEmail.value;
const pass = txtPassword.value;
console.log(txtEmail.value);//Shows correct value
console.log(txtPassword.value);//Shows correct value
const promise = firebase.auth().signInWithEmailAndPassword(email, pass);
promise.catch(e => console.log(e.message));
});
signup.addEventListener('click', e => {
//Get email and password
const email = txtEmail.value;
const pass = txtPassword.value;
const auth = firebase.auth();
auth.createUserWithEmailAndPassword(email,pass)
.catch(function(error){
console.log(error.code);
console.log(error.message);
});
});
signout.addEventListener('click',e=> {
firebase.auth().signOut().then(function() {
// Sign-out successful.
})
.catch(function(error) {
console.log(error.code);
console.log(error.message);
});
});
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log(user);
console.log('User is signed in');
} else {
console.log(user);
console.log('User is not signed in');
}
});
</script>
Really need help figuring this one out. I've spent like 4 hours on it now. Also, when I initially signup the user, it also signs them in (shows up in the Firebase console!). It's just so weird.

Categories

Resources