11from __future__ import annotations
22
33import os
4- import re
5- from enum import Enum
64
75from typing_extensions import TYPE_CHECKING , Optional , TypedDict
86
9- from posit .connect .oauth .associations import ContentItemAssociations
10-
7+ from ..oauth import types
118from ..resources import Resources
129from .integrations import Integrations
1310from .sessions import Sessions
1411
1512if TYPE_CHECKING :
16- from posit .connect .external import aws
17-
1813 from ..context import Context
1914
20- GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange"
21-
22-
23- class OAuthTokenType (str , Enum ):
24- ACCESS_TOKEN = "urn:ietf:params:oauth:token-type:access_token"
25- AWS_CREDENTIALS = "urn:ietf:params:aws:token-type:credentials"
26- API_KEY = "urn:posit:connect:api-key"
27- CONTENT_SESSION_TOKEN = "urn:posit:connect:content-session-token"
28- USER_SESSION_TOKEN = "urn:posit:connect:user-session-token"
29-
30-
31- class OAuthIntegrationAuthType (str , Enum ):
32- """OAuth integration authentication type."""
33-
34- VIEWER = "Viewer"
35- SERVICE_ACCOUNT = "Service Account"
36- VISITOR_API_KEY = "Visitor API Key"
37-
38-
39- class OAuthIntegrationType (str , Enum ):
40- """OAuth integration type."""
41-
42- AWS = "aws"
43- AZURE = "azure"
44- CONNECT = "connect"
45- SNOWFLAKE = "snowflake"
46- CUSTOM = "custom"
47- # TODO add the rest
48-
4915
5016def _get_content_session_token () -> str :
5117 """Return the content session token.
@@ -85,14 +51,14 @@ def sessions(self):
8551 def get_credentials (
8652 self ,
8753 user_session_token : Optional [str ] = None ,
88- requested_token_type : Optional [str | OAuthTokenType ] = None ,
54+ requested_token_type : Optional [str | types . OAuthTokenType ] = None ,
8955 audience : Optional [str ] = None ,
9056 ) -> Credentials :
9157 """Perform an oauth credential exchange with a user-session-token."""
9258 # craft a credential exchange request
9359 data = {}
94- data ["grant_type" ] = GRANT_TYPE
95- data ["subject_token_type" ] = OAuthTokenType .USER_SESSION_TOKEN
60+ data ["grant_type" ] = types . GRANT_TYPE
61+ data ["subject_token_type" ] = types . OAuthTokenType .USER_SESSION_TOKEN
9662 if user_session_token :
9763 data ["subject_token" ] = user_session_token
9864 if requested_token_type :
@@ -106,14 +72,14 @@ def get_credentials(
10672 def get_content_credentials (
10773 self ,
10874 content_session_token : Optional [str ] = None ,
109- requested_token_type : Optional [str | OAuthTokenType ] = None ,
75+ requested_token_type : Optional [str | types . OAuthTokenType ] = None ,
11076 audience : Optional [str ] = None ,
11177 ) -> Credentials :
11278 """Perform an oauth credential exchange with a content-session-token."""
11379 # craft a credential exchange request
11480 data = {}
115- data ["grant_type" ] = GRANT_TYPE
116- data ["subject_token_type" ] = OAuthTokenType .CONTENT_SESSION_TOKEN
81+ data ["grant_type" ] = types . GRANT_TYPE
82+ data ["subject_token_type" ] = types . OAuthTokenType .CONTENT_SESSION_TOKEN
11783 data ["subject_token" ] = content_session_token or _get_content_session_token ()
11884 if requested_token_type :
11985 data ["requested_token_type" ] = requested_token_type
@@ -123,74 +89,6 @@ def get_content_credentials(
12389 response = self ._ctx .client .post (self ._path , data = data )
12490 return Credentials (** response .json ())
12591
126- def get_credentials_by (
127- self ,
128- user_session_token : str ,
129- content_session_token : Optional [str ] = None ,
130- integration_type : Optional [OAuthIntegrationType ] = None ,
131- auth_type : Optional [OAuthIntegrationAuthType ] = None ,
132- name : Optional [str | re .Pattern ] = None ,
133- guid : Optional [str ] = None ,
134- ) -> Credentials | aws .Credentials :
135- """Perform an oauth credential exchange for all integrations associated with the current content item."""
136- content_guid = os .getenv ("CONNECT_CONTENT_GUID" )
137- if not content_guid :
138- raise ValueError ("CONNECT_CONTENT_GUID environment variable is required." )
139- content_associations = ContentItemAssociations (self ._ctx , content_guid = content_guid ).find ()
140- # associations format: [{
141- # content_guid: uuid
142- # app_guid: uuid
143- # oauth_integration_guid: uuid
144- # oauth_integration_name: string
145- # oauth_integration_description: string┃null
146- # oauth_integration_template: string
147- # oauth_integration_auth_type: string
148- # created_time: date-time
149- # }]
150- for association in content_associations :
151- match = True
152-
153- if (
154- integration_type is not None
155- and association .get ("oauth_integration_template" ) != integration_type
156- ):
157- match = False
158-
159- if (
160- auth_type is not None
161- and association .get ("oauth_integration_auth_type" ) != auth_type
162- ):
163- match = False
164-
165- if name is not None :
166- integration_name = association .get ("oauth_integration_name" , "" )
167- if isinstance (name , re .Pattern ):
168- if not name .search (integration_name ):
169- match = False
170- else :
171- if integration_name != name :
172- match = False
173-
174- if guid is not None and association .get ("oauth_integration_guid" ) != guid :
175- match = False
176-
177- if match :
178- # Use the first matching association to get credentials
179- if association .get ("oauth_integration_auth_type" ) in [
180- OAuthIntegrationAuthType .VIEWER ,
181- OAuthIntegrationAuthType .VISITOR_API_KEY ,
182- ]:
183- return self .get_credentials (
184- user_session_token = user_session_token ,
185- audience = association .get ("oauth_integration_guid" ),
186- )
187- return self .get_content_credentials (
188- content_session_token = content_session_token ,
189- audience = association .get ("oauth_integration_guid" ),
190- )
191-
192- raise ValueError ("No matching OAuth integration found for the specified criteria." )
193-
19492
19593class Credentials (TypedDict , total = False ):
19694 access_token : str
0 commit comments