Skip to content

Parse.FacebookUtils.logIn is creating new users when Facebook ID already exists. #4897

Closed

Description

@jose-carballo

We have been using a very simple flow to log in users using Facebook that has been working for almost a year and a half, and now it has stopped working.

We use Parse.FacebookUtils.logIn to log in an existing user, or creating a new one.

var facebookAuthData = {
    "id": <fb_id>,
    "access_token": <fb_access_token>,
    "expiration_date": <fb_expiration_date>
};
Parse.FacebookUtils.logIn(facebookAuthData, {
    success: function(user) {
        if (user.isNew()) {
            // New user....
        } else {
            // Old user...
        }
    },
    error: ...
});

But it's happening that although there is an existing user in the database with the exact <fb_id> that we pass to Parse.FacebookUtils.logIn(), it is creating a new user instead of login the existing user. Furthermore, this "new" user is created with a weird/random "username" in the database.

Some more details:

  • Parse server version: 2.8.2. FB Graph version 3.0.

  • We only see the issue in our "Production" environment. This is a Heroku dyno with a mongoLab add-on. Note that it uses a replica set.

  • Our development environment uses a free-tier Heroku dyno, with a mongoLab add-on without a replica set. We DON'T see the issue here.

  • New users that have never logged in, can successfully log-in using Facebook, and re-login Ok. The ones that are having trouble were old users that logged in through Facebook a while back (using FB Graph v2.2).

  • After Parse.FacebookUtils.login() returns a "new" user when it shouldn't, when we try to save to the new user (i.e. to set the email), the error returned by parse can be inconsistent. Sometimes it will say "code=203, message=Account already exists for this email address." (since we had previously created the user and assigned the email address), but if I manually delete the malformed new user, sometimes instead of creating another malformed user, it will just say "Invalid access token". Very weird.

  • I've tried with older versions of Parse Server too (like 2.7.4) and the same issue happens.

I've tried for days trying to understand why this is happening with no luck. Any help appreciated, especially since this one reached our Production environment and previously FB logged users are being locked out.

Thanks in advance for the help.

Activity

  1. cbaker6 commented on Jul 16, 2018

    @cbaker6
    Contributor

    I have this same problem with FacebookUtils and TwitterUtils whenever I use Parse Server 2.8 or higher. On ParseServer 2.74 and below, I don't have this issue. As a note, I use the Parse SDK for iOS, version 1.17.1. To further clarify, this issue occurs with users who had created or linked their account using an older Parse Server version. I haven't verified if it for new facebook or twitter users.

    I haven't looked at the code, but it seems like FacebookUtils and TwitterUtils doesn't query authData correctly for facebookId and twitterId for duplicates anymore and instead just adds another facebookId and twitterId, even if it's already in the _User table.

  2. jose-carballo commented on Jul 16, 2018

    @jose-carballo
    Author

    As per @cbaker6 comment, I re-tested using Parse 2.7.2, and the issue does not happen. Confirmed in 2.8.2.

  3. flovilmart commented on Jul 16, 2018

    @flovilmart
    Contributor

    Are you able to provide some verbose logs for the issue, as well as potentially a way to consistently reproduce it (including database etc...) is uou’re a le to reproduce the issue in a failing test this would greatly help as well. Otherwise we’ll still look into it.

    One last thing, can you check/ share with us which indexes exist on the _User collection?

  4. jose-carballo commented on Jul 17, 2018

    @jose-carballo
    Author

    Extract of our package.json:

    {
      "dependencies": {
        "@parse/simple-mailgun-adapter": "^1.0.2",
        "axios": "^0.18.0",
        "bcryptjs": "^2.4.3",
        "express": "~4.16.x",
        "kerberos": "^0.0.24",
        "lodash": "^4.17.10",
        "moment": "^2.22.2",
        "nan": "^2.10.0",
        "node-gyp": ">=3.7.0",
        "node-pre-gyp": "^0.10.2",
        "npm": ">=6.1.0",
        "parse": "~1.11.1",
        "parse-dashboard": "~1.2.0",
        "parse-server": "~2.8.2",
        "pre-commit": "^1.2.2",
        "request": "^2.87.0",
        "request-promise": "^4.2.2",
        "semver": "^5.5.0",
        "socks": "~2.2.0",
        "underscore": "~1.9.1"
      },
      "scripts": {
        "start": "node index.js",
        ...
      },
      "engines": {
        "node": ">=10.0.0"
      }
    }
    

    Here is the log when Parse is deployed (kerberos compiles with warnings):

    $ git push heroku v1.8.2:master -f
    Total 0 (delta 0), reused 0 (delta 0)
    remote: Compressing source files... done.
    remote: Building source:
    remote:
    remote: -----> Node.js app detected
    remote:
    remote: -----> Creating runtime environment
    remote:
    remote:        NPM_CONFIG_LOGLEVEL=error
    remote:        NODE_VERBOSE=false
    remote:        NODE_ENV=production
    remote:        NODE_MODULES_CACHE=false
    remote:
    remote: -----> Installing binaries
    remote:        engines.node (package.json):  >=10.0.0
    remote:        engines.npm (package.json):   unspecified (use default)
    remote:
    remote:        Resolving node version >=10.0.0...
    remote:        Downloading and installing node 10.6.0...
    remote:        Using default npm version: 6.1.0
    remote:
    remote: -----> Restoring cache
    remote:        Skipping cache restore (disabled)
    remote:
    remote: -----> Building dependencies
    remote:        Installing node modules (package.json + package-lock)
    remote:
    remote:        > bcrypt@2.0.1 install /tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/bcrypt
    remote:        > node-pre-gyp install --fallback-to-build
    remote:
    remote:        [bcrypt] Success: "/tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/bcrypt/lib/binding/bcrypt_lib.node" is installed via remote
    remote:
    remote:        > kerberos@0.0.24 install /tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/kerberos
    remote:        > (node-gyp rebuild) || (exit 0)
    remote:
    remote:        make: Entering directory '/tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/kerberos/build'
    remote:        CXX(target) Release/obj.target/kerberos/lib/kerberos.o
    remote:        ../lib/kerberos.cc: In static member function ‘static void Kerberos::After(uv_work_t*)’:
    remote:        ../lib/kerberos.cc:948:50: warning: ‘v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const’ is deprecated [-Wdeprecated-declarations]
    remote:        worker->callback->Call(ARRAY_SIZE(info), info);
    remote:        ^
    remote:        In file included from ../lib/kerberos.h:9:0,
    remote:        from ../lib/kerberos.cc:1:
    remote:        ../../nan/nan.h:1618:3: note: declared here
    remote:        Call(int argc, v8::Local<v8::Value> argv[]) const {
    remote:        ^
    remote:        ../lib/kerberos.cc:972:50: warning: ‘v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const’ is deprecated [-Wdeprecated-declarations]
    remote:        worker->callback->Call(ARRAY_SIZE(info), info);
    remote:        ^
    remote:        In file included from ../lib/kerberos.h:9:0,
    remote:        from ../lib/kerberos.cc:1:
    remote:        ../../nan/nan.h:1618:3: note: declared here
    remote:        Call(int argc, v8::Local<v8::Value> argv[]) const {
    remote:        ^
    remote:        CXX(target) Release/obj.target/kerberos/lib/worker.o
    remote:        CC(target) Release/obj.target/kerberos/lib/kerberosgss.o
    remote:        ../lib/kerberosgss.c:36:0: warning: ignoring #pragma clang diagnostic [-Wunknown-pragmas]
    remote:        #pragma clang diagnostic push
    remote:        ^
    remote:        ../lib/kerberosgss.c:37:0: warning: ignoring #pragma clang diagnostic [-Wunknown-pragmas]
    remote:        #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    remote:        ^
    remote:        ../lib/kerberosgss.c: In function ‘authenticate_gss_client_wrap’:
    remote:        ../lib/kerberosgss.c:446:19: warning: variable ‘server_conf_flags’ set but not used [-Wunused-but-set-variable]
    remote:        char buf[4096], server_conf_flags;
    remote:        ^
    remote:        ../lib/kerberosgss.c: At top level:
    remote:        ../lib/kerberosgss.c:1236:0: warning: ignoring #pragma clang diagnostic [-Wunknown-pragmas]
    remote:        #pragma clang diagnostic pop
    remote:        ^
    remote:        CC(target) Release/obj.target/kerberos/lib/base64.o
    remote:        CXX(target) Release/obj.target/kerberos/lib/kerberos_context.o
    remote:        SOLINK_MODULE(target) Release/obj.target/kerberos.node
    remote:        COPY Release/kerberos.node
    remote:        make: Leaving directory '/tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/kerberos/build'
    remote:
    remote:        > pre-commit@1.2.2 install /tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/pre-commit
    remote:        > node install.js
    remote:
    remote:
    remote:        > spawn-sync@1.0.15 postinstall /tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/spawn-sync
    remote:        > node postinstall
    remote:
    remote:
    remote:        > nodemon@1.17.5 postinstall /tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/nodemon
    remote:        > node bin/postinstall || exit 0
    remote:
    remote:        Love nodemon? You can now support the project via the open collective:
    remote:        > https://opencollective.com/nodemon/donate
    remote:
    remote:
    remote:        > parse-server@2.8.2 postinstall /tmp/build_bd81344b7effebfd0db2762cdf22abea/node_modules/parse-server
    remote:        > node -p 'require("./postinstall.js")()'
    remote:
    remote:
    remote:        1111111111
    remote:        1111111111111111
    remote:        1111111111111111111111
    remote:        11111111111111111111111111
    remote:        111111111111111       11111111
    remote:        1111111111111             111111
    remote:        1111111111111   111111111   111111
    remote:        111111111111   11111111111   111111
    remote:        1111111111111   11111111111   111111
    remote:        1111111111111   1111111111    111111
    remote:        1111111111111111111111111    1111111
    remote:        11111111                    11111111
    remote:        111111         1111111111111111111
    remote:        11111   11111  111111111111111111
    remote:        11111         11111111111111111
    remote:        111111     111111111111111111
    remote:        11111111111111111111111111
    remote:        1111111111111111111111
    remote:        111111111111111111
    remote:        11111111111
    remote:
    remote:
    remote:        Thanks for installing parse 🙏
    remote:        Please consider donating to our open collective
    remote:        to help us maintain this package.
    remote:
    remote:        👉 https://opencollective.com/parse-server
    remote:
    remote:        added 1423 packages from 1491 contributors and audited 8063 packages in 36.955s
    remote:        found 8 vulnerabilities (4 low, 4 moderate)
    remote:        run `npm audit fix` to fix them, or `npm audit` for details
    remote:
    remote: -----> Caching build
    remote:        Clearing previous node cache
    remote:        Skipping cache save (disabled by config)
    remote:
    remote: -----> Pruning devDependencies
    remote:        removed 220 packages and audited 6620 packages in 8.974s
    remote:        found 7 vulnerabilities (3 low, 4 moderate)
    remote:        run `npm audit fix` to fix them, or `npm audit` for details
    remote:
    remote: -----> Build succeeded!
    remote: -----> Discovering process types
    remote:        Procfile declares types     -> (none)
    remote:        Default types for buildpack -> web
    remote:
    remote: -----> Compressing...
    remote:        Done: 45.1M
    remote: -----> Launching...
    remote:        Released v143
    remote:        <my heroku app> deployed to Heroku
    remote:
    remote: Verifying deploy... done.
    To <my heroku remote repo>
     + 7905cfe...9915b97 v1.8.2 -> master (forced update)
    

    When the existing user tries to logging to facebook (a user that already has a FB auth data well defined), the Parse.FacebookUtils.logIn() utility will return a new user with random username (expressed in the log below: Q2NGibf9AGcl3W7s6Ud881TiX), instead of returning the existing one which has the same authData.facebook.id. Note that the "Account already exists for this email address." happens after I have received the undesired new user and assign it an email. This is what it logged during the FB login attempt:

    2018-07-17T06:29:25.742808+00:00 app[web.1]: �[36mverbose�[39m: REQUEST for [POST] /users: {
    2018-07-17T06:29:25.742822+00:00 app[web.1]:   "authData": {
    2018-07-17T06:29:25.742824+00:00 app[web.1]:     "facebook": {
    2018-07-17T06:29:25.742826+00:00 app[web.1]:       "id": "<fb_id>",
    2018-07-17T06:29:25.742831+00:00 app[web.1]:       "access_token": "<fb_token>",
    2018-07-17T06:29:25.742833+00:00 app[web.1]:       "expiration_date": "2026-08-17T17:35:02.659Z"
    2018-07-17T06:29:25.742835+00:00 app[web.1]:     }
    2018-07-17T06:29:25.742836+00:00 app[web.1]:   }
    2018-07-17T06:29:25.742838+00:00 app[web.1]: } method=POST, url=/users, host=<my_heroku_app>, connection=close, content-type=text/plain, origin=file://, if-none-match=W/"3b7-v0XpDL5Ht2PFXiJZ4QnlSoxPaOI", accept=*/*, user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79, accept-language=es-es, accept-encoding=br, gzip, deflate, x-request-id=81938098-5cdc-4be0-960e-0b9a2f486dbb, x-forwarded-for=<ip>, x-forwarded-proto=https, x-forwarded-port=443, via=1.1 vegur, connect-time=1, x-request-start=1531808965738, total-route-time=0, content-length=406, id=<fb_id>, access_token=<fb_token>, expiration_date=2026-08-17T17:35:02.659Z
    2018-07-17T06:29:25.837790+00:00 app[web.1]: �[36mverbose�[39m: RESPONSE from [POST] /users: {
    2018-07-17T06:29:25.837795+00:00 app[web.1]:   "status": 201,
    2018-07-17T06:29:25.837797+00:00 app[web.1]:   "response": {
    2018-07-17T06:29:25.837799+00:00 app[web.1]:     "objectId": "9Rrk8Xn8HJ",
    2018-07-17T06:29:25.837804+00:00 app[web.1]:     "createdAt": "2018-07-17T06:29:25.745Z",
    2018-07-17T06:29:25.837806+00:00 app[web.1]:     "username": "Q2NGibf9AGcl3W7s6Ud881TiX",
    2018-07-17T06:29:25.837808+00:00 app[web.1]:     "sessionToken": "r:<some_session_token>"
    2018-07-17T06:29:25.837809+00:00 app[web.1]:   },
    2018-07-17T06:29:25.837811+00:00 app[web.1]:   "location": "https://<my_heroku_app>/users/9Rrk8Xn8HJ"
    2018-07-17T06:29:25.837814+00:00 app[web.1]: } status=201, objectId=9Rrk8Xn8HJ, createdAt=2018-07-17T06:29:25.745Z, username=Q2NGibf9AGcl3W7s6Ud881TiX, sessionToken=r:<some_session_token>, location=https://<my_heroku_app>/users/9Rrk8Xn8HJ
    2018-07-17T06:29:25.839443+00:00 heroku[router]: at=info method=POST path="/users" host=<my_heroku_app> request_id=81938098-5cdc-4be0-960e-0b9a2f486dbb fwd="<ip>" dyno=web.1 connect=1ms service=99ms status=201 bytes=751 protocol=https
    2018-07-17T06:29:26.023821+00:00 app[web.1]: �[36mverbose�[39m: REQUEST for [PUT] /classes/_User/9Rrk8Xn8HJ: {
    2018-07-17T06:29:26.023839+00:00 app[web.1]:   "nombre": "<some_name>",
    2018-07-17T06:29:26.023841+00:00 app[web.1]:   "email": "<some_email>",
    2018-07-17T06:29:26.023843+00:00 app[web.1]:   "imageUrl": "<some_img_url>",
    2018-07-17T06:29:26.023845+00:00 app[web.1]:   "genero": "F"
    2018-07-17T06:29:26.023847+00:00 app[web.1]: } method=PUT, url=/classes/_User/9Rrk8Xn8HJ, host=<my_heroku_app>, connection=close, content-type=text/plain, origin=file://, accept=*/*, user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79, accept-language=es-es, accept-encoding=br, gzip, deflate, x-request-id=1301cc6b-158f-4a4c-82e1-0f1343c83ac2, x-forwarded-for=186.15.145.21, x-forwarded-proto=https, x-forwarded-port=443, via=1.1 vegur, connect-time=1, x-request-start=1531808966003, total-route-time=0, content-length=410, nombre=<some_name>, email=<some_email>, imageUrl=<some_img_url>, genero=F
    2018-07-17T06:29:26.052244+00:00 app[web.1]: �[31merror�[39m: Error generating response. ParseError {
    2018-07-17T06:29:26.052247+00:00 app[web.1]:   code: 203,
    2018-07-17T06:29:26.052252+00:00 app[web.1]:   message: 'Account already exists for this email address.' } code=203, message=Account already exists for this email address.
    2018-07-17T06:29:26.053969+00:00 app[web.1]: �[31merror�[39m: Account already exists for this email address. code=203, message=Account already exists for this email address.
    2018-07-17T06:29:26.054682+00:00 heroku[router]: at=info method=POST path="/classes/_User/9Rrk8Xn8HJ" host=<my_heroku_app> request_id=1301cc6b-158f-4a4c-82e1-0f1343c83ac2 fwd="<ip>" dyno=web.1 connect=1ms service=49ms status=400 bytes=602 protocol=https
    

    I cannot share my environment, but I can confirm that the issue can be reproduced consistently with Parse v2.8.2, just let me know how I can help. Right now I've deployed 2.7.4 to avoid the issue in Production.

    Some notes about the environment:

    • This deployment is running MongoDB version 3.0.15 (MMAPv1). This is a standard heroku production deployment which has been working for about year and a half with no intervention other than Parse Server updates.

    • rs.conf() raw data output:

    {
      "_id": "<some_id>",
      "version": 3,
      "members": [
        {
          "_id": 0,
          "host": "<some_host>",
          "arbiterOnly": false,
          "buildIndexes": true,
          "hidden": false,
          "priority": 1,
          "tags": {},
          "slaveDelay": 0,
          "votes": 1
        },
        {
          "_id": 1,
          "host": "<some_host>",
          "arbiterOnly": false,
          "buildIndexes": true,
          "hidden": false,
          "priority": 1,
          "tags": {},
          "slaveDelay": 0,
          "votes": 1
        },
        {
          "_id": 10,
          "host": "<some_host>",
          "arbiterOnly": true,
          "buildIndexes": true,
          "hidden": false,
          "priority": 1,
          "tags": {},
          "slaveDelay": 0,
          "votes": 1
        }
      ],
      "settings": {
        "chainingAllowed": true,
        "heartbeatTimeoutSecs": 10,
        "getLastErrorModes": {},
        "getLastErrorDefaults": {
          "w": 1,
          "wtimeout": 0
        }
      }
    }
    
    • rs.status() raw output:
    {
      "set": "rs-<some_id>",
      "date": {
        "$date": "2018-07-17T06:49:04.723Z"
      },
      "myState": 1,
      "members": [
        {
          "_id": 0,
          "name": "<some_name>",
          "health": 1,
          "state": 1,
          "stateStr": "PRIMARY",
          "uptime": 75758,
          "optime": {
            "$ts": 1531809010,
            "$inc": 1
          },
          "optimeDate": {
            "$date": "2018-07-17T06:30:10.000Z"
          },
          "electionTime": {
            "$ts": 1531734394,
            "$inc": 1
          },
          "electionDate": {
            "$date": "2018-07-16T09:46:34.000Z"
          },
          "configVersion": 3,
          "self": true,
          "serverId": "<some_server_id>"
        },
        {
          "_id": 1,
          "name": "<some_name>",
          "health": 1,
          "state": 2,
          "stateStr": "SECONDARY",
          "uptime": 75757,
          "optime": {
            "$ts": 1531809010,
            "$inc": 1
          },
          "optimeDate": {
            "$date": "2018-07-17T06:30:10.000Z"
          },
          "lastHeartbeat": {
            "$date": "2018-07-17T06:49:03.133Z"
          },
          "lastHeartbeatRecv": {
            "$date": "2018-07-17T06:49:03.448Z"
          },
          "pingMs": 0,
          "syncingTo": "<some_name>",
          "configVersion": 3,
          "serverId": "<some_name>"
        },
        {
          "_id": 10,
          "name": "<some_name>,
          "health": 1,
          "state": 7,
          "stateStr": "ARBITER",
          "uptime": 75757,
          "lastHeartbeat": {
            "$date": "2018-07-17T06:49:04.078Z"
          },
          "lastHeartbeatRecv": {
            "$date": "2018-07-17T06:49:03.854Z"
          },
          "pingMs": 16,
          "configVersion": 3,
          "serverId": "<some_name>"
        }
      ],
      "ok": 1
    }
    

    The _User collection has 1 index:

    db['system.indexes'].find() Raw Output
    {
      "v": 1,
      "key": {
        "_id": 1
      },
      "name": "_id_",
      "ns": "<some_name>._User"
    }
    
  5. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    That’s : odd that only one index on the_ User table is there (on id) as on startup, the server should create more indexes on the DB. Is it possible for you pull out the first logs after the server starts?

  6. jose-carballo commented on Jul 17, 2018

    @jose-carballo
    Author

    Here are the logs from the server when deploying/starting.

    [api]: Build started by user <my_user>
    2018-07-17T07:19:59.979141+00:00 app[api]: Release v145 created by user <my_user>
    2018-07-17T07:19:59.979141+00:00 app[api]: Deploy <commit> by user <my_user>
    2018-07-17T07:20:00.467469+00:00 heroku[web.1]: Restarting
    2018-07-17T07:20:00.468014+00:00 heroku[web.1]: State changed from up to starting
    2018-07-17T07:20:01.498843+00:00 heroku[web.1]: Stopping all processes with SIGTERM
    2018-07-17T07:20:01.692041+00:00 heroku[web.1]: Process exited with status 143
    2018-07-17T07:20:00.000000+00:00 app[api]: Build succeeded
    2018-07-17T07:20:06.101319+00:00 heroku[web.1]: Starting process with command `npm start`
    2018-07-17T07:20:08.662033+00:00 app[web.1]: [heroku-exec] Starting
    2018-07-17T07:20:08.983022+00:00 app[web.1]: 
    2018-07-17T07:20:08.983125+00:00 app[web.1]: > <parse-server>@1.8.2 start /app
    2018-07-17T07:20:08.983136+00:00 app[web.1]: > node index.js
    2018-07-17T07:20:08.983257+00:00 app[web.1]: 
    2018-07-17T07:20:10.872877+00:00 app[web.1]: �[36mverbose�[39m: Support key pairs Map {}
    2018-07-17T07:20:10.879253+00:00 app[web.1]: (node:49) ExperimentalWarning: The http2 module is an experimental API.
    2018-07-17T07:20:10.881139+00:00 app[web.1]: parse-server-example running on port 37266.
    2018-07-17T07:20:11.088284+00:00 app[web.1]: �[33mwarn�[39m: Unable to ensure uniqueness for usernames:  code=137, message=Tried to ensure field uniqueness for a class that already has duplicates.
    2018-07-17T07:20:11.092748+00:00 app[web.1]: (node:49) UnhandledPromiseRejectionWarning: [object Object]
    2018-07-17T07:20:11.092821+00:00 app[web.1]: (node:49) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
    2018-07-17T07:20:11.092881+00:00 app[web.1]: (node:49) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    2018-07-17T07:20:11.096851+00:00 app[web.1]: �[33mwarn�[39m: Unable to ensure uniqueness for user email addresses:  code=137, message=Tried to ensure field uniqueness for a class that already has duplicates.
    2018-07-17T07:20:11.230664+00:00 heroku[web.1]: State changed from starting to up
    2018-07-17T07:20:11.929446+00:00 heroku[router]: at=info method=GET path="/health" host=<my_heroku_app> request_id=b75307c5-d36b-41bd-8bb0-2c6fdf4dc811 fwd="<ip>" dyno=web.1 connect=1ms service=9ms status=200 bytes=538 protocol=https```
    
  7. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    Yeah, so that means there’s already duplicated entries with the same username in the _User table.

    You may want to remove those duplicates and restart the server to ensure all indexes are properly created on startup. While this may not exactly be the root cause, this will help

  8. jose-carballo commented on Jul 17, 2018

    @jose-carballo
    Author

    I will look up for duplicate usernames. According to our logic there shouldn't be any, but well if it happened it may be from the earlier development times.

    Would the "email" duplicate entries also be a problem? This may be related to "anonymous" users (FB log in's without email permissions), and in such case I am not able to fix that.

  9. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    Yes, emails should be unique too, and perhaps the initialization will fail at a later point. Do you have the same log when starting a server against your production DB, with an earlier version of the server?

  10. jose-carballo commented on Jul 17, 2018

    @jose-carballo
    Author

    Server log deploying version 2.7.4:

    2018-07-17T07:59:04.000000+00:00 app[api]: Build started by user <my_user>
    2018-07-17T08:00:15.303994+00:00 app[api]: Deploy d2d16e6f by user <my_user>
    2018-07-17T08:00:15.303994+00:00 app[api]: Release v150 created by user <my_user>
    2018-07-17T08:00:15.000000+00:00 app[api]: Build succeeded
    2018-07-17T08:00:17.162696+00:00 heroku[web.1]: Restarting
    2018-07-17T08:00:17.163201+00:00 heroku[web.1]: State changed from up to starting
    2018-07-17T08:00:18.394267+00:00 heroku[web.1]: Stopping all processes with SIGTERM
    2018-07-17T08:00:18.496795+00:00 heroku[web.1]: Process exited with status 143
    2018-07-17T08:00:26.253317+00:00 heroku[web.1]: Starting process with command `npm start`
    2018-07-17T08:00:29.814129+00:00 app[web.1]: [heroku-exec] Starting
    2018-07-17T08:00:30.468972+00:00 app[web.1]: 
    2018-07-17T08:00:30.469256+00:00 app[web.1]: > <parse_server>@1.8.3 start /app
    2018-07-17T08:00:30.469259+00:00 app[web.1]: > node index.js
    2018-07-17T08:00:30.469261+00:00 app[web.1]: 
    2018-07-17T08:00:33.855064+00:00 app[web.1]: �[36mverbose�[39m: Support key pairs Map {}
    2018-07-17T08:00:33.885778+00:00 app[web.1]: parse-server-example running on port 38682.
    2018-07-17T08:00:33.886590+00:00 app[web.1]: �[32minfo�[39m: Parse LiveQuery Server starts running
    2018-07-17T08:00:34.275030+00:00 heroku[web.1]: State changed from starting to up
    2018-07-17T08:00:34.598629+00:00 app[web.1]: �[33mwarn�[39m: Unable to ensure uniqueness for usernames:  code=137, message=Tried to ensure field uniqueness for a class that already has duplicates.
    2018-07-17T08:00:34.601176+00:00 app[web.1]: (node:49) UnhandledPromiseRejectionWarning: [object Object]
    2018-07-17T08:00:34.601351+00:00 app[web.1]: (node:49) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
    2018-07-17T08:00:34.601427+00:00 app[web.1]: (node:49) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    2018-07-17T08:00:34.601998+00:00 app[web.1]: �[33mwarn�[39m: Unable to ensure uniqueness for user email addresses:  code=137, message=Tried to ensure field uniqueness for a class that already has duplicates.
    2018-07-17T08:00:35.158012+00:00 heroku[router]: at=info method=GET path="/health" host=<my_heroku_app> request_id=613bd60b-84b4-4eb8-b632-4db53e2e4e7d fwd="<ip>" dyno=web.1 connect=1ms service=17ms status=200 bytes=538 protocol=https
    

    When you say that emails should be unique, does it mean that they cannot be left blank? I really don't see an easy way to change that, as for quite a long time we've supported users using FB login and declining email permissions - actually, many people decline this permission. Even if we change the login flow to request an email address in such a case, we already have a lot of users in the database without email. If it should be, probably is better to express that clearly in documentation, or possibly enforce it somehow.

  11. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    They can be left blank. Usernames can’t/ should not.

    As I can see in this log, this issue is there as well with 2.7.4, so that’s not it, fixing it should still be done. I’ll check why the original Facebook id can’t be found. Perhaps the unique sparse index can’t be built either on those.

  12. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    @tai-x Another question, can you pull from the DB the raw document for a user that fails to login and another that succeeds in logging in?

  13. CIO-DOTNET commented on Jul 17, 2018

    @CIO-DOTNET

    Hi @tai-x, I have noticed your environment is completely different from the one described in issue #4407 (where you left your initial comment). The issue seems to be the related, perhaps parse-server should not look for duplicate email addresses if the email field provided is null or empty? (since the email field is not required?)

    To answer your initial question left in issue #4407, the way I solved my issue was by dropping the "User" Class through the parse dashboard, then creating a new "User" Class by selecting the "User" Class option in the dialog window that appears. Have in mind you would of course need to backup any data and structural changes made to your "User" Class before dropping it.

  14. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    Dropping the user table will destroy the data...

    d not look for duplicate email addresses if the email field provided is null or empty

    This is mongodb index creation, the email index is sparse so null /undefined is indeed allowed.

  15. cbaker6 commented on Jul 17, 2018

    @cbaker6
    Contributor

    Here is the log from Parse-server 2.7.4, this one works correctly by connecting to the old user who has logged in via Facebook using previous versions of Parse:

    verbose: REQUEST for [POST] /parse/users: {
      "authData": {
        "facebook": {
          "id": "8379****",
          "access_token": "EAAKn2SZA5kRkBALZAoSglQ2VNrDwhbJZAi9Ehpw4hXdz0YZAsHjASZC3W8PpJ6eoMqSCrz0k8o9OrogdDrbhCYzBTCgiBgMMeAhiO0Hhz5wkGt62t9Dmgj836Km7kiEZATkKub4Q3ZBxxQeQlmKwZB8gfN3rAPNNToTwfZAZA5DoY6TIym32XUBFH1ZA1q3lKzOsZC2d0dGI8yqZBjfZArFASSw*******",
          "expiration_date": "2018-09-15T14:55:14.785Z"
        }
      }
    } method=POST, url=/parse/users, host=n*****edu:1337, content-type=application/json; charset=utf-8, x-parse-revocable-session=1, accept=*/*, x-parse-application-id=SBC0DswFA7RdbIQJ8Z6JWkchaZsRbNfvIgg8C2W2, x-parse-installation-id=27b6dfdb-9878-488e-be2e-8849fbae1074, x-parse-os-version=11.4 (15F79), accept-language=en-us, accept-encoding=br, gzip, deflate, x-parse-client-version=i1.17.1, content-length=347, user-agent=AlleyOop/3 CFNetwork/901.1 Darwin/17.6.0, connection=keep-alive, x-parse-app-build-version=3, x-parse-app-display-version=2.04, id=8379****, access_token=EAAKn2SZA5kRkBALZAoSglQ2VNrDwhbJZAi9Ehpw4hXdz0YZAsHjASZC3W8PpJ6eoMqSCrz0k8o9OrogdDrbhCYzBTCgiBgMMeAhiO0Hhz5wkGt62t9Dmgj836Km7kiEZATkKub4Q3ZBxxQeQlmKwZB8gfN3rAPNNToTwfZAZA5DoY6TIym32XUBFH1ZA1q3lKzOsZC2d0dGI8yqZBjfZArFASSw*******, expiration_date=2018-09-15T14:55:14.785Z
    verbose: RESPONSE from [POST] /parse/users: {
      "response": {
        "objectId": "YrCVyDcejf",
        "createdAt": "2015-01-02T19:09:59.788Z",
        "updatedAt": "2018-07-17T18:53:50.175Z",
        "email": "c***@ufl.edu",
        "username": "coreyiphone6",
        "usernameLiteral": "CoreyIphone6",
        "displayName": "Corey E Baker",
        "authData": {
          "twitter": {
            "auth_token": "***",
            "id": "***",
            "consumer_key": "** kvKGRA5D59dT*****",
            "auth_token_secret": "*****",
            "consumer_secret": "*****",
            "screen_name": "iKilledChivalry"
          },
          "facebook": {
            "id": "8379****",
            "access_token": "EAAKn2SZA5kRkBALZAoSglQ2VNrDwhbJZAi9Ehpw4hXdz0YZAsHjASZC3W8PpJ6eoMqSCrz0k8o9OrogdDrbhCYzBTCgiBgMMeAhiO0Hhz5wkGt62t9Dmgj836Km7kiEZATkKub4Q3ZBxxQeQlmKwZB8gfN3rAPNNToTwfZAZA5DoY6TIym32XUBFH1ZA1q3lKzOsZC2d0dGI8yqZBjfZArFASSw*******",
            "expiration_date": "2018-09-15T14:55:14.785Z"
          }
        },
        "twitterId": "***",
        "twitterFriends": [
          ""
        ],
        "_failed_login_count": 5,
        "_account_lockout_expires_at": "2017-02-08T23:30:19.899Z",
        "facebookId": "8379****",
        "facebookFriends": [
          
        ],
        "sessionToken": "r:bbb57dd2954da772a8b9ff09b37f419b"
      },
      "location": "https://n*****edu:1337/parse/users/YrCVyDcejf"
    } objectId=YrCVyDcejf, createdAt=2015-01-02T19:09:59.788Z, updatedAt=2018-07-17T18:53:50.175Z, email=c***@ufl.edu, username=coreyiphone6, usernameLiteral=CoreyIphone6, displayName=Corey E Baker, auth_token=***, id=***, consumer_key=** kvKGRA5D59dT*****, auth_token_secret=*****, consumer_secret=*****, screen_name=iKilledChivalry, id=8379****, access_token=EAAKn2SZA5kRkBALZAoSglQ2VNrDwhbJZAi9Ehpw4hXdz0YZAsHjASZC3W8PpJ6eoMqSCrz0k8o9OrogdDrbhCYzBTCgiBgMMeAhiO0Hhz5wkGt62t9Dmgj836Km7kiEZATkKub4Q3ZBxxQeQlmKwZB8gfN3rAPNNToTwfZAZA5DoY6TIym32XUBFH1ZA1q3lKzOsZC2d0dGI8yqZBjfZArFASSw*******, expiration_date=2018-09-15T14:55:14.785Z, twitterId=***, twitterFriends=[2207036778], _failed_login_count=5, _account_lockout_expires_at=Wed Feb 08 2017 18:30:19 GMT-0500 (EST), facebookId=8379****, facebookFriends=[], sessionToken=r:bbb57dd2954da772a8b9ff09b37f419b, location=https://n*****edu:1337/parse/users/YrCVyDcejf
    
    

    Log from 2.8.2, which creates a new account instead of linking to the old user:

    verbose: REQUEST for [POST] /parse/users: {
      "authData": {
        "facebook": {
          "id": "8379****",
          "access_token": "EAAKn2SZA5kRkBADpd9Kwd0JeXWkLVeswsZC5fk5DdST3DfnoOP6Xxiqk1hiTNSXZAhZCcDVxCEeQZCYO6EZCjktZAuxcfkXpDnZB8MqZBxDat7ZA1CqBm3FY1GWUY6PnXP8QDr0bVMCpjf4vZAftOI2I7iOZB9sTsvZBRmQIC3Lgi9Bm6VurrFTeoFQbmzCArEPAZBkXBb7Xq81Smz5aC9XcN0YFh41NZBqtR6**************",
          "expiration_date": "2018-09-15T14:55:15.064Z"
        }
      }
    } method=POST, url=/parse/users, host=n*****edu:1337, content-type=application/json; charset=utf-8, x-parse-revocable-session=1, accept=*/*, x-parse-application-id=SBC0DswFA7RdbIQJ8Z6JWkchaZsRbNfvIgg8C2W2, x-parse-installation-id=b5ff282d-a2bc-4566-ac03-31730d80798f, x-parse-os-version=11.4 (15F79), accept-language=en-us, accept-encoding=br, gzip, deflate, x-parse-client-version=i1.17.1, content-length=347, user-agent=AlleyOop/3 CFNetwork/901.1 Darwin/17.6.0, connection=keep-alive, x-parse-app-build-version=3, x-parse-app-display-version=2.04, id=8379****, access_token=EAAKn2SZA5kRkBADpd9Kwd0JeXWkLVeswsZC5fk5DdST3DfnoOP6Xxiqk1hiTNSXZAhZCcDVxCEeQZCYO6EZCjktZAuxcfkXpDnZB8MqZBxDat7ZA1CqBm3FY1GWUY6PnXP8QDr0bVMCpjf4vZAftOI2I7iOZB9sTsvZBRmQIC3Lgi9Bm6VurrFTeoFQbmzCArEPAZBkXBb7Xq81Smz5aC9XcN0YFh41NZBqtR6**************, expiration_date=2018-09-15T14:55:15.064Z
    verbose: RESPONSE from [POST] /parse/users: {
      "status": 201,
      "response": {
        "objectId": "XWPlckYLhs",
        "createdAt": "2018-07-17T18:48:41.263Z",
        "username": "81b2frJTm5tl73fdXNmDDjX8q",
        "sessionToken": "r:9320edf4dd9f7b996bcaff9854b83dad"
      },
      "location": "https://n*****edu:1337/parse/users/XWPlckYLhs"
    } status=201, objectId=XWPlckYLhs, createdAt=2018-07-17T18:48:41.263Z, username=81b2frJTm5tl73fdXNmDDjX8q, sessionToken=r:9320edf4dd9f7b996bcaff9854b83dad, location=https://n*****edu:1337/parse/users/XWPlckYLhs
    verbose: REQUEST for [PUT] /parse/classes/_User/XWPlckYLhs: {
      "email": "c***@ufl.edu",
      "username": "81b2frjtm5tl73fdxnmddjx8q",
      "usernameLiteral": "81b2frJTm5tl73fdXNmDDjX8q",
      "displayName": "Corey E Baker",
      "authData": {
        "facebook": {
          "id": "8379****",
          "access_token": "EAAKn2SZA5kRkBADpd9Kwd0JeXWkLVeswsZC5fk5DdST3DfnoOP6Xxiqk1hiTNSXZAhZCcDVxCEeQZCYO6EZCjktZAuxcfkXpDnZB8MqZBxDat7ZA1CqBm3FY1GWUY6PnXP8QDr0bVMCpjf4vZAftOI2I7iOZB9sTsvZBRmQIC3Lgi9Bm6VurrFTeoFQbmzCArEPAZBkXBb7Xq81Smz5aC9XcN0YFh41NZBqtR6**************",
          "expiration_date": "2018-09-15T14:55:15.064Z"
        }
      },
      "facebookId": "8379****"
    } method=PUT, url=/parse/classes/_User/XWPlckYLhs, host=n*****edu:1337, content-type=application/json; charset=utf-8, accept=*/*, x-parse-session-token=r:9320edf4dd9f7b996bcaff9854b83dad, x-parse-application-id=SBC0DswFA7RdbIQJ8Z6JWkchaZsRbNfvIgg8C2W2, x-parse-installation-id=b5ff282d-a2bc-4566-ac03-31730d80798f, x-parse-os-version=11.4 (15F79), accept-language=en-us, accept-encoding=br, gzip, deflate, x-parse-client-version=i1.17.1, content-length=516, user-agent=AlleyOop/3 CFNetwork/901.1 Darwin/17.6.0, connection=keep-alive, x-parse-app-build-version=3, x-parse-app-display-version=2.04, email=c***@ufl.edu, username=81b2frjtm5tl73fdxnmddjx8q, usernameLiteral=81b2frJTm5tl73fdXNmDDjX8q, displayName=Corey E Baker, id=8379****, access_token=EAAKn2SZA5kRkBADpd9Kwd0JeXWkLVeswsZC5fk5DdST3DfnoOP6Xxiqk1hiTNSXZAhZCcDVxCEeQZCYO6EZCjktZAuxcfkXpDnZB8MqZBxDat7ZA1CqBm3FY1GWUY6PnXP8QDr0bVMCpjf4vZAftOI2I7iOZB9sTsvZBRmQIC3Lgi9Bm6VurrFTeoFQbmzCArEPAZBkXBb7Xq81Smz5aC9XcN0YFh41NZBqtR6**************, expiration_date=2018-09-15T14:55:15.064Z, facebookId=8379****
    verbose: RESPONSE from [PUT] /parse/classes/_User/XWPlckYLhs: {
      "response": {
        "updatedAt": "2018-07-17T18:50:57.761Z"
      }
    } updatedAt=2018-07-17T18:50:57.761Z
    
    

    Note: as stated by @tai-x, on 2.8.2, if I login via Facebook and let it create a new account. Sign-out, then sign-in again, it logs back into the new account it created.

    In addition, I don't allow duplicate emails or duplicate usernames in my mongodb. I also don't have any blank email addresses.

    Update: here is the log after "install" and "start" just incase it's needed. I don't get any uniqueness warnings on start-up:

    alleyoopsocial-parse-server@2.0.0 /Users/netreconlab/Documents/Server/alleyoop_parse_server
    └─┬ parse-server@2.7.4 
      ├─┬ @parse/push-adapter@2.0.2 
      │ ├─┬ apn@2.2.0 
      │ │ └── http2@3.3.6 
      │ └─┬ node-gcm@0.14.10 
      │   ├── lodash@3.10.1 
      │   └─┬ request@2.81.0 
      │     ├── aws-sign2@0.6.0 
      │     ├── form-data@2.1.4 
      │     ├─┬ har-validator@4.2.1 
      │     │ ├─┬ ajv@4.11.8 
      │     │ │ └─┬ json-stable-stringify@1.0.1 
      │     │ │   └── jsonify@0.0.0 
      │     │ └── har-schema@1.0.5 
      │     ├─┬ hawk@3.1.3 
      │     │ ├── boom@2.10.1 
      │     │ ├── cryptiles@2.0.5 
      │     │ ├── hoek@2.16.3 
      │     │ └── sntp@1.0.9 
      │     ├─┬ http-signature@1.1.1 
      │     │ └── assert-plus@0.2.0 
      │     ├── performance-now@0.2.0 
      │     └── qs@6.4.0 
      ├─┬ @parse/simple-mailgun-adapter@1.0.1 
      │ └─┬ mailgun-js@0.13.1 
      │   ├── async@2.5.0 
      │   ├── form-data@2.2.0 
      │   └─┬ proxy-agent@2.1.0 
      │     └── lru-cache@2.6.5 
      ├─┬ bcrypt@1.0.3 
      │ ├── nan@2.6.2 
      │ └─┬ node-pre-gyp@0.6.36 
      │   ├─┬ rc@1.2.8 
      │   │ └── deep-extend@0.6.0 
      │   ├─┬ tar@2.2.1 
      │   │ ├── block-stream@0.0.9 
      │   │ └─┬ fstream@1.0.11 
      │   │   └── graceful-fs@4.1.11 
      │   └─┬ tar-pack@3.4.1 
      │     ├── fstream-ignore@1.0.5 
      │     └── uid-number@0.0.6 
      ├─┬ body-parser@1.18.2 
      │ └── qs@6.5.1 
      ├── commander@2.15.0 
      ├── deepcopy@0.6.3 
      ├── mime@2.2.0 
      ├─┬ mongodb@3.0.4 
      │ └── mongodb-core@3.0.4 
      ├─┬ pg-promise@8.2.1 
      │ └─┬ pg@7.4.1
      │   └─┬ pg-types@1.12.1
      │     └── postgres-interval@1.1.2 
      ├─┬ request@2.83.0 
      │ ├── form-data@2.3.2 
      │ └─┬ hawk@6.0.2 
      │   ├── boom@4.3.1 
      │   ├── cryptiles@3.1.2 
      │   ├── hoek@4.2.1 
      │   └── sntp@2.1.0 
      ├── uws@9.148.0 
      └── ws@5.0.0 
    
    netrecon:alleyoop_parse_server netreconlab$ npm start
    
    > alleyoopsocial-parse-server@2.0.0 start /Users/netreconlab/Documents/Server/alleyoop_parse_server
    > node index.js
    
    verbose: Support key pairs Map {}
    alleyoop-parse-server running on port 1337.
    verbose: REQUEST for [GET] /parse/classes/_Installation: {
      "where": {},
      "limit": 0,
      "count": 1
    }
    
  16. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    @cbaker6 are you able to share here the user object, right from mongodb, without all the transformations applied to it from parse server?

  17. jose-carballo commented on Jul 17, 2018

    @jose-carballo
    Author

    @flovilmart

    Here is the user document that existed previously (removing some of the non-important columns that we added to our User class).

    {
        "_id": "DN5ix4I0m9",
        "updatedAt": "2016-07-10T02:50:10.580Z",
        "createdAt": "2016-04-25T06:26:51.313Z",
        "name": "<some_name>",
        "email": "<some_email>",
        "username": "<some_username>",
        "_hashed_password": "<some_password>",
        "_auth_data_facebook": {
            "id": "70754445267000855",
            "access_token": "<some_access_token>",
            "expiration_date": "2028-03-18T10:28:17.124Z"
        },
        "sessionToken": "<some_session_token>",
        "_updated_at": {
            "$date": "2018-06-25T01:16:43.254Z"
        }
    }
    

    Here is the malformed "new" user document that shouldn't have been created, untouched. It has some fields in the document that are not present in the old user above (_wperm, _rperm, _acl), as well as missing some apparently default ones (_hashed_password, sessionToken) and the rest of custom columns we added to the User class.

    {
        "_id": "kVG2JtpyhE",
        "username": "syhCbAjJoTq7jAuPRn9HMmBAn",
        "_wperm": [
            "kVG2JtpyhE"
        ],
        "_rperm": [
            "*",
            "kVG2JtpyhE"
        ],
        "_auth_data_facebook": {
            "id": "70754445267000855",
            "access_token": "<some_access_token>",
            "expiration_date": "2028-03-18T10:28:16.633Z"
        },
        "_acl": {
            "kVG2JtpyhE": {
                "w": true,
                "r": true
            },
            "*": {
                "r": true
            }
        },
        "_created_at": {
            "$date": "2018-07-17T19:55:30.713Z"
        },
        "_updated_at": {
            "$date": "2018-07-17T19:55:30.713Z"
        }
    }
    

    Regards,

  18. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    @tai-x this is exactly the conclusion I was reaching now. In recent versions the user object follow ACL’s and it is possible that legacy users without any ACL are getting locked out.

    The new feature was introduced so a developer can close a user’s account without deleting it by marking the ACL completely private.

    There are 2 ways to fix it for 2.8.2:

    1. Add read/write ACL to the user himself so he can access and therefore login.
    2. Fix on the server for this case that was overlooked.

    For now you can stick to 2.7.4 or update your old user’s ACL’s so they can read themselves.

    I’ll be working on a patch for this

  19. jose-carballo commented on Jul 17, 2018

    @jose-carballo
    Author

    Thanks for your help @flovilmart. Let me know when you have a patch to test it or if you need more info.

  20. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    Thanks for providing the data, i’ll Keep you posted here. I need to think about the possible side effects. As this issue also shows that a locked out account would let the user create a new account anyway.

  21. flovilmart commented on Jul 17, 2018

    @flovilmart
    Contributor

    @tai-x you can try the branch fix/issue-4897 it should fix the issue. If you're using npm >= 6, you can use the branch directly by setting the parse-server dependency to https://github.com/parse-community/parse-server#fix/issue-4897

  22. jose-carballo commented on Jul 17, 2018

    @jose-carballo
    Author

    Fixed. Nice!

  23. flovilmart commented on Jul 18, 2018

    @flovilmart
    Contributor

    Glad to hear!

  24. cbaker6 commented on Jul 18, 2018

    @cbaker6
    Contributor

    @flovilmart my data looked like @tai-x's, missing the ACL in mongodb for legacy users, but showing all ACLs in Parse Dashboard:

    User created with legacy version:

    {
    	"_id" : "OldjvvMVaG",
    	"_created_at" : ISODate("2015-07-13T18:05:21.502Z"),
    	"_updated_at" : ISODate("2018-06-27T17:35:42.215Z"),
    	"_perishable_token" : "***",
    	"_auth_data_facebook" : {
    		"access_token" : "***",
    		"expiration_date" : ISODate("2015-09-11T18:05:19.475Z"),
    		"id" : "1010***"
    	},
    	"username" : "jerbear323",
    	"_session_token" : "LzYBc7QEElr85m3kGJFvHu3AH",
    	"_hashed_password" : "",
    	"facebookFriends" : [
    		***
    	],
    	"email" : "jam323@ufl.edu",
    	"usernameLiteral" : "JerBear323",
    	"displayName" : "Jeremy",
    	"facebookId" : "1010***"
    }
    
    

    User created with newer version of Parse server:

    {
    	"_id" : "5aDx6moNEU",
    	"username" : "bhaskark2",
    	"usernameLiteral" : "bhaskark2",
    	"displayName" : "bhaskark2",
    	"email" : "b**@gmail.com",
    	"_hashed_password" : "",
    	"_wperm" : [
    		"5aDx6moNEU"
    	],
    	"_rperm" : [
    		"*",
    		"5aDx6moNEU"
    	],
    	"_acl" : {
    		"5aDx6moNEU" : {
    			"w" : true,
    			"r" : true
    		},
    		"*" : {
    			"r" : true
    		}
    	},
    	"_created_at" : ISODate("2017-03-22T17:16:00.908Z"),
    	"_updated_at" : ISODate("2017-03-22T17:16:00.908Z")
    }
    

    @flovilmart I wasn't able to test fix-issue-4897, but I did write a CloudCode job that fixed the ACL's for all users as you suggested. After running, ParseServer 2.82 properly logged in Facebook and Twitter users using FacebookUtils and TwitterUtils. The job is below if anyone needs it:

    Parse.Cloud.job("fixLegacyUserPermissions", function(request, status) {
                    
        // the params passed through the start request
        var params = request.params;
        // Headers from the request that triggered the job
        var headers = request.headers;
                    
        // get the parse-server logger
        var log = request.log;
                    
        // Update the Job status message
        status.message("Starting to fixLegacyUserPermissions for all activities in DB");
                    
        var query = new Parse.Query('_User');
        query.notEqualTo('username', null);
    
        query.find({useMasterKey: true,
          success: function(results) {
                 
            if (results == null){
                status.error("Warning no results were found in query");
            }else{
               
              var counter = 0;
              var counterForTotalObjects = 0;
              var fixingActivity = false;
               
              console.log("Found "+ results.length.toString() + " items that need to be fixed")
               
              for (var i = 0; i < results.length; i++) {
                  var object = results[i];
    
                  var newACL = new Parse.ACL();
                  newACL.setWriteAccess(object, true);
                  newACL.setReadAccess(object, true);
                  newACL.setPublicReadAccess(true);
                  object.setACL(newACL);
                            
                  object.save(null, {useMasterKey: true,
                    success: function(){
                        counter = counter + 1;
                        status.message("Updated permissions for " + counter.toString() + " Users " + object.id);
                        counterForTotalObjects = counterForTotalObjects + 1;
                        if(counterForTotalObjects == (results.length)){
                            status.success("Fixed " + counter + " items");
                        }
                    }, error: function(returnedError) {
                        status.error("Error in fixLegacyUserPermissions: " + returnedError);
                        counterForTotalObjects = counterForTotalObjects + 1;
                        if(counterForTotalObjects == (results.length)){
                            status.success();
                        }
                    }
                  });
    
               }
               
            }
    
            if (!fixingActivity){
              status.message("No users needed to be fixed");
                status.success();
            }
          },
          error: function(error){
              status.error('Error saving User.'+error.toString());
          }
                              
      });
    });
    
  25. flovilmart commented on Jul 18, 2018

    @flovilmart
    Contributor

    Awesome! If that’s resolved for you then that’s awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions