Skip to content

Commit

Permalink
Merge branch 'alpha' into redis-store
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrezza committed Mar 6, 2023
2 parents 3af2584 + 0f1979f commit 2cc16b4
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 10 deletions.
21 changes: 21 additions & 0 deletions changelogs/CHANGELOG_alpha.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# [6.1.0-alpha.5](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.4...6.1.0-alpha.5) (2023-03-06)


### Bug Fixes

* LiveQuery can return incorrectly formatted date ([#8456](https://github.com/parse-community/parse-server/issues/8456)) ([4ce135a](https://github.com/parse-community/parse-server/commit/4ce135a4fe930776044bc8fd786a4e17a0144e03))

# [6.1.0-alpha.4](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.3...6.1.0-alpha.4) (2023-03-06)


### Bug Fixes

* Parameters missing in `afterFind` trigger of authentication adapters ([#8458](https://github.com/parse-community/parse-server/issues/8458)) ([ce34747](https://github.com/parse-community/parse-server/commit/ce34747e8af54cb0b6b975da38f779a5955d2d59))

# [6.1.0-alpha.3](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.2...6.1.0-alpha.3) (2023-03-06)


### Features

* Add `afterFind` trigger to authentication adapters ([#8444](https://github.com/parse-community/parse-server/issues/8444)) ([c793bb8](https://github.com/parse-community/parse-server/commit/c793bb88e7485743c7ceb65fe419cde75833ff33))

# [6.1.0-alpha.2](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.1...6.1.0-alpha.2) (2023-03-05)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "parse-server",
"version": "6.1.0-alpha.2",
"version": "6.1.0-alpha.5",
"description": "An express module providing a Parse-compatible API server",
"main": "lib/index.js",
"repository": {
Expand Down
37 changes: 37 additions & 0 deletions spec/AuthenticationAdaptersV2.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ describe('Auth Adapter features', () => {
validateLogin: () => Promise.resolve(),
};

const modernAdapter3 = {
validateAppId: () => Promise.resolve(),
validateSetUp: () => Promise.resolve(),
validateUpdate: () => Promise.resolve(),
validateLogin: () => Promise.resolve(),
validateOptions: () => Promise.resolve(),
afterFind() {
return {
foo: 'bar',
};
},
};

const wrongAdapter = {
validateAppId: () => Promise.resolve(),
};
Expand Down Expand Up @@ -332,6 +345,30 @@ describe('Auth Adapter features', () => {
expect(user.getSessionToken()).toBeDefined();
});

it('should strip out authData if required', async () => {
const spy = spyOn(modernAdapter3, 'validateOptions').and.callThrough();
const afterSpy = spyOn(modernAdapter3, 'afterFind').and.callThrough();
await reconfigureServer({ auth: { modernAdapter3 }, silent: false });
const user = new Parse.User();
await user.save({ authData: { modernAdapter3: { id: 'modernAdapter3Data' } } });
await user.fetch({ sessionToken: user.getSessionToken() });
const authData = user.get('authData').modernAdapter3;
expect(authData).toEqual({ foo: 'bar' });
for (const call of afterSpy.calls.all()) {
const args = call.args[0];
if (args.user) {
user._objCount = args.user._objCount;
break;
}
}
expect(afterSpy).toHaveBeenCalledWith(
{ ip: '127.0.0.1', user, master: false },
{ id: 'modernAdapter3Data' },
undefined
);
expect(spy).toHaveBeenCalled();
});

it('should throw if no triggers found', async () => {
await reconfigureServer({ auth: { wrongAdapter } });
const user = new Parse.User();
Expand Down
2 changes: 1 addition & 1 deletion spec/MongoStorageAdapter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
expect(object.date[0] instanceof Date).toBeTrue();
expect(object.bar.date[0] instanceof Date).toBeTrue();
expect(object.foo.test.date[0] instanceof Date).toBeTrue();
const obj = await new Parse.Query('MyClass').first({useMasterKey: true});
const obj = await new Parse.Query('MyClass').first({ useMasterKey: true });
expect(obj.get('date')[0] instanceof Date).toBeTrue();
expect(obj.get('bar').date[0] instanceof Date).toBeTrue();
expect(obj.get('foo').test.date[0] instanceof Date).toBeTrue();
Expand Down
47 changes: 45 additions & 2 deletions spec/ParseLiveQueryServer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,49 @@ describe('ParseLiveQueryServer', function () {
parseLiveQueryServer._onAfterSave(message);
});

it('sends correct object for dates', async () => {
jasmine.restoreLibrary('../lib/LiveQuery/QueryTools', 'matchesQuery');

const parseLiveQueryServer = new ParseLiveQueryServer({});

const date = new Date();
const message = {
currentParseObject: {
date: { __type: 'Date', iso: date.toISOString() },
__type: 'Object',
key: 'value',
className: testClassName,
},
};
// Add mock client
const clientId = 1;
const client = addMockClient(parseLiveQueryServer, clientId);

const requestId2 = 2;

await addMockSubscription(parseLiveQueryServer, clientId, requestId2);

parseLiveQueryServer._matchesACL = function () {
return Promise.resolve(true);
};

parseLiveQueryServer._inflateParseObject(message);
parseLiveQueryServer._onAfterSave(message);

// Make sure we send leave and enter command to client
await timeout();

expect(client.pushCreate).toHaveBeenCalledWith(
requestId2,
{
className: 'TestObject',
key: 'value',
date: { __type: 'Date', iso: date.toISOString() },
},
null
);
});

it('can handle object save command which does not match any subscription', async done => {
const parseLiveQueryServer = new ParseLiveQueryServer({});
// Make mock request message
Expand Down Expand Up @@ -1138,8 +1181,7 @@ describe('ParseLiveQueryServer', function () {
expect(toSend.original).toBeUndefined();
expect(spy).toHaveBeenCalledWith({
usage: 'Subscribing using fields parameter',
solution:
`Subscribe using "keys" instead.`,
solution: `Subscribe using "keys" instead.`,
});
});

Expand Down Expand Up @@ -1945,6 +1987,7 @@ describe('ParseLiveQueryServer', function () {
} else {
subscription.clientRequestIds = new Map([[clientId, [requestId]]]);
}
subscription.query = query.where;
return subscription;
}

Expand Down
18 changes: 18 additions & 0 deletions src/Adapters/Auth/AuthAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ export class AuthAdapter {
challenge(challengeData, authData, options, request) {
return Promise.resolve({});
}

/**
* Triggered when auth data is fetched
* @param {Object} authData authData
* @param {Object} options additional adapter options
* @returns {Promise<Object>} Any overrides required to authData
*/
afterFind(authData, options) {
return Promise.resolve({});
}

/**
* Triggered when the adapter is first attached to Parse Server
* @param {Object} options Adapter Options
*/
validateOptions(options) {
/* */
}
}

export default AuthAdapter;
47 changes: 44 additions & 3 deletions src/Adapters/Auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,27 @@ function loadAuthAdapter(provider, authOptions) {
return;
}

const adapter = defaultAdapter instanceof AuthAdapter ? defaultAdapter : Object.assign({}, defaultAdapter);
const adapter =
defaultAdapter instanceof AuthAdapter ? defaultAdapter : Object.assign({}, defaultAdapter);
const keys = [
'validateAuthData',
'validateAppId',
'validateSetUp',
'validateLogin',
'validateUpdate',
'challenge',
'policy'
'validateOptions',
'policy',
'afterFind',
];
const defaultAuthAdapter = new AuthAdapter();
keys.forEach(key => {
const existing = adapter?.[key];
if (existing && typeof existing === 'function' && existing.toString() === defaultAuthAdapter[key].toString()) {
if (
existing &&
typeof existing === 'function' &&
existing.toString() === defaultAuthAdapter[key].toString()
) {
adapter[key] = null;
}
});
Expand All @@ -184,6 +191,9 @@ function loadAuthAdapter(provider, authOptions) {
});
}
}
if (adapter.validateOptions) {
adapter.validateOptions(providerOptions);
}

return { adapter, appIds, providerOptions };
}
Expand All @@ -204,9 +214,40 @@ module.exports = function (authOptions = {}, enableAnonymousUsers = true) {
return { validator: authDataValidator(provider, adapter, appIds, providerOptions), adapter };
};

const runAfterFind = async (req, authData) => {
if (!authData) {
return;
}
const adapters = Object.keys(authData);
await Promise.all(
adapters.map(async provider => {
const authAdapter = getValidatorForProvider(provider);
if (!authAdapter) {
return;
}
const {
adapter: { afterFind },
providerOptions,
} = authAdapter;
if (afterFind && typeof afterFind === 'function') {
const requestObject = {
ip: req.config.ip,
user: req.auth.user,
master: req.auth.isMaster,
};
const result = afterFind(requestObject, authData[provider], providerOptions);
if (result) {
authData[provider] = result;
}
}
})
);
};

return Object.freeze({
getValidatorForProvider,
setEnableAnonymousUsers,
runAfterFind,
});
};

Expand Down
3 changes: 2 additions & 1 deletion src/LiveQuery/ParseLiveQueryServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import UserRouter from '../Routers/UsersRouter';
import DatabaseController from '../Controllers/DatabaseController';
import { isDeepStrictEqual } from 'util';
import Deprecator from '../Deprecator/Deprecator';
import deepcopy from 'deepcopy';

class ParseLiveQueryServer {
clients: Map;
Expand Down Expand Up @@ -496,7 +497,7 @@ class ParseLiveQueryServer {
if (!parseObject) {
return false;
}
return matchesQuery(parseObject, subscription.query);
return matchesQuery(deepcopy(parseObject), subscription.query);
}

async _clearCachedRoles(userId: string) {
Expand Down
17 changes: 17 additions & 0 deletions src/RestQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ RestQuery.prototype.execute = function (executeOptions) {
.then(() => {
return this.runAfterFindTrigger();
})
.then(() => {
return this.handleAuthAdapters();
})
.then(() => {
return this.response;
});
Expand Down Expand Up @@ -842,6 +845,20 @@ RestQuery.prototype.runAfterFindTrigger = function () {
});
};

RestQuery.prototype.handleAuthAdapters = async function () {
if (this.className !== '_User' || this.findOptions.explain) {
return;
}
await Promise.all(
this.response.results.map(result =>
this.config.authDataManager.runAfterFind(
{ config: this.config, auth: this.auth },
result.authData
)
)
);
};

// Adds included values to the response.
// Path is a list of field names.
// Returns a promise for an augmented response.
Expand Down
1 change: 1 addition & 0 deletions src/Routers/UsersRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ export class UsersRouter extends ClassesRouter {
if (authDataResponse) {
user.authDataResponse = authDataResponse;
}
await req.config.authDataManager.runAfterFind(req, user.authData);

return { response: user };
}
Expand Down

0 comments on commit 2cc16b4

Please sign in to comment.