Skip to content

Commit

Permalink
Merge 44d7d61 into f80d833
Browse files Browse the repository at this point in the history
  • Loading branch information
dplewis authored Aug 29, 2023
2 parents f80d833 + 44d7d61 commit b7b3329
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 9 deletions.
4 changes: 2 additions & 2 deletions integration/test/ParseUserTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -979,11 +979,11 @@ describe('Parse User', () => {
await Parse.FacebookUtils.link(user);

expect(Parse.FacebookUtils.isLinked(user)).toBe(true);
expect(Parse.AnonymousUtils.isLinked(user)).toBe(true);
expect(Parse.AnonymousUtils.isLinked(user)).toBe(false);
await Parse.FacebookUtils.unlink(user);

expect(Parse.FacebookUtils.isLinked(user)).toBe(false);
expect(Parse.AnonymousUtils.isLinked(user)).toBe(true);
expect(Parse.AnonymousUtils.isLinked(user)).toBe(false);
});

it('can link with twitter', async () => {
Expand Down
30 changes: 23 additions & 7 deletions src/ParseUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,15 @@ class ParseUser extends ParseObject {
throw new Error('Invalid type: authData field should be an object');
}
authData[authType] = options.authData;
const oldAnonymousData = authData.anonymous;
this.stripAnonymity();

const controller = CoreManager.getUserController();
return controller.linkWith(this, authData, saveOpts);
return controller.linkWith(this, authData, saveOpts).catch((e) => {
delete authData[authType];
this.restoreAnonimity(oldAnonymousData);
throw e;
});
} else {
return new Promise((resolve, reject) => {
provider.authenticate({
Expand Down Expand Up @@ -310,6 +316,21 @@ class ParseUser extends ParseObject {
return !!current && current.id === this.id;
}

stripAnonymity() {
const authData = this.get('authData');
if (authData && typeof authData === 'object' && authData.hasOwnProperty('anonymous')) {
// We need to set anonymous to null instead of deleting it in order to remove it from Parse.
authData.anonymous = null;
}
}

restoreAnonimity(anonymousData: any) {
if (anonymousData) {
const authData = this.get('authData');
authData.anonymous = anonymousData;
}
}

/**
* Returns get("username").
*
Expand All @@ -329,12 +350,7 @@ class ParseUser extends ParseObject {
* @param {string} username
*/
setUsername(username: string) {
// Strip anonymity
const authData = this.get('authData');
if (authData && typeof authData === 'object' && authData.hasOwnProperty('anonymous')) {
// We need to set anonymous to null instead of deleting it in order to remove it from Parse.
authData.anonymous = null;
}
this.stripAnonymity();
this.set('username', username);
}

Expand Down
137 changes: 137 additions & 0 deletions src/__tests__/ParseUser-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,143 @@ describe('ParseUser', () => {
spy.mockRestore();
});

it('can strip anonymous user on linkWith', async () => {
ParseUser.enableUnsafeCurrentUser();
ParseUser._clearCache();
CoreManager.setRESTController({
request() {
return Promise.resolve(
{
objectId: 'uidstrip',
sessionToken: 'r:123abc',
authData: {
anonymous: {
id: 'anonymousId',
},
},
},
200
);
},
ajax() {},
});
const user = await AnonymousUtils.logIn();

expect(user.get('authData').anonymous).toBeDefined();

ParseUser._setCurrentUserCache(user);

CoreManager.setRESTController({
request() {
return Promise.resolve(
{
objectId: 'uidstrip',
sessionToken: 'r:123abc',
authData: {
test: {
id: 'id',
access_token: 'access_token',
},
},
},
200
);
},
ajax() {},
});
const provider = {
authenticate(options) {
if (options.success) {
options.success(this, {
id: 'id',
access_token: 'access_token',
});
}
},
restoreAuthentication() {},
getAuthType() {
return 'test';
},
deauthenticate() {},
};

await user.linkWith(provider, null, { useMasterKey: true });

expect(user.get('authData')).toEqual({
test: { id: 'id', access_token: 'access_token' },
});
});

it('can restore anonymous user on linkWith failure', async () => {
ParseUser.enableUnsafeCurrentUser();
ParseUser._clearCache();
CoreManager.setRESTController({
request() {
return Promise.resolve(
{
objectId: 'uidrestore',
sessionToken: 'r:123abc',
authData: {
anonymous: {
id: 'anonymousId',
},
},
},
200
);
},
ajax() {},
});
const user = await AnonymousUtils.logIn();
expect(user.get('authData').anonymous).toBeDefined();

ParseUser._setCurrentUserCache(user);

const provider = {
authenticate(options) {
if (options.success) {
options.success(this, {
id: 'id',
access_token: 'access_token',
});
}
},
restoreAuthentication() {},
getAuthType() {
return 'test';
},
deauthenticate() {},
};

const UserController = CoreManager.getUserController();
CoreManager.setUserController({
linkWith(user) {
expect(user.get('authData').anonymous).toEqual(null);
return Promise.reject('authentication error');
},
currentUserAsync() {},
setCurrentUser() {},
currentUser() {},
signUp() {},
logIn() {},
become() {},
logOut() {},
me() {},
requestPasswordReset() {},
upgradeToRevocableSession() {},
requestEmailVerification() {},
verifyPassword() {},
});
try {
await user.linkWith(provider, null, { useMasterKey: true });
expect(true).toBe(false);
} catch (e) {
expect(e).toBe('authentication error');
}
expect(user.get('authData')).toEqual({ anonymous: { id: 'anonymousId' } });
CoreManager.setUserController(UserController);
});

it('can logout anonymous user', async () => {
ParseUser.enableUnsafeCurrentUser();
ParseUser._clearCache();
Expand Down

0 comments on commit b7b3329

Please sign in to comment.