/pybitbucket/auth.py

https://gitlab.com/ztane/python-bitbucket · Python · 171 lines · 138 code · 27 blank · 6 comment · 9 complexity · 7ed68e17e21250c033f38305b333c25d MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. """
  3. Classes for abstracting over different forms of Bitbucket authentication.
  4. """
  5. from requests.utils import default_user_agent
  6. from requests import Session
  7. from requests.auth import HTTPBasicAuth
  8. from requests_oauthlib import OAuth1Session, OAuth2Session
  9. from uritemplate import expand
  10. from pybitbucket import metadata
  11. class Authenticator(object):
  12. @staticmethod
  13. def user_agent_header():
  14. return u'{0}/{1} {2}'.format(
  15. metadata.package,
  16. metadata.version,
  17. default_user_agent())
  18. @staticmethod
  19. def headers(email=None, user_agent=None):
  20. user_agent = user_agent or Authenticator.user_agent_header()
  21. headers = {
  22. 'Accept': 'application/json',
  23. 'User-Agent': user_agent,
  24. }
  25. if email:
  26. headers.update({'From': email})
  27. return headers
  28. def start_http_session(self):
  29. session = Session()
  30. session.headers.update(self.headers())
  31. return session
  32. def get_username(self):
  33. return ""
  34. def who_am_i(self):
  35. response = self.session.get(self.who_am_i_url)
  36. response.raise_for_status()
  37. return response.json()['username']
  38. def __init__(self, server_base_uri=None):
  39. self.server_base_uri = server_base_uri or 'https://api.bitbucket.org'
  40. self.who_am_i_url = expand(
  41. '{+server_base_uri}/2.0/user',
  42. {'server_base_uri': self.server_base_uri})
  43. self.session = self.start_http_session()
  44. class Anonymous(Authenticator):
  45. pass
  46. class BasicAuthenticator(Authenticator):
  47. def start_http_session(self):
  48. session = Session()
  49. session.headers.update(self.headers(email=self.client_email))
  50. session.auth = HTTPBasicAuth(self.username, self.password)
  51. return session
  52. def get_username(self):
  53. return self.username
  54. def __init__(
  55. self,
  56. username,
  57. password,
  58. client_email,
  59. server_base_uri=None):
  60. self.username = username
  61. self.password = password
  62. self.client_email = client_email
  63. super(self.__class__, self).__init__(server_base_uri=server_base_uri)
  64. class OAuth1Authenticator(Authenticator):
  65. def __init__(
  66. self,
  67. client_key,
  68. client_secret,
  69. client_email=None,
  70. access_token=None,
  71. access_token_secret=None,
  72. server_base_uri=None):
  73. self.client_key = client_key
  74. self.client_secret = client_secret
  75. self.client_email = client_email
  76. self.access_token = access_token
  77. self.access_token_secret = access_token_secret
  78. self.username = None
  79. super(self.__class__, self).__init__(server_base_uri=server_base_uri)
  80. def get_username(self):
  81. if not self.username:
  82. self.username = self.who_am_i()
  83. return self.username
  84. def start_http_session(self):
  85. session = OAuth1Session(
  86. self.client_key,
  87. client_secret=self.client_secret,
  88. resource_owner_key=self.access_token,
  89. resource_owner_secret=self.access_token_secret)
  90. session.headers.update(self.headers(email=self.client_email))
  91. return session
  92. class OAuth2Grant(object):
  93. def obtain_authorization(self, session, auth_uri):
  94. raise NotImplementedError()
  95. # return redirect_response
  96. class OAuth2Authenticator(Authenticator):
  97. def __init__(
  98. self,
  99. client_id,
  100. client_secret,
  101. client_email,
  102. grant,
  103. redirect_uris=None,
  104. server_base_uri=None,
  105. redirect_response=None,
  106. client_name=None,
  107. client_description=None,
  108. auth_uri=None,
  109. token_uri=None):
  110. self.client_id = client_id
  111. self.client_secret = client_secret
  112. self.client_email = client_email
  113. self.grant = grant
  114. self.redirect_uris = redirect_uris
  115. self.client_name = client_name
  116. self.client_description = client_description
  117. self.redirect_response = redirect_response
  118. self.username = None
  119. self.server_base_uri = server_base_uri or 'https://api.bitbucket.org'
  120. self.auth_uri = (
  121. auth_uri or expand(
  122. '{+server_base_uri}/site/oauth2/authorize',
  123. {'server_base_uri': self.server_base_uri}))
  124. self.token_uri = (
  125. token_uri or expand(
  126. '{+server_base_uri}/site/oauth2/access_token',
  127. {'server_base_uri': self.server_base_uri}))
  128. super(self.__class__, self).__init__(server_base_uri=server_base_uri)
  129. def start_http_session(self):
  130. session = OAuth2Session(self.client_id)
  131. session.headers.update(self.headers(email=self.client_email))
  132. if not session.authorized:
  133. self.redirect_response = self.grant.obtain_authorization(
  134. session,
  135. self.auth_uri)
  136. session.fetch_token(
  137. self.token_uri,
  138. authorization_response=self.redirect_response)
  139. return session
  140. def get_username(self):
  141. if not self.username:
  142. self.username = self.who_am_i()
  143. return self.username