1

I am attempting to make all my user sessions with Parse exclusive, meaning if a user is already logged in on a certain device in a certain location, if another device logs in with the same credentials, I want the previous session(s) to be terminated, with a message of an alert view of course. Sort of like the old AOL Instant Messaging format. I figured the code for this action should be written in the login logic, so I wrote this within my login "succession" code :

 PFUser.logInWithUsernameInBackground(userName, password: passWord) {
        (user, error: NSError?) -> Void in
        if user != nil || error == nil {
            dispatch_async(dispatch_get_main_queue()) {
                self.performSegueWithIdentifier("loginSuccess", sender: self)

                 PFCloud.callFunctionInBackground("currentUser", withParameters: ["PFUser":"currentUser"])
                    //..... Get other currentUser session tokens and destroy them

            }

        } else {

Thats probably not the correct cloud code call, but you get the point. When the user logs in once again on another device, I want to grab the other sessions and terminate them. Does anyone know the correct way to go about making this request in swift?

John Durand
  • 1,934
  • 5
  • 22
  • 34

1 Answers1

2

I speak swift with a stutter, but I think I can answer adequately in almost-swift. The key idea is to start the success segue only after the cloud says it's okay. Here's what I think you want:

PFUser.logInWithUsernameInBackground(userName, password: passWord) {
    (user, error: NSError?) -> Void in
    if (user != nil) {
        // don't do the segue until we know it's unique login
        // pass no params to the cloud in swift (not sure if [] is the way to say that)
        PFCloud.callFunctionInBackground("isLoginRedundant", withParameters: []) {
            (response: AnyObject?, error: NSError?) -> Void in
            let dictionary = response as! [String:Bool]
            var isRedundant : Bool
            isRedundant = dictionary["isRedundant"]!
            if (isRedundant) {
                // I think you can adequately undo everything about the login by logging out
                PFUser.logOutInBackgroundWithBlock() { (error: NSError?) -> Void in
                    // update the UI to say, login rejected because you're logged in elsewhere
                    // maybe do a segue here?
                }
            } else {
                // good login and non-redundant, do the segue
                self.performSegueWithIdentifier("loginSuccess", sender: self)
            }
        }
    } else {
        // login failed for typical reasons, update the UI
    }
} 

Please don't take me too seriously on swift syntax. The idea is to nest the segue in the completion handlers to know that you need to do it before starting it. Also, please note that the explicit placement on the main_queue within the completion handler is unnecessary. The SDK runs those blocks on the main.

A simple check to determine if a user's session is redundant (not unique) looks like this...

Parse.Cloud.define("isLoginRedundant", function(request, response) {
    var sessionQuery = new Parse.Query(Parse.Session);
    sessionQuery.equalTo("user", request.user);
    sessionQuery.find().then(function(sessions) {
        response.success( { isRedundant: sessions.length>1 } );
    }, function(error) {
        response.error(error);
    });
});
danh
  • 62,181
  • 10
  • 95
  • 136
  • okay i see, so in your answer, the only place where i should write my own custom code is after the logoutInBackground? other than that thats basically the structure i should roll with correct? – John Durand Aug 27 '15 at 19:53
  • yes. there, after the logout is complete, and at the leaf level for the other conditions (where the comments say "update the ui") – danh Aug 27 '15 at 19:55
  • so this will just stop an excess login not terminate the current session correct ? – John Durand Aug 27 '15 at 20:05
  • Login creates a session and logout does the inverse (destroys it). I think that's what you want, right? – danh Aug 27 '15 at 20:06
  • yes, but i want to make sure that it just destroys the "excess" sessions, not the original sessions. you understand? – John Durand Aug 27 '15 at 20:14
  • meaning, if i am logged into a device already, and I try to log into another device, this method will send me an alert and destroy the new session I'm trying to create because i already have one active – John Durand Aug 27 '15 at 20:15
  • I'm getting the error `"Cannot invoke 'callFunctionInBackground' with an argument list of type '(String, withParameters: [String: PFUser?], (AnyObject?,NSError?) -> Void)` ... on the following line `PFCloud.callFunctionInBackground("isLoginRedundant", withParameters: ["currentUser":user])` .... why so? – John Durand Aug 27 '15 at 20:32
  • About that last comment, I think now that there's no point in sending the user, because the cloud function can check request.user for the same value. I guess the correct param is `[]` (or however you say "empty dictionary" in swift). See edit. – danh Aug 27 '15 at 20:37
  • About your prior comments. The idea is (I think) you will detect in the cloud that request.user has more than one session associated with it, and indicate that in the response. The client, learning that this login is a second login, will do a logout, thereby deleting the second session. – danh Aug 27 '15 at 20:40
  • yup thats all. As long as the client is not allowed to continue to another session thats all. – John Durand Aug 27 '15 at 20:43
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/88130/discussion-between-danh-and-john-durand). – danh Aug 27 '15 at 20:43
  • wow, what a great point of view @danh, i might implement this – Mike Strong Aug 27 '15 at 23:53
  • hey, i wrote you in the chat about this method. So after my migration to swift 2 and Xcode 7, for some reason, instead of not allowing a second session at all, parse allows the session to go through, showing the alert view after the second session has been granted access. How do I fix this? – John Durand Sep 18 '15 at 07:45
  • http://chat.stackoverflow.com/rooms/88130/discussion-between-danh-and-john-durand theres the chat once again – John Durand Sep 18 '15 at 07:45