Repository: parse-community/Parse-SDK-JS (JavaScript)

Issue:
Add context container in `Parse.Cloud.beforeLogin` and `Parse.Cloud.afterLogin`
### New Feature / Enhancement Checklist
<!--
    Check every following box [x] before submitting your issue.
    Click the "Preview" tab for better readability.
    Thanks for contributing to Parse Platform!
-->

- [x] I am not disclosing a [vulnerability](https://github.com/parse-community/parse-server/blob/master/SECURITY.md).
- [x] I am not just asking a [question](https://github.com/parse-community/.github/blob/master/SUPPORT.md).
- [x] I have searched through [existing issues](https://github.com/parse-community/Parse-SDK-JS/issues?q=is%3Aissue).

### Current Limitation
It is currently not possible to access context data in Parse.Cloud.beforeLogin and Parse.Cloud.afterLogin hook triggers.

### Feature / Enhancement Description
Similar to Parse.Cloud.beforeSave and Parse.Cloud.afterSave triggers, where it is possible to get context data feom the context object via the request parameter of the trigger callback.

### Example Use Case
1. This could help facilitate MFA authentication such as in cases when an email verification needs to be passed alongside parse email auth data before login is permitted.
2. It may also come in handy in context switching during or after login such as in case of performing certain actions based on context data after login.

### Alternatives / Workarounds
In my project, I was forced to use Redis cache and making additional request to the server which wasn't really necessary. 
Also, lack of this feature resulted in extra code.

### 3rd Party References
None


Discussion:

### Thanks for opening this issue!

- 🎉 We are excited about your ideas for improvement!

<!-- parse-issue-bot-meta-tag-id {"suggestPr":false,"thanksFeature":true,"thanksPr":false} -->


I believe this needs to be added to the server first before the SDK.



Patch:
diff --git a/src/ParseUser.js b/src/ParseUser.js
index 146221614..8ba9ba8c0 100644
--- a/src/ParseUser.js
+++ b/src/ParseUser.js
@@ -469,7 +469,12 @@ class ParseUser extends ParseObject {
     if (options.hasOwnProperty('usePost')) {
       loginOptions.usePost = options.usePost;
     }
-
+    if (
+      options.hasOwnProperty('context') &&
+      Object.prototype.toString.call(options.context) === '[object Object]'
+    ) {
+      loginOptions.context = options.context;
+    }
     const controller = CoreManager.getUserController();
     return controller.logIn(this, loginOptions);
   }


Test patch:
diff --git a/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js
index 889418ec0..631842b8e 100644
--- a/src/__tests__/ParseUser-test.js
+++ b/src/__tests__/ParseUser-test.js
@@ -1942,6 +1942,27 @@ describe('ParseUser', () => {
     expect(controller.request.mock.calls[0][3].context).toEqual(context);
   });
 
+  it('can login with context', async () => {
+    CoreManager.setRESTController({
+      ajax() {},
+      request() {
+        return Promise.resolve(
+          {
+            objectId: 'uid33',
+            username: 'username',
+            sessionToken: '123abc',
+          },
+          200
+        );
+      },
+    });
+    const controller = CoreManager.getRESTController();
+    jest.spyOn(controller, 'request');
+    const context = { a: 'a' };
+    await ParseUser.logIn('username', 'password', { context });
+    expect(controller.request.mock.calls[0][3].context).toEqual(context);
+  });
+
   it('can verify user password', async () => {
     ParseUser.enableUnsafeCurrentUser();
     ParseUser._clearCache();