Skip to content

Commit 9f3062a

Browse files
committed
Allow to save other authData
1 parent bd877b1 commit 9f3062a

File tree

4 files changed

+98
-9
lines changed

4 files changed

+98
-9
lines changed

spec/AuthenticationAdapters.spec.js

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,7 +1837,7 @@ describe('Auth Adapter features', () => {
18371837
expect(secondCall[2].auth).toBeDefined();
18381838
expect(secondCall[2].config.headers).toBeDefined();
18391839
expect(secondCall[3] instanceof Parse.User).toBeTruthy();
1840-
expect(secondCall[3].get('username')).toEqual('test');
1840+
expect(secondCall[3].id).toEqual(user.id);
18411841
});
18421842
it('should require authData on username/password signup', async () => {
18431843
spyOn(requiredAdapter, 'validateAuthData').and.resolveTo({});
@@ -1999,10 +1999,13 @@ describe('Auth Adapter features', () => {
19991999
});
20002000
expect(user2.getSessionToken()).toBeDefined();
20012001
});
2002-
it('should return authData response on non username login', async () => {
2003-
spyOn(requiredAdapter, 'validateAuthData').and.resolveTo({ response: { someData: true } });
2002+
it('should return authData response and save some info on non username login', async () => {
2003+
spyOn(requiredAdapter, 'validateAuthData').and.resolveTo({
2004+
response: { someData: true },
2005+
});
20042006
spyOn(alwaysValidateAdapter, 'validateAuthData').and.resolveTo({
20052007
response: { someData2: true },
2008+
save: { otherData: true },
20062009
});
20072010
await reconfigureServer({
20082011
auth: { requiredAdapter, alwaysValidateAdapter },
@@ -2031,11 +2034,23 @@ describe('Auth Adapter features', () => {
20312034
});
20322035

20332036
expect(user2.get('authDataResponse')).toEqual({ alwaysValidateAdapter: { someData2: true } });
2037+
2038+
const userViaMasterKey = new Parse.User();
2039+
userViaMasterKey.id = user2.id;
2040+
await userViaMasterKey.fetch({ useMasterKey: true });
2041+
expect(userViaMasterKey.get('authData')).toEqual({
2042+
requiredAdapter: { id: 'requiredAdapter' },
2043+
alwaysValidateAdapter: { otherData: true },
2044+
});
20342045
});
2035-
it('should return authData response on username login', async () => {
2036-
spyOn(requiredAdapter, 'validateAuthData').and.resolveTo({ response: { someData: true } });
2046+
2047+
it('should return authData response and save some info on username login', async () => {
2048+
spyOn(requiredAdapter, 'validateAuthData').and.resolveTo({
2049+
response: { someData: true },
2050+
});
20372051
spyOn(alwaysValidateAdapter, 'validateAuthData').and.resolveTo({
20382052
response: { someData2: true },
2053+
save: { otherData: true },
20392054
});
20402055
await reconfigureServer({
20412056
auth: { requiredAdapter, alwaysValidateAdapter },
@@ -2073,7 +2088,57 @@ describe('Auth Adapter features', () => {
20732088
expect(JSON.parse(res.text).authDataResponse).toEqual({
20742089
alwaysValidateAdapter: { someData2: true },
20752090
});
2091+
2092+
const userViaMasterKey = new Parse.User();
2093+
userViaMasterKey.id = user.id;
2094+
await userViaMasterKey.fetch({ useMasterKey: true });
2095+
expect(userViaMasterKey.get('authData')).toEqual({
2096+
requiredAdapter: { id: 'requiredAdapter' },
2097+
alwaysValidateAdapter: { otherData: true },
2098+
});
20762099
});
2100+
2101+
it('should pass user to auth adapter on update by matching session', async () => {
2102+
spyOn(alwaysValidateAdapter, 'validateAuthData').and.resolveTo({});
2103+
await reconfigureServer({ auth: { alwaysValidateAdapter } });
2104+
2105+
const user = new Parse.User();
2106+
2107+
const payload = { someData: true };
2108+
2109+
await user.save({
2110+
username: 'test',
2111+
password: 'password',
2112+
});
2113+
2114+
expect(user.getSessionToken()).toBeDefined();
2115+
2116+
await user.save(
2117+
{ authData: { alwaysValidateAdapter: payload } },
2118+
{ sessionToken: user.getSessionToken() }
2119+
);
2120+
2121+
const firstCall = alwaysValidateAdapter.validateAuthData.calls.argsFor(0);
2122+
expect(firstCall[0]).toEqual(payload);
2123+
expect(firstCall[1]).toEqual(alwaysValidateAdapter);
2124+
expect(firstCall[2].config).toBeDefined();
2125+
expect(firstCall[2].auth).toBeDefined();
2126+
expect(firstCall[2].config.headers).toBeDefined();
2127+
expect(firstCall[3] instanceof Parse.User).toBeTruthy();
2128+
expect(firstCall[3].id).toEqual(user.id);
2129+
2130+
await user.save({ authData: { alwaysValidateAdapter: payload } }, { useMasterKey: true });
2131+
2132+
const secondCall = alwaysValidateAdapter.validateAuthData.calls.argsFor(1);
2133+
expect(secondCall[0]).toEqual(payload);
2134+
expect(secondCall[1]).toEqual(alwaysValidateAdapter);
2135+
expect(secondCall[2].config).toBeDefined();
2136+
expect(secondCall[2].auth).toBeDefined();
2137+
expect(secondCall[2].config.headers).toBeDefined();
2138+
expect(secondCall[3] instanceof Parse.User).toBeTruthy();
2139+
expect(secondCall[3].id).toEqual(user.id);
2140+
});
2141+
20772142
it('should return challenge with no logged user', async () => {
20782143
spyOn(challengeAdapter, 'challenge').and.resolveTo({ token: 'test' });
20792144

src/Adapters/Auth/AuthAdapter.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ export class AuthAdapter {
4040
@returns a promise that resolves, the resolved value will be handled by the server like:
4141
- resolve undefined|void|{} parse server will save authData
4242
- resolve { doNotSave: boolean, response: Object} parse server will do not save provided authData and send response to the client under authDataResponse
43-
- resolve { response: Object} parse server will save authData and send response to the client under authDataResponse
43+
- resolve { response: Object } parse server will save authData and send response to the client under authDataResponse
44+
- resolve { response: Object, save: Object } parse server will save the object provided into `save` key and send response to the client under authDataResponse
4445
*/
4546
validateAuthData(authData, options, req) {
4647
return Promise.resolve({});

src/Auth.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,22 @@ const getRequiredProviders = config => {
444444
// Validate each authData step by step and return the provider responses
445445
const handleAuthDataValidation = (authData, req, foundUser) => {
446446
let user;
447-
if (foundUser) user = Parse.User.fromJSON({ className: '_User', ...foundUser });
447+
if (foundUser) {
448+
user = Parse.User.fromJSON({ className: '_User', ...foundUser });
449+
// Find the user by session and current object id
450+
// Only pass user if it's the current one or master key
451+
} else if (
452+
(req.auth &&
453+
req.auth.user &&
454+
typeof req.getUserId === 'function' &&
455+
req.getUserId() === req.auth.user.id) ||
456+
(req.auth && req.auth.isMaster)
457+
) {
458+
user = new Parse.User();
459+
user.id = req.auth.isMaster ? req.getUserId() : req.auth.user.id;
460+
user.fetch({ useMasterKey: true });
461+
}
462+
448463
// Perform validation as step by step pipeline
449464
// for better error consistency and also to avoid to trigger a provider (like OTP SMS)
450465
// if another one fail
@@ -476,9 +491,11 @@ const handleAuthDataValidation = (authData, req, foundUser) => {
476491
// Some auth providers after initialization will avoid
477492
// to replace authData already stored
478493
if (!validationResult.doNotSave) {
479-
acc.authData[provider] = authData[provider];
494+
acc.authData[provider] = validationResult.save || authData[provider];
480495
}
481496
} else {
497+
// Support current authData behavior
498+
// no result store the new AuthData
482499
acc.authData[provider] = authData[provider];
483500
}
484501
return acc;

src/RestWrite.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,10 +424,16 @@ RestWrite.prototype.validateAuthData = function () {
424424
var hasToken = providerAuthData && providerAuthData.id;
425425
return hasToken || providerAuthData == null;
426426
});
427-
if (canHandleAuthData || hasUsernameAndPassword) {
427+
if (
428+
canHandleAuthData ||
429+
hasUsernameAndPassword ||
430+
this.auth.isMaster ||
431+
(this.auth.user && this.auth.user.id === this.getUserId())
432+
) {
428433
return this.handleAuthData(authData);
429434
}
430435
}
436+
console.log('Je throw ici', this.auth);
431437
throw new Parse.Error(
432438
Parse.Error.UNSUPPORTED_SERVICE,
433439
'This authentication method is unsupported.'

0 commit comments

Comments
 (0)