Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"_synchronizeAllAuthData is not a function" when running in production after 2.9.0 update #992

Closed
pocketcolin opened this issue Nov 11, 2019 · 23 comments

Comments

@pocketcolin
Copy link
Contributor

Issue Description

After updating to Parse 2.9.0, we started noticing a new error when running Parse.User.current(), but only when running in production. Downgrading to 2.8.0 fixes the issue. The error thrown is:

TypeError: n._synchronizeAllAuthData is not a function
  at Object.currentUser (ParseUser.js:1266)

Steps to reproduce

  1. Run a web app using the Parse SDK v2.9.0 in production (NODE_ENV=production)
  2. Successfully authenticate as user using Parse.User.logIn method
  3. Reload the web page and trigger Parse.User.current()

Expected Results

Should return a Parse.User object with the current user.

Actual Outcome

Throws error: "_synchronizeAllAuthData is not a function"

Environment Setup

  • Server

    • parse-server version (Be specific! Don't say 'latest'.) : 3.9.0
    • Operating System: Mac OS 10.14.5
    • Hardware: MacBook Pro 2019
    • Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): Localhost
  • JS SDK

    • JS SDK version: 2.9.0
    • Application? (Browser, Node, React-Native, etc): VueJS App

Logs/Trace

ParseUser.js:1266 Uncaught (in promise) TypeError: n._synchronizeAllAuthData is not a function
    at Object.currentUser (ParseUser.js:1266)
    at Function.value (ParseUser.js:781)
    at actions.ts:81
    at l (runtime.js:45)
    at Generator._invoke (runtime.js:271)
    at Generator.M.forEach.e.<computed> [as next] (runtime.js:97)
    at qe (app.c0811891.js:1)
    at a (app.c0811891.js:1)
    at app.c0811891.js:1
    at new Promise (<anonymous>)
@jamesmogg
Copy link

I had this issue today, it only occurred once i deployed the code to a docker container, running locally on the React webpack dev it didn't happen.

Specs of the failed system were

Parse-server 2.9.0
Express 4.17.1
node v12.13.0
Alpine Linux
React 16.11.0

Error thrown was
"_synchronizeAllAuthData is not a function"

With a fresh browser you could call the login and make queries, on refresh it would throw the error until you clear the localStorage.

@pocketcolin
Copy link
Contributor Author

pocketcolin commented Nov 11, 2019 via email

@grosscorporation
Copy link

grosscorporation commented Nov 12, 2019

Getting the same error in production:

TypeError: t._synchronizeAuthData is not a function at

Uncaught (in promise) Error: XMLHttpRequest failed: {}

@stage88
Copy link

stage88 commented Nov 14, 2019

I am getting something similar, not sure if related. This happens in a production build of an iOS app, regardless if deployed on device or simulator.

XMLHttpRequest failed: {"line":519,"column":4087,"sourceURL": "/Users/sam/Library/Developer/ CoreSimulator/Devices/ IE6DBED1-8CAD-4A6E-84FF- E352C4DBA528/data/Containers/ Bundle/Application/ B359A263-9AC8-4021-8E23-106D92 C20143/AusTVStaging.app/ main.jsbundle"}

image

I extracted line 519 from the bundle, on column 4087 (marked below with "<---") is the following method:

request: function(t, n, u, l) {
        l = l || {};
        var p = s.default.get("SERVER_URL");
        "/" !== p[p.length - 1] && (p += "/"), (p += n);
        var c = {};
        if (u && "object" == typeof u) for (var E in u) c[E] = u[E];
        "POST" !== t && ((c._method = t), (t = "POST")),
          (c._ApplicationId = s.default.get("APPLICATION_ID"));
        var T = s.default.get("JAVASCRIPT_KEY");
        T && (c._JavaScriptKey = T),
          (c._ClientVersion = s.default.get("VERSION"));
        var y = l.useMasterKey;
        if ((void 0 === y && (y = s.default.get("USE_MASTER_KEY")), y)) {
          if (!s.default.get("MASTER_KEY"))
            throw new Error(
              "Cannot use the Master Key, it has not been provided."
            );
          delete c._JavaScriptKey, (c._MasterKey = s.default.get("MASTER_KEY"));
        }
        s.default.get("FORCE_REVOCABLE_SESSION") && (c._RevocableSession = "1");
        var S,
          O = l.installationId;
        O && "string" == typeof O
          ? (S = Promise.resolve(O))
          : (S = s.default.getInstallationController().currentInstallationId());
        return S.then(function(t) {
          c._InstallationId = t;
          var n = s.default.getUserController();
          return l && "string" == typeof l.sessionToken
            ? Promise.resolve(l.sessionToken)
            : n
            ? n.currentUserAsync().then(function(t) {
                return t
                  ? Promise.resolve(t.getSessionToken()) <---- here
                  : Promise.resolve(null);
              })
            : Promise.resolve(null);
        })
          .then(function(n) {
            n && (c._SessionToken = n);
            var s = JSON.stringify(c);
            return v.ajax(t, p, s, {}, l).then(function(t) {
              var n = t.response,
                s = t.status;
              return l.returnStatus ? f({}, n, { _status: s }) : n;
            });
          })
          .catch(function(t) {
            var n;
            if (t && t.responseText)
              try {
                var s = JSON.parse(t.responseText);
                n = new o.default(s.code, s.error);
              } catch (s) {
                n = new o.default(
                  o.default.INVALID_JSON,
                  "Received an error with invalid JSON from Parse: " +
                    t.responseText
                );
              }
            else
              n = new o.default(
                o.default.CONNECTION_FAILED,
                "XMLHttpRequest failed: " + JSON.stringify(t)
              );
            return Promise.reject(n);
          });
      }

I downgraded to 2.8.0 and issue is now gone.

@dplewis
Copy link
Member

dplewis commented Nov 14, 2019

Hey guys the issue is caused by #978

Looks like this doesn't like minified code (ParseUser doesn't exist as it has been minified to a variable like 'e'). We could revert this or someone can try a PR.

dplewis added a commit that referenced this issue Nov 14, 2019
Revert #978
@dplewis
Copy link
Member

dplewis commented Nov 14, 2019

I opened a PR #999.

Can you see if it works for you?

@pocketcolin
Copy link
Contributor Author

Can confirm, PR #999 fixed the issue we were seeing.

@RaschidJFR
Copy link
Contributor

I've updated to 2.9.1 but the problem persists. So I rolled back to 2.8.0, the problem is fixed for me.

@dplewis
Copy link
Member

dplewis commented Nov 15, 2019

@RaschidJFR did you try clearing your cache / refresh the browser?

@RaschidJFR
Copy link
Contributor

Same problem even in different browser and incognito mode

@dplewis
Copy link
Member

dplewis commented Nov 19, 2019

@RaschidJFR Are you receiving the same errors as above? Also are you using a Parse.User subclass?

@RaschidJFR
Copy link
Contributor

I was indeed using a subclass in my Ionic app, but even without it the error persists.

This simple block:

Parse.initialize(environment.parse.appId, environment.parse.javaScriptKey);
(Parse as any).serverURL = environment.parse.serverUrl;
Parse.User.current();

throws this errors:

custom-error-handler.service.ts:37 TypeError: current._synchronizeAllAuthData is not a function
    at Object.currentUser (ParseUser.js:1264)
    at Function.value (ParseUser.js:781)
    at AppComponent.initParse (app.component.ts:37)
    at AppComponent.initializeApp (app.component.ts:30)
    at new AppComponent (app.component.ts:19)
    at createClass (core.js:27869)
    at createDirectiveInstance (core.js:27685)
    at createViewNodes (core.js:38315)
    at createRootView (core.js:38187)
    at callWithDebugContext (core.js:39716)

@dplewis
Copy link
Member

dplewis commented Nov 21, 2019

Can you debug the currentUser function? I do have an ionic app. I’ll try to replicate this.

@josenriq
Copy link

Same here. I upgraded to 2.9.1, and now even after going back to 2.8.0 the issue remains.

I am using a subclass for Parse.User.

The error is thrown here, ParseUser.js, line 1203:

    var current = _ParseObject2.default.fromJSON(userData);
    // After this call, current doesn't have the _synchronizeAllAuthData function

    currentUserCache = current;

    // and so it crashes here:
    current._synchronizeAllAuthData();

    return current;

@josenriq
Copy link

josenriq commented Nov 22, 2019

FYI, I found a fix for my specific issue. I was subclassing Parse.User with my own User class, and then I was calling:

Parse.Object.registerSubclass('_User', User);

At boot up, User.current() is called, the stored class name is User, not _User. And so Parse cannot find the constructor and returns a regular Parse.Object instead, which lacks the _synchronizeAllAuthData function.

tl;dr:
I changed the registerSubClass function to:

Parse.Object.registerSubclass('User', User); // no underscore
Parse.Object.registerSubclass('_User', User); // left this one too, just in case

Hope this helps anyone out there with this issue.

@dplewis
Copy link
Member

dplewis commented Nov 22, 2019

@josenriq thanks for reporting a fix. I can do a PR that will register to both User and _User.

@dplewis
Copy link
Member

dplewis commented Nov 22, 2019

@josenriq This was brought up. parse-community/docs#680 (comment)

Im against overriding the _User subclass, but it seems like a lot of developers are doing it.

@dplewis
Copy link
Member

dplewis commented Nov 22, 2019

@RaschidJFR Quick question how are you subclassing your Parse.User and registering it? Is it 'User' or '_User'?

Can you see if the fix above works for you?

@RaschidJFR
Copy link
Contributor

RaschidJFR commented Nov 22, 2019

I always use _User. And yes, to me it’s really handy to create my own customized User subclasses with the functions and props my apps need. I usually work on Angular (typescript).

@josenriq thanks for having a look at the issue. I’ll try your solution.

@josenriq
Copy link

I'm afraid this issue keeps happening for subclassed Parse.User classes and minified code.

For example, in an Angular project, unless you eject the configuration or install a custom builder to intercept Terser and keep class names, the following code breaks:

https://github.com/parse-community/Parse-SDK-JS/blob/master/src/ParseUser.js#L874

    json.className = user.constructor.name === ParseUser.name ? '_User' : user.constructor.name;

because user.constructor.name is not the same name that was passed via Parse.Object.registerSubclass. Instead, it is an arbitrary string produced by minification. And thus, when ParseUser.current() is called, the minified className is not found, and a regular Parse object is returned instead a User instance.

dplewis added a commit that referenced this issue Dec 2, 2019
After much discussion the proper way to subclass is a user is `Parse.Object.registerSubclass('_User', CustomUser);`

Revert ##978
davimacedo pushed a commit that referenced this issue Dec 2, 2019
After much discussion the proper way to subclass is a user is `Parse.Object.registerSubclass('_User', CustomUser);`

Revert ##978
@taivo
Copy link

taivo commented Dec 5, 2019

@dplewis what do you think about

json.className = user.className === ParseUser.name ? '_User' : user.className;

instead of

json.className = '_User'

@RaschidJFR
Copy link
Contributor

I confirm that from 2.10.0 is working again. Thanks @dplewis

@kyawswarthwin
Copy link

"parse": "^2.13.0",
"@types/parse": "^2.12.1",
Not working

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants