Skip to content

Commit

Permalink
Communication identity api redesign (#16420)
Browse files Browse the repository at this point in the history
* copy identity client files from admin to new pkg

* add back version.py for wheel generation

* update _version.py

* remove redundant files

* fixed error with init file

* update identity sdk with swagger changes

* update swagger + regenerate

* fix async impl + tests

* Updated sync identity client and tests

* Use Azure.Core.AccessToken instead of CommunicationUserToken

* Updated formatting in CHANGELOG

* Updated CHANGELOG

* Updated CHANGELOG

* fix typo in samples

* update samples to include new method

* Update Readme and Samples

* docstring + formatting fixes

* more docstring fixes

* whitespace fixes

* formatting + doc fixes

* fix sync client test

* bodyreplacer modified to handle nested json

* generate sanitized recordings

* Updated formatting for method documentation

* Fix trailing whitespace

Co-authored-by: Lakshman Sundaralingam <lakshmans@microsoft.com>
  • Loading branch information
beltr0n and lsundaralingam authored Feb 2, 2021
1 parent 74d5b49 commit 30b917b
Show file tree
Hide file tree
Showing 39 changed files with 1,134 additions and 574 deletions.
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.\
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
[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

0 comments on commit 30b917b

Please sign in to comment.