Ensure legacy users with authData are not locked out (#4898)
* Adds fix for issue, ensuring legacy users with no ACL are properly handled * Runs tests only on mongo
This commit is contained in:
@@ -3706,4 +3706,36 @@ describe('Parse.User testing', () => {
|
|||||||
expect(results.length).toBe(1);
|
expect(results.length).toBe(1);
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('issue #4897', () => {
|
||||||
|
it_only_db('mongo')("should be able to login with a legacy user (no ACL)", async () => {
|
||||||
|
// This issue is a side effect of the locked users and legacy users which don't have ACL's
|
||||||
|
// In this scenario, a legacy user wasn't be able to login as there's no ACL on it
|
||||||
|
const database = Config.get(Parse.applicationId).database;
|
||||||
|
const collection = await database.adapter._adaptiveCollection('_User');
|
||||||
|
await collection.insertOne({
|
||||||
|
"_id": "ABCDEF1234",
|
||||||
|
"name": "<some_name>",
|
||||||
|
"email": "<some_email>",
|
||||||
|
"username": "<some_username>",
|
||||||
|
"_hashed_password": "<some_password>",
|
||||||
|
"_auth_data_facebook": {
|
||||||
|
"id": "8675309",
|
||||||
|
"access_token": "jenny"
|
||||||
|
},
|
||||||
|
"sessionToken": "<some_session_token>",
|
||||||
|
});
|
||||||
|
const provider = getMockFacebookProvider();
|
||||||
|
Parse.User._registerAuthenticationProvider(provider);
|
||||||
|
const model = await Parse.User._logInWith("facebook", {});
|
||||||
|
expect(model.id).toBe('ABCDEF1234');
|
||||||
|
ok(model instanceof Parse.User, "Model should be a Parse.User");
|
||||||
|
strictEqual(Parse.User.current(), model);
|
||||||
|
ok(model.extended(), "Should have used subclass.");
|
||||||
|
strictEqual(provider.authData.id, provider.synchronizedUserId);
|
||||||
|
strictEqual(provider.authData.access_token, provider.synchronizedAuthToken);
|
||||||
|
strictEqual(provider.authData.expiration_date, provider.synchronizedExpiration);
|
||||||
|
ok(model._isLinked("facebook"), "User should be linked to facebook");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ class DatabaseController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (const updateOperation in update) {
|
for (const updateOperation in update) {
|
||||||
if (Object.keys(updateOperation).some(innerKey => innerKey.includes('$') || innerKey.includes('.'))) {
|
if (update[updateOperation] && typeof update[updateOperation] === 'object' && Object.keys(update[updateOperation]).some(innerKey => innerKey.includes('$') || innerKey.includes('.'))) {
|
||||||
throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters");
|
throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -660,7 +660,7 @@ class DatabaseController {
|
|||||||
* @param {boolean} fast set to true if it's ok to just delete rows and not indexes
|
* @param {boolean} fast set to true if it's ok to just delete rows and not indexes
|
||||||
* @returns {Promise<void>} when the deletions completes
|
* @returns {Promise<void>} when the deletions completes
|
||||||
*/
|
*/
|
||||||
deleteEverything(fast: boolean = false): Promise<void> {
|
deleteEverything(fast: boolean = false): Promise<any> {
|
||||||
this.schemaPromise = null;
|
this.schemaPromise = null;
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
this.adapter.deleteAllClasses(fast),
|
this.adapter.deleteAllClasses(fast),
|
||||||
|
|||||||
@@ -278,13 +278,23 @@ RestWrite.prototype.findUsersWithAuthData = function(authData) {
|
|||||||
return findPromise;
|
return findPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RestWrite.prototype.filteredObjectsByACL = function(objects) {
|
||||||
|
if (this.auth.isMaster) {
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
return objects.filter((object) => {
|
||||||
|
if (!object.ACL) {
|
||||||
|
return true; // legacy users that have no ACL field on them
|
||||||
|
}
|
||||||
|
// Regular users that have been locked out.
|
||||||
|
return object.ACL && Object.keys(object.ACL).length > 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
RestWrite.prototype.handleAuthData = function(authData) {
|
RestWrite.prototype.handleAuthData = function(authData) {
|
||||||
let results;
|
let results;
|
||||||
return this.findUsersWithAuthData(authData).then((r) => {
|
return this.findUsersWithAuthData(authData).then((r) => {
|
||||||
results = r.filter((user) => {
|
results = this.filteredObjectsByACL(r);
|
||||||
return !this.auth.isMaster && user.ACL && Object.keys(user.ACL).length > 0;
|
|
||||||
});
|
|
||||||
if (results.length > 1) {
|
if (results.length > 1) {
|
||||||
// More than 1 user with the passed id's
|
// More than 1 user with the passed id's
|
||||||
throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED,
|
throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED,
|
||||||
|
|||||||
Reference in New Issue
Block a user