AsyncStorage for react native expo with firebase - javascript

Everytime when I run the app, I get a warning about the AsyncStorage. But the warning previously was just saying install something else to replace it and thats all. But now the warning is saying it will be removed in future released. So I had no choice to install it by following: https://react-native-async-storage.github.io/async-storage/docs/install
Installing : npm install #react-native-async-storage/async-storage
According to the usage from the link above, AsyncStorage is now added after await
Example from the usage:
const storeData = async (value) => {
try {
await AsyncStorage.setItem('#storage_Key', value)
} catch (e) {
// saving error
}
}
Which I tried to add to the await codes I have for my authentication with firebase.
Original Login:
const handleLogin = async () => {
try {
if (email && password) {
const { user } = await signInWithEmailAndPassword(auth, email, password)
console.log('Logged in as :' , user.email);
}
} catch (error) {
console.log({error});
setShowError(true);
}
}
Edited login for the await line and also importing:
import AsyncStorage from '#react-native-async-storage/async-storage';
const { user } = await AsyncStorage.signInWithEmailAndPassword(auth, email, password)
After editing, my login did not work anymore. I get the error of {"error": [TypeError: _asyncStorage.default.signInWithEmailAndPassword is not a function. (In '_asyncStorage.default.signInWithEmailAndPassword(_firebase.auth, email, password)', '_asyncStorage.default.signInWithEmailAndPassword' is undefined)]} How do I do to correct this? As I have 2 more function that uses await
Under my register screen, i also have the line that uses await:
const handleSignUp = async () => {
try {
if (email && password) {
setShowError(false);
const { user } = await createUserWithEmailAndPassword(auth, email, password)
console.log('Registered as :' , user.email);
try{
await signOut(auth)
console.log("Signed out successfully")
navigation.replace("Login")
}catch (error) {
console.log({error});
}
}
} catch (error) {
console.log({error});
setShowError(true);
}
}
Under my app.js, i also has that line for logout:
const handleSignOut = async () => {
try {
await signOut(auth);
console.log("Signed out successfully");
RootNavigation.navigate('Login');
} catch (error) {
console.log({ error });
}
}
My bad on not linking it to firebase. This is indeed firebase code that is run with expo. I am using firebase authentication with expo thus having this issue. Is there anyway to implement this AsyncStorage with firebase? Or do I not have to worry about this even though the old version is going to be removed?

Related

How to make a post request by SERVER not by user

Node.js CODE
exports.user = async (req, res) => {
try {
const { wallet } = req.body;
if (!wallet) {
res.status(400).json({ error: "Not logged in" });
return;
} else {
user = User.findone(wallet);
// if user is not found then create a new user and mark as loggged In
if (!user) {
User.create({
user: wallet,
});
}
// if user found then create a session token and mark as logged
in
res.send({
user: wallet,
});
}
} catch (error) {
console.log(`ERROR::`, error);
}
};
REACTJs CODE
// post call/update
const axiosCall = async () => {
// core login will give a unique username by fulling a transcation
// core.login i dont have any control
const userAccount = await core.login();
try {
const res = await Axios.post(`${API}/user`, userAccount, dataToken);
setData({
...data,
error: "",
success: res.data.message,
});
} catch (error) {
setData({
...data,
error: error.response.data.error,
});
}
};
Now here the problem occurs when some one could modify userAccount in the front-end or someone could send a body with wallet: anything to my route localhost:3000/api/user
There is no option for me to check if some actually used core.login(); to get the wallet address.
So is there any solution?
I was thinking to allow only my server IP or localhost to hit the route localhost:3000/api/user and is that even possible?
Also there is another issue anyone could modify userAccount in front-end.

Having trouble with promise inside async function

having a real problem with getting this code to work. I have everything set up working great with Appwrite. I'm getting a response back from the server, but in my promise.then it finishes the other code and returns undefined from the login function. so then the post async function is sending a blank array in the try block. I've tried setting this code up every way I can think of but it never works. Sorry, i'm still trying to wrap my head around the promises and async js.
import { Appwrite } from 'appwrite';
export async function post({ locals, request }) {
const { email, password } = await request.json();
function login() {
// add logic to authenticate user with external service here
const sdk = new Appwrite();
sdk
.setEndpoint('https://') // API Endpoint
.setProject('') // project ID
;
let promise = sdk.account.createSession(email, password);
let userLogin;
promise.then(function (response) {
console.log(response); // Success
userLogin = response.providerUid;
console.log(userLogin);
}, function (error) {
console.log(error); // Failure
});
console.log('login.json.js', { email, password: !!password });
console.log(userLogin);
return userLogin;
}
try {
const user = login();
locals.user = user;
return {
status: 200
};
} catch (error) {
const message = `Error in endpoint /api/login.json: ${error}`;
return {
status: 500,
body: message
};
}
}
You're returning userLogin in login before it's even populated in the asynchronous promise.then chain
Also, since you're currently handling the rejection in your promise.then(onFulfilled, onRejected) that would mean any rejection is handled inside login and your try/catch (once written correctly) would never have an error to catch since login handled it already
One more potential issue - if const { email, password } = await request.json(); rejects, then the error will be thrown to whatever called post - is that what you want? or did that also need to be handled inside post?
Anyway here's how to fix your code:
import { Appwrite } from 'appwrite';
export async function post({ locals, request }) {
// note: if this throws then the error will be handled by whatever calls `post`
const { email, password } = await request.json();
function login() {
// add logic to authenticate user with external service here
const sdk = new Appwrite();
sdk
.setEndpoint('https://') // API Endpoint
.setProject('') // project ID
;
const promise = sdk.account.createSession(email, password);
return promise.then(function(response) {
let userLogin = response.providerUid;
return userLogin;
// or without redundant `userLogin` variable
// return response.providerUid;
});
}
try {
const user = await login();
locals.user = user;
return { status: 200 };
} catch (error) {
const message = `Error in endpoint /api/login.json: ${error}`;
return { status: 500, body: message };
}
}
Or, making login async
import { Appwrite } from 'appwrite';
export async function post({ locals, request }) {
// note: if this throws then the error will be handled by whatever calls `post`
const { email, password } = await request.json();
async function login() {
// add logic to authenticate user with external service here
const sdk = new Appwrite();
sdk
.setEndpoint('https://') // API Endpoint
.setProject('') // project ID
;
let response = await sdk.account.createSession(email, password);
let userLogin = response.providerUid;
return userLogin;
}
try {
const user = await login();
locals.user = user;
return {
status: 200
};
} catch (error) {
const message = `Error in endpoint /api/login.json: ${error}`;
return {
status: 500,
body: message
};
}
}
Or, removing inner Login function completely
import { Appwrite } from 'appwrite';
export async function post({ locals, request }) {
// note: if this throws then the error will be handled by whatever calls `post`
const { email, password } = await request.json();
try {
const sdk = new Appwrite();
sdk.setEndpoint('https://') // API Endpoint
.setProject(''); // project ID
const response = await sdk.account.createSession(email, password);
console.log(response); // Success
locals.user = response.providerUid;
return { status: 200 };
} catch (error) {
const message = `Error in endpoint /api/login.json: ${error}`;
return { status: 500, body: message };
}
}

Async storage cannot retrieve data from react native

I am using AsyncStorage to keep user data to phone. After registering the user, i am trying to retrieve the user if exist one and automate redirect to profile page.
but I have problems with async storage because it returns only the word 'user' in the console...
in the login component ->
import AsyncStorage from '#react-native-async-storage/async-storage';
const loggedUser = async () => {
try {
const u = await AsyncStorage.getItem('user');
console.log(u);
} catch (error) {
console.log(error);
}
};
/**
*
* This function retrieve the data from the server and store it to the local database..
*
*/
const executeLogin = async (email, password) => {
try
{
// Get data and store in async storage
const response = await data.post('/api/login', {email, password});
storeData('user', response.data); -> //Check the code bellow for the source
}
// Catch all errors bellow
catch (error)
{
if (error.response.status === 404 && error.response.data === 'Wrong credentials') {
Alert.alert('Whoops!', 'You entered the wrong credentials. Please try again.');
}
else {
Alert.alert('Whoops!', 'Something went wrong. This is an unexpecred error. We will try to fix it as soon as possible');
}
}
};
export default executeLogin;
The code block above calls the axios and supose to store the data to async storage. But I have no ideea also if it worked because it gave me no error...
import AsyncStorage from '#react-native-async-storage/async-storage';
/**
*
* This function must only accept serialised object with JSON.stringfy() method
*
*/
const storeData = async object => {
try
{
await AsyncStorage.setItem('user', object);
}
catch (error)
{
console.log(error);
}
}
export default storeData;
This is the store function
Cannot understand what I am doing wrong....
Thanks, Daniel

How to link auth providers with native plugins?

I'm facing a firebase error auth/account-exists-with-different-credential when I'm trying to sign in an already existing account(with different auth provider) with facebook. I know this question has been asked many times like here and here but all solutions works for web and I'm stuck with native plugins. I'm using Google Plus and Facebook Connect plugins to sign in on native platforms.
Code:
async continueWithGoogle() {
try {
const googleResponse = await this.googlePlus.login({ webClientId: environment.firebaseConfig.webClientId })
const googleCredential = firebase.default.auth.GoogleAuthProvider.credential(googleResponse.idToken);
const firebaseResponse = await firebase.default.auth().signInWithCredential(googleCredential);
return firebaseResponse;
} catch (error) {
console.log('continue with google: ', error);
}
}
async continueWithFacebook() {
try {
const fbResponse = await this.facebook.login(['email']);
const fbCredential = firebase.default.auth.FacebookAuthProvider.credential(fbResponse.authResponse.accessToken);
const firebaseResponse = await firebase.default.auth().signInWithCredential(fbCredential);
return firebaseResponse;
} catch (error) {
if (error.code === 'auth/account-exists-with-different-credential') {
// What should I do here?
}
console.log('continue with fb: ', error);
}
}
Can I solve this error without using any web method like signInWithRedirect() or signInWithPopup()?

How to make sure all data is written into Firestore in a sequential order?

I'm trying to create a user profile that states that that profile is from one of the business owners in my app. It is supposed to create the profile and then merge info such as the 'roles' array with 'businessOwner' in it and also add the 'businessId'.
Sometimes, the code will work seamlessly. At other times, only the roles and the businessId will be passed to the created user (and all of the other information won't!).
async function writeToFirebase(values) {
authService.createUserWithEmailAndPassword(values.user.email, values.user.senha).then(
async function (user) {
userService.createUserProfileDocument(values.user)
const uid = user.user.uid
const userRef = await userService.doc(uid)
console.log('userRef', userRef)
try {
values.user.uid = uid
const { id } = await businessPendingApprovalService.collection().add(values)
await userRef.set({ roles: ['businessOwner'], businessId: id }, { merge: true })
} catch (error) {
console.error('error merging info')
}
},
function (error) {
var errorCode = error.code
var errorMessage = error.message
console.log(errorCode, errorMessage)
},
)
}
This is createUserWithEmailAndPassword:
async createUserProfileDocument(user, additionalData) {
if (!user) return
const userRef = this.firestore.doc(`users/${user.uid}`)
const snapshot = await userRef.get()
if (!snapshot.exists) {
const { displayName, email, photoURL, providerData } = user
try {
await userRef.set({
displayName,
email,
photoURL,
...additionalData,
providerData: providerData[0].providerId,
})
} catch (error) {
console.error('error creating user: ', error)
}
}
return this.getUserDocument(user.uid)
}
I think that the issue is on this line const snapshot = await userRef.get().
As stated in documentation you should fetch the snapshot using then() function in order to return the promise first.
I think you need to await on the below as well:-
await userService.createUserProfileDocument(values.user)
Since you are setting the user info here(await userRef.set), if you will not wait for the promise, then sometimes, your next block of code(await userRef.set({ roles: ['businessOwner'],) executes and after then your promise might get resolved. Because of this, you might not get the other information sometimes.
You also need to handle the error case of createUserProfileDocument.

Categories