From 2a6940710154aaf64d2bd58bd02d53165003052b Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 17:23:24 +0200 Subject: [PATCH 1/8] Formatted OAuth2FlowNoRedirectResult Changed singel args to : param --- dropbox/oauth.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index 733b9f1a..c5a40a6b 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -44,20 +44,17 @@ class OAuth2FlowNoRedirectResult(object): 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. + :arg str access_token: Token to be used to authenticate later requests. + :arg str refresh_token: Token to be used to acquire new access token when existing one + expires. + :arg expiration: Either the number of seconds from now that the token expires in or the + datetime at which the token expires. + :type expiration: int, datetime + :arg str account_id: The Dropbox user's account ID. + :arg str user_id: Deprecated (use account_id instead). + :arg str refresh_token: Token to be used to acquire new access token when existing one + expires. + :arg list scope: List of scopes to request in base oauth flow. """ self.access_token = access_token if not expiration: From 1c88d6994a49a4ca4b97d5bc2917f593a8325b9b Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 17:27:30 +0200 Subject: [PATCH 2/8] Deleted duplicate parameters --- dropbox/oauth.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index c5a40a6b..9f121019 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -44,17 +44,15 @@ class OAuth2FlowNoRedirectResult(object): def __init__(self, access_token, account_id, user_id, refresh_token, expiration, scope): """ - :arg str access_token: Token to be used to authenticate later requests. - :arg str refresh_token: Token to be used to acquire new access token when existing one + :param str access_token: Token to be used to authenticate later requests. + :param str account_id: The Dropbox user's account ID. + :param str user_id: Deprecated (use :py:meth:account_id instead). + :param str refresh_token: Token to be used to acquire new access token when existing one expires. - :arg expiration: Either the number of seconds from now that the token expires in or the + :param expiration: Either the number of seconds from now that the token expires in or the datetime at which the token expires. :type expiration: int, datetime - :arg str account_id: The Dropbox user's account ID. - :arg str user_id: Deprecated (use account_id instead). - :arg str refresh_token: Token to be used to acquire new access token when existing one - expires. - :arg list scope: List of scopes to request in base oauth flow. + :param list scope: List of scopes to request in base oauth flow. """ self.access_token = access_token if not expiration: From a7366a10adfbe8967c1772b9ad5c46564c03d629 Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 17:44:24 +0200 Subject: [PATCH 3/8] Updated OAuth2FlowResult Also fixed some mistakes from the previous commit. --- dropbox/oauth.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index 9f121019..2b4891ec 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -47,11 +47,12 @@ def __init__(self, access_token, account_id, user_id, refresh_token, expiration, :param str access_token: Token to be used to authenticate later requests. :param str account_id: The Dropbox user's account ID. :param str user_id: Deprecated (use :py:meth:account_id instead). + :param str user_id: Deprecated (use :attr:`account_id` instead). :param str refresh_token: Token to be used to acquire new access token when existing one expires. :param expiration: Either the number of seconds from now that the token expires in or the datetime at which the token expires. - :type expiration: int, datetime + :type expiration: int or datetime :param list scope: List of scopes to request in base oauth flow. """ self.access_token = access_token @@ -87,9 +88,7 @@ def __init__(self, access_token, account_id, user_id, url_state, refresh_token, """ Same as OAuth2FlowNoRedirectResult but with url_state. - Args: - url_state (str): The url state that was set by - :meth:`DropboxOAuth2Flow.start`. + :param str url_state: The url state that was set by :meth:`DropboxOAuth2Flow.start`. """ super(OAuth2FlowResult, self).__init__( access_token=access_token, From 9eb33567c6dc0897b40c170ab29ebe78f2761ba1 Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 17:44:53 +0200 Subject: [PATCH 4/8] Cleaned up from previous commit --- dropbox/oauth.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index 2b4891ec..3e03797d 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -46,7 +46,6 @@ def __init__(self, access_token, account_id, user_id, refresh_token, expiration, """ :param str access_token: Token to be used to authenticate later requests. :param str account_id: The Dropbox user's account ID. - :param str user_id: Deprecated (use :py:meth:account_id instead). :param str user_id: Deprecated (use :attr:`account_id` instead). :param str refresh_token: Token to be used to acquire new access token when existing one expires. From e7dbab24cb204588f5bfef0e1b5a242c4ea61f40 Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 18:01:06 +0200 Subject: [PATCH 5/8] Add link to oauth examples --- dropbox/oauth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index 3e03797d..3d619aa4 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -272,7 +272,7 @@ class DropboxOAuth2FlowNoRedirect(DropboxOAuth2FlowBase): OAuth 2 authorization helper for apps that can't provide a redirect URI (such as the command-line example apps). - See examples under example/oauth + See examples under `example/oauth `_ """ @@ -359,7 +359,7 @@ class DropboxOAuth2Flow(DropboxOAuth2FlowBase): user authorize your app. The second involves getting an OAuth 2 access token from Dropbox. - See examples under example/oauth + See examples under `example/oauth `_ """ From d1b7cdbd3124b8a69211f5648da03502f11e1594 Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 18:28:10 +0200 Subject: [PATCH 6/8] Formatted line lenght and added sphinx tags --- dropbox/oauth.py | 181 +++++++++++++++++++++-------------------------- 1 file changed, 80 insertions(+), 101 deletions(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index 3d619aa4..5f60efc5 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -79,13 +79,13 @@ def __repr__(self): class OAuth2FlowResult(OAuth2FlowNoRedirectResult): """ - Authorization information for an OAuth2Flow with redirect. + Authorization information for an :class:OAuth2Flow with redirect. """ def __init__(self, access_token, account_id, user_id, url_state, refresh_token, expires_in, scope): """ - Same as OAuth2FlowNoRedirectResult but with url_state. + Same as :class:OAuth2FlowNoRedirectResult but with url_state. :param str url_state: The url state that was set by :meth:`DropboxOAuth2Flow.start`. """ @@ -227,9 +227,8 @@ def _finish(self, code, redirect_uri, code_verifier): def build_path(self, target, params=None): """Build the path component for an API URL. - This method urlencodes the parameters, adds them - to the end of the target url, and puts a marker for the API - version in front. + This method urlencodes the parameters, adds them to the end of the target url, and puts a + marker for the API version in front. :param str target: A target url (e.g. '/files') to build upon. :param dict params: Optional dictionary of parameters (name to value). @@ -256,8 +255,7 @@ def build_path(self, target, params=None): def build_url(self, target, params=None, host=API_HOST): """Build an API URL. - This method adds scheme and hostname to the path - returned from build_path. + This method adds scheme and hostname to the path returned from build_path. :param str target: A target url (e.g. '/files') to build upon. :param dict params: Optional dictionary of parameters (name to value). @@ -283,10 +281,9 @@ def __init__(self, consumer_key, consumer_secret=None, locale=None, token_access :param str consumer_key: Your API app's "app key". :param str consumer_secret: Your API app's "app secret". - :param str locale: The locale of the user of your application. For - example "en" or "en_US". Some API calls return localized data and - error messages; this setting tells the server which locale to use. - By default, the server uses "en_US". + :param str locale: The locale of the user of your application. For example "en" or "en_US". + Some API calls return localized data and error messages; this setting tells the server + which locale to use. By default, the server uses "en_US". :param str token_access_type: the type of token to be requested. From the following enum: @@ -294,22 +291,21 @@ def __init__(self, consumer_key, consumer_secret=None, locale=None, token_access * 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 + :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 + * *Note*: if this user has never linked the app, include_granted_scopes must be None :param bool use_pkce: Whether or not to use Sha256 based PKCE. PKCE should be only use on client apps which doesn't call your server. It is less secure than non-PKCE flow but can be used if you are unable to safely retrieve your app secret. :param Optional[float] timeout: Maximum duration in seconds that - client will wait for any single packet from the - server. After the timeout the client will give up on - connection. If `None`, client will wait forever. Defaults + client will wait for any single packet from the server. After the timeout the client + will give up on connection. If `None`, client will wait forever. Defaults to 100 seconds. """ super(DropboxOAuth2FlowNoRedirect, self).__init__( @@ -327,10 +323,9 @@ def start(self): """ Starts the OAuth 2 authorization process. - :return: The URL for a page on Dropbox's website. This page will let - the user "approve" your app, which gives your app permission to - access the user's Dropbox account. Tell the user to visit this URL - and approve your app. + :return: The URL for a page on Dropbox's website. This page will let the user "approve" + your app, which gives your app permission to 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, scope=self.scope, @@ -339,13 +334,13 @@ def start(self): def finish(self, code): """ - If the user approves your app, they will be presented with an - "authorization code". Have the user copy/paste that authorization code - into your app and then call this method to get an access token. + If the user approves your app, they will be presented with an "authorization code". + Have the user copy/paste that authorization code into your app and then call this method to + get an access token. :param str code: The authorization code shown to the user when they approved your app. - :rtype: OAuth2FlowNoRedirectResult + :rtype: :class:OAuth2FlowNoRedirectResult :raises: The same exceptions as :meth:`DropboxOAuth2Flow.finish()`. """ return self._finish(code, None, self.code_verifier) @@ -353,11 +348,10 @@ def finish(self, code): class DropboxOAuth2Flow(DropboxOAuth2FlowBase): """ - OAuth 2 authorization helper. Use this for web apps. + OAuth 2 authorization helper. Use this for web apps. - OAuth 2 has a two-step authorization process. The first step is having the - user authorize your app. The second involves getting an OAuth 2 access - token from Dropbox. + OAuth 2 has a two-step authorization process. The first step is having the user authorize your + app. The second involves getting an OAuth 2 access token from Dropbox. See examples under `example/oauth `_ @@ -372,41 +366,38 @@ def __init__(self, consumer_key, redirect_uri, session, :param str consumer_key: Your API app's "app key". :param str consumer_secret: Your API app's "app secret". - :param str redirect_uri: The URI that the Dropbox server will redirect - the user to after the user finishes authorizing your app. This URI - must be HTTPS-based and pre-registered with the Dropbox servers, - though localhost URIs are allowed without pre-registration and can - be either HTTP or HTTPS. - :param dict session: A dict-like object that represents the current - user's web session (will be used to save the CSRF token). - :param str csrf_token_session_key: The key to use when storing the CSRF - token in the session (for example: "dropbox-auth-csrf-token"). - :param str locale: The locale of the user of your application. For - example "en" or "en_US". Some API calls return localized data and - error messages; this setting tells the server which locale to use. - By default, the server uses "en_US". - :param str token_access_type: the type of token to be requested. + :param str redirect_uri: The URI that the Dropbox server will redirect the user to after the + user finishes authorizing your app. This URI must be HTTPS-based and pre-registered + with the Dropbox servers, though localhost URIs are allowed without pre-registration and + can be either HTTP or HTTPS. + :param dict session: A dict-like object that represents the current user's web session + (Will be used to save the CSRF token). + :param str csrf_token_session_key: The key to use when storing the CSRF token in the session + (For example: "dropbox-auth-csrf-token"). + :param str locale: The locale of the user of your application. For example "en" or "en_US". + Some API calls return localized data and error messages; this setting tells the server + which locale to use. By default, the server uses "en_US". + :param str token_access_type: The type of token to be requested. From the following enum: * 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, + :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 + :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 + * *Note*: If this user has never linked the app, :attr:`include_granted_scopes` must \ + be `None` :param bool use_pkce: Whether or not to use Sha256 based PKCE - :param Optional[float] timeout: Maximum duration in seconds that - client will wait for any single packet from the - server. After the timeout the client will give up on - connection. If `None`, client will wait forever. Defaults - to 100 seconds. + :param Optional[float] timeout: Maximum duration in seconds that client will wait for any + single packet from the server. After the timeout the client will give up on connection. + If `None`, client will wait forever. Defaults to 100 seconds. """ super(DropboxOAuth2Flow, self).__init__( @@ -427,24 +418,19 @@ def start(self, url_state=None): """ Starts the OAuth 2 authorization process. - This function builds an "authorization URL". You should redirect your - user's browser to this URL, which will give them an opportunity to - grant your app access to their Dropbox account. When the user - completes this process, they will be automatically redirected to the - ``redirect_uri`` you passed in to the constructor. - - This function will also save a CSRF token to - ``session[csrf_token_session_key]`` (as provided to the constructor). - This CSRF token will be checked on :meth:`finish()` to prevent request - forgery. - - :param str url_state: Any data that you would like to keep in the URL - through the authorization process. This exact value will be - returned to you by :meth:`finish()`. - :return: The URL for a page on Dropbox's website. This page will let - the user "approve" your app, which gives your app permission to - access the user's Dropbox account. Tell the user to visit this URL - and approve your app. + This function builds an "authorization URL". You should redirect your user's browser to this + URL, which will give them an opportunity to grant your app access to their Dropbox + account. When the user completes this process, they will be automatically redirected to + the :attr:`redirect_uri` you passed in to the constructor. This function will also save + a CSRF token to :attr:`session[csrf_token_session_key]` + (as provided to the constructor). This CSRF token will be checked on :meth:`finish()` + to prevent request forgery. + + :param str url_state: Any data that you would like to keep in the URL through the + authorization process. This exact value will be returned to you by :meth:`finish()`. + :return: The URL for a page on Dropbox's website. This page will let the user "approve" your + app, which gives your app permission to access the user's Dropbox account. Tell the user + to visit this URL and approve your app. """ csrf_token = base64.urlsafe_b64encode(os.urandom(16)).decode('ascii') state = csrf_token @@ -459,23 +445,19 @@ def start(self, url_state=None): def finish(self, query_params): """ - Call this after the user has visited the authorize URL (see - :meth:`start()`), approved your app and was redirected to your redirect - URI. + Call this after the user has visited the authorize URL (see :meth:`start()`), approved your + app and was redirected to your redirect URI. - :param dict query_params: The query parameters on the GET request to - your redirect URI. + :param dict query_params: The query parameters on the GET request to your redirect URI. :rtype: OAuth2FlowResult - :raises: :class:`BadRequestException` If the redirect URL was missing - parameters or if the given parameters were not valid. - :raises: :class:`BadStateException` If there's no CSRF token in the - session. - :raises: :class:`CsrfException` If the ``state`` query parameter - doesn't contain the CSRF token from the user's session. - :raises: :class:`NotApprovedException` If the user chose not to - approve your app. - :raises: :class:`ProviderException` If Dropbox redirected to your - redirect URI with some unexpected error identifier and error message. + :raises: :class:`BadRequestException` If the redirect URL was missing parameters or if the + given parameters were not valid. + :raises: :class:`BadStateException` If there's no CSRF token in the session. + :raises: :class:`CsrfException` If the :attr:`state` query parameter doesn't contain the + CSRF token from the user's session. + :raises: :class:`NotApprovedException` If the user chose not to approve your app. + :raises: :class:`ProviderException` If Dropbox redirected to your redirect URI with some + unexpected error identifier and error message. """ # Check well-formedness of request. @@ -546,8 +528,7 @@ def finish(self, query_params): class BadRequestException(Exception): """ - Thrown if the redirect URL was missing parameters or if the - given parameters were not valid. + Thrown if the redirect URL was missing parameters or if the given parameters were not valid. The recommended action is to show an HTTP 400 error page. """ @@ -556,19 +537,18 @@ class BadRequestException(Exception): class BadStateException(Exception): """ - Thrown if all the parameters are correct, but there's no CSRF token in the - session. This probably means that the session expired. + Thrown if all the parameters are correct, but there's no CSRF token in the session. This + probably means that the session expired. - The recommended action is to redirect the user's browser to try the - approval process again. + The recommended action is to redirect the user's browser to try the approval process again. """ pass class CsrfException(Exception): """ - Thrown if the given 'state' parameter doesn't contain the CSRF token from - the user's session. This is blocked to prevent CSRF attacks. + Thrown if the given 'state' parameter doesn't contain the CSRF token from the user's session. + This is blocked to prevent CSRF attacks. The recommended action is to respond with an HTTP 403 error page. """ @@ -584,11 +564,10 @@ class NotApprovedException(Exception): class ProviderException(Exception): """ - Dropbox redirected to your redirect URI with some unexpected error - identifier and error message. + Dropbox redirected to your redirect URI with some unexpected error identifier and error message. - The recommended action is to log the error, tell the user something went - wrong, and let them try again. + The recommended action is to log the error, tell the user something went wrong, and let them try + again. """ pass @@ -614,11 +593,11 @@ def _safe_equals(a, b): def _params_to_urlencoded(params): """ - Returns a application/x-www-form-urlencoded ``str`` representing the - key/value pairs in ``params``. + Returns a application/x-www-form-urlencoded :class:`str` representing the key/value pairs in + :attr:`params`. - Keys are values are ``str()``'d before calling ``urllib.urlencode``, with - the exception of unicode objects which are utf8-encoded. + Keys are values are ``str()``'d before calling :meth:`urllib.urlencode`, with the exception of + unicode objects which are utf8-encoded. """ def encode(o): if isinstance(o, six.binary_type): From 7274f0bc5a728d461ad3a937dee5ae5d13de3b25 Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 18:37:50 +0200 Subject: [PATCH 7/8] Added missing classes --- dropbox/oauth.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index 5f60efc5..9021791f 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -79,13 +79,13 @@ def __repr__(self): class OAuth2FlowResult(OAuth2FlowNoRedirectResult): """ - Authorization information for an :class:OAuth2Flow with redirect. + Authorization information for an :class:`OAuth2Flow` with redirect. """ def __init__(self, access_token, account_id, user_id, url_state, refresh_token, expires_in, scope): """ - Same as :class:OAuth2FlowNoRedirectResult but with url_state. + Same as :class:`OAuth2FlowNoRedirectResult` but with url_state. :param str url_state: The url state that was set by :meth:`DropboxOAuth2Flow.start`. """ @@ -340,7 +340,7 @@ def finish(self, code): :param str code: The authorization code shown to the user when they approved your app. - :rtype: :class:OAuth2FlowNoRedirectResult + :rtype: :class:`OAuth2FlowNoRedirectResult` :raises: The same exceptions as :meth:`DropboxOAuth2Flow.finish()`. """ return self._finish(code, None, self.code_verifier) @@ -449,7 +449,7 @@ def finish(self, query_params): app and was redirected to your redirect URI. :param dict query_params: The query parameters on the GET request to your redirect URI. - :rtype: OAuth2FlowResult + :rtype: class:`OAuth2FlowResult` :raises: :class:`BadRequestException` If the redirect URL was missing parameters or if the given parameters were not valid. :raises: :class:`BadStateException` If there's no CSRF token in the session. From 9e7d4fbd15bd6127aae1a6ef12f0ecc6c7306607 Mon Sep 17 00:00:00 2001 From: Lucurus Date: Thu, 17 Sep 2020 21:32:30 +0200 Subject: [PATCH 8/8] Fixed linter error --- dropbox/oauth.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dropbox/oauth.py b/dropbox/oauth.py index 9021791f..6d8cbdd8 100644 --- a/dropbox/oauth.py +++ b/dropbox/oauth.py @@ -270,7 +270,8 @@ class DropboxOAuth2FlowNoRedirect(DropboxOAuth2FlowBase): OAuth 2 authorization helper for apps that can't provide a redirect URI (such as the command-line example apps). - See examples under `example/oauth `_ + See examples under `example/oauth `_ """ @@ -353,7 +354,8 @@ class DropboxOAuth2Flow(DropboxOAuth2FlowBase): OAuth 2 has a two-step authorization process. The first step is having the user authorize your app. The second involves getting an OAuth 2 access token from Dropbox. - See examples under `example/oauth `_ + See examples under `example/oauth `_ """