Skip to content

Commit

Permalink
fix: Throwing error in Cloud Code Triggers afterLogin, `afterLogout…
Browse files Browse the repository at this point in the history
…` crashes server (parse-community#8280)

BREAKING CHANGE: Throwing an error in Cloud Code Triggers `afterLogin`, `afterLogout` returns a rejected promise; in previous releases it crashed the server if you did not handle the error on the Node.js process level; consider adapting your code if your app currently handles these errors on the Node.js process level with `process.on('unhandledRejection', ...)`
  • Loading branch information
dblythy committed Feb 15, 2023
1 parent 5c37dcd commit 8b1dd43
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 37 deletions.
30 changes: 30 additions & 0 deletions spec/CloudCode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3103,6 +3103,36 @@ describe('beforeLogin hook', () => {
done();
});

it('does not crash server when throwing in afterLogin hook', async () => {
const error = new Parse.Error(2000, 'afterLogin error');
const trigger = {
afterLogin() {
throw error;
},
};
const spy = spyOn(trigger, 'afterLogin').and.callThrough();
Parse.Cloud.afterLogin(trigger.afterLogin);
await Parse.User.signUp('user', 'pass');
const response = await Parse.User.logIn('user', 'pass').catch(e => e);
expect(spy).toHaveBeenCalled();
expect(response).toEqual(error);
});

it('does not crash server when throwing in afterLogout hook', async () => {
const error = new Parse.Error(2000, 'afterLogout error');
const trigger = {
afterLogout() {
throw error;
},
};
const spy = spyOn(trigger, 'afterLogout').and.callThrough();
Parse.Cloud.afterLogout(trigger.afterLogout);
await Parse.User.signUp('user', 'pass');
const response = await Parse.User.logOut().catch(e => e);
expect(spy).toHaveBeenCalled();
expect(response).toEqual(error);
});

it('should have expected data in request', async done => {
Parse.Cloud.beforeLogin(req => {
expect(req.object).toBeDefined();
Expand Down
61 changes: 24 additions & 37 deletions src/Routers/UsersRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ export class UsersRouter extends ClassesRouter {
await createSession();

const afterLoginUser = Parse.User.fromJSON(Object.assign({ className: '_User' }, user));
maybeRunTrigger(
await maybeRunTrigger(
TriggerTypes.afterLogin,
{ ...req.auth, user: afterLoginUser },
afterLoginUser,
Expand Down Expand Up @@ -360,49 +360,36 @@ export class UsersRouter extends ClassesRouter {
});
}

handleLogOut(req) {
async handleLogOut(req) {
const success = { response: {} };
if (req.info && req.info.sessionToken) {
return rest
.find(
const records = await rest.find(
req.config,
Auth.master(req.config),
'_Session',
{ sessionToken: req.info.sessionToken },
undefined,
req.info.clientSDK,
req.info.context
);
if (records.results && records.results.length) {
await rest.del(
req.config,
Auth.master(req.config),
'_Session',
{ sessionToken: req.info.sessionToken },
undefined,
req.info.clientSDK,
records.results[0].objectId,
req.info.context
)
.then(records => {
if (records.results && records.results.length) {
return rest
.del(
req.config,
Auth.master(req.config),
'_Session',
records.results[0].objectId,
req.info.context
)
.then(() => {
this._runAfterLogoutTrigger(req, records.results[0]);
return Promise.resolve(success);
});
}
return Promise.resolve(success);
});
);
await maybeRunTrigger(
TriggerTypes.afterLogout,
req.auth,
Parse.Session.fromJSON(Object.assign({ className: '_Session' }, records.results[0])),
null,
req.config
);
}
}
return Promise.resolve(success);
}

_runAfterLogoutTrigger(req, session) {
// After logout trigger
maybeRunTrigger(
TriggerTypes.afterLogout,
req.auth,
Parse.Session.fromJSON(Object.assign({ className: '_Session' }, session)),
null,
req.config
);
return success;
}

_throwOnBadEmailConfig(req) {
Expand Down

0 comments on commit 8b1dd43

Please sign in to comment.