I have a custom Wix profile page (made with Velo) that displays the user's information. To get that information, I have to query a database, and to query that database I have to get the currently logged in user's login email address. Fortunately, Wix has an API for that, currentMember. However, using currentMember.getMember() is returning undefined on the profile page. But after I reload the profile page, it returns an object with the correct member data (including the email I need). Why is this happening? Another thing I noticed is that I'm getting the following error in the console:
the error I'm getting
I was thinking that since the error said the URL was preloaded, perhaps the page loaded before I logged in, and thus the member object being returned is undefined, since the user hadn't logged in yet.
Here is the code I used to log the member object to the console:
import { currentMember } from 'wix-members';
$w.onReady(function () {
currentMember.getMember()
.then((member) => {
console.log(member);
});
}
And this was logging undefined, but when I reload, it gives the correct info.
I had a similar issue whereby a member logs in, but member object returned was not available until a refresh of the page occurred.
I solved this with the use of the "wix-members" onLogin() api. Below is the code I hacked together.
authentication.onLogin((memberInfo) => {
const memberId = memberInfo.id;
if (memberId) {
console.log("MEMBER ID: " + memberId);
local.setItem("auth", memberId);
} else {
currentMember.getMember()
.then((member) => {
if (member) {
console.log("MEMBER ID: " + member._id);
local.setItem("auth", member._id);
}
else {
console.log("NOT LOGGED IN!");
}
})
.catch((error) => {
console.error(error);
});
}
});
I had to use an if / else as the memberInfo.id property always appears undefined. I left it in the code (for my use case) in case it begins to work as expected again.
I used this in the masterPage.js onReady().
Related
I built a push notification system on my backend using expo-server-sdk-node. When I want to send notifications, I lookup the expoPushToken in my database. The docs states the following error(s) should be handled:
DeviceNotRegistered: the device cannot receive push notifications
anymore and you should stop sending messages to the corresponding Expo
push token.
However, I am unsure how to handle this error since there are no direct pushTokens available in the error message. See the following example:
[{
status: 'error',
message: '"ExponentPushToken[XXXXXXXXXXXXXXX]" is not a registered push notification recipient',
details: { error: 'DeviceNotRegistered' }
}]
This device should now be removed from my database, but to do that I need the ExponentPushToken[XXXXXXXXXXXXXXX] value. And because the notifications are sent in batches I lose the reference to the user. What is the proper way to do this?
I thought of the following two ways:
1: Just split(") and filter the value, but this depends on the error message.
2: Loop over all my pushTokens, and find where includes(originalValue) in message, but this would mean I'd have to loop over an excessive amount of users every time it fails.
Any recommendations?
I faced the same issue, and here's what I did.
Considering this code
for (let chunk of chunks) {
try {
let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
console.log(ticketChunk);
tickets.push(...ticketChunk);
// If a ticket contains an error code in ticket.details.error
//
} catch (error) {
console.error(error);
}
}
Once I send a batch of notifications (100 most likely).
I loop through the tickets, if ticket.status === 'error' and check for ticket.details.error === 'DeviceNotRegistered' as in the code above.
Since the order of sent notifications is the order in which the response tickets are received.
Using the current index of the tickets loop, I can access the token at the same index in the chunk I sent.
for (let chunk of chunks) {
try {
let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
tickets.push(...ticketChunk);
// If a ticket contains an error code in ticket.details.error
let ticketIndex = 0;
for (let ticket of tickets) {
if (ticket.status === 'error' && ticket.details.error === 'DeviceNotRegistered') {
// Get the expo token from the `chunk` using `ticketIndex`
// Unsubscribe the token or do whatever you want to
}
ticketIndex++;
}
} catch (error) {
console.error(error);
}
}
NB: The code might contain syntax errors, it's the idea I am trying to pass across. I did the same thing with php
It's not documented behaviour (at least I didn't found it in the documentation), but in the ticket error response I can see the expoPushToken in the details object. See the screenshot attached:
I am trying to authorize the site through Firebase, everything works as it should, the data is sent to the Firebase server.
But further, in the signIn function, I try to create a h2-element and put the mail data into it, which the user entered and clicked on the Login button (I want the mail to be displayed on the site instead of the name), then an error appears on the line where I highlighted with a red arrow: "autorizationName is null, undefined ", no data is sent to html. I can’t understand why, so help, please, I’m recently studying JS to figure it out.
This can happen if I added one JS script to two HTML pages?
That is, index.html and autorization.html to the two I added autorization.js
I wanted it to be redirected to the main page when authorizing from one page.
const login = document.querySelector(".form-login")
login.addEventListener('click', signIn)
function signIn() {
const email = document.querySelector(".email").value
const password = document.querySelector(".password").value
// e.preventDefault()
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log("Email firebase: ", user.email);
const user2 = JSON.parse(JSON.stringify(user.email))
const autorizationName = document.querySelector(".autorization-name__container");
const autorizationNameTitle = document.createElement("h2");
autorizationNameTitle.textContent = user2;
autorizationNameTitle.classList.add("autorization-name__title");
autorizationName.appendChild(autorizationNameTitle); // Error: autorizationName is null, undefined
window.location.replace("http://192.168.1.65:5500/")
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
alert(errorMessage + ", " + errorCode);
});
}
Here are screenshots:
At the line of
autorizationName.appendChild(autorizationNameTitle);
you are getting an error which says that authorizationName is null, undefined. So, logically, we need to take a look at the place where its value was modified the last time (in this case, it is its initialization):
const autorizationName = document.querySelector(".autorization-name__container");
And it is a known fact that if your call to document.querySelector yields undefined, then the selector did not match any elements. So, the reason for the error is that there is no element in your page with the class of authorization-name__container at the time you try to find it. So, you will need to fix the selector or find out when the given element is created.
It is 100% an error with the string '.authorization-name__container', try to copy paste this class from where you have it in your code and double check for mispelled words. Then if that doesn't work try to use an id instead of a class
I have updated my Firebase Realtime Database access rules, and have noticed some clients now tries to access paths they do not have access to. This is ok - but my problem is that my code stops after being unable to read a restricted node.
I see below error in my console, and then loading of subsequent data stops:
permission_denied at /notes/no-access-node
I begin by collecting access nodes from /access_notes/uid and continue to read all data from /notes/noteId.
My code for collecting notes from the database below:
//*** SUBSCRIPTION */
database.ref(`access_notes/${uid}`).on('value', (myNotAccessSnaps) => {
let subscrPromises = []
let collectedNots = {}
// Collect all categories we have access to
myNotAccessSnaps.forEach((accessSnap) => {
const noteId = accessSnap.key
subscrPromises.push(
database.ref(`notes/${noteId}`)
.once('value', (notSnap)=>{
const notData = notSnap.val()
const note = { id: notSnap.key, ...notData}
collectedNotes[note.id] = note
},
(error) => {
console.warn('Note does not exist or no access', error)
})
)
})
Promise.all(subscrPromises)
.then(() => {
const notesArray = Object.values(collectedNotes)
...
})
.catch((error) => { console.error(error); return Promise.resolve(true) })
I do not want the client to halt on permission_denied!
Is there a way to see if the user has access to a node /notes/no_access_note without raising an error?
Kind regards /K
I do not want the client to halt on permission_denied!
You're using Promise.all, which MDN documents as:
Promise.all() will reject immediately upon any of the input promises rejecting.
You may want to look at Promise.allSettled(), which MDN documents as:
[Promise.allSettled()] is typically used when you have multiple asynchronous tasks that are not dependent on one another to complete successfully, or you'd always like to know the result of each promise.
Is there a way to see if the user has access to a node /notes/no_access_note without raising an error?
As far as I know the SDK always logs data access permissions errors and this cannot be suppressed.
Trying to access data that the user doesn't have access to is considered a programming error in Firebase. In normal operation you code should ensure that it never encounters such an error.
This means that your data access should follow the happy path of accessing data it knows it has access to. So you store the list of the notes the user has access to, and then from that list access each individual note.
So in your situation I'd recommend finding out why you're trying to read a note the user doesn't have access to, instead of trying to hide the message from the console.
I've been trying to fix the problem for a whole day and couldn't make it work. I'm getting irritated, firebase docs are such a mess it's insane..
So I'm trying to implement email verification on my React app. I wen't with the docs, and google do send the email, I can click it, it's all good.
But, the email verified state doesn't change at all, and believe me I've went through all the stackoverflow topics.
firebase.auth().doSignInWithEmailAndPassword(email, password)
.then(() => {
console.log(firebase.auth().currentUser);
firebase.auth().currentUser.reload()
.then(() => {
console.log(firebase.auth().currentUser);
})
})
So I've found i need to reload the user to see the changes applied, tho they just won't work no matter what I do.
Both console logs return email.verified = false at all times.
I'm hopeless, anyone have any idea on how to make this work?
I was wondering whether me setting up custom domain as a verification link has to do anything with that? I'm testing on localhost, link is linking to live website.
Please help :(
The method you should call is signInWithEmailAndPassword, so remove the "do" in the function call:
firebase.auth().signInWithEmailAndPassword(email, password)
.then((credential) => {
const currentUser = credential.user;
console.log(firebase.auth().currentUser);
firebase.auth().currentUser.reload()
.then(() => {
console.log(firebase.auth().currentUser);
})
}).catch((err) => {console.error("Problem with sign in ", err);}
Use the credential returned from this function and assign its user value to currentUser to validate that the user has been authenticated.
Lastly, remember to add a catch at the end whenever you use then. In this case, err will contain a property err.code that will tell you why the user could not be authenticated.
I had the same problem. You need to reload your current user using a timer and then listen to user changes (not auth changes) in a Streambuilder. As soon as the user clicks the link they will be redirected to your main page.
Use a Streambuilder to listen to changes to the user:
StreamBuilder<User?>(
stream: FirebaseAuth.instance
.userChanges(), // monitor the changes to the user
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return LoadingScreen(); // show loading screen while loading
if (snapshot.hasData && !snapshot.data!.emailVerified) {
return VerifyEmailScreen();
} // if not verified show the verify email screen
if (snapshot.hasData) {
return MainScreen();
} // if logged in already show main screen
return OnboardingScreen(); // if not logged in already show the auth screen
},
),
In your VerifyEmailScreen() create a timer in it's initState like this:
void initState() {
Timer.periodic(Duration(seconds: 5), (timer) {
FirebaseAuth.instance.currentUser?.reload();
});
super.initState();
}
I hope it helps your problem.
Cheers
I only want to allow a user to insert a document when his email is verified, I wrote the following code.
Events.allow({
insert: function (userId, doc) {
var user = Meteor.users.find({_id: userId});
console.log(user); // logs a large object
// if the user's email is verified
if (user.emails[0].verified) {
return true;
}
return false;
}
});
Running this, I get an error, "internal server error", looking at the server, I get TypeError: Cannot read property '0' of undefined, which means that something is wrong with my user object. So I logged the object, and instead of seeing a user, I get a huge object, abbreviated below:
{ _mongo:
// lots of stuff
}
I think that's the top level mongoDB object that Meteor uses.
How in the world is Meteor.users.find({_id: userId}) returning the MongoDB object instead of the user I'm looking for?
You're probably looking for findOne, and not find. find returns a cursor to the result, findOne returns the first matched document.