Skip to content

Commit 1ad3462

Browse files
move and update fund_by method to oauth.integrations
1 parent 810f9eb commit 1ad3462

File tree

2 files changed

+75
-44
lines changed

2 files changed

+75
-44
lines changed

src/posit/connect/oauth/associations.py

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22

33
from __future__ import annotations
44

5-
import re
6-
7-
from typing_extensions import TYPE_CHECKING, List, Optional
5+
from typing_extensions import TYPE_CHECKING, List
86

97
# from ..context import requires
108
from ..resources import BaseResource, Resources
119

1210
if TYPE_CHECKING:
1311
from ..context import Context
14-
from ..oauth import types
1512

1613

1714
class Association(BaseResource):
@@ -67,53 +64,15 @@ def find(self) -> List[Association]:
6764
for result in response.json()
6865
]
6966

70-
# TODO turn this on before merging
71-
# @requires("2025.07.0")
72-
def find_by(
73-
self,
74-
integration_type: Optional[types.OAuthIntegrationType] = None,
75-
auth_type: Optional[types.OAuthIntegrationAuthType] = None,
76-
name: Optional[str] = None,
77-
guid: Optional[str] = None,
78-
) -> Association | None:
79-
for association in self.find():
80-
match = True
81-
82-
if (
83-
integration_type is not None
84-
and association.get("oauth_integration_template") != integration_type
85-
):
86-
match = False
87-
88-
if (
89-
auth_type is not None
90-
and association.get("oauth_integration_auth_type") != auth_type
91-
):
92-
match = False
93-
94-
if name is not None:
95-
integration_name = association.get("oauth_integration_name", "")
96-
if not re.search(name, integration_name):
97-
match = False
98-
99-
if guid is not None and association.get("oauth_integration_guid") != guid:
100-
match = False
101-
102-
if match:
103-
return association
104-
return None
105-
10667
def delete(self) -> None:
10768
"""Delete integration associations."""
10869
data = []
10970

11071
path = f"v1/content/{self.content_guid}/oauth/integrations/associations"
11172
self._ctx.client.put(path, json=data)
11273

113-
def update(self, integration_guid: str | list[str]) -> None:
74+
def update(self, integration_guid: list[str]) -> None:
11475
"""Set integration associations."""
115-
if isinstance(integration_guid, str):
116-
integration_guid = [integration_guid]
11776
data = [{"oauth_integration_guid": guid} for guid in integration_guid]
11877

11978
path = f"v1/content/{self.content_guid}/oauth/integrations/associations"

src/posit/connect/oauth/integrations.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
"""OAuth integration resources."""
22

3-
from typing_extensions import List, Optional, overload
3+
from __future__ import annotations
4+
5+
import re
6+
7+
from typing_extensions import TYPE_CHECKING, List, Optional, overload
48

59
from ..resources import BaseResource, Resources
610
from .associations import IntegrationAssociations
711

12+
if TYPE_CHECKING:
13+
from ..oauth import types
14+
815

916
class Integration(BaseResource):
1017
"""OAuth integration resource."""
@@ -118,6 +125,71 @@ def find(self) -> List[Integration]:
118125
for result in response.json()
119126
]
120127

128+
# TODO turn this on before merging
129+
# @requires("2025.07.0")
130+
def find_by(
131+
self,
132+
integration_type: Optional[types.OAuthIntegrationType] = None,
133+
auth_type: Optional[types.OAuthIntegrationAuthType] = None,
134+
name: Optional[str] = None,
135+
description: Optional[str] = None,
136+
guid: Optional[str] = None,
137+
config: Optional[dict] = None,
138+
) -> Integration | None:
139+
"""Find an OAuth integration by various criteria.
140+
141+
Parameters
142+
----------
143+
integration_type : Optional[types.OAuthIntegrationType]
144+
The type of the integration (e.g., "aws", "azure").
145+
auth_type : Optional[types.OAuthIntegrationAuthType]
146+
The authentication type of the integration (e.g., "Viewer", "Service Account").
147+
name : Optional[str]
148+
A regex pattern to match the integration name.
149+
description : Optional[str]
150+
A regex pattern to match the integration description.
151+
guid : Optional[str]
152+
The unique identifier of the integration.
153+
config : Optional[dict]
154+
A dictionary of configuration key-value pairs to match against the integration's config. This will
155+
vary based on the integration type.
156+
157+
Returns
158+
-------
159+
Integration | None
160+
The first matching integration, or None if no match is found.
161+
"""
162+
for integration in self.find():
163+
match = True
164+
165+
if integration_type is not None and integration.get("template") != integration_type:
166+
match = False
167+
168+
if auth_type is not None and integration.get("auth_type") != auth_type:
169+
match = False
170+
171+
if name is not None:
172+
integration_name = integration.get("name", "")
173+
if not re.search(name, integration_name):
174+
match = False
175+
176+
if description is not None:
177+
integration_description = integration.get("description", "")
178+
if not re.search(description, integration_description):
179+
match = False
180+
181+
if guid is not None and integration.get("guid") != guid:
182+
match = False
183+
184+
if config is not None:
185+
integration_config = integration.get("config", {})
186+
if not all(integration_config.get(k) == v for k, v in config.items()):
187+
match = False
188+
189+
if match:
190+
return integration
191+
return None
192+
121193
def get(self, guid: str) -> Integration:
122194
"""Get an OAuth integration.
123195

0 commit comments

Comments
 (0)