Skip to content

Commit f7b7cb3

Browse files
feat(chat): add Pylon identity verification for chat widget
1 parent 688cf2e commit f7b7cb3

7 files changed

Lines changed: 229 additions & 4 deletions

File tree

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 172
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-888178c57cb0f9d7aede8f3fc5ec24bd62f619b728f00716f352b3b5a2fa306d.yml
3-
openapi_spec_hash: 701f004e9dcb6dd3472d8468a789c338
4-
config_hash: 8758ac1f8d8913bd960a98b4f05d6391
1+
configured_endpoints: 173
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-51c0e9db3fb9e3aadf35fb4fcf76107a2fcd9da1b8ff6cd593c1ae23d1a24bc3.yml
3+
openapi_spec_hash: db222df8620e2270763bef95ff247445
4+
config_hash: 2fa5dd58c6ab4dd15de320fa0f85dde8

api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ from gitpod.types import (
4242
JoinableOrganization,
4343
LoginProvider,
4444
AccountRetrieveResponse,
45+
AccountGetChatIdentityTokenResponse,
4546
AccountGetSSOLoginURLResponse,
4647
AccountListSSOLoginsResponse,
4748
)
@@ -51,6 +52,7 @@ Methods:
5152

5253
- <code title="post /gitpod.v1.AccountService/GetAccount">client.accounts.<a href="./src/gitpod/resources/accounts.py">retrieve</a>(\*\*<a href="src/gitpod/types/account_retrieve_params.py">params</a>) -> <a href="./src/gitpod/types/account_retrieve_response.py">AccountRetrieveResponse</a></code>
5354
- <code title="post /gitpod.v1.AccountService/DeleteAccount">client.accounts.<a href="./src/gitpod/resources/accounts.py">delete</a>(\*\*<a href="src/gitpod/types/account_delete_params.py">params</a>) -> object</code>
55+
- <code title="post /gitpod.v1.AccountService/GetChatIdentityToken">client.accounts.<a href="./src/gitpod/resources/accounts.py">get_chat_identity_token</a>(\*\*<a href="src/gitpod/types/account_get_chat_identity_token_params.py">params</a>) -> <a href="./src/gitpod/types/account_get_chat_identity_token_response.py">AccountGetChatIdentityTokenResponse</a></code>
5456
- <code title="post /gitpod.v1.AccountService/GetSSOLoginURL">client.accounts.<a href="./src/gitpod/resources/accounts.py">get_sso_login_url</a>(\*\*<a href="src/gitpod/types/account_get_sso_login_url_params.py">params</a>) -> <a href="./src/gitpod/types/account_get_sso_login_url_response.py">AccountGetSSOLoginURLResponse</a></code>
5557
- <code title="post /gitpod.v1.AccountService/ListJoinableOrganizations">client.accounts.<a href="./src/gitpod/resources/accounts.py">list_joinable_organizations</a>(\*\*<a href="src/gitpod/types/account_list_joinable_organizations_params.py">params</a>) -> <a href="./src/gitpod/types/joinable_organization.py">SyncJoinableOrganizationsPage[JoinableOrganization]</a></code>
5658
- <code title="post /gitpod.v1.AccountService/ListLoginProviders">client.accounts.<a href="./src/gitpod/resources/accounts.py">list_login_providers</a>(\*\*<a href="src/gitpod/types/account_list_login_providers_params.py">params</a>) -> <a href="./src/gitpod/types/login_provider.py">SyncLoginProvidersPage[LoginProvider]</a></code>

src/gitpod/resources/accounts.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
account_list_sso_logins_params,
1313
account_get_sso_login_url_params,
1414
account_list_login_providers_params,
15+
account_get_chat_identity_token_params,
1516
account_list_joinable_organizations_params,
1617
)
1718
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
@@ -38,6 +39,7 @@
3839
from ..types.account_retrieve_response import AccountRetrieveResponse
3940
from ..types.account_list_sso_logins_response import AccountListSSOLoginsResponse
4041
from ..types.account_get_sso_login_url_response import AccountGetSSOLoginURLResponse
42+
from ..types.account_get_chat_identity_token_response import AccountGetChatIdentityTokenResponse
4143

4244
__all__ = ["AccountsResource", "AsyncAccountsResource"]
4345

@@ -170,6 +172,58 @@ def delete(
170172
cast_to=object,
171173
)
172174

175+
def get_chat_identity_token(
176+
self,
177+
*,
178+
empty: bool | Omit = omit,
179+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
180+
# The extra values given here take precedence over values defined on the client or passed to this method.
181+
extra_headers: Headers | None = None,
182+
extra_query: Query | None = None,
183+
extra_body: Body | None = None,
184+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
185+
) -> AccountGetChatIdentityTokenResponse:
186+
"""
187+
Gets the chat identity token for the currently authenticated account.
188+
189+
Use this method to:
190+
191+
- Obtain a verification hash for in-app chat identity verification
192+
- Secure chat sessions against impersonation
193+
194+
The returned hash is an HMAC-SHA256 signature of the account's email, used by
195+
the chat widget to verify user identity.
196+
197+
### Examples
198+
199+
- Get chat identity token:
200+
201+
Retrieves the identity verification hash for the authenticated account.
202+
203+
```yaml
204+
{}
205+
```
206+
207+
Args:
208+
extra_headers: Send extra headers
209+
210+
extra_query: Add additional query parameters to the request
211+
212+
extra_body: Add additional JSON properties to the request
213+
214+
timeout: Override the client-level default timeout for this request, in seconds
215+
"""
216+
return self._post(
217+
"/gitpod.v1.AccountService/GetChatIdentityToken",
218+
body=maybe_transform(
219+
{"empty": empty}, account_get_chat_identity_token_params.AccountGetChatIdentityTokenParams
220+
),
221+
options=make_request_options(
222+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
223+
),
224+
cast_to=AccountGetChatIdentityTokenResponse,
225+
)
226+
173227
def get_sso_login_url(
174228
self,
175229
*,
@@ -580,6 +634,58 @@ async def delete(
580634
cast_to=object,
581635
)
582636

637+
async def get_chat_identity_token(
638+
self,
639+
*,
640+
empty: bool | Omit = omit,
641+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
642+
# The extra values given here take precedence over values defined on the client or passed to this method.
643+
extra_headers: Headers | None = None,
644+
extra_query: Query | None = None,
645+
extra_body: Body | None = None,
646+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
647+
) -> AccountGetChatIdentityTokenResponse:
648+
"""
649+
Gets the chat identity token for the currently authenticated account.
650+
651+
Use this method to:
652+
653+
- Obtain a verification hash for in-app chat identity verification
654+
- Secure chat sessions against impersonation
655+
656+
The returned hash is an HMAC-SHA256 signature of the account's email, used by
657+
the chat widget to verify user identity.
658+
659+
### Examples
660+
661+
- Get chat identity token:
662+
663+
Retrieves the identity verification hash for the authenticated account.
664+
665+
```yaml
666+
{}
667+
```
668+
669+
Args:
670+
extra_headers: Send extra headers
671+
672+
extra_query: Add additional query parameters to the request
673+
674+
extra_body: Add additional JSON properties to the request
675+
676+
timeout: Override the client-level default timeout for this request, in seconds
677+
"""
678+
return await self._post(
679+
"/gitpod.v1.AccountService/GetChatIdentityToken",
680+
body=await async_maybe_transform(
681+
{"empty": empty}, account_get_chat_identity_token_params.AccountGetChatIdentityTokenParams
682+
),
683+
options=make_request_options(
684+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
685+
),
686+
cast_to=AccountGetChatIdentityTokenResponse,
687+
)
688+
583689
async def get_sso_login_url(
584690
self,
585691
*,
@@ -872,6 +978,9 @@ def __init__(self, accounts: AccountsResource) -> None:
872978
self.delete = to_raw_response_wrapper(
873979
accounts.delete,
874980
)
981+
self.get_chat_identity_token = to_raw_response_wrapper(
982+
accounts.get_chat_identity_token,
983+
)
875984
self.get_sso_login_url = to_raw_response_wrapper(
876985
accounts.get_sso_login_url,
877986
)
@@ -896,6 +1005,9 @@ def __init__(self, accounts: AsyncAccountsResource) -> None:
8961005
self.delete = async_to_raw_response_wrapper(
8971006
accounts.delete,
8981007
)
1008+
self.get_chat_identity_token = async_to_raw_response_wrapper(
1009+
accounts.get_chat_identity_token,
1010+
)
8991011
self.get_sso_login_url = async_to_raw_response_wrapper(
9001012
accounts.get_sso_login_url,
9011013
)
@@ -920,6 +1032,9 @@ def __init__(self, accounts: AccountsResource) -> None:
9201032
self.delete = to_streamed_response_wrapper(
9211033
accounts.delete,
9221034
)
1035+
self.get_chat_identity_token = to_streamed_response_wrapper(
1036+
accounts.get_chat_identity_token,
1037+
)
9231038
self.get_sso_login_url = to_streamed_response_wrapper(
9241039
accounts.get_sso_login_url,
9251040
)
@@ -944,6 +1059,9 @@ def __init__(self, accounts: AsyncAccountsResource) -> None:
9441059
self.delete = async_to_streamed_response_wrapper(
9451060
accounts.delete,
9461061
)
1062+
self.get_chat_identity_token = async_to_streamed_response_wrapper(
1063+
accounts.get_chat_identity_token,
1064+
)
9471065
self.get_sso_login_url = async_to_streamed_response_wrapper(
9481066
accounts.get_sso_login_url,
9491067
)

src/gitpod/types/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@
227227
from .runner_check_repository_access_params import (
228228
RunnerCheckRepositoryAccessParams as RunnerCheckRepositoryAccessParams,
229229
)
230+
from .account_get_chat_identity_token_params import (
231+
AccountGetChatIdentityTokenParams as AccountGetChatIdentityTokenParams,
232+
)
230233
from .environment_create_from_project_params import (
231234
EnvironmentCreateFromProjectParams as EnvironmentCreateFromProjectParams,
232235
)
@@ -242,6 +245,9 @@
242245
from .runner_check_repository_access_response import (
243246
RunnerCheckRepositoryAccessResponse as RunnerCheckRepositoryAccessResponse,
244247
)
248+
from .account_get_chat_identity_token_response import (
249+
AccountGetChatIdentityTokenResponse as AccountGetChatIdentityTokenResponse,
250+
)
245251
from .environment_create_from_project_response import (
246252
EnvironmentCreateFromProjectResponse as EnvironmentCreateFromProjectResponse,
247253
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing_extensions import TypedDict
6+
7+
__all__ = ["AccountGetChatIdentityTokenParams"]
8+
9+
10+
class AccountGetChatIdentityTokenParams(TypedDict, total=False):
11+
empty: bool
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from pydantic import Field as FieldInfo
4+
5+
from .._models import BaseModel
6+
7+
__all__ = ["AccountGetChatIdentityTokenResponse"]
8+
9+
10+
class AccountGetChatIdentityTokenResponse(BaseModel):
11+
email_hash: str = FieldInfo(alias="emailHash")
12+
"""
13+
email_hash is the HMAC-SHA256 hash of the account's email address, used for chat
14+
widget identity verification
15+
"""

tests/api_resources/test_accounts.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
AccountRetrieveResponse,
1616
AccountListSSOLoginsResponse,
1717
AccountGetSSOLoginURLResponse,
18+
AccountGetChatIdentityTokenResponse,
1819
)
1920
from gitpod.pagination import (
2021
SyncLoginsPage,
@@ -110,6 +111,42 @@ def test_streaming_response_delete(self, client: Gitpod) -> None:
110111

111112
assert cast(Any, response.is_closed) is True
112113

114+
@pytest.mark.skip(reason="Prism tests are disabled")
115+
@parametrize
116+
def test_method_get_chat_identity_token(self, client: Gitpod) -> None:
117+
account = client.accounts.get_chat_identity_token()
118+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
119+
120+
@pytest.mark.skip(reason="Prism tests are disabled")
121+
@parametrize
122+
def test_method_get_chat_identity_token_with_all_params(self, client: Gitpod) -> None:
123+
account = client.accounts.get_chat_identity_token(
124+
empty=True,
125+
)
126+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
127+
128+
@pytest.mark.skip(reason="Prism tests are disabled")
129+
@parametrize
130+
def test_raw_response_get_chat_identity_token(self, client: Gitpod) -> None:
131+
response = client.accounts.with_raw_response.get_chat_identity_token()
132+
133+
assert response.is_closed is True
134+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
135+
account = response.parse()
136+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
137+
138+
@pytest.mark.skip(reason="Prism tests are disabled")
139+
@parametrize
140+
def test_streaming_response_get_chat_identity_token(self, client: Gitpod) -> None:
141+
with client.accounts.with_streaming_response.get_chat_identity_token() as response:
142+
assert not response.is_closed
143+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
144+
145+
account = response.parse()
146+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
147+
148+
assert cast(Any, response.is_closed) is True
149+
113150
@pytest.mark.skip(reason="Prism tests are disabled")
114151
@parametrize
115152
def test_method_get_sso_login_url(self, client: Gitpod) -> None:
@@ -373,6 +410,42 @@ async def test_streaming_response_delete(self, async_client: AsyncGitpod) -> Non
373410

374411
assert cast(Any, response.is_closed) is True
375412

413+
@pytest.mark.skip(reason="Prism tests are disabled")
414+
@parametrize
415+
async def test_method_get_chat_identity_token(self, async_client: AsyncGitpod) -> None:
416+
account = await async_client.accounts.get_chat_identity_token()
417+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
418+
419+
@pytest.mark.skip(reason="Prism tests are disabled")
420+
@parametrize
421+
async def test_method_get_chat_identity_token_with_all_params(self, async_client: AsyncGitpod) -> None:
422+
account = await async_client.accounts.get_chat_identity_token(
423+
empty=True,
424+
)
425+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
426+
427+
@pytest.mark.skip(reason="Prism tests are disabled")
428+
@parametrize
429+
async def test_raw_response_get_chat_identity_token(self, async_client: AsyncGitpod) -> None:
430+
response = await async_client.accounts.with_raw_response.get_chat_identity_token()
431+
432+
assert response.is_closed is True
433+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
434+
account = await response.parse()
435+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
436+
437+
@pytest.mark.skip(reason="Prism tests are disabled")
438+
@parametrize
439+
async def test_streaming_response_get_chat_identity_token(self, async_client: AsyncGitpod) -> None:
440+
async with async_client.accounts.with_streaming_response.get_chat_identity_token() as response:
441+
assert not response.is_closed
442+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
443+
444+
account = await response.parse()
445+
assert_matches_type(AccountGetChatIdentityTokenResponse, account, path=["response"])
446+
447+
assert cast(Any, response.is_closed) is True
448+
376449
@pytest.mark.skip(reason="Prism tests are disabled")
377450
@parametrize
378451
async def test_method_get_sso_login_url(self, async_client: AsyncGitpod) -> None:

0 commit comments

Comments
 (0)