Skip to content

Commit 25c8932

Browse files
authored
Updated user_login method to work correctly with updated Piazza API (#65)
1 parent 9ceacf8 commit 25c8932

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

piazza_api/rpc.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,42 @@ def user_login(self, email=None, password=None):
6060
:type password: str
6161
:param password: The password used for authentication
6262
"""
63+
64+
# Need to get the CSRF token first
65+
response = self.session.get('https://piazza.com/main/csrf_token')
66+
67+
# Make sure a CSRF token was retrieved, otherwise bail
68+
if response.text.upper().find('CSRF_TOKEN') == -1:
69+
raise AuthenticationError("Could not get CSRF token")
70+
71+
# Remove double quotes and semicolon (ASCI 34 & 59) from response string.
72+
# Then split the string on "=" to parse out the actual CSRF token
73+
csrf_token = response.text.translate({34: None, 59: None}).split("=")[1]
74+
6375
email = six.moves.input("Email: ") if email is None else email
6476
password = getpass.getpass() if password is None else password
6577

66-
login_data = {
67-
"method": "user.login",
68-
"params": {"email": email,
69-
"pass": password}
70-
}
71-
# If the user/password match, the server respond will contain a
72-
# session cookie that you can use to authenticate future requests.
73-
r = self.session.post(
74-
self.base_api_urls["logic"],
75-
data=json.dumps(login_data),
78+
# Log in using credentials and CSRF token and store cookie in session
79+
response = self.session.post(
80+
'https://piazza.com/class',
81+
data=f'from=%2Fsignup&email={email}&password={password}&remember=on&csrf_token={csrf_token}'
7682
)
77-
if r.json()["result"] not in ["OK"]:
78-
raise AuthenticationError("Could not authenticate.\n{}"
79-
.format(r.json()))
83+
84+
# If non-successful http response, bail
85+
if response.status_code != 200:
86+
raise AuthenticationError(f"Could not authenticate.\n{response.text}")
87+
88+
# Piazza might give a successful http response even if there is some other
89+
# kind of authentication problem. Need to parse the response html for error message
90+
pos = response.text.upper().find('VAR ERROR_MSG')
91+
errorMsg = None
92+
if pos != -1:
93+
end = response.text[pos:].find(';')
94+
errorMsg = response.text[pos:pos+end].translate({34: None}).split('=')[1].strip()
95+
96+
if errorMsg is not None:
97+
raise AuthenticationError(f"Could not authenticate.\n{errorMsg}")
98+
8099

81100
def demo_login(self, auth=None, url=None):
82101
"""Authenticate with a "Share Your Class" URL using a demo user.

0 commit comments

Comments
 (0)