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

Communication identity api redesign #16420

Merged
merged 30 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7238b6c
copy identity client files from admin to new pkg
beltr0n Jan 22, 2021
f06edc1
add back version.py for wheel generation
beltr0n Jan 22, 2021
95dad5f
update _version.py
beltr0n Jan 22, 2021
42e7bfe
remove redundant files
beltr0n Jan 22, 2021
727b73c
fixed error with init file
beltr0n Jan 22, 2021
41e6d57
update identity sdk with swagger changes
beltr0n Jan 23, 2021
bc00046
update swagger + regenerate
beltr0n Jan 28, 2021
2023e51
fix async impl + tests
beltr0n Jan 28, 2021
94752a2
Merge pull request #1 from beltr0n/bertong-communication-identity-red…
beltr0n Jan 28, 2021
2c3bddf
Updated sync identity client and tests
lsundaralingam Jan 28, 2021
6e619e3
Merge pull request #2 from lsundaralingam/communication-identity-rede…
beltr0n Jan 28, 2021
996e35d
Use Azure.Core.AccessToken instead of CommunicationUserToken
lsundaralingam Jan 28, 2021
7fabad5
Updated formatting in CHANGELOG
lsundaralingam Jan 28, 2021
bff5406
Updated CHANGELOG
lsundaralingam Jan 29, 2021
b4e62f7
Updated CHANGELOG
lsundaralingam Jan 29, 2021
745848a
Merge pull request #3 from lsundaralingam/communication-identity-rede…
beltr0n Jan 29, 2021
3f12d66
fix typo in samples
beltr0n Jan 28, 2021
366fe36
update samples to include new method
beltr0n Jan 28, 2021
96c1376
Update Readme and Samples
beltr0n Jan 28, 2021
17af7c0
docstring + formatting fixes
beltr0n Jan 29, 2021
725d8ab
more docstring fixes
beltr0n Jan 29, 2021
ec749be
whitespace fixes
beltr0n Jan 29, 2021
6827ba5
formatting + doc fixes
beltr0n Jan 29, 2021
e6dded8
fix sync client test
beltr0n Jan 29, 2021
935635a
bodyreplacer modified to handle nested json
beltr0n Jan 29, 2021
1373bf5
generate sanitized recordings
beltr0n Jan 29, 2021
d2eec01
Updated formatting for method documentation
lsundaralingam Jan 30, 2021
a74c808
Merge pull request #4 from lsundaralingam/bertong-communication-ident…
beltr0n Jan 30, 2021
b4b3565
Fix trailing whitespace
lsundaralingam Jan 30, 2021
2b13610
Merge pull request #5 from lsundaralingam/bertong-communication-ident…
beltr0n Jan 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions sdk/communication/azure-communication-identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

### Added
- Added CommunicationIdentityClient (originally was part of the azure.communication.administration package).
- Added ability to create a user and issue token for it at the same time.

### Breaking
- CommunicationIdentityClient.revoke_tokens now revoke all the currently issued tokens instead of revoking tokens issued prior to a given time.
- CommunicationIdentityClient.issue_tokens returns an instance of `azure.core.credentials.AccessToken` instead of `CommunicationUserToken`.

<!-- LINKS -->
[read_me]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/communication/azure-communication-identity/README.md
Expand Down
48 changes: 43 additions & 5 deletions sdk/communication/azure-communication-identity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,58 @@ endpoint = os.getenv('AZURE_COMMUNICATION_SERVICE_ENDPOINT')

# To use Azure Active Directory Authentication (DefaultAzureCredential) make sure to have
# AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET as env variables.
identity_client_managed_identity = CommunicationIdentityClient.(endpoint, DefaultAzureCredential())
identity_client_managed_identity = CommunicationIdentityClient(endpoint, DefaultAzureCredential())

#You can also authenticate using your connection string
identity_client = CommunicationIdentityClient.from_connection_string(connection_str)

```

# Examples
## Examples
The following section provides several code snippets covering some of the most common Azure Communication Services tasks, including:

[Create/delete Azure Communication Service identities][identitysamples]
### Creating a new user

[Create/revoke scoped user access tokens][identitysamples]
Use the `create_user` method to create a new user.
```python
user = identity_client.create_user()
print("User created with id:" + user.identifier)
```

Alternatively, use the `create_user_with_token` method to create a new user and issue a token for it.\
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Remove \ after the .

Copy link
Member Author

@beltr0n beltr0n Feb 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, i'm doing this to force a newline here. I can still remove it if you think we shouldn't

For this option, a list of `CommunicationTokenScope` must be defined (see "Issuing an access token" for more information)

```python
user, tokenresponse = identity_client.create_user_with_token(scopes=[CommunicationTokenScope.CHAT])
print("User id:" + user.identifier)
print("Token issued with value: " + tokenresponse.token)
```

### Issuing or Refreshing an access token for a user

Use the `issue_token` method to issue or refresh a scoped access token for the user. \
Pass in the user object as a parameter, and a list of `CommunicationTokenScope`. Scope options are:
- `CHAT` (Chat)
- `VOIP` (VoIP)

```python
tokenresponse = identity_client.issue_token(user, scopes=[CommunicationTokenScope.CHAT])
print("Token issued with value: " + tokenresponse.token)
```

### Revoking a user's access tokens

Use `revoke_tokens` to revoke all access tokens for a user. Pass in the user object as a parameter
```python
identity_client.revoke_tokens(user)
```

### Deleting a user

Use the `delete_user` method to delete a user. Pass in the user object as a parameter
```python
identity_client.delete_user(user)
```

# Troubleshooting
The Azure Communication Service Identity client will raise exceptions defined in [Azure Core][azure_core].
Expand All @@ -73,5 +112,4 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

<!-- LINKS -->
[identitysamples]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/communication/azure-communication-identity/samples/identity_samples.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we remove this sample?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link was to just the sync sample. We instead have a place where we link to both the sync/async samples (under "next steps"). The place this link was being used was also just a link, and I've replaced it with fully fleshed out samples instead.

[azure_core]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/core/azure-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,16 @@
from ._communication_identity_client import CommunicationIdentityClient

from ._generated.models import (
CommunicationTokenRequest,
CommunicationIdentityToken
CommunicationTokenScope
)

from ._shared.models import CommunicationUserIdentifier


__all__ = [
'CommunicationIdentityClient',

# from _identity
'CommunicationTokenRequest',
'CommunicationIdentityToken',
'CommunicationTokenScope',

# from _shared
'CommunicationUserIdentifier'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
# ------------------------------------

from azure.core.tracing.decorator import distributed_trace
from azure.core.credentials import AccessToken

from ._generated._communication_identity_client\
import CommunicationIdentityClient as CommunicationIdentityClientGen
from ._generated.models import CommunicationIdentityToken
from ._shared.utils import parse_connection_str, get_authentication_policy
from ._shared.models import CommunicationUserIdentifier
from ._version import SDK_MONIKER
Expand Down Expand Up @@ -62,7 +62,7 @@ def from_connection_string(
:param str conn_str:
A connection string to an Azure Communication Service resource.
:returns: Instance of CommunicationIdentityClient.
:rtype: ~azure.communication.CommunicationIdentityClient
:rtype: ~azure.communication.identity.CommunicationIdentityClient

.. admonition:: Example:

Expand All @@ -82,11 +82,32 @@ def create_user(self, **kwargs):
# type: (...) -> CommunicationUserIdentifier
"""create a single Communication user

return: CommunicationUserIdentifier
rtype: ~azure.communication.identity.CommunicationUserIdentifier
:return: CommunicationUserIdentifier
:rtype: ~azure.communication.identity.CommunicationUserIdentifier
"""
return self._identity_service_client.communication_identity.create(
cls=lambda pr, u, e: CommunicationUserIdentifier(u.id),
cls=lambda pr, u, e: CommunicationUserIdentifier(u.identity.id),
**kwargs)

@distributed_trace
def create_user_with_token(
self,
scopes, # type: List[Union[str, "_model.CommunicationTokenScope"]]
**kwargs # type: Any
):
# type: (...) -> Tuple[CommunicationUserIdentifier, AccessToken]
"""create a single Communication user with an identity token.
:param scopes:
List of scopes to be added to the token.
:type scopes: list[str or ~azure.communication.identity.models.CommunicationTokenScope]
:return: A tuple of a CommunicationUserIdentifier and a AccessToken.
:rtype:
tuple of (~azure.communication.identity.CommunicationUserIdentifier, ~azure.core.credentials.AccessToken)
"""
return self._identity_service_client.communication_identity.create(
cls=lambda pr, u, e: (CommunicationUserIdentifier(u.identity.id),
AccessToken(u.access_token.token, u.access_token.expires_on)),
create_token_with_scopes=scopes,
**kwargs)

@distributed_trace
Expand All @@ -111,43 +132,40 @@ def delete_user(
def issue_token(
self,
user, # type: CommunicationUserIdentifier
scopes, # type: List[str]
scopes, # List[Union[str, "_model.CommunicationTokenScope"]]
**kwargs # type: Any
):
# type: (...) -> CommunicationIdentityToken
# type: (...) -> AccessToken
"""Generates a new token for an identity.

:param user: Azure Communication User
:type user: ~azure.communication.identity.CommunicationUserIdentifier
:param scopes:
List of scopes to be added to the token.
:type scopes: list[str]
:return: CommunicationIdentityToken
:rtype: ~azure.communication.identity.CommunicationIdentityToken
:type scopes: list[str or ~azure.communication.identity.models.CommunicationTokenScope]
:return: AccessToken
:rtype: ~azure.core.credentials.AccessToken
"""
return self._identity_service_client.communication_identity.issue_token(
return self._identity_service_client.communication_identity.issue_access_token(
user.identifier,
scopes,
cls=lambda pr, u, e: AccessToken(u.token, u.expires_on),
**kwargs)

@distributed_trace
def revoke_tokens(
self,
user, # type: CommunicationUserIdentifier
issued_before=None, # type: Optional[datetime.datetime]
**kwargs # type: Any
):
# type: (...) -> None
"""Schedule revocation of all tokens of an identity.

:param user: Azure Communication User.
:type user: ~azure.communication.identity.CommunicationUserIdentifier.
:param issued_before: All tokens that are issued prior to this time should get revoked.
:type issued_before: ~datetime.datetime.
:return: None
:rtype: None
"""
return self._identity_service_client.communication_identity.update(
return self._identity_service_client.communication_identity.revoke_access_tokens(
user.identifier if user else None,
tokens_valid_from=issued_before,
**kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class CommunicationIdentityClient(object):

:ivar communication_identity: CommunicationIdentityOperations operations
:vartype communication_identity: azure.communication.identity.operations.CommunicationIdentityOperations
:param endpoint: Auth and Identity endpoint.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -41,6 +41,7 @@ def __init__(

client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
self._serialize = Serializer(client_models)
self._serialize.client_side_validation = False
self._deserialize = Deserializer(client_models)

self.communication_identity = CommunicationIdentityOperations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class CommunicationIdentityClientConfiguration(Configuration):
Note that all parameters used to create this instance are saved as instance
attributes.

:param endpoint: Auth and Identity endpoint.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -38,7 +38,7 @@ def __init__(
super(CommunicationIdentityClientConfiguration, self).__init__(**kwargs)

self.endpoint = endpoint
self.api_version = "2020-07-20-preview2"
self.api_version = "2021-03-07"
kwargs.setdefault('sdk_moniker', 'communicationidentityclient/{}'.format(VERSION))
self._configure(**kwargs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class CommunicationIdentityClient(object):

:ivar communication_identity: CommunicationIdentityOperations operations
:vartype communication_identity: azure.communication.identity.aio.operations.CommunicationIdentityOperations
:param endpoint: Auth and Identity endpoint.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -36,6 +36,7 @@ def __init__(

client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
self._serialize = Serializer(client_models)
self._serialize.client_side_validation = False
self._deserialize = Deserializer(client_models)

self.communication_identity = CommunicationIdentityOperations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CommunicationIdentityClientConfiguration(Configuration):
Note that all parameters used to create this instance are saved as instance
attributes.

:param endpoint: Auth and Identity endpoint.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -33,7 +33,7 @@ def __init__(
super(CommunicationIdentityClientConfiguration, self).__init__(**kwargs)

self.endpoint = endpoint
self.api_version = "2020-07-20-preview2"
self.api_version = "2021-03-07"
kwargs.setdefault('sdk_moniker', 'communicationidentityclient/{}'.format(VERSION))
self._configure(**kwargs)

Expand Down
Loading