From 0c892dd4977df9defa3fd8102ff33d534ab2f752 Mon Sep 17 00:00:00 2001 From: Stephen Rosen Date: Fri, 13 Sep 2024 22:07:32 -0500 Subject: [PATCH] Refactor Authorization docs (leaving stub pages behind) (#1046) * Move authorizer documentation into authorization/ - Move `authorization.rst` to `authorization/globus_authorizers.rst` - Create a stub at `authorization.rst` (orphan doc) which directs users to the new page - Introduce `authorization/index.rst` with a single-item TOC * Move scope docs into `authorization/` - Move `scopes.rst` to `authorization/scopes_and_consents/scopes.rst` - Add `scopes.rst` as a stub, pointing to the new page - Reduce `experimental/scope_parser.rst` to a stub (was full doc!) - Move `MutableScope` docs to a separate page in `scopes_and_consents/` and note it as deprecated (doc note only) - Update `MutableScope` usage docs to use `Scope` instead - Update toctrees to include the new docs * Apply suggestions from code review Co-authored-by: derek-globus <113056046+derek-globus@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Changes per review * Apply suggestions from code review Co-authored-by: Ada <107940310+ada-globus@users.noreply.github.com> --------- Co-authored-by: derek-globus <113056046+derek-globus@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Ada <107940310+ada-globus@users.noreply.github.com> --- docs/authorization.rst | 87 +------ docs/authorization/globus_authorizers.rst | 93 +++++++ docs/authorization/index.rst | 10 + .../scopes_and_consents/index.rst | 33 +++ .../scopes_and_consents/mutable_scopes.rst | 95 +++++++ .../scopes_and_consents/scopes.rst | 246 ++++++++++++++++++ docs/experimental/scope_parser.rst | 32 +-- docs/index.rst | 3 +- docs/scopes.rst | 213 +-------------- docs/services/index.rst | 4 +- docs/tutorial.rst | 2 +- 11 files changed, 488 insertions(+), 330 deletions(-) create mode 100644 docs/authorization/globus_authorizers.rst create mode 100644 docs/authorization/index.rst create mode 100644 docs/authorization/scopes_and_consents/index.rst create mode 100644 docs/authorization/scopes_and_consents/mutable_scopes.rst create mode 100644 docs/authorization/scopes_and_consents/scopes.rst diff --git a/docs/authorization.rst b/docs/authorization.rst index bba9dd5af..369569e8e 100644 --- a/docs/authorization.rst +++ b/docs/authorization.rst @@ -1,85 +1,4 @@ -.. _authorization: +:orphan: -API Authorization -================= - -.. currentmodule:: globus_sdk.authorizers - -Authorizing calls against Globus can be a complex process. -In particular, if you are using Refresh Tokens and short-lived Access Tokens, -you may need to take particular care managing your Authorization state. - -Within the SDK, we solve this problem by using :class:`GlobusAuthorizer`\s, -which are attached to clients. A :class:`GlobusAuthorizer` is an object which -defines the following two operations: - -- get an ``Authorization`` header -- handle a 401 Unauthorized error - -Whenever using the :ref:`Service Clients `, you should be passing in an -authorizer when you create a new client unless otherwise specified. - -The type of authorizer you will use depends very much on your application, but -if you want examples you should look at the :ref:`examples section -`. -It may help to start with the examples and come back to the full documentation -afterwards. - -The Authorizer Interface ------------------------- - -We define the interface for ``GlobusAuthorizer`` objects in terms of an -Abstract Base Class: - -.. autoclass:: GlobusAuthorizer - :members: - :member-order: bysource - -``GlobusAuthorizer`` objects that fetch new access tokens when their existing -ones expire or a 401 is received implement the RenewingAuthorizer class - -.. autoclass:: RenewingAuthorizer - :members: get_authorization_header, handle_missing_authorization - :member-order: bysource - :show-inheritance: - -``GlobusAuthorizer`` objects which have a static authorization header are all -implemented using the static authorizer class: - -.. autoclass:: StaticGlobusAuthorizer - :members: - :member-order: bysource - :show-inheritance: - -Authorizer Types ----------------- - -.. currentmodule:: globus_sdk - -All of these types of authorizers can be imported from -``globus_sdk.authorizers``. - -.. autoclass:: NullAuthorizer - :members: - :member-order: bysource - :show-inheritance: - -.. autoclass:: BasicAuthorizer - :members: - :member-order: bysource - :show-inheritance: - -.. autoclass:: AccessTokenAuthorizer - :members: - :member-order: bysource - :show-inheritance: - -.. autoclass:: RefreshTokenAuthorizer - :members: - :member-order: bysource - :show-inheritance: - -.. autoclass:: ClientCredentialsAuthorizer - :members: - :member-order: bysource - :show-inheritance: +The documentation which was found on this page has moved to +:ref:`Globus Authorizers `. diff --git a/docs/authorization/globus_authorizers.rst b/docs/authorization/globus_authorizers.rst new file mode 100644 index 000000000..bb82bd847 --- /dev/null +++ b/docs/authorization/globus_authorizers.rst @@ -0,0 +1,93 @@ +.. _globus_authorizers: + +Globus Authorizers +================== + +.. currentmodule:: globus_sdk.authorizers + +Globus SDK clients need credentials (tokens) to authenticate against services +and authorize their various API calls. Using Globus Auth, the Globus OAuth2 +service, clients can be provided with credentials which are either static or +dynamic. + +The interface used to handle these credentials is :class:`GlobusAuthorizer`. +:class:`GlobusAuthorizer` defines methods which provide an ``Authorization`` +header for HTTP requests, and different implementations handle Refresh Tokens, +Access Tokens, Client Credentials, and their various usage modes. + +A :class:`GlobusAuthorizer` is an object which defines the following two +operations: + +- get an ``Authorization`` header +- handle a 401 Unauthorized error + +Clients contain authorizers, and use them to get and refresh their credentials. +Whenever using the :ref:`Service Clients `, you should be passing in an +authorizer when you create a new client unless otherwise specified. + +The type of authorizer you will use depends very much on your application, but +if you want examples you should look at the :ref:`examples section +`. +It may help to start with the examples and come back to the reference +documentation afterwards. + +The Authorizer Interface +------------------------ + +We define the interface for ``GlobusAuthorizer`` objects in terms of an +Abstract Base Class: + +.. autoclass:: GlobusAuthorizer + :members: + :member-order: bysource + +Authorizers within this SDK fall into two categories: + + * "Static Authorizers" already contain all authorization data and simply format it + into the proper authorization header. + These all inherit from the ``StaticGlobusAuthorizer`` class. + + * "Renewing Authorizer" take some initial parameters but internally define a + functional behavior to acquire new authorization data as necessary. + These all inherit from the ``RenewingGlobusAuthorizer`` class. + +.. autoclass:: StaticGlobusAuthorizer + :member-order: bysource + :show-inheritance: + +.. autoclass:: RenewingAuthorizer + :member-order: bysource + :show-inheritance: + +Authorizer Types +---------------- + +.. currentmodule:: globus_sdk + +All of these types of authorizers can be imported from +``globus_sdk.authorizers``. + +.. autoclass:: AccessTokenAuthorizer + :members: + :member-order: bysource + :show-inheritance: + +.. autoclass:: RefreshTokenAuthorizer + :members: + :member-order: bysource + :show-inheritance: + +.. autoclass:: ClientCredentialsAuthorizer + :members: + :member-order: bysource + :show-inheritance: + +.. autoclass:: BasicAuthorizer + :members: + :member-order: bysource + :show-inheritance: + +.. autoclass:: NullAuthorizer + :members: + :member-order: bysource + :show-inheritance: diff --git a/docs/authorization/index.rst b/docs/authorization/index.rst new file mode 100644 index 000000000..7e92ef2a7 --- /dev/null +++ b/docs/authorization/index.rst @@ -0,0 +1,10 @@ +Globus SDK Authorization +======================== + +Components of the Globus SDK which handle application authorization. + +.. toctree:: + :maxdepth: 1 + + globus_authorizers + scopes_and_consents/index diff --git a/docs/authorization/scopes_and_consents/index.rst b/docs/authorization/scopes_and_consents/index.rst new file mode 100644 index 000000000..81adef1d8 --- /dev/null +++ b/docs/authorization/scopes_and_consents/index.rst @@ -0,0 +1,33 @@ +Scopes and Consents +=================== + +Globus uses OAuth2 scopes to control access to different APIs and allow +applications provide a least-privilege security guarantee to their users. + +Overview +-------- + +A "Consent" is a record, in Globus Auth, that an application is allowed to take +some action on behalf of a user. A "Scope" is the name of some action or set of +actions. + +For example, ``urn:globus:auth:scope:groups.api.globus.org:all`` is a scope +which gives full access to Globus Groups. Users _consent_ to allow applications, +like the Globus CLI, to get credentials which are "valid for this scope", and +thereby to view and manipulate their group memberships. + +For more information, see +`this docs.globus.org explanation of scopes and consents +`_. + +Reference +--------- + +Within the Globus SDK, Scopes and Consents are modeled using several objects +which make learning about and manipulating these data easier. + +.. toctree:: + :maxdepth: 1 + + scopes + mutable_scopes diff --git a/docs/authorization/scopes_and_consents/mutable_scopes.rst b/docs/authorization/scopes_and_consents/mutable_scopes.rst new file mode 100644 index 000000000..17dd8dff3 --- /dev/null +++ b/docs/authorization/scopes_and_consents/mutable_scopes.rst @@ -0,0 +1,95 @@ +.. _mutable_scopes: + +.. currentmodule:: globus_sdk.scopes + +MutableScopes +============= + +.. warning:: + + The ``MutableScope`` class and its interfaces are considered a legacy + feature. They will be deprecated and removed in a future SDK release. + + Users should prefer to use ``globus_sdk.Scope`` instead. + ``globus_sdk.Scope``, documented in :ref:`the scopes documentation `, + provides strictly more features and has a superior interface. + +In order to support optional and dependent scopes, a type is +provided by ``globus_sdk.scopes``: the ``MutableScope`` class. + +``MutableScope`` can be constructed directly or via a ``ScopeBuilder``'s +``make_mutable`` method, given a scope's short name. + +For example, one can create a ``MutableScope`` from the Groups "all" scope +as follows: + +.. code-block:: python + + from globus_sdk.scopes import GroupsScopes + + scope = GroupsScopes.make_mutable("all") + +``MutableScope`` objects primarily provide two main pieces of functionality: +dynamically building a scope tree and serializing to a string. + +Dynamic Scope Construction +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``MutableScope`` objects provide a tree-like interface for constructing scopes +and their dependencies. + +For example, the transfer scope dependent upon a collection scope may be +constructed by means of ``MutableScope`` methods and the ``make_mutable`` method +of scope builders thusly: + +.. code-block:: python + + from globus_sdk.scopes import GCSCollectionScopeBuilder, TransferScopes + + MAPPED_COLLECTION_ID = "...ID HERE..." + + # create the scopes with make_mutable + transfer_scope = TransferScopes.make_mutable("all") + data_access_scope = GCSCollectionScopeBuilder(MAPPED_COLLECTION_ID).make_mutable( + "data_access", optional=True + ) + # add data_access as a dependency + transfer_scope.add_dependency(data_access_scope) + +``MutableScope``\s can be used in most of the same locations where scope +strings can be used, but you can also call ``str()`` on them to get a +stringified representation. + +Serializing Scopes +~~~~~~~~~~~~~~~~~~ + +Whenever scopes are being sent to Globus services, they need to be encoded as +strings. All mutable scope objects support this by means of their defined +``serialize`` method. Note that ``__str__`` for a ``MutableScope`` is just an +alias for ``serialize``. For example, the following is valid usage to demonstrate +``str()``, ``repr()``, and ``serialize()``: + +.. code-block:: pycon + + >>> from globus_sdk.scopes import MutableScope + >>> foo = MutableScope("foo") + >>> bar = MutableScope("bar") + >>> bar.add_dependency("baz") + >>> foo.add_dependency(bar) + >>> print(str(foo)) + foo[bar[baz]] + >>> print(bar.serialize()) + bar[baz] + >>> alpha = MutableScope("alpha") + >>> alpha.add_dependency(MutableScope("beta", optional=True)) + >>> print(str(alpha)) + alpha[*beta] + >>> print(repr(alpha)) + MutableScope("alpha", dependencies=[MutableScope("beta", optional=True)]) + +MutableScope Reference +~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: MutableScope + :members: + :show-inheritance: diff --git a/docs/authorization/scopes_and_consents/scopes.rst b/docs/authorization/scopes_and_consents/scopes.rst new file mode 100644 index 000000000..fe9802b62 --- /dev/null +++ b/docs/authorization/scopes_and_consents/scopes.rst @@ -0,0 +1,246 @@ +.. _scopes: + +.. currentmodule:: globus_sdk.scopes + +Scopes and ScopeBuilders +======================== + +OAuth2 Scopes for various Globus services are represented by ``ScopeBuilder`` +objects. + +A number of preset scope builders are provided and populated with useful data, +and they are also accessible via the relevant client classes. + +Direct Use (As Constants) +------------------------- + +To use the scope builders directly, import from ``globus_sdk.scopes``. + +For example, one might use the Transfer "all" scope during a login flow like +so: + +.. code-block:: python + + import globus_sdk + from globus_sdk.scopes import TransferScopes + + CLIENT_ID = "" + + client = globus_sdk.NativeAppAuthClient(CLIENT_ID) + client.oauth2_start_flow(requested_scopes=[TransferScopes.all]) + ... + +As Client Attributes +-------------------- + +Token scopes are associated with a particular client which will use that token. +Because of this, each service client contains a ``ScopeBuilder`` attribute (``client.scopes``) defining the relevant scopes for that client. + +For most client classes, this is a class attribute. For example, accessing +``TransferClient.scopes`` is valid: + +.. code-block:: python + + import globus_sdk + + CLIENT_ID = "" + + client = globus_sdk.NativeAppAuthClient(CLIENT_ID) + client.oauth2_start_flow(requested_scopes=[globus_sdk.TransferClient.scopes.all]) + ... + + # or, potentially, after there is a concrete client + _tc = globus_sdk.TransferClient() + client.oauth2_start_flow(requested_scopes=[_tc.scopes.all]) + +As Instance Attributes and Methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some client classes only provide their scopes for instances. These cases cover +services which are distributed or contain multiple subservices with their own +scopes. + +For example, ``GCSClient`` and ``SpecificFlowClient`` each have a ``scopes`` +attribute of ``None`` on their classes. + +In the case of ``SpecificFlowClient``, scopes are populated whenever an +instance is instantiated. So the following usage is valid: + +.. code-block:: python + + import globus_sdk + + FLOW_ID = "" + + client = globus_sdk.SpecificFlowClient(FLOW_ID) + flow_user_scope = client.scopes.user + +In the case of GCS, a distributed service, ``scopes`` is always ``None``. +However, :meth:`globus_sdk.GCSClient.get_gcs_endpoint_scopes` and +:meth:`globus_sdk.GCSClient.get_gcs_collection_scopes` are available helpers +for getting specific collections of scopes. + +Using a Scope Builder to Get Matching Tokens +-------------------------------------------- + +A ``ScopeBuilder`` contains the resource server name used to get token data +from a token response. +To elaborate on the above example: + +.. code-block:: python + + import globus_sdk + from globus_sdk.scopes import TransferScopes + + CLIENT_ID = "" + + client = globus_sdk.NativeAppAuthClient(CLIENT_ID) + client.oauth2_start_flow(requested_scopes=[TransferScopes.all]) + authorize_url = client.oauth2_get_authorize_url() + print("Please go to this URL and login:", authorize_url) + auth_code = input("Please enter the code you get after login here: ").strip() + token_response = client.oauth2_exchange_code_for_tokens(auth_code) + + # use the `resource_server` of a ScopeBuilder to grab the associated token + # data from the response + tokendata = token_response.by_resource_server[TransferScopes.resource_server] + +Scope objects +------------- + +The SDK provides a ``Scope`` object which is the class model for a scope. +``Scope``\s can be parsed from strings and serialized to strings, and support +programmatic manipulations to describe dependent scopes. + +``Scope`` can be constructed using its initializer, or one of its two main +parsing methods: ``Scope.parse`` and ``Scope.deserialize``. +``parse`` produces a list of scopes from a string, while ``deserialize`` +produces exactly one. + +For example, one can create a ``Scope`` from the Groups "all" scope +as follows: + +.. code-block:: python + + from globus_sdk.scopes import GroupsScopes, Scope + + group_scope = Scope.deserialize(GroupsScopes.all) + +``Scope`` objects primarily provide three main pieces of functionality: + + * parsing (deserializing) + * stringifying (serializing) + * scope tree construction + +Scope Construction +~~~~~~~~~~~~~~~~~~ + +``Scope`` objects provide a tree-like interface for constructing scopes +and their dependencies. + +For example, the transfer scope dependent upon a collection scope may be +constructed by means of ``Scope`` methods thusly: + +.. code-block:: python + + from globus_sdk.scopes import GCSCollectionScopeBuilder, TransferScopes, Scope + + MAPPED_COLLECTION_ID = "...ID HERE..." + + # create the scope object, and get the data_access_scope as a string + transfer_scope = Scope(TransferScopes.all) + data_access_scope = GCSCollectionScopeBuilder(MAPPED_COLLECTION_ID).data_access + # add data_access as an optional dependency + transfer_scope.add_dependency(data_access_scope, optional=True) + +``Scope``\s can be used in most of the same locations where scope +strings can be used, but you can also call ``scope.serialize()`` to get a +stringified representation. + +Serializing Scopes +~~~~~~~~~~~~~~~~~~ + +Whenever scopes are being sent to Globus services, they need to be encoded as +strings. All scope objects support this by means of their defined +``serialize`` method. Note that ``__str__`` for a ``Scope`` is just an +alias for ``serialize``. For example, the following is an example of +``str()``, ``repr()``, and ``serialize()`` usage: + +.. code-block:: pycon + + >>> from globus_sdk.scopes import Scope + >>> foo = Scope("foo") + >>> bar = Scope("bar") + >>> bar.add_dependency("baz") + >>> foo.add_dependency(bar) + >>> print(str(foo)) + foo[bar[baz]] + >>> print(bar.serialize()) + bar[baz] + >>> alpha = Scope("alpha") + >>> alpha.add_dependency("beta", optional=True) + >>> print(str(alpha)) + alpha[*beta] + >>> print(repr(alpha)) + Scope("alpha", dependencies=[Scope("beta", optional=True)]) + +Scope Reference +~~~~~~~~~~~~~~~ + +.. autoclass:: Scope + :members: + :member-order: bysource + +.. autoclass:: ScopeParseError + +.. autoclass:: ScopeCycleError + +ScopeBuilders +------------- + +ScopeBuilder Types +~~~~~~~~~~~~~~~~~~ + +.. autoclass:: ScopeBuilder + :members: + :show-inheritance: + +.. autoclass:: GCSEndpointScopeBuilder + :members: + :show-inheritance: + +.. autoclass:: GCSCollectionScopeBuilder + :members: + :show-inheritance: + +.. autoclass:: SpecificFlowScopeBuilder + :members: + :show-inheritance: + +ScopeBuilder Constants +~~~~~~~~~~~~~~~~~~~~~~ + +.. autodata:: globus_sdk.scopes.data.AuthScopes + :annotation: + +.. autodata:: globus_sdk.scopes.data.FlowsScopes + :annotation: + +.. autodata:: globus_sdk.scopes.data.GroupsScopes + :annotation: + +.. autodata:: globus_sdk.scopes.data.NexusScopes + :annotation: + +.. autodata:: globus_sdk.scopes.data.SearchScopes + :annotation: + +.. note:: + + ``TimersScopes`` is also available under the legacy name ``TimerScopes``. + +.. autodata:: globus_sdk.scopes.data.TimersScopes + :annotation: + +.. autodata:: globus_sdk.scopes.data.TransferScopes + :annotation: diff --git a/docs/experimental/scope_parser.rst b/docs/experimental/scope_parser.rst index a4af34fbb..1957debbb 100644 --- a/docs/experimental/scope_parser.rst +++ b/docs/experimental/scope_parser.rst @@ -3,33 +3,5 @@ Scope Parser ============ -.. currentmodule:: globus_sdk.experimental.scope_parser - -This component defines a ``Scope`` object and exposes use of a parser which can -parse scope strings into trees of ``Scope`` objects. -It should be regarded as very similar to the existing ``MutableScope`` object in -``globus_sdk.scopes``. Key differences from ``MutableScope``: - -- ``Scope.parse`` is available, for parsing scopes from strings -- The Globus SDK does not support using ``Scope`` in all of the locations where - ``MutableScope`` is supported -- Scope objects must be stringified for use -- ``Scope`` objects define a ``__contains__`` method, allowing one to check if one scope - properly contains another - -.. note:: - - The scope trees produced by parsing represent prospective consent structures as - would be produced by a single authentication flow in Auth. No external APIs (e.g., - the Get Consents API) are used to validate or mutate the data. - -Reference ---------- - -.. autoclass:: Scope - :members: - :member-order: bysource - :special-members: - -.. autoclass:: ScopeParseError - -.. autoclass:: ScopeCycleError +The experimental scope parser has been promoted into +:ref:`the main Scope implementation `. diff --git a/docs/index.rst b/docs/index.rst index 5b152c4c4..b739ebdc9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -32,9 +32,8 @@ Table of Contents :maxdepth: 2 services/index - scopes local_endpoints - authorization + Authorization tokenstorage config core/index diff --git a/docs/scopes.rst b/docs/scopes.rst index ade7e917c..4a9180682 100644 --- a/docs/scopes.rst +++ b/docs/scopes.rst @@ -1,212 +1,3 @@ -.. _scopes: +:orphan: -.. currentmodule:: globus_sdk.scopes - -Scopes and ScopeBuilders -======================== - -OAuth2 Scopes for various Globus services are represented by ``ScopeBuilder`` -objects. - -A number of pre-set scope builders are provided and populated with useful data, -and they are also accessible via the relevant client classes. - -Direct Use (as constants) -------------------------- - -To use the scope builders directly, import from ``globus_sdk.scopes``. - -For example, one might use the Transfer "all" scope during a login flow like -so: - -.. code-block:: python - - import globus_sdk - from globus_sdk.scopes import TransferScopes - - CLIENT_ID = "" - - client = globus_sdk.NativeAppAuthClient(CLIENT_ID) - client.oauth2_start_flow(requested_scopes=[TransferScopes.all]) - ... - -As Client Class Attributes --------------------------- - -Because the scopes for a token are associated with some concrete client which -will use that token, it makes sense to associate a scope with a client class. - -The Globus SDK does this by providing the ``ScopeBuilder`` for a service as an -attribute of the client. For example, - -.. code-block:: python - - import globus_sdk - - CLIENT_ID = "" - - client = globus_sdk.NativeAppAuthClient(CLIENT_ID) - client.oauth2_start_flow(requested_scopes=[globus_sdk.TransferClient.scopes.all]) - ... - - # or, potentially, after there is a concrete client - _tc = globus_sdk.TransferClient() - client.oauth2_start_flow(requested_scopes=[_tc.scopes.all]) - -Using a Scope Builder to Get Matching Tokens --------------------------------------------- - -A ``ScopeBuilder`` contains the resource server name used to get token data -from a token response. -To elaborate on the above example: - -.. code-block:: python - - import globus_sdk - from globus_sdk.scopes import TransferScopes - - CLIENT_ID = "" - - client = globus_sdk.NativeAppAuthClient(CLIENT_ID) - client.oauth2_start_flow(requested_scopes=[TransferScopes.all]) - authorize_url = client.oauth2_get_authorize_url() - print("Please go to this URL and login:", authorize_url) - auth_code = input("Please enter the code you get after login here: ").strip() - token_response = client.oauth2_exchange_code_for_tokens(auth_code) - - # use the `resource_server` of a ScopeBuilder to grab the associated token - # data from the response - tokendata = token_response.by_resource_server[TransferScopes.resource_server] - -MutableScope objects --------------------- - -In order to support optional and dependent scopes, an additional type is -provided by ``globus_sdk.scopes``: the ``MutableScope`` class. - -``MutableScope`` can be constructed directly or via a ``ScopeBuilder``'s -``make_mutable`` method, given a scope's short name. - -For example, one can create a ``MutableScope`` from the Groups "all" scope -as follows: - -.. code-block:: python - - from globus_sdk.scopes import GroupsScopes - - scope = GroupsScopes.make_mutable("all") - -``MutableScope`` objects primarily provide two main pieces of functionality: -dynamically building a scope tree and serializing to a string. - -Dynamic Scope Construction -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``MutableScope`` objects provide a tree-like interface for constructing scopes -and their dependencies. - -For example, the transfer scope dependent upon a collection scope may be -constructed by means of ``MutableScope`` methods and the ``make_mutable`` method -of scope builders thusly: - -.. code-block:: python - - from globus_sdk.scopes import GCSCollectionScopeBuilder, TransferScopes - - MAPPED_COLLECTION_ID = "...ID HERE..." - - # create the scopes with make_mutable - transfer_scope = TransferScopes.make_mutable("all") - data_access_scope = GCSCollectionScopeBuilder(MAPPED_COLLECTION_ID).make_mutable( - "data_access", optional=True - ) - # add data_access as a dependency - transfer_scope.add_dependency(data_access_scope) - -``MutableScope``\s can be used in most of the same locations where scope -strings can be used, but you can also call ``str()`` on them to get a -stringified representation. - -Serializing Scopes -~~~~~~~~~~~~~~~~~~ - -Whenever scopes are being sent to Globus services, they need to be encoded as -strings. All mutable scope objects support this by means of their defined -``serialize`` method. Note that ``__str__`` for a ``MutableScope`` is just an -alias for ``serialize``. For example, the following is valid usage to demonstrate -``str()``, ``repr()``, and ``serialize()``: - -.. code-block:: pycon - - >>> from globus_sdk.scopes import MutableScope - >>> foo = MutableScope("foo") - >>> bar = MutableScope("bar") - >>> bar.add_dependency("baz") - >>> foo.add_dependency(bar) - >>> print(str(foo)) - foo[bar[baz]] - >>> print(bar.serialize()) - bar[baz] - >>> alpha = MutableScope("alpha") - >>> alpha.add_dependency(MutableScope("beta", optional=True)) - >>> print(str(alpha)) - alpha[*beta] - >>> print(repr(alpha)) - MutableScope("alpha", dependencies=[MutableScope("beta", optional=True)]) - -MutableScope Reference -~~~~~~~~~~~~~~~~~~~~~~ - -.. autoclass:: MutableScope - :members: - :show-inheritance: - -ScopeBuilders -------------- - -ScopeBuilder Types -~~~~~~~~~~~~~~~~~~ - -.. autoclass:: ScopeBuilder - :members: - :show-inheritance: - -.. autoclass:: GCSEndpointScopeBuilder - :members: - :show-inheritance: - -.. autoclass:: GCSCollectionScopeBuilder - :members: - :show-inheritance: - -.. autoclass:: SpecificFlowScopeBuilder - :members: - :show-inheritance: - -ScopeBuilder Constants -~~~~~~~~~~~~~~~~~~~~~~ - -.. autodata:: globus_sdk.scopes.data.AuthScopes - :annotation: - -.. autodata:: globus_sdk.scopes.data.FlowsScopes - :annotation: - -.. autodata:: globus_sdk.scopes.data.GroupsScopes - :annotation: - -.. autodata:: globus_sdk.scopes.data.NexusScopes - :annotation: - -.. autodata:: globus_sdk.scopes.data.SearchScopes - :annotation: - -.. note:: - - ``TimersScopes`` is also available under the legacy name ``TimerScopes``. - -.. autodata:: globus_sdk.scopes.data.TimersScopes - :annotation: - -.. autodata:: globus_sdk.scopes.data.TransferScopes - :annotation: +The documentation which was found on this page has moved to :ref:`Scopes `. diff --git a/docs/services/index.rst b/docs/services/index.rst index 57388b0fb..553c67668 100644 --- a/docs/services/index.rst +++ b/docs/services/index.rst @@ -6,8 +6,8 @@ Service Clients .. currentmodule:: globus_sdk The Globus SDK provides a client class for every public Globus API. -Each client object takes authentication credentials from config files, -environment variables, or programmatically via :ref:`GlobusAuthorizers `. +Each client object takes authentication credentials via +:ref:`GlobusAuthorizers `. Once instantiated, a Client gives you high-level interface to make API calls, without needing to know Globus API endpoints or their various parameters. diff --git a/docs/tutorial.rst b/docs/tutorial.rst index c61daa7f9..f27e4d010 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -120,7 +120,7 @@ Run the following code sample to get your Access Tokens: The Globus SDK offers several features for managing credentials. The following components are useful for further reading: -* :ref:`using GlobusAuthorizer objects ` handle passing tokens to Globus, +* :ref:`using GlobusAuthorizer objects ` handle passing tokens to Globus, and may handle token expiration * :ref:`TokenStorage ` objects handle storage of tokens