Skip to content

Commit 45704f2

Browse files
authored
feat: initial implementation of oauth API session / integration resources (#267)
Refactors our oauth-centric API resources into a common `oauth` meta-resource. Provides initial CRUD implementations for `sessions` and `integrations`.
1 parent f446ba0 commit 45704f2

File tree

16 files changed

+864
-71
lines changed

16 files changed

+864
-71
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Before contributing to the `posit-sdk`, ensure that the following prerequisites
2727

2828
## Tooling
2929

30-
Use the default make target to execute the full build pipeline. For details on specific targets, refer to the [Makefile](./Makefile).
30+
Use the default make target to execute the full build pipeline. For details on specific targets, run `make help`, or review the [Makefile](./Makefile) itself.
3131

3232
## Style Guide
3333

integration/tests/posit/connect/oauth/__init__.py

Whitespace-only changes.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import pytest
2+
from packaging import version
3+
4+
from posit import connect
5+
6+
from .. import CONNECT_VERSION
7+
8+
9+
@pytest.mark.skipif(
10+
CONNECT_VERSION <= version.parse("2024.06.0"),
11+
reason="OAuth Integrations not supported.",
12+
)
13+
class TestIntegrations:
14+
@classmethod
15+
def setup_class(cls):
16+
cls.client = connect.Client()
17+
cls.integration = cls.client.oauth.integrations.create(
18+
name="example integration",
19+
description="integration description",
20+
template="custom",
21+
config={
22+
"auth_mode": "Confidential",
23+
"authorization_uri": "https://example.com/__tenand_id__/oauth2/v2.0/authorize",
24+
"client_id": "client_id",
25+
"client_secret": "client_secret",
26+
"scopes": "a b c",
27+
"token_endpoint_auth_method": "client_secret_post",
28+
"token_uri": "https://example.com/__tenant_id__/oauth2/v2.0/token",
29+
},
30+
)
31+
32+
cls.another_integration = cls.client.oauth.integrations.create(
33+
name="another example integration",
34+
description="another integration description",
35+
template="custom",
36+
config={
37+
"auth_mode": "Confidential",
38+
"authorization_uri": "https://example.com/__tenand_id__/oauth2/v2.0/authorize",
39+
"client_id": "client_id",
40+
"client_secret": "client_secret",
41+
"scopes": "a b c",
42+
"token_endpoint_auth_method": "client_secret_post",
43+
"token_uri": "https://example.com/__tenant_id__/oauth2/v2.0/token",
44+
},
45+
)
46+
47+
@classmethod
48+
def teardown_class(cls):
49+
cls.integration.delete()
50+
cls.another_integration.delete()
51+
assert len(cls.client.oauth.integrations.find()) == 0
52+
53+
def test_get(self):
54+
result = self.client.oauth.integrations.get(self.integration.guid)
55+
assert result == self.integration
56+
57+
def test_find(self):
58+
results = self.client.oauth.integrations.find()
59+
assert len(results) == 2
60+
assert results[0] == self.integration
61+
assert results[1] == self.another_integration
62+
63+
def test_create_update_delete(self):
64+
# create a new integration
65+
66+
integration = self.client.oauth.integrations.create(
67+
name="new integration",
68+
description="new integration description",
69+
template="custom",
70+
config={
71+
"auth_mode": "Confidential",
72+
"authorization_uri": "https://example.com/__tenand_id__/oauth2/v2.0/authorize",
73+
"client_id": "client_id",
74+
"client_secret": "client_secret",
75+
"scopes": "a b c",
76+
"token_endpoint_auth_method": "client_secret_post",
77+
"token_uri": "https://example.com/__tenant_id__/oauth2/v2.0/token",
78+
},
79+
)
80+
81+
created = self.client.oauth.integrations.get(integration.guid)
82+
assert created == integration
83+
84+
all_integrations = self.client.oauth.integrations.find()
85+
assert len(all_integrations) == 3
86+
87+
# update the new integration
88+
89+
created.update(name="updated integration name")
90+
updated = self.client.oauth.integrations.get(integration.guid)
91+
assert updated.name == "updated integration name"
92+
93+
# delete the new integration
94+
95+
created.delete()
96+
all_integrations_after_delete = self.client.oauth.integrations.find()
97+
assert len(all_integrations_after_delete) == 2

src/posit/connect/client.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from .content import Content
1515
from .groups import Groups
1616
from .metrics import Metrics
17-
from .oauth import OAuthIntegration
17+
from .oauth import OAuth
1818
from .tasks import Tasks
1919
from .users import User, Users
2020

@@ -41,6 +41,8 @@ class Client:
4141
Connect user resource.
4242
metrics: Metrics
4343
Metrics resource.
44+
oauth: OAuth
45+
OAuth resource.
4446
tasks: Tasks
4547
Tasks resource.
4648
users: Users
@@ -184,18 +186,6 @@ def me(self) -> User:
184186
"""
185187
return me.get(self.resource_params)
186188

187-
@property
188-
def oauth(self) -> OAuthIntegration:
189-
"""
190-
An OAuthIntegration.
191-
192-
Returns
193-
-------
194-
OAuthIntegration
195-
The OAuth integration instance.
196-
"""
197-
return OAuthIntegration(self.cfg, self.session)
198-
199189
@property
200190
def groups(self) -> Groups:
201191
"""The groups resource interface.
@@ -271,6 +261,18 @@ def metrics(self) -> Metrics:
271261
"""
272262
return Metrics(self.resource_params)
273263

264+
@property
265+
def oauth(self) -> OAuth:
266+
"""
267+
The OAuth API interface.
268+
269+
Returns
270+
-------
271+
OAuth
272+
The oauth API instance.
273+
"""
274+
return OAuth(self.resource_params, self.cfg.api_key)
275+
274276
def __del__(self):
275277
"""Close the session when the Client instance is deleted."""
276278
if hasattr(self, "session") and self.session is not None:

src/posit/connect/oauth.py

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .oauth import OAuth as OAuth

0 commit comments

Comments
 (0)