Hi Parse Community,
I’m having trouble to do two features with Parse. I’ve been exploring documentation, APIs and code source and I can’t find how to do these :
- If I revoke a sessionToken in the backend (so for example I remove a row of a currently logged in user), is there an event I can catch on the frontend to automatically force a logout
I tried to activate LiveQuery on the _Session
class but if I try to log in I’m getting this error: Error: Cannot modify readonly attribute: sessionToken
- I’d like to be able to know the users who have an opened WebSocket connection with the parse server. Basically I’d like to be able to list the connected Users. Which is not equivalent to the Sessions since a Session is not deleted if a WebSocket is closed by the client.
I see in the source code that the parseWebSocketServer
keeps a list of clients. I’m wondering if it’s possible to use it to retrieve those users.
Thanks in advance.
Thomas
As an answer to your first question, Parse SDK throws an Invalid Session Token error when session token is broke(or deleted in your case). When you are making a query or calling a cloud code, try to catch this error. So you can logout user.
Hi uzaysan,
Thanks for you reply. I’ve noticed the Invalid Session Token
and I’m already catching this event on each query I’m doing in the front side. However, even though the session token has been removed in the db, if the user has opened websocket connections he will still receive some Parse.Object through liveQueries.
That’s why I’d like to force a logout as soon as the user session is deleted.
I dont know exactly this is what you want, But this is how I would do If I was ever gonna need what you need.
First add user to Parse.Installation in beoreSave Trigger:
Parse.Cloud.beforeSave(Parse.Installation, (request) => {
request.object.set("user", request.user);
});
Then Use afterDelete Trigger for Session objects. Get user of session and send them a push notification.
Parse.Cloud.afterDelete(Parse.Session, (request) => {
const query = new Parse.Query(Parse.Installation);
const invalidUser = new Parse.User({id:request.object.get("user").id});
query.equalTo("user",invalidUser);
Parse.Push.send({
where: query,
data: { "type":"invalidSessionToken",
"token":""+request.object.get("sessionToken")}
}, { useMasterKey: true })
.then(function() {
// Push sent!
}, function(error) {
// There was a problem :(
});
});
In your push reciever compare the type value and sessiontoken:
if(pushData.get("type").equals("invalidSessionToken"){
if(pushData.get("token").equals(ParseUser.getCurrentUser().getSessionToken())){
ParseUser.logOut();
}
}
Something like this can be done
2 Likes
You just could add another class called Events (Or something like that). Then use Parse SDK to listen events collection via LiveQuery client. Send events to clients and if one of those is “session destroy” logout your user.
Thanks @uzaysan! I never used the push method, and I didn’t even known there was an Parse.Installation
class. I’ll have a look into that, but since I want to be able to tell the client to logout also on a web app, I’m not sure if Parse.push is not limited to mobile app.
Hi @santiagosemhan,
That’s a really nice idea, I like it. Thanks for your input!
1 Like
At the end, I’ve used another approach to resolve my two points.
On the client app, I’m calling a cloud function every minute and store a lastActivityAt: Date
field.
Thanks to this solution, if the session of the user is deleted the call will fail and so we can force a logout on the front side. And I can also analyse who is connected to my app by fetching all the Session with a recent User.lastActivityAt
It is kind of sad, that I have to use a setInterval solution, though.
Thanks for your help!
I am trying to implement afterDelete
on Parse.Session
but I can’t make the server to load the code. I simplified it to a bare minimum:
Parse.Cloud.afterDelete(Parse.Session, async (request) => {
const installId = request.object.get('installationId');
const userId = request.user.id;
request.log.info(`session deleted installId ${installId}, userId ${userId}`);
});
it behaves the same no matter I use async in the afterDelete(Parse.Session, async (request) =>
or not. It shows in the system log:
Error loading your cloud code:
undefined
The following variant does not show that error but also do not trigger the event:
Parse.Cloud.afterDelete("Session", async (request) => {
...
});
I am aiming to implement a deletion of the Installation
after the session is removed. In the afterLogout
trigger the following works:
Parse.Cloud.afterLogout(async request => {
const { object: session } = request;
const query = new Parse.Query(Parse.Installation);
const installId = session.get('installationId');
const userId = session.get("user").id;
query.equalTo("userId", userId); //userId is indexed
query.equalTo("installationId", installId);
query.find({useMasterKey: true}).then((installations) => {
Parse.Object.destroyAll(installations, {useMasterKey: true});
}).catch((error) => {
request.log.info(`Error deleting related installations ${error.code}: ${error.message}`);
});
});
But I would like to implement it in the Session’s afterDelete
to cover also cases where user gets banned, deletes account, session is old and expired,…
Having look at the source code here it seems that only the afterLogout
trigger is available to Parse.Session
so I think that what was proposed above is not possible.
Please, correct me if I am wrong.
Yes. I believe that triggers currently do not work for Session class.