-
Couldn't load subscription status.
- Fork 330
Add Support for Scopes #185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,4 +12,6 @@ __pycache__/ | |
| *.pyc | ||
| *.pyo | ||
| *~ | ||
| .venv | ||
| .venv | ||
| venv/ | ||
| venv3/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
| url_encode = urllib.urlencode # pylint: disable=no-member,useless-suppression | ||
|
|
||
| TOKEN_ACCESS_TYPES = ['offline', 'online', 'legacy'] | ||
| INCLUDE_GRANTED_SCOPES_TYPES = ['user', 'team'] | ||
|
|
||
| class OAuth2FlowNoRedirectResult(object): | ||
| """ | ||
|
|
@@ -39,17 +40,22 @@ class OAuth2FlowNoRedirectResult(object): | |
| in using them, please contact Dropbox support | ||
| """ | ||
|
|
||
| def __init__(self, access_token, account_id, user_id, refresh_token, expiration): | ||
| def __init__(self, access_token, account_id, user_id, refresh_token, expiration, scope): | ||
| """ | ||
| Args: | ||
| access_token (str): Token to be used to authenticate later | ||
| requests. | ||
| refresh_token (str): Token to be used to acquire new access token | ||
| when existing one expires | ||
| expiration (int, datetime): Either the number of seconds from now that the token expires | ||
| in or the datetime at which the token expires | ||
| account_id (str): The Dropbox user's account ID. | ||
| user_id (str): Deprecated (use account_id instead). | ||
| refresh_token (str): Token to be used to acquire new access token | ||
| when existing one expires | ||
| expiration (int, datetime): Either the number of seconds from now that the token expires | ||
| in or the datetime at which the token expires | ||
| scope (list): list of scopes to request in base oauth flow. | ||
| """ | ||
| self.access_token = access_token | ||
| if not expiration: | ||
|
|
@@ -61,14 +67,16 @@ def __init__(self, access_token, account_id, user_id, refresh_token, expiration) | |
| self.refresh_token = refresh_token | ||
| self.account_id = account_id | ||
| self.user_id = user_id | ||
| self.scope = scope | ||
|
|
||
| def __repr__(self): | ||
| return 'OAuth2FlowNoRedirectResult(%s, %s, %s, %s, %s)' % ( | ||
| return 'OAuth2FlowNoRedirectResult(%s, %s, %s, %s, %s, %s)' % ( | ||
| self.access_token, | ||
| self.account_id, | ||
| self.user_id, | ||
| self.refresh_token, | ||
| self.expires_at, | ||
| self.scope, | ||
| ) | ||
|
|
||
|
|
||
|
|
@@ -77,7 +85,8 @@ class OAuth2FlowResult(OAuth2FlowNoRedirectResult): | |
| Authorization information for an OAuth2Flow with redirect. | ||
| """ | ||
|
|
||
| def __init__(self, access_token, account_id, user_id, url_state, refresh_token, expires_in): | ||
| def __init__(self, access_token, account_id, user_id, url_state, refresh_token, | ||
| expires_in, scope): | ||
| """ | ||
| Same as OAuth2FlowNoRedirectResult but with url_state. | ||
|
|
||
|
|
@@ -86,20 +95,23 @@ def __init__(self, access_token, account_id, user_id, url_state, refresh_token, | |
| :meth:`DropboxOAuth2Flow.start`. | ||
| """ | ||
| super(OAuth2FlowResult, self).__init__( | ||
| access_token, account_id, user_id, refresh_token, expires_in) | ||
| access_token, account_id, user_id, refresh_token, expires_in, scope) | ||
| self.url_state = url_state | ||
|
|
||
| @classmethod | ||
| def from_no_redirect_result(cls, result, url_state): | ||
| assert isinstance(result, OAuth2FlowNoRedirectResult) | ||
| return cls(result.access_token, result.account_id, result.user_id, | ||
| url_state, result.refresh_token, result.expires_at) | ||
| url_state, result.refresh_token, result.expires_at, result.scope) | ||
|
|
||
| def __repr__(self): | ||
| return 'OAuth2FlowResult(%s, %s, %s, %s, %s, %s)' % ( | ||
| return 'OAuth2FlowResult(%s, %s, %s, %s, %s, %s, %s, %s, %s)' % ( | ||
| self.access_token, | ||
| self.refresh_token, | ||
| self.expires_at, | ||
| self.account_id, | ||
| self.user_id, | ||
| self.scope, | ||
| self.url_state, | ||
| self.refresh_token, | ||
| self.expires_at, | ||
|
|
@@ -108,14 +120,22 @@ def __repr__(self): | |
|
|
||
| class DropboxOAuth2FlowBase(object): | ||
|
|
||
| def __init__(self, consumer_key, consumer_secret, locale=None, token_access_type='legacy'): | ||
| def __init__(self, consumer_key, consumer_secret, locale=None, token_access_type='legacy', | ||
| scope=None, include_granted_scopes=None): | ||
| if scope is not None: | ||
| assert len(scope) > 0 and isinstance(scope, list), \ | ||
| "Scope list must be of type list" | ||
|
|
||
| self.consumer_key = consumer_key | ||
| self.consumer_secret = consumer_secret | ||
| self.locale = locale | ||
| self.token_access_type = token_access_type | ||
| self.requests_session = pinned_session() | ||
| self.scope = scope | ||
| self.include_granted_scopes = include_granted_scopes | ||
|
|
||
| def _get_authorize_url(self, redirect_uri, state, token_access_type): | ||
| def _get_authorize_url(self, redirect_uri, state, token_access_type, scope=None, | ||
| include_granted_scopes=None): | ||
| params = dict(response_type='code', | ||
| client_id=self.consumer_key) | ||
| if redirect_uri is not None: | ||
|
|
@@ -127,6 +147,12 @@ def _get_authorize_url(self, redirect_uri, state, token_access_type): | |
| if token_access_type != 'legacy': | ||
| params['token_access_type'] = token_access_type | ||
|
|
||
| if scope is not None: | ||
| params['scope'] = " ".join(scope) | ||
| if include_granted_scopes is not None: | ||
| assert include_granted_scopes in INCLUDE_GRANTED_SCOPES_TYPES | ||
| params['include_granted_scopes'] = str(include_granted_scopes) | ||
|
|
||
| return self.build_url('/oauth2/authorize', params, WEB_HOST) | ||
|
|
||
| def _finish(self, code, redirect_uri): | ||
|
|
@@ -163,6 +189,11 @@ def _finish(self, code, redirect_uri): | |
| else: | ||
| expires_in = None | ||
|
|
||
| if 'scope' in d: | ||
| scope = d['scope'] | ||
| else: | ||
| scope = None | ||
|
|
||
| uid = d['uid'] | ||
|
|
||
| return OAuth2FlowNoRedirectResult( | ||
|
|
@@ -171,7 +202,7 @@ def _finish(self, code, redirect_uri): | |
| uid, | ||
| refresh_token, | ||
| expires_in, | ||
| ) | ||
| scope) | ||
|
|
||
| def build_path(self, target, params=None): | ||
| """Build the path component for an API URL. | ||
|
|
@@ -228,21 +259,23 @@ class DropboxOAuth2FlowNoRedirect(DropboxOAuth2FlowBase): | |
| auth_flow = DropboxOAuth2FlowNoRedirect(APP_KEY, APP_SECRET) | ||
|
|
||
| authorize_url = auth_flow.start() | ||
| print "1. Go to: " + authorize_url | ||
| print "2. Click \\"Allow\\" (you might have to log in first)." | ||
| print "3. Copy the authorization code." | ||
| print("1. Go to: " + authorize_url) | ||
| print("2. Click \\"Allow\\" (you might have to log in first).") | ||
| print("3. Copy the authorization code.") | ||
| auth_code = raw_input("Enter the authorization code here: ").strip() | ||
|
|
||
| try: | ||
| oauth_result = auth_flow.finish(auth_code) | ||
| except Exception, e: | ||
| except Exception as e: | ||
| print('Error: %s' % (e,)) | ||
| return | ||
|
|
||
| dbx = Dropbox(oauth_result.access_token) | ||
| """ | ||
|
|
||
| def __init__(self, consumer_key, consumer_secret, locale=None, token_access_type='legacy'): # noqa: E501; pylint: disable=useless-super-delegation | ||
| def __init__(self, consumer_key, consumer_secret, locale=None, token_access_type='legacy', | ||
| scope=None, include_granted_scopes=None): | ||
| # noqa: E501; pylint: disable=useless-super-delegation | ||
| """ | ||
| Construct an instance. | ||
|
|
||
|
|
@@ -258,12 +291,21 @@ def __init__(self, consumer_key, consumer_secret, locale=None, token_access_type | |
| legacy - creates one long-lived token with no expiration | ||
| online - create one short-lived token with an expiration | ||
| offline - create one short-lived token with an expiration with a refresh token | ||
| :param list scope: list of scopes to request in base oauth flow. If left blank, | ||
| will default to all scopes for app | ||
| :param str include_granted_scopes: which scopes to include from previous grants | ||
| From the following enum: | ||
| user - include user scopes in the grant | ||
| team - include team scopes in the grant | ||
| Note: if this user has never linked the app, include_granted_scopes must be None | ||
| """ | ||
| super(DropboxOAuth2FlowNoRedirect, self).__init__( | ||
| consumer_key, | ||
| consumer_secret, | ||
| locale, | ||
| token_access_type, | ||
| scope, | ||
| include_granted_scopes, | ||
| ) | ||
|
|
||
| def start(self): | ||
|
|
@@ -275,7 +317,8 @@ def start(self): | |
| access the user's Dropbox account. Tell the user to visit this URL | ||
| and approve your app. | ||
| """ | ||
| return self._get_authorize_url(None, None, self.token_access_type) | ||
| return self._get_authorize_url(None, None, self.token_access_type, self.scope, | ||
| self.include_granted_scopes) | ||
|
|
||
| def finish(self, code): | ||
| """ | ||
|
|
@@ -337,7 +380,8 @@ def dropbox_auth_finish(web_app_session, request): | |
| """ | ||
|
|
||
| def __init__(self, consumer_key, consumer_secret, redirect_uri, session, | ||
| csrf_token_session_key, locale=None, token_access_type='legacy'): | ||
| csrf_token_session_key, locale=None, token_access_type='legacy', | ||
| scope=None, include_granted_scopes=None): | ||
| """ | ||
| Construct an instance. | ||
|
|
||
|
|
@@ -361,9 +405,17 @@ def __init__(self, consumer_key, consumer_secret, redirect_uri, session, | |
| legacy - creates one long-lived token with no expiration | ||
| online - create one short-lived token with an expiration | ||
| offline - create one short-lived token with an expiration with a refresh token | ||
| :param list scope: list of scopes to request in base oauth flow. If left blank, | ||
| will default to all scopes for app | ||
| :param str include_granted_scopes: which scopes to include from previous grants | ||
| From the following enum: | ||
| user - include user scopes in the grant | ||
| team - include team scopes in the grant | ||
| Note: if this user has never linked the app, include_granted_scopes must be None | ||
| """ | ||
| super(DropboxOAuth2Flow, self).__init__(consumer_key, consumer_secret, | ||
| locale, token_access_type) | ||
| super(DropboxOAuth2Flow, self).__init__(consumer_key, consumer_secret, locale, | ||
| token_access_type, scope, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest passing kwargs with keyword |
||
| include_granted_scopes) | ||
| self.redirect_uri = redirect_uri | ||
| self.session = session | ||
| self.csrf_token_session_key = csrf_token_session_key | ||
|
|
@@ -397,7 +449,8 @@ def start(self, url_state=None): | |
| state += "|" + url_state | ||
| self.session[self.csrf_token_session_key] = csrf_token | ||
|
|
||
| return self._get_authorize_url(self.redirect_uri, state, self.token_access_type) | ||
| return self._get_authorize_url(self.redirect_uri, state, self.token_access_type, | ||
| self.scope, self.include_granted_scopes) | ||
|
|
||
| def finish(self, query_params): | ||
| """ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #!/usr/bin/env python3 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth adding document right now. Saying that this example is only for certain partners. Otherwise this might confuse people. The example/readme part in Github is educational. So we want to make sure they are as clear as possible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually will change this to a working example so people can use it today There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool |
||
|
|
||
| import dropbox | ||
| from dropbox import DropboxOAuth2FlowNoRedirect | ||
|
|
||
| APP_KEY = "" | ||
| APP_SECRET = "" | ||
|
|
||
| auth_flow = DropboxOAuth2FlowNoRedirect(APP_KEY, APP_SECRET) | ||
|
|
||
| authorize_url = auth_flow.start() | ||
| print("1. Go to: " + authorize_url) | ||
| print("2. Click \"Allow\" (you might have to log in first).") | ||
| print("3. Copy the authorization code.") | ||
| auth_code = input("Enter the authorization code here: ").strip() | ||
|
|
||
| try: | ||
| oauth_result = auth_flow.finish(auth_code) | ||
| print(oauth_result) | ||
| except Exception as e: | ||
| print('Error: %s' % (e,)) | ||
|
|
||
| dbx = dropbox.Dropbox(oauth2_access_token=oauth_result.access_token, | ||
| app_key=APP_KEY, app_secret=APP_SECRET) | ||
| dbx.users_get_current_account() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| pytest | ||
| mock | ||
| pytest-mock | ||
| pytest-mock |
Uh oh!
There was an error while loading. Please reload this page.