From 302dd239f6087ca98a192ebf780f6e98c957e7b4 Mon Sep 17 00:00:00 2001 From: Avin Pattath Date: Thu, 4 Feb 2021 15:37:53 -0800 Subject: [PATCH 01/11] generate turn sdk api from swagger --- .../CommunicationIdentityRestClient.cs | 89 ++++- .../TurnCredentialsResponse.Serialization.cs | 42 ++ .../Models/TurnCredentialsResponse.cs | 46 +++ .../Models/TurnServer.Serialization.cs | 41 ++ .../src/Generated/Models/TurnServer.cs | 47 +++ .../src/autorest.md | 7 +- .../src/swaggers/Common.json | 134 +++++++ .../src/swaggers/CommunicationIdentity.json | 359 ++++++++++++++++++ .../src/swaggers/CommunicationTurn.json | 134 +++++++ 9 files changed, 885 insertions(+), 14 deletions(-) create mode 100644 sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.Serialization.cs create mode 100644 sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.cs create mode 100644 sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.Serialization.cs create mode 100644 sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.cs create mode 100644 sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json create mode 100644 sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json create mode 100644 sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs index e8db84566e2f..db759deec662 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs @@ -20,7 +20,6 @@ namespace Azure.Communication.Identity internal partial class CommunicationIdentityRestClient { private string endpoint; - private string apiVersion; private ClientDiagnostics _clientDiagnostics; private HttpPipeline _pipeline; @@ -28,21 +27,15 @@ internal partial class CommunicationIdentityRestClient /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. /// The communication resource, for example https://my-resource.communication.azure.com. - /// Api Version. - /// or is null. - public CommunicationIdentityRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, string apiVersion = "2021-03-07") + /// is null. + public CommunicationIdentityRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } - if (apiVersion == null) - { - throw new ArgumentNullException(nameof(apiVersion)); - } this.endpoint = endpoint; - this.apiVersion = apiVersion; _clientDiagnostics = clientDiagnostics; _pipeline = pipeline; } @@ -55,7 +48,7 @@ internal HttpMessage CreateCreateRequest(IEnumerable cr var uri = new RawRequestUriBuilder(); uri.AppendRaw(endpoint, false); uri.AppendPath("/identities", false); - uri.AppendQuery("api-version", apiVersion, true); + uri.AppendQuery("api-version", "2021-03-07", true); request.Uri = uri; request.Headers.Add("Accept", "application/json"); request.Headers.Add("Content-Type", "application/json"); @@ -122,7 +115,7 @@ internal HttpMessage CreateDeleteRequest(string id) uri.AppendRaw(endpoint, false); uri.AppendPath("/identities/", false); uri.AppendPath(id, true); - uri.AppendQuery("api-version", apiVersion, true); + uri.AppendQuery("api-version", "2021-03-07", true); request.Uri = uri; request.Headers.Add("Accept", "application/json"); return message; @@ -182,7 +175,7 @@ internal HttpMessage CreateRevokeAccessTokensRequest(string id) uri.AppendPath("/identities/", false); uri.AppendPath(id, true); uri.AppendPath("/:revokeAccessTokens", false); - uri.AppendQuery("api-version", apiVersion, true); + uri.AppendQuery("api-version", "2021-03-07", true); request.Uri = uri; request.Headers.Add("Accept", "application/json"); return message; @@ -242,7 +235,7 @@ internal HttpMessage CreateIssueAccessTokenRequest(string id, IEnumerable IssueAccessToken(string id, IE throw _clientDiagnostics.CreateRequestFailedException(message.Response); } } + + internal HttpMessage CreateIssueTurnCredentialsRequest(string id) + { + var message = _pipeline.CreateMessage(); + var request = message.Request; + request.Method = RequestMethod.Post; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw(endpoint, false); + uri.AppendPath("/turn/", false); + uri.AppendPath(id, true); + uri.AppendPath("/:issueCredentials", false); + uri.AppendQuery("api-version", "2021-02-22-preview1", true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + return message; + } + + /// Issue TURN credentials for an existing identity. + /// Identifier of the existing identity to issue credentials for. + /// The cancellation token to use. + /// is null. + public async Task> IssueTurnCredentialsAsync(string id, CancellationToken cancellationToken = default) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + using var message = CreateIssueTurnCredentialsRequest(id); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + switch (message.Response.Status) + { + case 200: + { + TurnCredentialsResponse value = default; + using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); + value = TurnCredentialsResponse.DeserializeTurnCredentialsResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(message.Response).ConfigureAwait(false); + } + } + + /// Issue TURN credentials for an existing identity. + /// Identifier of the existing identity to issue credentials for. + /// The cancellation token to use. + /// is null. + public Response IssueTurnCredentials(string id, CancellationToken cancellationToken = default) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + using var message = CreateIssueTurnCredentialsRequest(id); + _pipeline.Send(message, cancellationToken); + switch (message.Response.Status) + { + case 200: + { + TurnCredentialsResponse value = default; + using var document = JsonDocument.Parse(message.Response.ContentStream); + value = TurnCredentialsResponse.DeserializeTurnCredentialsResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw _clientDiagnostics.CreateRequestFailedException(message.Response); + } + } } } diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.Serialization.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.Serialization.cs new file mode 100644 index 000000000000..3849df63adf5 --- /dev/null +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.Serialization.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Communication.Identity.Models +{ + public partial class TurnCredentialsResponse + { + internal static TurnCredentialsResponse DeserializeTurnCredentialsResponse(JsonElement element) + { + DateTimeOffset expiresOn = default; + IReadOnlyList turnServers = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("expiresOn")) + { + expiresOn = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("turnServers")) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(TurnServer.DeserializeTurnServer(item)); + } + turnServers = array; + continue; + } + } + return new TurnCredentialsResponse(expiresOn, turnServers); + } + } +} diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.cs new file mode 100644 index 000000000000..9fe3b71674b7 --- /dev/null +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Communication.Identity.Models +{ + /// A TURN credentials response. + public partial class TurnCredentialsResponse + { + /// Initializes a new instance of TurnCredentialsResponse. + /// The date for which the username and credentials are not longer valid. + /// An array representing the credentials and the TURN server URL. + /// is null. + internal TurnCredentialsResponse(DateTimeOffset expiresOn, IEnumerable turnServers) + { + if (turnServers == null) + { + throw new ArgumentNullException(nameof(turnServers)); + } + + ExpiresOn = expiresOn; + TurnServers = turnServers.ToList(); + } + + /// Initializes a new instance of TurnCredentialsResponse. + /// The date for which the username and credentials are not longer valid. + /// An array representing the credentials and the TURN server URL. + internal TurnCredentialsResponse(DateTimeOffset expiresOn, IReadOnlyList turnServers) + { + ExpiresOn = expiresOn; + TurnServers = turnServers; + } + + /// The date for which the username and credentials are not longer valid. + public DateTimeOffset ExpiresOn { get; } + /// An array representing the credentials and the TURN server URL. + public IReadOnlyList TurnServers { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.Serialization.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.Serialization.cs new file mode 100644 index 000000000000..c319b65bcd7e --- /dev/null +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.Serialization.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Communication.Identity.Models +{ + public partial class TurnServer + { + internal static TurnServer DeserializeTurnServer(JsonElement element) + { + string urls = default; + string username = default; + string credential = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("urls")) + { + urls = property.Value.GetString(); + continue; + } + if (property.NameEquals("username")) + { + username = property.Value.GetString(); + continue; + } + if (property.NameEquals("credential")) + { + credential = property.Value.GetString(); + continue; + } + } + return new TurnServer(urls, username, credential); + } + } +} diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.cs new file mode 100644 index 000000000000..f8b7a9fa722b --- /dev/null +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Communication.Identity.Models +{ + /// An instance of a TURN server with credentials. + public partial class TurnServer + { + /// Initializes a new instance of TurnServer. + /// URL of the server. + /// User account name which uniquely identifies the credentials. + /// Credential for the server. + /// , , or is null. + internal TurnServer(string urls, string username, string credential) + { + if (urls == null) + { + throw new ArgumentNullException(nameof(urls)); + } + if (username == null) + { + throw new ArgumentNullException(nameof(username)); + } + if (credential == null) + { + throw new ArgumentNullException(nameof(credential)); + } + + Urls = urls; + Username = username; + Credential = credential; + } + + /// URL of the server. + public string Urls { get; } + /// User account name which uniquely identifies the credentials. + public string Username { get; } + /// Credential for the server. + public string Credential { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Identity/src/autorest.md b/sdk/communication/Azure.Communication.Identity/src/autorest.md index c9fa62846115..e30b7a7217a8 100644 --- a/sdk/communication/Azure.Communication.Identity/src/autorest.md +++ b/sdk/communication/Azure.Communication.Identity/src/autorest.md @@ -7,6 +7,11 @@ Run `dotnet msbuild /t:GenerateCode` to generate code. ``` yaml input-file: - - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/5b19c6e69cd2bb9dbe4e5c1237b2c5a175d90ca5/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/stable/2021-03-07/CommunicationIdentity.json +# - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/5b19c6e69cd2bb9dbe4e5c1237b2c5a175d90ca5/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/stable/2021-03-07/CommunicationIdentity.json +# - https://github.com/apattath/azure-rest-api-specs/blob/08ac674efacce0ae35371f8b1d8c45b5a1420503/specification/communication/data-plane/Microsoft.CommunicationServicesTurn/preview/2021-02-22-preview1/CommunicationTurn.json +# - https://github.com/apattath/azure-rest-api-specs/blob/9edffc88b87fdc90a4d339a0b49487d611304c6f/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/stable/2021-03-07/CommunicationIdentity.json +# - https://github.com/apattath/azure-rest-api-specs/blob/9edffc88b87fdc90a4d339a0b49487d611304c6f/specification/communication/data-plane/Microsoft.CommunicationServicesTurn/preview/2021-02-22-preview1/CommunicationTurn.json + - ./swaggers/CommunicationIdentity.json + - ./swaggers/CommunicationTurn.json payload-flattening-threshold: 3 ``` diff --git a/sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json b/sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json new file mode 100644 index 000000000000..c9fe49b34e88 --- /dev/null +++ b/sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json @@ -0,0 +1,134 @@ +{ + "swagger": "2.0", + "info": { + "title": "Communication", + "description": "Communication Services API common types.", + "version": "2020-11-19-preview1" + }, + "paths": {}, + "definitions": { + "CommunicationErrorResponse": { + "description": "The Communication Services error.", + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "description": "The Communication Services error.", + "$ref": "#/definitions/CommunicationError" + } + } + }, + "CommunicationError": { + "description": "The Communication Services error.", + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "description": "The error code." + }, + "message": { + "type": "string", + "description": "The error message." + }, + "target": { + "type": "string", + "readOnly": true, + "description": "The error target." + }, + "details": { + "type": "array", + "items": { + "$ref": "#/definitions/CommunicationError" + }, + "readOnly": true, + "description": "Further details about specific errors that led to this error." + }, + "innererror": { + "x-ms-client-name": "innerError", + "readOnly": true, + "$ref": "#/definitions/CommunicationError", + "description": "The inner error if any." + } + }, + "x-nullable": true + }, + "CommunicationIdentifierKind": { + "description": "The kind of a communication identifier.", + "type": "string", + "enum": [ + "unknown", + "communicationUser", + "phoneNumber", + "callingApplication", + "microsoftTeamsUser" + ], + "x-ms-enum": { + "name": "CommunicationIdentifierKind", + "modelAsString": true + } + }, + "CommunicationCloudEnvironmentModel": { + "description": "The cloud that the identifier belongs to.", + "type": "string", + "enum": [ + "public", + "dod", + "gcch" + ], + "x-ms-enum": { + "name": "CommunicationCloudEnvironmentModel", + "modelAsString": true + } + }, + "CommunicationIdentifierModel": { + "description": "Identifies a participant in Azure Communication services. A participant is, for example, a phone number or an Azure communication user.", + "type": "object", + "required": [ + "kind" + ], + "properties": { + "kind": { + "$ref": "#/definitions/CommunicationIdentifierKind", + "description": "Kind of the communication identifier." + }, + "id": { + "type": "string", + "description": "Full Id of the identifier." + }, + "phoneNumber": { + "type": "string", + "description": "The phone number in E.164 format." + }, + "microsoftTeamsUserId": { + "type": "string", + "description": "The AAD object Id of the Microsoft Teams user." + }, + "isAnonymous": { + "type": "boolean", + "description": "True if the identifier is anonymous." + }, + "cloud": { + "$ref": "#/definitions/CommunicationCloudEnvironmentModel", + "description": "The cloud that the identifier belongs to." + } + } + } + }, + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow.", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + } +} diff --git a/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json b/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json new file mode 100644 index 000000000000..b6fc0a963536 --- /dev/null +++ b/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json @@ -0,0 +1,359 @@ +{ + "swagger": "2.0", + "info": { + "title": "CommunicationIdentityClient", + "description": "Azure Communication Identity Service", + "version": "2021-03-07" + }, + "paths": { + "/identities": { + "post": { + "tags": [ + "Identity" + ], + "summary": "Create a new identity.", + "operationId": "CommunicationIdentity_Create", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/CommunicationIdentityCreateRequest" + } + } + ], + "responses": { + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/CommunicationErrorResponse" + } + }, + "201": { + "description": "Created - Returns the created identity.", + "schema": { + "$ref": "#/definitions/CommunicationIdentityAccessTokenResult" + } + } + }, + "x-ms-examples": { + "Create an Identity": { + "$ref": "./examples/CreateIdentity.json" + } + } + } + }, + "/identities/{id}": { + "delete": { + "tags": [ + "Identity" + ], + "summary": "Delete the identity, revoke all tokens for the identity and delete all associated data.", + "operationId": "CommunicationIdentity_Delete", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "Identifier of the identity to be deleted.", + "required": true, + "type": "string" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/CommunicationErrorResponse" + } + }, + "204": { + "description": "Success" + } + }, + "x-ms-examples": { + "Delete an identity": { + "$ref": "./examples/DeleteIdentity.json" + } + } + } + }, + "/identities/{id}/:revokeAccessTokens": { + "post": { + "tags": [ + "Identity" + ], + "summary": "Revoke all access tokens for the specific identity.", + "operationId": "CommunicationIdentity_RevokeAccessTokens", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "Identifier of the identity.", + "required": true, + "type": "string" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/CommunicationErrorResponse" + } + }, + "204": { + "description": "Success" + } + }, + "x-ms-examples": { + "Revoke access tokens": { + "$ref": "./examples/RevokeAccessTokens.json" + } + } + } + }, + "/identities/{id}/:issueAccessToken": { + "post": { + "tags": [ + "Token" + ], + "summary": "Issue a new token for an identity.", + "operationId": "CommunicationIdentity_IssueAccessToken", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "Identifier of the identity to issue token for.", + "required": true, + "type": "string" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "in": "body", + "name": "body", + "description": "Requesting scopes for the new token.", + "required": true, + "schema": { + "$ref": "#/definitions/CommunicationIdentityAccessTokenRequest" + } + } + ], + "responses": { + "default": { + "description": "Error", + "schema": { + "$ref": "#/definitions/CommunicationErrorResponse" + } + }, + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/CommunicationIdentityAccessToken" + } + } + }, + "x-ms-examples": { + "Issue an access token": { + "$ref": "./examples/IssueAccessToken.json" + } + } + } + } + }, + "definitions": { + "CommunicationIdentityTokenScope": { + "description": "List of scopes for an access token.", + "enum": [ + "chat", + "voip" + ], + "type": "string", + "x-ms-enum": { + "name": "CommunicationIdentityTokenScope", + "modelAsString": true + } + }, + "CommunicationIdentityCreateRequest": { + "type": "object", + "properties": { + "createTokenWithScopes": { + "description": "Also create access token for the created identity.", + "type": "array", + "items": { + "$ref": "#/definitions/CommunicationIdentityTokenScope" + } + } + } + }, + "CommunicationError": { + "description": "The Communication Services error.", + "required": [ + "code", + "message" + ], + "type": "object", + "properties": { + "code": { + "description": "The error code.", + "type": "string" + }, + "message": { + "description": "The error message.", + "type": "string" + }, + "target": { + "description": "The error target.", + "type": "string", + "readOnly": true + }, + "details": { + "description": "Further details about specific errors that led to this error.", + "type": "array", + "items": { + "$ref": "#/definitions/CommunicationError" + }, + "readOnly": true + }, + "innerError": { + "$ref": "#/definitions/CommunicationError" + } + } + }, + "CommunicationErrorResponse": { + "description": "The Communication Services error.", + "required": [ + "error" + ], + "type": "object", + "properties": { + "error": { + "$ref": "#/definitions/CommunicationError" + } + } + }, + "CommunicationIdentity": { + "description": "A communication identity.", + "required": [ + "id" + ], + "type": "object", + "properties": { + "id": { + "description": "Identifier of the identity.", + "type": "string" + } + } + }, + "CommunicationIdentityAccessToken": { + "description": "An access token.", + "required": [ + "expiresOn", + "token" + ], + "type": "object", + "properties": { + "token": { + "description": "The access token issued for the identity.", + "type": "string" + }, + "expiresOn": { + "format": "date-time", + "description": "The expiry time of the token.", + "type": "string" + } + } + }, + "CommunicationIdentityAccessTokenResult": { + "description": "A communication identity with access token.", + "required": [ + "identity" + ], + "type": "object", + "properties": { + "identity": { + "$ref": "#/definitions/CommunicationIdentity" + }, + "accessToken": { + "$ref": "#/definitions/CommunicationIdentityAccessToken" + } + } + }, + "CommunicationIdentityAccessTokenRequest": { + "required": [ + "scopes" + ], + "type": "object", + "properties": { + "scopes": { + "description": "List of scopes attached to the token.", + "type": "array", + "items": { + "$ref": "#/definitions/CommunicationIdentityTokenScope" + } + } + } + } + }, + "parameters": { + "ApiVersionParameter": { + "in": "query", + "name": "api-version", + "description": "Version of API to invoke.", + "required": true, + "type": "string" + } + }, + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "x-ms-parameterized-host": { + "hostTemplate": "{endpoint}", + "useSchemePrefix": false, + "parameters": [ + { + "name": "endpoint", + "description": "The communication resource, for example https://my-resource.communication.azure.com", + "required": true, + "type": "string", + "in": "path", + "x-ms-skip-url-encoding": true, + "x-ms-parameter-location": "client" + } + ] + } +} diff --git a/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json b/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json new file mode 100644 index 000000000000..1111d5583e4b --- /dev/null +++ b/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json @@ -0,0 +1,134 @@ +{ + "swagger": "2.0", + "info": { + "title": "CommunicationIdentityClient", + "description": "Azure Communication Relay Service", + "version": "2021-02-22-preview1" + }, + "paths": { + "/turn/{id}/:issueCredentials": { + "post": { + "tags": [ + "Turn" + ], + "summary": "Issue TURN credentials for an existing identity.", + "operationId": "CommunicationIdentity_IssueTurnCredentials", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "description": "Identifier of the existing identity to issue credentials for.", + "required": true, + "type": "string" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "default": { + "description": "Error", + "schema": { + "$ref": "./CommunicationIdentity.json#/definitions/CommunicationErrorResponse" + } + }, + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/TurnCredentialsResponse" + } + } + }, + "x-ms-examples": { + "Issue Turn Credentials": { + "$ref": "./examples/IssueTurnCredentials.json" + } + } + } + } + }, + "definitions": { + "TurnServer": { + "description": "An instance of a TURN server with credentials.", + "required": [ + "credential", + "urls", + "username" + ], + "type": "object", + "properties": { + "urls": { + "description": "URL of the server.", + "type": "string" + }, + "username": { + "description": "User account name which uniquely identifies the credentials.", + "type": "string" + }, + "credential": { + "description": "Credential for the server.", + "type": "string" + } + } + }, + "TurnCredentialsResponse": { + "description": "A TURN credentials response.", + "required": [ + "expiresOn", + "turnServers" + ], + "type": "object", + "properties": { + "expiresOn": { + "format": "date-time", + "description": "The date for which the username and credentials are not longer valid.", + "type": "string" + }, + "turnServers": { + "description": "An array representing the credentials and the TURN server URL.", + "type": "array", + "items": { + "$ref": "#/definitions/TurnServer" + } + } + } + } + }, + "parameters": { + "ApiVersionParameter": { + "in": "query", + "name": "api-version", + "description": "Version of API to invoke.", + "required": true, + "type": "string" + } + }, + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "x-ms-parameterized-host": { + "hostTemplate": "{endpoint}", + "useSchemePrefix": false, + "parameters": [ + { + "name": "endpoint", + "description": "The communication resource, for example https://my-resource.communication.azure.com", + "required": true, + "type": "string", + "in": "path", + "x-ms-skip-url-encoding": true, + "x-ms-parameter-location": "client" + } + ] + } +} From d954da9786381589cf334ad17aacaa3dc4c77609 Mon Sep 17 00:00:00 2001 From: Avin Pattath Date: Fri, 5 Feb 2021 10:56:42 -0800 Subject: [PATCH 02/11] generated sdk with same preview version for both swaggers --- .../CommunicationIdentityRestClient.cs | 21 ++++++++++++------- .../src/swaggers/CommunicationIdentity.json | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs index db759deec662..c045bcac8b84 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs @@ -20,6 +20,7 @@ namespace Azure.Communication.Identity internal partial class CommunicationIdentityRestClient { private string endpoint; + private string apiVersion; private ClientDiagnostics _clientDiagnostics; private HttpPipeline _pipeline; @@ -27,15 +28,21 @@ internal partial class CommunicationIdentityRestClient /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. /// The communication resource, for example https://my-resource.communication.azure.com. - /// is null. - public CommunicationIdentityRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint) + /// Api Version. + /// or is null. + public CommunicationIdentityRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, string apiVersion = "2021-02-22-preview1") { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } + if (apiVersion == null) + { + throw new ArgumentNullException(nameof(apiVersion)); + } this.endpoint = endpoint; + this.apiVersion = apiVersion; _clientDiagnostics = clientDiagnostics; _pipeline = pipeline; } @@ -48,7 +55,7 @@ internal HttpMessage CreateCreateRequest(IEnumerable cr var uri = new RawRequestUriBuilder(); uri.AppendRaw(endpoint, false); uri.AppendPath("/identities", false); - uri.AppendQuery("api-version", "2021-03-07", true); + uri.AppendQuery("api-version", apiVersion, true); request.Uri = uri; request.Headers.Add("Accept", "application/json"); request.Headers.Add("Content-Type", "application/json"); @@ -115,7 +122,7 @@ internal HttpMessage CreateDeleteRequest(string id) uri.AppendRaw(endpoint, false); uri.AppendPath("/identities/", false); uri.AppendPath(id, true); - uri.AppendQuery("api-version", "2021-03-07", true); + uri.AppendQuery("api-version", apiVersion, true); request.Uri = uri; request.Headers.Add("Accept", "application/json"); return message; @@ -175,7 +182,7 @@ internal HttpMessage CreateRevokeAccessTokensRequest(string id) uri.AppendPath("/identities/", false); uri.AppendPath(id, true); uri.AppendPath("/:revokeAccessTokens", false); - uri.AppendQuery("api-version", "2021-03-07", true); + uri.AppendQuery("api-version", apiVersion, true); request.Uri = uri; request.Headers.Add("Accept", "application/json"); return message; @@ -235,7 +242,7 @@ internal HttpMessage CreateIssueAccessTokenRequest(string id, IEnumerable Date: Mon, 8 Feb 2021 14:47:00 -0800 Subject: [PATCH 03/11] updated sdk with new swagger that adds CommunicationTurn models --- .../src/CommunicationIdentityClient.cs | 39 ++ .../CommunicationIdentityRestClient.cs | 12 +- .../CommunicationError.Serialization.cs | 8 +- .../Generated/Models/CommunicationError.cs | 4 +- ...nTurnCredentialsResponse.Serialization.cs} | 12 +- ...> CommunicationTurnCredentialsResponse.cs} | 12 +- ... CommunicationTurnServer.Serialization.cs} | 6 +- ...rnServer.cs => CommunicationTurnServer.cs} | 6 +- .../src/autorest.md | 7 +- .../src/swaggers/Common.json | 134 ------- .../src/swaggers/CommunicationIdentity.json | 359 ------------------ .../src/swaggers/CommunicationTurn.json | 134 ------- 12 files changed, 71 insertions(+), 662 deletions(-) rename sdk/communication/Azure.Communication.Identity/src/Generated/Models/{TurnCredentialsResponse.Serialization.cs => CommunicationTurnCredentialsResponse.Serialization.cs} (62%) rename sdk/communication/Azure.Communication.Identity/src/Generated/Models/{TurnCredentialsResponse.cs => CommunicationTurnCredentialsResponse.cs} (70%) rename sdk/communication/Azure.Communication.Identity/src/Generated/Models/{TurnServer.Serialization.cs => CommunicationTurnServer.Serialization.cs} (81%) rename sdk/communication/Azure.Communication.Identity/src/Generated/Models/{TurnServer.cs => CommunicationTurnServer.cs} (86%) delete mode 100644 sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json delete mode 100644 sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json delete mode 100644 sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json diff --git a/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs b/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs index e3d1667ac106..847374cd5fd7 100644 --- a/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs +++ b/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs @@ -290,6 +290,45 @@ public virtual async Task RevokeTokensAsync(CommunicationUserIdentifie } } + /// Issues a token for a . + /// The for whom to issue a token. + /// The cancellation token to use. + /// The server returned an error. + public virtual Response IssueTurnCredentials(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueToken)}"); + scope.Start(); + try + { + Response response = RestClient.IssueTurnCredentials(communicationUser.Id, cancellationToken); + return response; + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// Asynchronously issues a token for a . + /// The for whom to issue a token. + /// The cancellation token to use. + public virtual async Task> IssueTurnCredentialsAsync(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueToken)}"); + scope.Start(); + try + { + Response response = await RestClient.IssueTurnCredentialsAsync(communicationUser.Id, cancellationToken).ConfigureAwait(false); + return response; + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + private static T AssertNotNull(T argument, string argumentName) where T : class { diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs index c045bcac8b84..84e54faf1692 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/CommunicationIdentityRestClient.cs @@ -337,7 +337,7 @@ internal HttpMessage CreateIssueTurnCredentialsRequest(string id) /// Identifier of the existing identity to issue credentials for. /// The cancellation token to use. /// is null. - public async Task> IssueTurnCredentialsAsync(string id, CancellationToken cancellationToken = default) + public async Task> IssueTurnCredentialsAsync(string id, CancellationToken cancellationToken = default) { if (id == null) { @@ -350,9 +350,9 @@ public async Task> IssueTurnCredentialsAsync(s { case 200: { - TurnCredentialsResponse value = default; + CommunicationTurnCredentialsResponse value = default; using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); - value = TurnCredentialsResponse.DeserializeTurnCredentialsResponse(document.RootElement); + value = CommunicationTurnCredentialsResponse.DeserializeCommunicationTurnCredentialsResponse(document.RootElement); return Response.FromValue(value, message.Response); } default: @@ -364,7 +364,7 @@ public async Task> IssueTurnCredentialsAsync(s /// Identifier of the existing identity to issue credentials for. /// The cancellation token to use. /// is null. - public Response IssueTurnCredentials(string id, CancellationToken cancellationToken = default) + public Response IssueTurnCredentials(string id, CancellationToken cancellationToken = default) { if (id == null) { @@ -377,9 +377,9 @@ public Response IssueTurnCredentials(string id, Cancell { case 200: { - TurnCredentialsResponse value = default; + CommunicationTurnCredentialsResponse value = default; using var document = JsonDocument.Parse(message.Response.ContentStream); - value = TurnCredentialsResponse.DeserializeTurnCredentialsResponse(document.RootElement); + value = CommunicationTurnCredentialsResponse.DeserializeCommunicationTurnCredentialsResponse(document.RootElement); return Response.FromValue(value, message.Response); } default: diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.Serialization.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.Serialization.cs index 27e7e08b6515..5c97a4f25724 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.Serialization.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.Serialization.cs @@ -19,7 +19,7 @@ internal static CommunicationError DeserializeCommunicationError(JsonElement ele string message = default; Optional target = default; Optional> details = default; - Optional innerError = default; + Optional innererror = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("code")) @@ -52,18 +52,18 @@ internal static CommunicationError DeserializeCommunicationError(JsonElement ele details = array; continue; } - if (property.NameEquals("innerError")) + if (property.NameEquals("innererror")) { if (property.Value.ValueKind == JsonValueKind.Null) { property.ThrowNonNullablePropertyIsNull(); continue; } - innerError = DeserializeCommunicationError(property.Value); + innererror = DeserializeCommunicationError(property.Value); continue; } } - return new CommunicationError(code, message, target.Value, Optional.ToList(details), innerError.Value); + return new CommunicationError(code, message, target.Value, Optional.ToList(details), innererror.Value); } } } diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.cs index e00be6938c06..c0b23da10572 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationError.cs @@ -39,7 +39,7 @@ internal CommunicationError(string code, string message) /// The error message. /// The error target. /// Further details about specific errors that led to this error. - /// The Communication Services error. + /// The inner error if any. internal CommunicationError(string code, string message, string target, IReadOnlyList details, CommunicationError innerError) { Code = code; @@ -57,7 +57,7 @@ internal CommunicationError(string code, string message, string target, IReadOnl public string Target { get; } /// Further details about specific errors that led to this error. public IReadOnlyList Details { get; } - /// The Communication Services error. + /// The inner error if any. public CommunicationError InnerError { get; } } } diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.Serialization.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnCredentialsResponse.Serialization.cs similarity index 62% rename from sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.Serialization.cs rename to sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnCredentialsResponse.Serialization.cs index 3849df63adf5..4d10b6dc9f35 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.Serialization.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnCredentialsResponse.Serialization.cs @@ -12,12 +12,12 @@ namespace Azure.Communication.Identity.Models { - public partial class TurnCredentialsResponse + public partial class CommunicationTurnCredentialsResponse { - internal static TurnCredentialsResponse DeserializeTurnCredentialsResponse(JsonElement element) + internal static CommunicationTurnCredentialsResponse DeserializeCommunicationTurnCredentialsResponse(JsonElement element) { DateTimeOffset expiresOn = default; - IReadOnlyList turnServers = default; + IReadOnlyList turnServers = default; foreach (var property in element.EnumerateObject()) { if (property.NameEquals("expiresOn")) @@ -27,16 +27,16 @@ internal static TurnCredentialsResponse DeserializeTurnCredentialsResponse(JsonE } if (property.NameEquals("turnServers")) { - List array = new List(); + List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(TurnServer.DeserializeTurnServer(item)); + array.Add(CommunicationTurnServer.DeserializeCommunicationTurnServer(item)); } turnServers = array; continue; } } - return new TurnCredentialsResponse(expiresOn, turnServers); + return new CommunicationTurnCredentialsResponse(expiresOn, turnServers); } } } diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnCredentialsResponse.cs similarity index 70% rename from sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.cs rename to sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnCredentialsResponse.cs index 9fe3b71674b7..02d826f94524 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnCredentialsResponse.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnCredentialsResponse.cs @@ -12,13 +12,13 @@ namespace Azure.Communication.Identity.Models { /// A TURN credentials response. - public partial class TurnCredentialsResponse + public partial class CommunicationTurnCredentialsResponse { - /// Initializes a new instance of TurnCredentialsResponse. + /// Initializes a new instance of CommunicationTurnCredentialsResponse. /// The date for which the username and credentials are not longer valid. /// An array representing the credentials and the TURN server URL. /// is null. - internal TurnCredentialsResponse(DateTimeOffset expiresOn, IEnumerable turnServers) + internal CommunicationTurnCredentialsResponse(DateTimeOffset expiresOn, IEnumerable turnServers) { if (turnServers == null) { @@ -29,10 +29,10 @@ internal TurnCredentialsResponse(DateTimeOffset expiresOn, IEnumerable Initializes a new instance of TurnCredentialsResponse. + /// Initializes a new instance of CommunicationTurnCredentialsResponse. /// The date for which the username and credentials are not longer valid. /// An array representing the credentials and the TURN server URL. - internal TurnCredentialsResponse(DateTimeOffset expiresOn, IReadOnlyList turnServers) + internal CommunicationTurnCredentialsResponse(DateTimeOffset expiresOn, IReadOnlyList turnServers) { ExpiresOn = expiresOn; TurnServers = turnServers; @@ -41,6 +41,6 @@ internal TurnCredentialsResponse(DateTimeOffset expiresOn, IReadOnlyList The date for which the username and credentials are not longer valid. public DateTimeOffset ExpiresOn { get; } /// An array representing the credentials and the TURN server URL. - public IReadOnlyList TurnServers { get; } + public IReadOnlyList TurnServers { get; } } } diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.Serialization.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnServer.Serialization.cs similarity index 81% rename from sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.Serialization.cs rename to sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnServer.Serialization.cs index c319b65bcd7e..11ce3e6f159e 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.Serialization.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnServer.Serialization.cs @@ -10,9 +10,9 @@ namespace Azure.Communication.Identity.Models { - public partial class TurnServer + public partial class CommunicationTurnServer { - internal static TurnServer DeserializeTurnServer(JsonElement element) + internal static CommunicationTurnServer DeserializeCommunicationTurnServer(JsonElement element) { string urls = default; string username = default; @@ -35,7 +35,7 @@ internal static TurnServer DeserializeTurnServer(JsonElement element) continue; } } - return new TurnServer(urls, username, credential); + return new CommunicationTurnServer(urls, username, credential); } } } diff --git a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.cs b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnServer.cs similarity index 86% rename from sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.cs rename to sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnServer.cs index f8b7a9fa722b..674b51ce933f 100644 --- a/sdk/communication/Azure.Communication.Identity/src/Generated/Models/TurnServer.cs +++ b/sdk/communication/Azure.Communication.Identity/src/Generated/Models/CommunicationTurnServer.cs @@ -10,14 +10,14 @@ namespace Azure.Communication.Identity.Models { /// An instance of a TURN server with credentials. - public partial class TurnServer + public partial class CommunicationTurnServer { - /// Initializes a new instance of TurnServer. + /// Initializes a new instance of CommunicationTurnServer. /// URL of the server. /// User account name which uniquely identifies the credentials. /// Credential for the server. /// , , or is null. - internal TurnServer(string urls, string username, string credential) + internal CommunicationTurnServer(string urls, string username, string credential) { if (urls == null) { diff --git a/sdk/communication/Azure.Communication.Identity/src/autorest.md b/sdk/communication/Azure.Communication.Identity/src/autorest.md index e30b7a7217a8..59043ae3f0a6 100644 --- a/sdk/communication/Azure.Communication.Identity/src/autorest.md +++ b/sdk/communication/Azure.Communication.Identity/src/autorest.md @@ -8,10 +8,7 @@ Run `dotnet msbuild /t:GenerateCode` to generate code. ``` yaml input-file: # - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/5b19c6e69cd2bb9dbe4e5c1237b2c5a175d90ca5/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/stable/2021-03-07/CommunicationIdentity.json -# - https://github.com/apattath/azure-rest-api-specs/blob/08ac674efacce0ae35371f8b1d8c45b5a1420503/specification/communication/data-plane/Microsoft.CommunicationServicesTurn/preview/2021-02-22-preview1/CommunicationTurn.json -# - https://github.com/apattath/azure-rest-api-specs/blob/9edffc88b87fdc90a4d339a0b49487d611304c6f/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/stable/2021-03-07/CommunicationIdentity.json -# - https://github.com/apattath/azure-rest-api-specs/blob/9edffc88b87fdc90a4d339a0b49487d611304c6f/specification/communication/data-plane/Microsoft.CommunicationServicesTurn/preview/2021-02-22-preview1/CommunicationTurn.json - - ./swaggers/CommunicationIdentity.json - - ./swaggers/CommunicationTurn.json + - https://github.com/apattath/azure-rest-api-specs/blob/fd8b27c1124b5f371966045c25a4402fb7b558cd/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/preview/2021-02-22-preview1/CommunicationIdentity.json + - https://github.com/apattath/azure-rest-api-specs/blob/fd8b27c1124b5f371966045c25a4402fb7b558cd/specification/communication/data-plane/Microsoft.CommunicationServicesTurn/preview/2021-02-22-preview1/CommunicationTurn.json payload-flattening-threshold: 3 ``` diff --git a/sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json b/sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json deleted file mode 100644 index c9fe49b34e88..000000000000 --- a/sdk/communication/Azure.Communication.Identity/src/swaggers/Common.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "title": "Communication", - "description": "Communication Services API common types.", - "version": "2020-11-19-preview1" - }, - "paths": {}, - "definitions": { - "CommunicationErrorResponse": { - "description": "The Communication Services error.", - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "description": "The Communication Services error.", - "$ref": "#/definitions/CommunicationError" - } - } - }, - "CommunicationError": { - "description": "The Communication Services error.", - "type": "object", - "required": [ - "code", - "message" - ], - "properties": { - "code": { - "type": "string", - "description": "The error code." - }, - "message": { - "type": "string", - "description": "The error message." - }, - "target": { - "type": "string", - "readOnly": true, - "description": "The error target." - }, - "details": { - "type": "array", - "items": { - "$ref": "#/definitions/CommunicationError" - }, - "readOnly": true, - "description": "Further details about specific errors that led to this error." - }, - "innererror": { - "x-ms-client-name": "innerError", - "readOnly": true, - "$ref": "#/definitions/CommunicationError", - "description": "The inner error if any." - } - }, - "x-nullable": true - }, - "CommunicationIdentifierKind": { - "description": "The kind of a communication identifier.", - "type": "string", - "enum": [ - "unknown", - "communicationUser", - "phoneNumber", - "callingApplication", - "microsoftTeamsUser" - ], - "x-ms-enum": { - "name": "CommunicationIdentifierKind", - "modelAsString": true - } - }, - "CommunicationCloudEnvironmentModel": { - "description": "The cloud that the identifier belongs to.", - "type": "string", - "enum": [ - "public", - "dod", - "gcch" - ], - "x-ms-enum": { - "name": "CommunicationCloudEnvironmentModel", - "modelAsString": true - } - }, - "CommunicationIdentifierModel": { - "description": "Identifies a participant in Azure Communication services. A participant is, for example, a phone number or an Azure communication user.", - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "$ref": "#/definitions/CommunicationIdentifierKind", - "description": "Kind of the communication identifier." - }, - "id": { - "type": "string", - "description": "Full Id of the identifier." - }, - "phoneNumber": { - "type": "string", - "description": "The phone number in E.164 format." - }, - "microsoftTeamsUserId": { - "type": "string", - "description": "The AAD object Id of the Microsoft Teams user." - }, - "isAnonymous": { - "type": "boolean", - "description": "True if the identifier is anonymous." - }, - "cloud": { - "$ref": "#/definitions/CommunicationCloudEnvironmentModel", - "description": "The cloud that the identifier belongs to." - } - } - } - }, - "securityDefinitions": { - "azure_auth": { - "type": "oauth2", - "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", - "flow": "implicit", - "description": "Azure Active Directory OAuth2 Flow.", - "scopes": { - "user_impersonation": "impersonate your user account" - } - } - } -} diff --git a/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json b/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json deleted file mode 100644 index 875892416f06..000000000000 --- a/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationIdentity.json +++ /dev/null @@ -1,359 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "title": "CommunicationIdentityClient", - "description": "Azure Communication Identity Service", - "version": "2021-02-22-preview1" - }, - "paths": { - "/identities": { - "post": { - "tags": [ - "Identity" - ], - "summary": "Create a new identity.", - "operationId": "CommunicationIdentity_Create", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "in": "body", - "name": "body", - "schema": { - "$ref": "#/definitions/CommunicationIdentityCreateRequest" - } - } - ], - "responses": { - "default": { - "description": "Error", - "schema": { - "$ref": "#/definitions/CommunicationErrorResponse" - } - }, - "201": { - "description": "Created - Returns the created identity.", - "schema": { - "$ref": "#/definitions/CommunicationIdentityAccessTokenResult" - } - } - }, - "x-ms-examples": { - "Create an Identity": { - "$ref": "./examples/CreateIdentity.json" - } - } - } - }, - "/identities/{id}": { - "delete": { - "tags": [ - "Identity" - ], - "summary": "Delete the identity, revoke all tokens for the identity and delete all associated data.", - "operationId": "CommunicationIdentity_Delete", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "id", - "description": "Identifier of the identity to be deleted.", - "required": true, - "type": "string" - }, - { - "$ref": "#/parameters/ApiVersionParameter" - } - ], - "responses": { - "default": { - "description": "Error", - "schema": { - "$ref": "#/definitions/CommunicationErrorResponse" - } - }, - "204": { - "description": "Success" - } - }, - "x-ms-examples": { - "Delete an identity": { - "$ref": "./examples/DeleteIdentity.json" - } - } - } - }, - "/identities/{id}/:revokeAccessTokens": { - "post": { - "tags": [ - "Identity" - ], - "summary": "Revoke all access tokens for the specific identity.", - "operationId": "CommunicationIdentity_RevokeAccessTokens", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "id", - "description": "Identifier of the identity.", - "required": true, - "type": "string" - }, - { - "$ref": "#/parameters/ApiVersionParameter" - } - ], - "responses": { - "default": { - "description": "Error", - "schema": { - "$ref": "#/definitions/CommunicationErrorResponse" - } - }, - "204": { - "description": "Success" - } - }, - "x-ms-examples": { - "Revoke access tokens": { - "$ref": "./examples/RevokeAccessTokens.json" - } - } - } - }, - "/identities/{id}/:issueAccessToken": { - "post": { - "tags": [ - "Token" - ], - "summary": "Issue a new token for an identity.", - "operationId": "CommunicationIdentity_IssueAccessToken", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "id", - "description": "Identifier of the identity to issue token for.", - "required": true, - "type": "string" - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "in": "body", - "name": "body", - "description": "Requesting scopes for the new token.", - "required": true, - "schema": { - "$ref": "#/definitions/CommunicationIdentityAccessTokenRequest" - } - } - ], - "responses": { - "default": { - "description": "Error", - "schema": { - "$ref": "#/definitions/CommunicationErrorResponse" - } - }, - "200": { - "description": "Success", - "schema": { - "$ref": "#/definitions/CommunicationIdentityAccessToken" - } - } - }, - "x-ms-examples": { - "Issue an access token": { - "$ref": "./examples/IssueAccessToken.json" - } - } - } - } - }, - "definitions": { - "CommunicationIdentityTokenScope": { - "description": "List of scopes for an access token.", - "enum": [ - "chat", - "voip" - ], - "type": "string", - "x-ms-enum": { - "name": "CommunicationIdentityTokenScope", - "modelAsString": true - } - }, - "CommunicationIdentityCreateRequest": { - "type": "object", - "properties": { - "createTokenWithScopes": { - "description": "Also create access token for the created identity.", - "type": "array", - "items": { - "$ref": "#/definitions/CommunicationIdentityTokenScope" - } - } - } - }, - "CommunicationError": { - "description": "The Communication Services error.", - "required": [ - "code", - "message" - ], - "type": "object", - "properties": { - "code": { - "description": "The error code.", - "type": "string" - }, - "message": { - "description": "The error message.", - "type": "string" - }, - "target": { - "description": "The error target.", - "type": "string", - "readOnly": true - }, - "details": { - "description": "Further details about specific errors that led to this error.", - "type": "array", - "items": { - "$ref": "#/definitions/CommunicationError" - }, - "readOnly": true - }, - "innerError": { - "$ref": "#/definitions/CommunicationError" - } - } - }, - "CommunicationErrorResponse": { - "description": "The Communication Services error.", - "required": [ - "error" - ], - "type": "object", - "properties": { - "error": { - "$ref": "#/definitions/CommunicationError" - } - } - }, - "CommunicationIdentity": { - "description": "A communication identity.", - "required": [ - "id" - ], - "type": "object", - "properties": { - "id": { - "description": "Identifier of the identity.", - "type": "string" - } - } - }, - "CommunicationIdentityAccessToken": { - "description": "An access token.", - "required": [ - "expiresOn", - "token" - ], - "type": "object", - "properties": { - "token": { - "description": "The access token issued for the identity.", - "type": "string" - }, - "expiresOn": { - "format": "date-time", - "description": "The expiry time of the token.", - "type": "string" - } - } - }, - "CommunicationIdentityAccessTokenResult": { - "description": "A communication identity with access token.", - "required": [ - "identity" - ], - "type": "object", - "properties": { - "identity": { - "$ref": "#/definitions/CommunicationIdentity" - }, - "accessToken": { - "$ref": "#/definitions/CommunicationIdentityAccessToken" - } - } - }, - "CommunicationIdentityAccessTokenRequest": { - "required": [ - "scopes" - ], - "type": "object", - "properties": { - "scopes": { - "description": "List of scopes attached to the token.", - "type": "array", - "items": { - "$ref": "#/definitions/CommunicationIdentityTokenScope" - } - } - } - } - }, - "parameters": { - "ApiVersionParameter": { - "in": "query", - "name": "api-version", - "description": "Version of API to invoke.", - "required": true, - "type": "string" - } - }, - "securityDefinitions": { - "azure_auth": { - "type": "oauth2", - "flow": "implicit", - "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", - "scopes": { - "user_impersonation": "impersonate your user account" - } - } - }, - "x-ms-parameterized-host": { - "hostTemplate": "{endpoint}", - "useSchemePrefix": false, - "parameters": [ - { - "name": "endpoint", - "description": "The communication resource, for example https://my-resource.communication.azure.com", - "required": true, - "type": "string", - "in": "path", - "x-ms-skip-url-encoding": true, - "x-ms-parameter-location": "client" - } - ] - } -} diff --git a/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json b/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json deleted file mode 100644 index 1111d5583e4b..000000000000 --- a/sdk/communication/Azure.Communication.Identity/src/swaggers/CommunicationTurn.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "title": "CommunicationIdentityClient", - "description": "Azure Communication Relay Service", - "version": "2021-02-22-preview1" - }, - "paths": { - "/turn/{id}/:issueCredentials": { - "post": { - "tags": [ - "Turn" - ], - "summary": "Issue TURN credentials for an existing identity.", - "operationId": "CommunicationIdentity_IssueTurnCredentials", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "id", - "description": "Identifier of the existing identity to issue credentials for.", - "required": true, - "type": "string" - }, - { - "$ref": "#/parameters/ApiVersionParameter" - } - ], - "responses": { - "default": { - "description": "Error", - "schema": { - "$ref": "./CommunicationIdentity.json#/definitions/CommunicationErrorResponse" - } - }, - "200": { - "description": "Success", - "schema": { - "$ref": "#/definitions/TurnCredentialsResponse" - } - } - }, - "x-ms-examples": { - "Issue Turn Credentials": { - "$ref": "./examples/IssueTurnCredentials.json" - } - } - } - } - }, - "definitions": { - "TurnServer": { - "description": "An instance of a TURN server with credentials.", - "required": [ - "credential", - "urls", - "username" - ], - "type": "object", - "properties": { - "urls": { - "description": "URL of the server.", - "type": "string" - }, - "username": { - "description": "User account name which uniquely identifies the credentials.", - "type": "string" - }, - "credential": { - "description": "Credential for the server.", - "type": "string" - } - } - }, - "TurnCredentialsResponse": { - "description": "A TURN credentials response.", - "required": [ - "expiresOn", - "turnServers" - ], - "type": "object", - "properties": { - "expiresOn": { - "format": "date-time", - "description": "The date for which the username and credentials are not longer valid.", - "type": "string" - }, - "turnServers": { - "description": "An array representing the credentials and the TURN server URL.", - "type": "array", - "items": { - "$ref": "#/definitions/TurnServer" - } - } - } - } - }, - "parameters": { - "ApiVersionParameter": { - "in": "query", - "name": "api-version", - "description": "Version of API to invoke.", - "required": true, - "type": "string" - } - }, - "securityDefinitions": { - "azure_auth": { - "type": "oauth2", - "flow": "implicit", - "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", - "scopes": { - "user_impersonation": "impersonate your user account" - } - } - }, - "x-ms-parameterized-host": { - "hostTemplate": "{endpoint}", - "useSchemePrefix": false, - "parameters": [ - { - "name": "endpoint", - "description": "The communication resource, for example https://my-resource.communication.azure.com", - "required": true, - "type": "string", - "in": "path", - "x-ms-skip-url-encoding": true, - "x-ms-parameter-location": "client" - } - ] - } -} From 2e2d50f6577df0931fab6bf34a7dba8cc381c9ca Mon Sep 17 00:00:00 2001 From: Avin Pattath Date: Wed, 10 Feb 2021 12:02:59 -0800 Subject: [PATCH 04/11] add SDK test for turn credential issue API --- .../CommunicationIdentityClientLiveTests.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs b/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs index def9cd9c96ae..b10035821890 100644 --- a/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs +++ b/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Azure.Communication.Identity.Models; using Azure.Core; using Azure.Core.TestFramework; using Azure.Identity; @@ -61,6 +62,36 @@ void ValidateScopesIfNotSanitized() } } + [Test] + [TestCase(AuthMethod.ConnectionString, TestName = "IssuingTurnCredentialsWithConnectionString")] + [TestCase(AuthMethod.KeyCredential, TestName = "IssuingTurnCredentialsWithKeyCredential")] + [TestCase(AuthMethod.TokenCredential, TestName = "IssuingTurnCredentialsWithTokenCredential")] + public async Task IssuingTurnCredentialsGeneratesTurnCredentials(AuthMethod authMethod) + { + CommunicationIdentityClient client = authMethod switch + { + AuthMethod.ConnectionString => CreateClientWithConnectionString(), + AuthMethod.KeyCredential => CreateClientWithAzureKeyCredential(), + AuthMethod.TokenCredential => CreateClientWithTokenCredential(), + _ => throw new ArgumentOutOfRangeException(nameof(authMethod)), + }; + + Response userResponse = await client.CreateUserAsync(); + Response turnCredentialsResponse = await client.IssueTurnCredentialsAsync(userResponse.Value); + + Assert.IsNotNull(turnCredentialsResponse.Value); + Assert.IsNotNull(turnCredentialsResponse.Value.TurnServers); + // ToDo: Should we expect a set number of turn server credentials? + // ToDo: Are there any constraints on returned values that need to be verified? + // Should we sanitize credential responses or is it automatically sanitized as part of the pipeline? + foreach (CommunicationTurnServer serverCredential in turnCredentialsResponse.Value.TurnServers) + { + Assert.IsFalse(string.IsNullOrWhiteSpace(serverCredential.Urls)); + Assert.IsFalse(string.IsNullOrWhiteSpace(serverCredential.Username)); + Assert.IsFalse(string.IsNullOrWhiteSpace(serverCredential.Credential)); + } + } + public enum AuthMethod { ConnectionString, From 3b3bea8afd061cc8e1b0fc1b773643658e574a27 Mon Sep 17 00:00:00 2001 From: Avin Pattath Date: Thu, 11 Feb 2021 18:17:07 -0800 Subject: [PATCH 05/11] Update to use updated swaggers for turn and identity --- .../src/CommunicationIdentityClient.cs | 13 ++++++++----- .../Azure.Communication.Identity/src/autorest.md | 5 ++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs b/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs index 847374cd5fd7..05cf54b45c99 100644 --- a/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs +++ b/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs @@ -65,7 +65,8 @@ private CommunicationIdentityClient(CommunicationIdentityClientOptions options, RestClient = new CommunicationIdentityRestClient( _clientDiagnostics, options.BuildHttpPipeline(connectionString), - connectionString.GetRequired("endpoint")); + connectionString.GetRequired("endpoint"), + apiVersion: "2021-03-07"); } private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOptions options, AzureKeyCredential credential) @@ -74,7 +75,8 @@ private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOpt RestClient = new CommunicationIdentityRestClient( _clientDiagnostics, options.BuildHttpPipeline(credential), - endpoint.AbsoluteUri); + endpoint.AbsoluteUri, + apiVersion: "2021-03-07"); } private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOptions options, TokenCredential tokenCredential) @@ -83,7 +85,8 @@ private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOpt RestClient = new CommunicationIdentityRestClient( _clientDiagnostics, options.BuildHttpPipeline(tokenCredential), - endpoint.AbsoluteUri); + endpoint.AbsoluteUri, + apiVersion: "2021-03-07"); } /// Initializes a new instance of for mocking. @@ -296,7 +299,7 @@ public virtual async Task RevokeTokensAsync(CommunicationUserIdentifie /// The server returned an error. public virtual Response IssueTurnCredentials(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueToken)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueTurnCredentials)}"); scope.Start(); try { @@ -315,7 +318,7 @@ public virtual Response IssueTurnCredentia /// The cancellation token to use. public virtual async Task> IssueTurnCredentialsAsync(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueToken)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueTurnCredentials)}"); scope.Start(); try { diff --git a/sdk/communication/Azure.Communication.Identity/src/autorest.md b/sdk/communication/Azure.Communication.Identity/src/autorest.md index 59043ae3f0a6..00669dde0f1d 100644 --- a/sdk/communication/Azure.Communication.Identity/src/autorest.md +++ b/sdk/communication/Azure.Communication.Identity/src/autorest.md @@ -7,8 +7,7 @@ Run `dotnet msbuild /t:GenerateCode` to generate code. ``` yaml input-file: -# - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/5b19c6e69cd2bb9dbe4e5c1237b2c5a175d90ca5/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/stable/2021-03-07/CommunicationIdentity.json - - https://github.com/apattath/azure-rest-api-specs/blob/fd8b27c1124b5f371966045c25a4402fb7b558cd/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/preview/2021-02-22-preview1/CommunicationIdentity.json - - https://github.com/apattath/azure-rest-api-specs/blob/fd8b27c1124b5f371966045c25a4402fb7b558cd/specification/communication/data-plane/Microsoft.CommunicationServicesTurn/preview/2021-02-22-preview1/CommunicationTurn.json + - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/a1eee0489c374782a934ec1f093abd16fa7718ca/specification/communication/data-plane/Microsoft.CommunicationServicesIdentity/preview/2021-02-22-preview1/CommunicationIdentity.json + - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/a1eee0489c374782a934ec1f093abd16fa7718ca/specification/communication/data-plane/Microsoft.CommunicationServicesTurn/preview/2021-02-22-preview1/CommunicationTurn.json payload-flattening-threshold: 3 ``` From 4d3552ec78080d187649665a95a7a377f796b149 Mon Sep 17 00:00:00 2001 From: Avin Pattath Date: Fri, 12 Feb 2021 18:50:35 -0800 Subject: [PATCH 06/11] Update SDK to use different clients for identity and turn endpoints. --- .../src/CommunicationIdentityClient.cs | 39 ++++++++++++++----- .../CommunicationIdentityClientLiveTests.cs | 1 + 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs b/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs index 05cf54b45c99..ee137b59b100 100644 --- a/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs +++ b/sdk/communication/Azure.Communication.Identity/src/CommunicationIdentityClient.cs @@ -18,7 +18,10 @@ namespace Azure.Communication.Identity public class CommunicationIdentityClient { private readonly ClientDiagnostics _clientDiagnostics; + private readonly HttpPipeline _pipeline; + private readonly string _endpoint; internal CommunicationIdentityRestClient RestClient { get; } + internal CommunicationIdentityRestClient RestClientForTurn { get; } /// Initializes a new instance of . /// The URI of the Azure Communication Services resource. @@ -62,30 +65,36 @@ public CommunicationIdentityClient(Uri endpoint, TokenCredential tokenCredential private CommunicationIdentityClient(CommunicationIdentityClientOptions options, ConnectionString connectionString) { _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = options.BuildHttpPipeline(connectionString); + _endpoint = connectionString.GetRequired("endpoint"); RestClient = new CommunicationIdentityRestClient( _clientDiagnostics, - options.BuildHttpPipeline(connectionString), - connectionString.GetRequired("endpoint"), + _pipeline, + _endpoint, apiVersion: "2021-03-07"); } private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOptions options, AzureKeyCredential credential) { _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = options.BuildHttpPipeline(credential); + _endpoint = endpoint.AbsoluteUri; RestClient = new CommunicationIdentityRestClient( _clientDiagnostics, - options.BuildHttpPipeline(credential), - endpoint.AbsoluteUri, + _pipeline, + _endpoint, apiVersion: "2021-03-07"); } private CommunicationIdentityClient(Uri endpoint, CommunicationIdentityClientOptions options, TokenCredential tokenCredential) { _clientDiagnostics = new ClientDiagnostics(options); - RestClient = new CommunicationIdentityRestClient( + _pipeline = options.BuildHttpPipeline(tokenCredential); + _endpoint = endpoint.AbsoluteUri; + RestClientForTurn = new CommunicationIdentityRestClient( _clientDiagnostics, - options.BuildHttpPipeline(tokenCredential), - endpoint.AbsoluteUri, + _pipeline, + _endpoint, apiVersion: "2021-03-07"); } @@ -299,11 +308,17 @@ public virtual async Task RevokeTokensAsync(CommunicationUserIdentifie /// The server returned an error. public virtual Response IssueTurnCredentials(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default) { + var RestClientForTurn = new CommunicationIdentityRestClient( + _clientDiagnostics, + _pipeline, + _endpoint, + apiVersion: "2021-12-12"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueTurnCredentials)}"); scope.Start(); try { - Response response = RestClient.IssueTurnCredentials(communicationUser.Id, cancellationToken); + Response response = RestClientForTurn.IssueTurnCredentials(communicationUser.Id, cancellationToken); return response; } catch (Exception ex) @@ -318,11 +333,17 @@ public virtual Response IssueTurnCredentia /// The cancellation token to use. public virtual async Task> IssueTurnCredentialsAsync(CommunicationUserIdentifier communicationUser, CancellationToken cancellationToken = default) { + var RestClientForTurn = new CommunicationIdentityRestClient( + _clientDiagnostics, + _pipeline, + _endpoint, + apiVersion: "2021-12-12"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CommunicationIdentityClient)}.{nameof(IssueTurnCredentials)}"); scope.Start(); try { - Response response = await RestClient.IssueTurnCredentialsAsync(communicationUser.Id, cancellationToken).ConfigureAwait(false); + Response response = await RestClientForTurn.IssueTurnCredentialsAsync(communicationUser.Id, cancellationToken).ConfigureAwait(false); return response; } catch (Exception ex) diff --git a/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs b/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs index b10035821890..d99547372cbb 100644 --- a/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs +++ b/sdk/communication/Azure.Communication.Identity/tests/CommunicationIdentityClient/CommunicationIdentityClientLiveTests.cs @@ -80,6 +80,7 @@ public async Task IssuingTurnCredentialsGeneratesTurnCredentials(AuthMethod auth Response turnCredentialsResponse = await client.IssueTurnCredentialsAsync(userResponse.Value); Assert.IsNotNull(turnCredentialsResponse.Value); + Assert.IsNotNull(turnCredentialsResponse.Value.ExpiresOn); Assert.IsNotNull(turnCredentialsResponse.Value.TurnServers); // ToDo: Should we expect a set number of turn server credentials? // ToDo: Are there any constraints on returned values that need to be verified? From 3583379b95246af6f694c41f25a4ece7e1f2c706 Mon Sep 17 00:00:00 2001 From: Avin Pattath Date: Tue, 16 Feb 2021 08:13:00 -0800 Subject: [PATCH 07/11] Update API by running Export-API.ps1 script --- ...re.Communication.Identity.netstandard2.0.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sdk/communication/Azure.Communication.Identity/api/Azure.Communication.Identity.netstandard2.0.cs b/sdk/communication/Azure.Communication.Identity/api/Azure.Communication.Identity.netstandard2.0.cs index 5b93834db90a..f1141d3c659e 100644 --- a/sdk/communication/Azure.Communication.Identity/api/Azure.Communication.Identity.netstandard2.0.cs +++ b/sdk/communication/Azure.Communication.Identity/api/Azure.Communication.Identity.netstandard2.0.cs @@ -15,6 +15,8 @@ public CommunicationIdentityClient(System.Uri endpoint, Azure.Core.TokenCredenti public virtual System.Threading.Tasks.Task DeleteUserAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response IssueToken(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Collections.Generic.IEnumerable scopes, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> IssueTokenAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Collections.Generic.IEnumerable scopes, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response IssueTurnCredentials(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> IssueTurnCredentialsAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response RevokeTokens(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task RevokeTokensAsync(Azure.Communication.CommunicationUserIdentifier communicationUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } @@ -45,3 +47,19 @@ public enum ServiceVersion public override string ToString() { throw null; } } } +namespace Azure.Communication.Identity.Models +{ + public partial class CommunicationTurnCredentialsResponse + { + internal CommunicationTurnCredentialsResponse() { } + public System.DateTimeOffset ExpiresOn { get { throw null; } } + public System.Collections.Generic.IReadOnlyList TurnServers { get { throw null; } } + } + public partial class CommunicationTurnServer + { + internal CommunicationTurnServer() { } + public string Credential { get { throw null; } } + public string Urls { get { throw null; } } + public string Username { get { throw null; } } + } +} From 129ff64c66fa500e6def9f1003ab9c4fd777d9a9 Mon Sep 17 00:00:00 2001 From: Avin Pattath Date: Tue, 16 Feb 2021 09:21:44 -0800 Subject: [PATCH 08/11] Update samples in the SDK to include TURN API --- .../samples/README.md | 5 ++- .../Sample1_CommunicationIdentityClient.md | 20 ++++++++++++ ...ample1_CommunicationIdentityClientAsync.md | 20 ++++++++++++ .../Sample1_CommunicationIdentityClient.cs | 32 +++++++++++++++++-- 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/sdk/communication/Azure.Communication.Identity/samples/README.md b/sdk/communication/Azure.Communication.Identity/samples/README.md index 74f6f18f5faa..e5d14c9a3ecf 100644 --- a/sdk/communication/Azure.Communication.Identity/samples/README.md +++ b/sdk/communication/Azure.Communication.Identity/samples/README.md @@ -16,12 +16,11 @@ To get started you will need to have an Azure Subscription. Once you have this y This client library allows to do following operations: - Generate user tokens that allows the holders to access Azure Communication Services. - - Purchase, configure and release phone numbers. + - Generate TURN server credentials that allows the holders to get access to a TURN server for media relay. #### You can find samples for each of these functions below. - - Generate user tokens [synchronously][sample_identity] or [asynchronously][sample_identity_async] + - Generate user tokens and TURN credentials [synchronously][sample_identity] or [asynchronously][sample_identity_async] [sample_identity]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClient.md [sample_identity_async]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClientAsync.md -[ diff --git a/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClient.md b/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClient.md index bcec26c194a9..3b92a4f8971e 100644 --- a/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClient.md +++ b/sdk/communication/Azure.Communication.Identity/samples/Sample1_CommunicationIdentityClient.md @@ -55,6 +55,26 @@ Console.WriteLine($"Token: {token}"); Console.WriteLine($"Expires On: {expiresOn}"); ``` +## Generate TURN credentials + +The example code snippet below shows how to generate TURN credentials for an Azure Communication user that was created following the steps above. +A set of TURN credentials are returned for the user. Each TURN credential consists of a url for a TURN server, its corresponding username and a credential. + +Every set of TURN credentials is stamped with an expiry date. Once the credentials are expired, you can renew the token by calling the same method. + +```C# Snippet:CreateTURNTokenAsync +Response turnTokenResponse = await client.IssueTurnCredentialsAsync(user); +DateTimeOffset turnTokenExpiresOn = turnTokenResponse.Value.ExpiresOn; +IReadOnlyList turnServers = turnTokenResponse.Value.TurnServers; +Console.WriteLine($"Expires On: {turnTokenExpiresOn}"); +foreach (CommunicationTurnServer turnServer in turnServers) +{ + Console.WriteLine($"TURN Url: {turnServer.Urls}"); + Console.WriteLine($"TURN Username: {turnServer.Username}"); + Console.WriteLine($"TURN Credential: {turnServer.Credential}"); +} +``` +