-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Access the internal scope of Parse Server using the new `mainte…
…nanceKey`; the internal scope contains unofficial and undocumented fields (prefixed with underscore `_`) which are used internally by Parse Server; you may want to manipulate these fields for out-of-band changes such as data migration or correction tasks; changes within the internal scope of Parse Server may happen at any time without notice or changelog entry, it is therefore recommended to look at the source code of Parse Server to understand the effects of manipulating internal fields before using the key; it is discouraged to use the `maintenanceKey` for routine operations in a production environment; see [access scopes](https://github.com/parse-community/parse-server#access-scopes) (#8212) BREAKING CHANGE: Fields in the internal scope of Parse Server (prefixed with underscore `_`) are only returned using the new `maintenanceKey`; previously the `masterKey` allowed reading of internal fields; see [access scopes](https://github.com/parse-community/parse-server#access-scopes) for a comparison of the keys' access permissions (#8212)
- Loading branch information
Showing
23 changed files
with
371 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3522,40 +3522,128 @@ describe('Parse.User testing', () => { | |
}); | ||
}); | ||
|
||
it('should not allow updates to hidden fields', done => { | ||
it('should not allow updates to hidden fields', async () => { | ||
const emailAdapter = { | ||
sendVerificationEmail: () => {}, | ||
sendPasswordResetEmail: () => Promise.resolve(), | ||
sendMail: () => Promise.resolve(), | ||
}; | ||
|
||
const user = new Parse.User(); | ||
user.set({ | ||
username: 'hello', | ||
password: 'world', | ||
email: '[email protected]', | ||
}); | ||
await reconfigureServer({ | ||
appName: 'unused', | ||
verifyUserEmails: true, | ||
emailAdapter: emailAdapter, | ||
publicServerURL: 'http://localhost:8378/1', | ||
}); | ||
await user.signUp(); | ||
user.set('_email_verify_token', 'bad', { ignoreValidation: true }); | ||
await expectAsync(user.save()).toBeRejectedWith( | ||
new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid field name: _email_verify_token.') | ||
); | ||
}); | ||
|
||
reconfigureServer({ | ||
it('should allow updates to fields with maintenanceKey', async () => { | ||
const emailAdapter = { | ||
sendVerificationEmail: () => {}, | ||
sendPasswordResetEmail: () => Promise.resolve(), | ||
sendMail: () => Promise.resolve(), | ||
}; | ||
const user = new Parse.User(); | ||
user.set({ | ||
username: 'hello', | ||
password: 'world', | ||
email: '[email protected]', | ||
}); | ||
await reconfigureServer({ | ||
appName: 'unused', | ||
maintenanceKey: 'test2', | ||
verifyUserEmails: true, | ||
emailVerifyTokenValidityDuration: 5, | ||
accountLockout: { | ||
duration: 1, | ||
threshold: 1, | ||
}, | ||
emailAdapter: emailAdapter, | ||
publicServerURL: 'http://localhost:8378/1', | ||
}) | ||
.then(() => { | ||
return user.signUp(); | ||
}) | ||
.then(() => { | ||
return Parse.User.current().set('_email_verify_token', 'bad').save(); | ||
}) | ||
.then(() => { | ||
fail('Should not be able to update email verification token'); | ||
done(); | ||
}) | ||
.catch(err => { | ||
expect(err).toBeDefined(); | ||
done(); | ||
}); | ||
}); | ||
await user.signUp(); | ||
for (let i = 0; i < 2; i++) { | ||
try { | ||
await Parse.User.logIn(user.getEmail(), 'abc'); | ||
} catch (e) { | ||
expect(e.code).toBe(Parse.Error.OBJECT_NOT_FOUND); | ||
expect( | ||
e.message === 'Invalid username/password.' || | ||
e.message === | ||
'Your account is locked due to multiple failed login attempts. Please try again after 1 minute(s)' | ||
).toBeTrue(); | ||
} | ||
} | ||
await Parse.User.requestPasswordReset(user.getEmail()); | ||
const headers = { | ||
'X-Parse-Application-Id': 'test', | ||
'X-Parse-Rest-API-Key': 'rest', | ||
'X-Parse-Maintenance-Key': 'test2', | ||
'Content-Type': 'application/json', | ||
}; | ||
const userMaster = await request({ | ||
method: 'GET', | ||
url: `http://localhost:8378/1/classes/_User`, | ||
json: true, | ||
headers, | ||
}).then(res => res.data.results[0]); | ||
expect(Object.keys(userMaster).sort()).toEqual( | ||
[ | ||
'ACL', | ||
'_account_lockout_expires_at', | ||
'_email_verify_token', | ||
'_email_verify_token_expires_at', | ||
'_failed_login_count', | ||
'_perishable_token', | ||
'createdAt', | ||
'email', | ||
'emailVerified', | ||
'objectId', | ||
'updatedAt', | ||
'username', | ||
].sort() | ||
); | ||
const toSet = { | ||
_account_lockout_expires_at: new Date(), | ||
_email_verify_token: 'abc', | ||
_email_verify_token_expires_at: new Date(), | ||
_failed_login_count: 0, | ||
_perishable_token_expires_at: new Date(), | ||
_perishable_token: 'abc', | ||
}; | ||
await request({ | ||
method: 'PUT', | ||
headers, | ||
url: Parse.serverURL + '/users/' + userMaster.objectId, | ||
json: true, | ||
body: toSet, | ||
}).then(res => res.data); | ||
const update = await request({ | ||
method: 'GET', | ||
url: `http://localhost:8378/1/classes/_User`, | ||
json: true, | ||
headers, | ||
}).then(res => res.data.results[0]); | ||
for (const key in toSet) { | ||
const value = toSet[key]; | ||
if (update[key] && update[key].iso) { | ||
expect(update[key].iso).toEqual(value.toISOString()); | ||
} else if (value.toISOString) { | ||
expect(update[key]).toEqual(value.toISOString()); | ||
} else { | ||
expect(update[key]).toEqual(value); | ||
} | ||
} | ||
}); | ||
|
||
it('should revoke sessions when setting paswword with masterKey (#3289)', done => { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ const publicServerURL = 'http://localhost:8378/1'; | |
describe('Regex Vulnerabilities', function () { | ||
beforeEach(async function () { | ||
await reconfigureServer({ | ||
maintenanceKey: 'test2', | ||
verifyUserEmails: true, | ||
emailAdapter, | ||
appName, | ||
|
@@ -98,11 +99,20 @@ describe('Regex Vulnerabilities', function () { | |
|
||
it('should work with plain token', async function () { | ||
expect(this.user.get('emailVerified')).toEqual(false); | ||
const current = await request({ | ||
method: 'GET', | ||
url: `http://localhost:8378/1/classes/_User/${this.user.id}`, | ||
json: true, | ||
headers: { | ||
'X-Parse-Application-Id': 'test', | ||
'X-Parse-Rest-API-Key': 'test', | ||
'X-Parse-Maintenance-Key': 'test2', | ||
'Content-Type': 'application/json', | ||
}, | ||
}).then(res => res.data); | ||
// It should work | ||
await request({ | ||
url: `${serverURL}/apps/test/[email protected]&token=${this.user.get( | ||
'_email_verify_token' | ||
)}`, | ||
url: `${serverURL}/apps/test/[email protected]&token=${current._email_verify_token}`, | ||
method: 'GET', | ||
}); | ||
await this.user.fetch({ useMasterKey: true }); | ||
|
@@ -164,8 +174,18 @@ describe('Regex Vulnerabilities', function () { | |
email: '[email protected]', | ||
}), | ||
}); | ||
await this.user.fetch({ useMasterKey: true }); | ||
const token = this.user.get('_perishable_token'); | ||
const current = await request({ | ||
method: 'GET', | ||
url: `http://localhost:8378/1/classes/_User/${this.user.id}`, | ||
json: true, | ||
headers: { | ||
'X-Parse-Application-Id': 'test', | ||
'X-Parse-Rest-API-Key': 'test', | ||
'X-Parse-Maintenance-Key': 'test2', | ||
'Content-Type': 'application/json', | ||
}, | ||
}).then(res => res.data); | ||
const token = current._perishable_token; | ||
const passwordResetResponse = await request({ | ||
url: `${serverURL}/apps/test/[email protected]&token=${token}`, | ||
method: 'GET', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.