Added onetime_password to create_authorization

github.AuthenticatedUser.create_authorization has been modified to
support two-factor authentication. When two-factor authentication
is enabled create_authorization will throw an TwoFactorException.
The onetime password can be then be passed to create_authorization
on a subsequent call.
This commit is contained in:
Cameron White
2013-12-19 04:05:26 -08:00
parent 66edeb601f
commit 36352598ae
3 changed files with 19 additions and 5 deletions
+9 -2
View File
@@ -397,7 +397,7 @@ class AuthenticatedUser(github.GithubObject.CompletableGithubObject):
"/user/watched/" + watched._identity
)
def create_authorization(self, scopes=github.GithubObject.NotSet, note=github.GithubObject.NotSet, note_url=github.GithubObject.NotSet, client_id=github.GithubObject.NotSet, client_secret=github.GithubObject.NotSet):
def create_authorization(self, scopes=github.GithubObject.NotSet, note=github.GithubObject.NotSet, note_url=github.GithubObject.NotSet, client_id=github.GithubObject.NotSet, client_secret=github.GithubObject.NotSet, onetime_password=None):
"""
:calls: `POST /authorizations <http://developer.github.com/v3/oauth>`_
:param scopes: list of string
@@ -405,6 +405,7 @@ class AuthenticatedUser(github.GithubObject.CompletableGithubObject):
:param note_url: string
:param client_id: string
:param client_secret: string
:param onetime_password: string
:rtype: :class:`github.Authorization.Authorization`
"""
assert scopes is github.GithubObject.NotSet or all(isinstance(element, (str, unicode)) for element in scopes), scopes
@@ -412,6 +413,7 @@ class AuthenticatedUser(github.GithubObject.CompletableGithubObject):
assert note_url is github.GithubObject.NotSet or isinstance(note_url, (str, unicode)), note_url
assert client_id is github.GithubObject.NotSet or isinstance(client_id, (str, unicode)), client_id
assert client_secret is github.GithubObject.NotSet or isinstance(client_secret, (str, unicode)), client_secret
assert onetime_password is None or isinstance(onetime_password, (str, unicode)), onetime_password
post_parameters = dict()
if scopes is not github.GithubObject.NotSet:
post_parameters["scopes"] = scopes
@@ -423,10 +425,15 @@ class AuthenticatedUser(github.GithubObject.CompletableGithubObject):
post_parameters["client_id"] = client_id
if client_secret is not github.GithubObject.NotSet:
post_parameters["client_secret"] = client_secret
if onetime_password is not None:
request_header = {'x-github-otp': onetime_password}
else:
request_header = None
headers, data = self._requester.requestJsonAndCheck(
"POST",
"/authorizations",
input=post_parameters
input=post_parameters,
headers=request_header,
)
return github.Authorization.Authorization(self._requester, headers, data, completed=True)
+5 -1
View File
@@ -60,7 +60,6 @@ class BadCredentialsException(GithubException):
Exception raised in case of bad credentials (when Github API replies with a 401 or 403 HTML status)
"""
class UnknownObjectException(GithubException):
"""
Exception raised when a non-existing object is requested (when Github API replies with a 404 HTML status)
@@ -108,3 +107,8 @@ class BadAttributeException(Exception):
The exception raised when PyGithub tried to parse the value
"""
return self.__transformationException
class TwoFactorException(GithubException):
"""
Exception raised when Github requires a onetime password for two-factor authentication
"""
+5 -2
View File
@@ -39,6 +39,7 @@ import urllib
import urlparse
import sys
import Consts
import re
atLeastPython26 = sys.hexversion >= 0x02060000
atLeastPython3 = sys.hexversion >= 0x03000000
@@ -173,12 +174,14 @@ class Requester:
def __check(self, status, responseHeaders, output):
output = self.__structuredFromJson(output)
if status >= 400:
raise self.__createException(status, output)
raise self.__createException(status, responseHeaders, output)
return responseHeaders, output
def __createException(self, status, output):
def __createException(self, status, headers, output):
if status == 401 and output.get("message") == "Bad credentials":
cls = GithubException.BadCredentialsException
if status == 401 and 'x-github-otp' in headers and re.match(r'.*required.*', headers['x-github-otp']):
cls = GithubException.TwoFactorException
elif status == 403 and output.get("message").startswith("Missing or invalid User Agent string"):
cls = GithubException.BadUserAgentException
elif status == 403 and output.get("message").startswith("API Rate Limit Exceeded"):