Skip to content
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

Consent forest sc 30764 #971

Merged
merged 11 commits into from
Apr 19, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Added
~~~~~

- Added a new AuthClient method ``get_consents`` and supporting local data objects.
These allows a client to poll and interact with the current Globus Auth consent state
of a particular identity rooted at their client. (:pr:`NUMBER`)
30 changes: 30 additions & 0 deletions docs/experimental/consents.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

.. py:currentmodule:: globus_sdk.experimental.consents

Consents
========

The Consents model provides a data model for loading consent information polled from
Globus Auth's ``get_consents`` API.

Consents are modeled as a ``ConsentForest`` full of ``ConsentTrees`` containing related
``Consents``. These consents detail a path of authorization grants that have been
provided by a user to client applications for token grants under certain scoped
contexts.

Reference
=========

.. autoclass:: ConsentForest
:members:

.. autoclass:: ConsentTree
:members:

.. autoclass:: Consent
:members:

.. autoexception:: ConsentParseError

.. autoexception:: ConsentTreeConstructionError

1 change: 1 addition & 0 deletions docs/experimental/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ Globus SDK Experimental Components

auth_requirements_errors
scope_parser
consents
9 changes: 9 additions & 0 deletions docs/services/auth.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,19 @@ Auth Responses
:members:
:show-inheritance:

.. autoclass:: GetConsentsResponse
:members:
:show-inheritance:

.. autoclass:: GetIdentitiesResponse
:members:
:show-inheritance:

Errors
------

.. autoexception:: AuthAPIError

OAuth2 Flow Managers
--------------------

Expand Down
3 changes: 3 additions & 0 deletions src/globus_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def _force_eager_imports() -> None:
"ConfidentialAppAuthClient",
"AuthAPIError",
"IdentityMap",
"GetConsentsResponse",
"GetIdentitiesResponse",
"OAuthDependentTokenResponse",
"OAuthTokenResponse",
Expand Down Expand Up @@ -172,6 +173,7 @@ def _force_eager_imports() -> None:
from .services.auth import ConfidentialAppAuthClient
from .services.auth import AuthAPIError
from .services.auth import IdentityMap
from .services.auth import GetConsentsResponse
from .services.auth import GetIdentitiesResponse
from .services.auth import OAuthDependentTokenResponse
from .services.auth import OAuthTokenResponse
Expand Down Expand Up @@ -298,6 +300,7 @@ def __getattr__(name: str) -> t.Any:
"GCSAPIError",
"GCSClient",
"GCSRoleDocument",
"GetConsentsResponse",
"GetIdentitiesResponse",
"GlobusAPIError",
"GlobusConnectPersonalOwnerInfo",
Expand Down
1 change: 1 addition & 0 deletions src/globus_sdk/_generate_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def __getattr__(name: str) -> t.Any:
# high-level helpers
"IdentityMap",
# responses
"GetConsentsResponse",
"GetIdentitiesResponse",
"OAuthDependentTokenResponse",
"OAuthTokenResponse",
Expand Down
49 changes: 49 additions & 0 deletions src/globus_sdk/_testing/data/auth/get_consents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from globus_sdk._testing.models import RegisteredResponse, ResponseSet

_DATA_ACCESS = (
"https://auth.globus.org/scopes/542a86fc-1766-450d-841f-065488a2ec01/data_access"
)

RESPONSES = ResponseSet(
default=RegisteredResponse(
service="auth",
path="/v2/api/identities/8ca28797-3541-4a5d-a264-05b00f91e608/consents",
json={
"consents": [
{
"created": "2022-09-21T17:10:14.270581+00:00",
"id": 142632,
"status": "approved",
"updated": "2022-09-21T17:10:14.270581+00:00",
"allows_refresh": True,
"dependency_path": [142632],
"scope_name": "urn:globus:auth:scope:transfer.api.globus.org:all",
"atomically_revocable": False,
"effective_identity": "8ca28797-3541-4a5d-a264-05b00f91e608",
"auto_approved": False,
"last_used": "2024-03-18T17:34:04.719126+00:00",
"scope": "89ecabba-4acf-4e2e-a98d-ce592ccc2818",
"client": "065db752-2f43-4fe1-a633-2ee68c9da889",
},
{
"created": "2024-03-18T17:32:51.496893+00:00",
"id": 433892,
"status": "approved",
"updated": "2024-03-18T17:32:51.496893+00:00",
"allows_refresh": True,
"dependency_path": [142632, 433892],
"scope_name": _DATA_ACCESS,
"atomically_revocable": True,
"effective_identity": "8ca28797-3541-4a5d-a264-05b00f91e608",
"auto_approved": False,
"last_used": "2024-03-18T17:33:05.178254+00:00",
"scope": "fe334c19-4fe6-4d03-ac73-8992beb231b6",
"client": "2fbdda78-a599-4cb5-ac3d-1fbcfbc6a754",
},
]
},
metadata={
"identity_id": "8ca28797-3541-4a5d-a264-05b00f91e608",
},
),
)
10 changes: 10 additions & 0 deletions src/globus_sdk/experimental/consents/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from ._errors import ConsentParseError, ConsentTreeConstructionError
from ._model import Consent, ConsentForest, ConsentTree

__all__ = [
"Consent",
"ConsentTree",
"ConsentForest",
"ConsentParseError",
"ConsentTreeConstructionError",
]
22 changes: 22 additions & 0 deletions src/globus_sdk/experimental/consents/_errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from __future__ import annotations

import typing as t

if t.TYPE_CHECKING:
from ._model import Consent


class ConsentParseError(Exception):
"""An error raised if consent parsing/loading fails."""

def __init__(self, message: str, raw_consent: dict[str, t.Any]):
super().__init__(message)
self.raw_consent = raw_consent


class ConsentTreeConstructionError(Exception):
"""An error raised if consent tree construction fails."""

def __init__(self, message: str, consents: list[Consent]):
super().__init__(message)
self.consents = consents
Loading