From 578b6176bef02d88317b24a4e77dddaba3901d4f Mon Sep 17 00:00:00 2001 From: MBSolomon <89044647+MBSolomon@users.noreply.github.com> Date: Thu, 26 Oct 2023 16:37:42 -0700 Subject: [PATCH 01/28] generated codespec for web pubsub --- sdk/messaging/azwebpubsub/CHANGELOG.md | 5 + sdk/messaging/azwebpubsub/LICENSE.txt | 21 + sdk/messaging/azwebpubsub/NOTICE.txt | 31 + sdk/messaging/azwebpubsub/README.md | 69 + sdk/messaging/azwebpubsub/autorest.md | 15 + sdk/messaging/azwebpubsub/build.go | 9 + sdk/messaging/azwebpubsub/ci.yml | 30 + sdk/messaging/azwebpubsub/client.go | 1223 +++++++++++++++++ sdk/messaging/azwebpubsub/constants.go | 46 + sdk/messaging/azwebpubsub/go.mod | 21 + sdk/messaging/azwebpubsub/go.sum | 14 + sdk/messaging/azwebpubsub/healthapi_client.go | 61 + sdk/messaging/azwebpubsub/internal/version.go | 18 + sdk/messaging/azwebpubsub/models.go | 56 + sdk/messaging/azwebpubsub/models_serde.go | 200 +++ sdk/messaging/azwebpubsub/options.go | 191 +++ sdk/messaging/azwebpubsub/package-lock.json | 6 + sdk/messaging/azwebpubsub/package.json | 1 + sdk/messaging/azwebpubsub/response_types.go | 131 ++ 19 files changed, 2148 insertions(+) create mode 100644 sdk/messaging/azwebpubsub/CHANGELOG.md create mode 100644 sdk/messaging/azwebpubsub/LICENSE.txt create mode 100644 sdk/messaging/azwebpubsub/NOTICE.txt create mode 100644 sdk/messaging/azwebpubsub/README.md create mode 100644 sdk/messaging/azwebpubsub/autorest.md create mode 100644 sdk/messaging/azwebpubsub/build.go create mode 100644 sdk/messaging/azwebpubsub/ci.yml create mode 100644 sdk/messaging/azwebpubsub/client.go create mode 100644 sdk/messaging/azwebpubsub/constants.go create mode 100644 sdk/messaging/azwebpubsub/go.mod create mode 100644 sdk/messaging/azwebpubsub/go.sum create mode 100644 sdk/messaging/azwebpubsub/healthapi_client.go create mode 100644 sdk/messaging/azwebpubsub/internal/version.go create mode 100644 sdk/messaging/azwebpubsub/models.go create mode 100644 sdk/messaging/azwebpubsub/models_serde.go create mode 100644 sdk/messaging/azwebpubsub/options.go create mode 100644 sdk/messaging/azwebpubsub/package-lock.json create mode 100644 sdk/messaging/azwebpubsub/package.json create mode 100644 sdk/messaging/azwebpubsub/response_types.go diff --git a/sdk/messaging/azwebpubsub/CHANGELOG.md b/sdk/messaging/azwebpubsub/CHANGELOG.md new file mode 100644 index 000000000000..ad4b95676df2 --- /dev/null +++ b/sdk/messaging/azwebpubsub/CHANGELOG.md @@ -0,0 +1,5 @@ +# Release History + +## 0.1.0 (2023-xx-xx) + +* Template package validating release pipeline \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/LICENSE.txt b/sdk/messaging/azwebpubsub/LICENSE.txt new file mode 100644 index 000000000000..ce29e72a36df --- /dev/null +++ b/sdk/messaging/azwebpubsub/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/NOTICE.txt b/sdk/messaging/azwebpubsub/NOTICE.txt new file mode 100644 index 000000000000..192a008914bf --- /dev/null +++ b/sdk/messaging/azwebpubsub/NOTICE.txt @@ -0,0 +1,31 @@ +azwebpubsub + +NOTICES AND INFORMATION +Do Not Translate or Localize + +This software incorporates material from third parties. Microsoft makes certain +open source code available at https://3rdpartysource.microsoft.com, or you may +send a check or money order for US $5.00, including the product name, the open +source component name, and version number, to: + +Source Code Compliance Team +Microsoft Corporation +One Microsoft Way +Redmond, WA 98052 +USA + +Notwithstanding any other terms, you may reverse engineer this software to the +extent required to debug changes to any libraries licensed under the GNU Lesser +General Public License. + +------------------------------------------------------------------------------ + +Azure SDK for Go uses third-party libraries or other resources that may be +distributed under licenses different than the Azure SDK for Go software. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: + + @microsoft.com + +The attached notices are provided for information only. \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/README.md b/sdk/messaging/azwebpubsub/README.md new file mode 100644 index 000000000000..76386ba402d6 --- /dev/null +++ b/sdk/messaging/azwebpubsub/README.md @@ -0,0 +1,69 @@ +# Azure Template Package client library for Go + +Azure Template Package client library for Go (`aztemplate`) matches necessary patterns that the development team has established to create a unified SDK written in the Go programming language. These libraries follow the Azure SDK Design Guidelines for Go. + +The library allows client libraries to expose common functionality in a consistent fashion. Once you learn how to use these APIs in one client library, you will know how to use them in other client libraries. + +## Getting started + +For a rich example of a well formatted readme, please check [here.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md) In addition, this is an [example readme](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-EXAMPLE.md) that should be emulated. Note that the top-level sections in this template align with that of the [template.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md) + +# Key concepts + +Bullet point list of your library's main concepts. + +# Examples + +Examples of some of the key concepts for your library. + +# Troubleshooting + +Running into issues? This section should contain details as to what to do there. + +# Next steps + +More sample code should go here, along with links out to the appropriate example tests. + +## Contributing +For details on contributing to this repository, see the [contributing guide][azure_sdk_for_go_contributing]. + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +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. + +### Additional Helpful Links for Contributors +Many people all over the world have helped make this project better. You'll want to check out: + +* [What are some good first issues for new contributors to the repo?](https://github.com/azure/azure-sdk-for-go/issues?q=is%3Aopen+is%3Aissue+label%3A%22up+for+grabs%22) +* [How to build and test your change][azure_sdk_for_go_contributing_developer_guide] +* [How you can make a change happen!][azure_sdk_for_go_contributing_pull_requests] +* Frequently Asked Questions (FAQ) and Conceptual Topics in the detailed [Azure SDK for Go wiki](https://github.com/azure/azure-sdk-for-go/wiki). + + +### Reporting security issues and security bugs + +Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) . You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the [Security TechCenter](https://www.microsoft.com/msrc/faqs-report-an-issue). + +### License + +Azure SDK for Go is licensed under the [MIT](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/template/aztemplate/LICENSE.txt) license. + + +[azure_sdk_for_go_contributing]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md +[azure_sdk_for_go_contributing_developer_guide]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md#developer-guide +[azure_sdk_for_go_contributing_pull_requests]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md#pull-requests +[azure_cli]: https://docs.microsoft.com/cli/azure +[azure_pattern_circuit_breaker]: https://docs.microsoft.com/azure/architecture/patterns/circuit-breaker +[azure_pattern_retry]: https://docs.microsoft.com/azure/architecture/patterns/retry +[azure_portal]: https://portal.azure.com +[azure_sub]: https://azure.microsoft.com/free/ +[cloud_shell]: https://docs.microsoft.com/azure/cloud-shell/overview +[cloud_shell_bash]: https://shell.azure.com/bash \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md new file mode 100644 index 000000000000..0cafde056c44 --- /dev/null +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -0,0 +1,15 @@ +## Go + +```yaml +title: WebPubSub +description: Azure Web PubSub client +clear-output-folder: false +export-clients: true +go: true +input-file: https://github.com/Azure/azure-rest-api-specs/blob/main/specification/webpubsub/data-plane/WebPubSub/stable/2023-07-01/webpubsub.json #TODO: change to hash for commit +license-header: MICROSOFT_MIT_NO_VERSION +module: github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub +openapi-type: "data-plane" +output-folder: ../azwebpubsub +use: "@autorest/go@4.0.0-preview.57" +``` \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/build.go b/sdk/messaging/azwebpubsub/build.go new file mode 100644 index 000000000000..cd74dd14c0c9 --- /dev/null +++ b/sdk/messaging/azwebpubsub/build.go @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +//go:build go1.18 +// +build go1.18 + +//go:generate autorest ./autorest.md +//go:generate goimports -w . + +package azwebpubsub diff --git a/sdk/messaging/azwebpubsub/ci.yml b/sdk/messaging/azwebpubsub/ci.yml new file mode 100644 index 000000000000..09cc844ff4f1 --- /dev/null +++ b/sdk/messaging/azwebpubsub/ci.yml @@ -0,0 +1,30 @@ +# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file. +trigger: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/messaging/azwebpubsub/ + - eng/ + +pr: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/messaging/azwebpubsub/ + - eng/ + + +stages: +- template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml + parameters: + ServiceDirectory: 'messaging/azwebpubsub/' \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/client.go b/sdk/messaging/azwebpubsub/client.go new file mode 100644 index 000000000000..46131bca8bfa --- /dev/null +++ b/sdk/messaging/azwebpubsub/client.go @@ -0,0 +1,1223 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azwebpubsub + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "io" + "net/http" + "net/url" + "strconv" + "strings" +) + +// Client contains the methods for the WebPubSub group. +// Don't use this type directly, use a constructor function instead. +type Client struct { + internal *azcore.Client + endpoint string +} + +// AddConnectionToGroup - Add a connection to the target group. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - group - Target group name, which length should be greater than 0 and less than 1025. +// - connectionID - Target connection Id +// - options - ClientAddConnectionToGroupOptions contains the optional parameters for the Client.AddConnectionToGroup method. +func (client *Client) AddConnectionToGroup(ctx context.Context, hub string, group string, connectionID string, options *ClientAddConnectionToGroupOptions) (ClientAddConnectionToGroupResponse, error) { + var err error + req, err := client.addConnectionToGroupCreateRequest(ctx, hub, group, connectionID, options) + if err != nil { + return ClientAddConnectionToGroupResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientAddConnectionToGroupResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ClientAddConnectionToGroupResponse{}, err + } + return ClientAddConnectionToGroupResponse{}, nil +} + +// addConnectionToGroupCreateRequest creates the AddConnectionToGroup request. +func (client *Client) addConnectionToGroupCreateRequest(ctx context.Context, hub string, group string, connectionID string, options *ClientAddConnectionToGroupOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/groups/{group}/connections/{connectionId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if group == "" { + return nil, errors.New("parameter group cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{group}", url.PathEscape(group)) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// AddConnectionsToGroups - Add filtered connections to multiple groups. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - groupsToAdd - Target groups and connection filter. +// - options - ClientAddConnectionsToGroupsOptions contains the optional parameters for the Client.AddConnectionsToGroups method. +func (client *Client) AddConnectionsToGroups(ctx context.Context, hub string, groupsToAdd AddToGroupsRequest, options *ClientAddConnectionsToGroupsOptions) (ClientAddConnectionsToGroupsResponse, error) { + var err error + req, err := client.addConnectionsToGroupsCreateRequest(ctx, hub, groupsToAdd, options) + if err != nil { + return ClientAddConnectionsToGroupsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientAddConnectionsToGroupsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ClientAddConnectionsToGroupsResponse{}, err + } + return ClientAddConnectionsToGroupsResponse{}, nil +} + +// addConnectionsToGroupsCreateRequest creates the AddConnectionsToGroups request. +func (client *Client) addConnectionsToGroupsCreateRequest(ctx context.Context, hub string, groupsToAdd AddToGroupsRequest, options *ClientAddConnectionsToGroupsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/:addToGroups" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + if err := runtime.MarshalAsJSON(req, groupsToAdd); err != nil { + return nil, err +} + return req, nil +} + +// AddUserToGroup - Add a user to the target group. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - group - Target group name, which length should be greater than 0 and less than 1025. +// - userID - Target user Id. +// - options - ClientAddUserToGroupOptions contains the optional parameters for the Client.AddUserToGroup method. +func (client *Client) AddUserToGroup(ctx context.Context, hub string, group string, userID string, options *ClientAddUserToGroupOptions) (ClientAddUserToGroupResponse, error) { + var err error + req, err := client.addUserToGroupCreateRequest(ctx, hub, group, userID, options) + if err != nil { + return ClientAddUserToGroupResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientAddUserToGroupResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ClientAddUserToGroupResponse{}, err + } + return ClientAddUserToGroupResponse{}, nil +} + +// addUserToGroupCreateRequest creates the AddUserToGroup request. +func (client *Client) addUserToGroupCreateRequest(ctx context.Context, hub string, group string, userID string, options *ClientAddUserToGroupOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/users/{userId}/groups/{group}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if group == "" { + return nil, errors.New("parameter group cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{group}", url.PathEscape(group)) + if userID == "" { + return nil, errors.New("parameter userID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{userId}", url.PathEscape(userID)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// CheckPermission - Check if a connection has permission to the specified action. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. +// - connectionID - Target connection Id. +// - options - ClientCheckPermissionOptions contains the optional parameters for the Client.CheckPermission method. +func (client *Client) CheckPermission(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientCheckPermissionOptions) (ClientCheckPermissionResponse, error) { + var err error + req, err := client.checkPermissionCreateRequest(ctx, hub, permission, connectionID, options) + if err != nil { + return ClientCheckPermissionResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientCheckPermissionResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { + err = runtime.NewResponseError(httpResp) + return ClientCheckPermissionResponse{}, err + } + return ClientCheckPermissionResponse{}, nil +} + +// checkPermissionCreateRequest creates the CheckPermission request. +func (client *Client) checkPermissionCreateRequest(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientCheckPermissionOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if permission == "" { + return nil, errors.New("parameter permission cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{permission}", url.PathEscape(string(permission))) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodHead, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.TargetName != nil { + reqQP.Set("targetName", *options.TargetName) + } + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + return req, nil +} + +// CloseAllConnections - Close the connections in the hub. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - options - ClientCloseAllConnectionsOptions contains the optional parameters for the Client.CloseAllConnections method. +func (client *Client) CloseAllConnections(ctx context.Context, hub string, options *ClientCloseAllConnectionsOptions) (ClientCloseAllConnectionsResponse, error) { + var err error + req, err := client.closeAllConnectionsCreateRequest(ctx, hub, options) + if err != nil { + return ClientCloseAllConnectionsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientCloseAllConnectionsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientCloseAllConnectionsResponse{}, err + } + return ClientCloseAllConnectionsResponse{}, nil +} + +// closeAllConnectionsCreateRequest creates the CloseAllConnections request. +func (client *Client) closeAllConnectionsCreateRequest(ctx context.Context, hub string, options *ClientCloseAllConnectionsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/:closeConnections" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Excluded != nil { + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } + } + if options != nil && options.Reason != nil { + reqQP.Set("reason", *options.Reason) + } + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// CloseConnection - Close the client connection. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - connectionID - Target connection Id. +// - options - ClientCloseConnectionOptions contains the optional parameters for the Client.CloseConnection method. +func (client *Client) CloseConnection(ctx context.Context, hub string, connectionID string, options *ClientCloseConnectionOptions) (ClientCloseConnectionResponse, error) { + var err error + req, err := client.closeConnectionCreateRequest(ctx, hub, connectionID, options) + if err != nil { + return ClientCloseConnectionResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientCloseConnectionResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientCloseConnectionResponse{}, err + } + return ClientCloseConnectionResponse{}, nil +} + +// closeConnectionCreateRequest creates the CloseConnection request. +func (client *Client) closeConnectionCreateRequest(ctx context.Context, hub string, connectionID string, options *ClientCloseConnectionOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/connections/{connectionId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Reason != nil { + reqQP.Set("reason", *options.Reason) + } + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// CloseGroupConnections - Close connections in the specific group. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - group - Target group name, which length should be greater than 0 and less than 1025. +// - options - ClientCloseGroupConnectionsOptions contains the optional parameters for the Client.CloseGroupConnections method. +func (client *Client) CloseGroupConnections(ctx context.Context, hub string, group string, options *ClientCloseGroupConnectionsOptions) (ClientCloseGroupConnectionsResponse, error) { + var err error + req, err := client.closeGroupConnectionsCreateRequest(ctx, hub, group, options) + if err != nil { + return ClientCloseGroupConnectionsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientCloseGroupConnectionsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientCloseGroupConnectionsResponse{}, err + } + return ClientCloseGroupConnectionsResponse{}, nil +} + +// closeGroupConnectionsCreateRequest creates the CloseGroupConnections request. +func (client *Client) closeGroupConnectionsCreateRequest(ctx context.Context, hub string, group string, options *ClientCloseGroupConnectionsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/groups/{group}/:closeConnections" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if group == "" { + return nil, errors.New("parameter group cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{group}", url.PathEscape(group)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Excluded != nil { + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } + } + if options != nil && options.Reason != nil { + reqQP.Set("reason", *options.Reason) + } + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// CloseUserConnections - Close connections for the specific user. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - userID - The user Id. +// - options - ClientCloseUserConnectionsOptions contains the optional parameters for the Client.CloseUserConnections method. +func (client *Client) CloseUserConnections(ctx context.Context, hub string, userID string, options *ClientCloseUserConnectionsOptions) (ClientCloseUserConnectionsResponse, error) { + var err error + req, err := client.closeUserConnectionsCreateRequest(ctx, hub, userID, options) + if err != nil { + return ClientCloseUserConnectionsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientCloseUserConnectionsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientCloseUserConnectionsResponse{}, err + } + return ClientCloseUserConnectionsResponse{}, nil +} + +// closeUserConnectionsCreateRequest creates the CloseUserConnections request. +func (client *Client) closeUserConnectionsCreateRequest(ctx context.Context, hub string, userID string, options *ClientCloseUserConnectionsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/users/{userId}/:closeConnections" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if userID == "" { + return nil, errors.New("parameter userID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{userId}", url.PathEscape(userID)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Excluded != nil { + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } + } + if options != nil && options.Reason != nil { + reqQP.Set("reason", *options.Reason) + } + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// ConnectionExists - Check if the connection with the given connectionId exists. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - connectionID - The connection Id. +// - options - ClientConnectionExistsOptions contains the optional parameters for the Client.ConnectionExists method. +func (client *Client) ConnectionExists(ctx context.Context, hub string, connectionID string, options *ClientConnectionExistsOptions) (ClientConnectionExistsResponse, error) { + var err error + req, err := client.connectionExistsCreateRequest(ctx, hub, connectionID, options) + if err != nil { + return ClientConnectionExistsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientConnectionExistsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { + err = runtime.NewResponseError(httpResp) + return ClientConnectionExistsResponse{}, err + } + return ClientConnectionExistsResponse{}, nil +} + +// connectionExistsCreateRequest creates the ConnectionExists request. +func (client *Client) connectionExistsCreateRequest(ctx context.Context, hub string, connectionID string, options *ClientConnectionExistsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/connections/{connectionId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodHead, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + return req, nil +} + +// GenerateClientToken - Generate token for the client to connect Azure Web PubSub service. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - options - ClientGenerateClientTokenOptions contains the optional parameters for the Client.GenerateClientToken method. +func (client *Client) GenerateClientToken(ctx context.Context, hub string, options *ClientGenerateClientTokenOptions) (ClientGenerateClientTokenResponse, error) { + var err error + req, err := client.generateClientTokenCreateRequest(ctx, hub, options) + if err != nil { + return ClientGenerateClientTokenResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientGenerateClientTokenResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ClientGenerateClientTokenResponse{}, err + } + resp, err := client.generateClientTokenHandleResponse(httpResp) + return resp, err +} + +// generateClientTokenCreateRequest creates the GenerateClientToken request. +func (client *Client) generateClientTokenCreateRequest(ctx context.Context, hub string, options *ClientGenerateClientTokenOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/:generateToken" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.UserID != nil { + reqQP.Set("userId", *options.UserID) + } + if options != nil && options.Role != nil { + for _, qv := range options.Role { + reqQP.Add("role", qv) + } + } + if options != nil && options.MinutesToExpire != nil { + reqQP.Set("minutesToExpire", strconv.FormatInt(int64(*options.MinutesToExpire), 10)) + } + reqQP.Set("api-version", "2023-07-01") + if options != nil && options.Group != nil { + for _, qv := range options.Group { + reqQP.Add("group", qv) + } + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json, text/json"} + return req, nil +} + +// generateClientTokenHandleResponse handles the GenerateClientToken response. +func (client *Client) generateClientTokenHandleResponse(resp *http.Response) (ClientGenerateClientTokenResponse, error) { + result := ClientGenerateClientTokenResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.ClientTokenResponse); err != nil { + return ClientGenerateClientTokenResponse{}, err + } + return result, nil +} + +// GrantPermission - Grant permission to the connection. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. +// - connectionID - Target connection Id. +// - options - ClientGrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. +func (client *Client) GrantPermission(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientGrantPermissionOptions) (ClientGrantPermissionResponse, error) { + var err error + req, err := client.grantPermissionCreateRequest(ctx, hub, permission, connectionID, options) + if err != nil { + return ClientGrantPermissionResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientGrantPermissionResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ClientGrantPermissionResponse{}, err + } + return ClientGrantPermissionResponse{}, nil +} + +// grantPermissionCreateRequest creates the GrantPermission request. +func (client *Client) grantPermissionCreateRequest(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientGrantPermissionOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if permission == "" { + return nil, errors.New("parameter permission cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{permission}", url.PathEscape(string(permission))) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.TargetName != nil { + reqQP.Set("targetName", *options.TargetName) + } + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// GroupExists - Check if there are any client connections inside the given group +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - group - Target group name, which length should be greater than 0 and less than 1025. +// - options - ClientGroupExistsOptions contains the optional parameters for the Client.GroupExists method. +func (client *Client) GroupExists(ctx context.Context, hub string, group string, options *ClientGroupExistsOptions) (ClientGroupExistsResponse, error) { + var err error + req, err := client.groupExistsCreateRequest(ctx, hub, group, options) + if err != nil { + return ClientGroupExistsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientGroupExistsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { + err = runtime.NewResponseError(httpResp) + return ClientGroupExistsResponse{}, err + } + return ClientGroupExistsResponse{}, nil +} + +// groupExistsCreateRequest creates the GroupExists request. +func (client *Client) groupExistsCreateRequest(ctx context.Context, hub string, group string, options *ClientGroupExistsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/groups/{group}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if group == "" { + return nil, errors.New("parameter group cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{group}", url.PathEscape(group)) + req, err := runtime.NewRequest(ctx, http.MethodHead, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + return req, nil +} + +// RemoveConnectionFromAllGroups - Remove a connection from all groups. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - connectionID - Target connection Id. +// - options - ClientRemoveConnectionFromAllGroupsOptions contains the optional parameters for the Client.RemoveConnectionFromAllGroups +// method. +func (client *Client) RemoveConnectionFromAllGroups(ctx context.Context, hub string, connectionID string, options *ClientRemoveConnectionFromAllGroupsOptions) (ClientRemoveConnectionFromAllGroupsResponse, error) { + var err error + req, err := client.removeConnectionFromAllGroupsCreateRequest(ctx, hub, connectionID, options) + if err != nil { + return ClientRemoveConnectionFromAllGroupsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientRemoveConnectionFromAllGroupsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientRemoveConnectionFromAllGroupsResponse{}, err + } + return ClientRemoveConnectionFromAllGroupsResponse{}, nil +} + +// removeConnectionFromAllGroupsCreateRequest creates the RemoveConnectionFromAllGroups request. +func (client *Client) removeConnectionFromAllGroupsCreateRequest(ctx context.Context, hub string, connectionID string, options *ClientRemoveConnectionFromAllGroupsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/connections/{connectionId}/groups" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// RemoveConnectionFromGroup - Remove a connection from the target group. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - group - Target group name, which length should be greater than 0 and less than 1025. +// - connectionID - Target connection Id. +// - options - ClientRemoveConnectionFromGroupOptions contains the optional parameters for the Client.RemoveConnectionFromGroup +// method. +func (client *Client) RemoveConnectionFromGroup(ctx context.Context, hub string, group string, connectionID string, options *ClientRemoveConnectionFromGroupOptions) (ClientRemoveConnectionFromGroupResponse, error) { + var err error + req, err := client.removeConnectionFromGroupCreateRequest(ctx, hub, group, connectionID, options) + if err != nil { + return ClientRemoveConnectionFromGroupResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientRemoveConnectionFromGroupResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientRemoveConnectionFromGroupResponse{}, err + } + return ClientRemoveConnectionFromGroupResponse{}, nil +} + +// removeConnectionFromGroupCreateRequest creates the RemoveConnectionFromGroup request. +func (client *Client) removeConnectionFromGroupCreateRequest(ctx context.Context, hub string, group string, connectionID string, options *ClientRemoveConnectionFromGroupOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/groups/{group}/connections/{connectionId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if group == "" { + return nil, errors.New("parameter group cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{group}", url.PathEscape(group)) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// RemoveConnectionsFromGroups - Remove filtered connections from multiple groups. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - groupsToRemove - Target groups and connection filter. +// - options - ClientRemoveConnectionsFromGroupsOptions contains the optional parameters for the Client.RemoveConnectionsFromGroups +// method. +func (client *Client) RemoveConnectionsFromGroups(ctx context.Context, hub string, groupsToRemove RemoveFromGroupsRequest, options *ClientRemoveConnectionsFromGroupsOptions) (ClientRemoveConnectionsFromGroupsResponse, error) { + var err error + req, err := client.removeConnectionsFromGroupsCreateRequest(ctx, hub, groupsToRemove, options) + if err != nil { + return ClientRemoveConnectionsFromGroupsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientRemoveConnectionsFromGroupsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return ClientRemoveConnectionsFromGroupsResponse{}, err + } + return ClientRemoveConnectionsFromGroupsResponse{}, nil +} + +// removeConnectionsFromGroupsCreateRequest creates the RemoveConnectionsFromGroups request. +func (client *Client) removeConnectionsFromGroupsCreateRequest(ctx context.Context, hub string, groupsToRemove RemoveFromGroupsRequest, options *ClientRemoveConnectionsFromGroupsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/:removeFromGroups" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + if err := runtime.MarshalAsJSON(req, groupsToRemove); err != nil { + return nil, err +} + return req, nil +} + +// RemoveUserFromAllGroups - Remove a user from all groups. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - userID - Target user Id. +// - options - ClientRemoveUserFromAllGroupsOptions contains the optional parameters for the Client.RemoveUserFromAllGroups +// method. +func (client *Client) RemoveUserFromAllGroups(ctx context.Context, hub string, userID string, options *ClientRemoveUserFromAllGroupsOptions) (ClientRemoveUserFromAllGroupsResponse, error) { + var err error + req, err := client.removeUserFromAllGroupsCreateRequest(ctx, hub, userID, options) + if err != nil { + return ClientRemoveUserFromAllGroupsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientRemoveUserFromAllGroupsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientRemoveUserFromAllGroupsResponse{}, err + } + return ClientRemoveUserFromAllGroupsResponse{}, nil +} + +// removeUserFromAllGroupsCreateRequest creates the RemoveUserFromAllGroups request. +func (client *Client) removeUserFromAllGroupsCreateRequest(ctx context.Context, hub string, userID string, options *ClientRemoveUserFromAllGroupsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/users/{userId}/groups" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if userID == "" { + return nil, errors.New("parameter userID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{userId}", url.PathEscape(userID)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// RemoveUserFromGroup - Remove a user from the target group. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - group - Target group name, which length should be greater than 0 and less than 1025. +// - userID - Target user Id. +// - options - ClientRemoveUserFromGroupOptions contains the optional parameters for the Client.RemoveUserFromGroup method. +func (client *Client) RemoveUserFromGroup(ctx context.Context, hub string, group string, userID string, options *ClientRemoveUserFromGroupOptions) (ClientRemoveUserFromGroupResponse, error) { + var err error + req, err := client.removeUserFromGroupCreateRequest(ctx, hub, group, userID, options) + if err != nil { + return ClientRemoveUserFromGroupResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientRemoveUserFromGroupResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientRemoveUserFromGroupResponse{}, err + } + return ClientRemoveUserFromGroupResponse{}, nil +} + +// removeUserFromGroupCreateRequest creates the RemoveUserFromGroup request. +func (client *Client) removeUserFromGroupCreateRequest(ctx context.Context, hub string, group string, userID string, options *ClientRemoveUserFromGroupOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/users/{userId}/groups/{group}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if group == "" { + return nil, errors.New("parameter group cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{group}", url.PathEscape(group)) + if userID == "" { + return nil, errors.New("parameter userID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{userId}", url.PathEscape(userID)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// RevokePermission - Revoke permission for the connection. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. +// - connectionID - Target connection Id. +// - options - ClientRevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. +func (client *Client) RevokePermission(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientRevokePermissionOptions) (ClientRevokePermissionResponse, error) { + var err error + req, err := client.revokePermissionCreateRequest(ctx, hub, permission, connectionID, options) + if err != nil { + return ClientRevokePermissionResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientRevokePermissionResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { + err = runtime.NewResponseError(httpResp) + return ClientRevokePermissionResponse{}, err + } + return ClientRevokePermissionResponse{}, nil +} + +// revokePermissionCreateRequest creates the RevokePermission request. +func (client *Client) revokePermissionCreateRequest(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientRevokePermissionOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if permission == "" { + return nil, errors.New("parameter permission cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{permission}", url.PathEscape(string(permission))) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.TargetName != nil { + reqQP.Set("targetName", *options.TargetName) + } + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// SendToAll - Broadcast content inside request body to all the connected client connections. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - contentType - Upload file type +// - message - The payload body. +// - options - ClientSendToAllOptions contains the optional parameters for the Client.SendToAll method. +func (client *Client) SendToAll(ctx context.Context, hub string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToAllOptions) (ClientSendToAllResponse, error) { + var err error + req, err := client.sendToAllCreateRequest(ctx, hub, contentType, message, options) + if err != nil { + return ClientSendToAllResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientSendToAllResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { + err = runtime.NewResponseError(httpResp) + return ClientSendToAllResponse{}, err + } + return ClientSendToAllResponse{}, nil +} + +// sendToAllCreateRequest creates the SendToAll request. +func (client *Client) sendToAllCreateRequest(ctx context.Context, hub string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToAllOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/:send" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Excluded != nil { + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } + } + reqQP.Set("api-version", "2023-07-01") + if options != nil && options.Filter != nil { + reqQP.Set("filter", *options.Filter) + } + if options != nil && options.MessageTTLSeconds != nil { + reqQP.Set("messageTtlSeconds", strconv.FormatInt(int64(*options.MessageTTLSeconds), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Content-Type"] = []string{string(contentType)} + req.Raw().Header["Accept"] = []string{"application/json"} + if err := req.SetBody(message, string(contentType)); err != nil { + return nil, err +} + return req, nil +} + +// SendToConnection - Send content inside request body to the specific connection. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - connectionID - The connection Id. +// - contentType - Upload file type +// - message - The payload body. +// - options - ClientSendToConnectionOptions contains the optional parameters for the Client.SendToConnection method. +func (client *Client) SendToConnection(ctx context.Context, hub string, connectionID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToConnectionOptions) (ClientSendToConnectionResponse, error) { + var err error + req, err := client.sendToConnectionCreateRequest(ctx, hub, connectionID, contentType, message, options) + if err != nil { + return ClientSendToConnectionResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientSendToConnectionResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { + err = runtime.NewResponseError(httpResp) + return ClientSendToConnectionResponse{}, err + } + return ClientSendToConnectionResponse{}, nil +} + +// sendToConnectionCreateRequest creates the SendToConnection request. +func (client *Client) sendToConnectionCreateRequest(ctx context.Context, hub string, connectionID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToConnectionOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/connections/{connectionId}/:send" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if connectionID == "" { + return nil, errors.New("parameter connectionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{connectionId}", url.PathEscape(connectionID)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + if options != nil && options.MessageTTLSeconds != nil { + reqQP.Set("messageTtlSeconds", strconv.FormatInt(int64(*options.MessageTTLSeconds), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Content-Type"] = []string{string(contentType)} + req.Raw().Header["Accept"] = []string{"application/json"} + if err := req.SetBody(message, string(contentType)); err != nil { + return nil, err +} + return req, nil +} + +// SendToGroup - Send content inside request body to a group of connections. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - group - Target group name, which length should be greater than 0 and less than 1025. +// - contentType - Upload file type +// - message - The payload body. +// - options - ClientSendToGroupOptions contains the optional parameters for the Client.SendToGroup method. +func (client *Client) SendToGroup(ctx context.Context, hub string, group string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToGroupOptions) (ClientSendToGroupResponse, error) { + var err error + req, err := client.sendToGroupCreateRequest(ctx, hub, group, contentType, message, options) + if err != nil { + return ClientSendToGroupResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientSendToGroupResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { + err = runtime.NewResponseError(httpResp) + return ClientSendToGroupResponse{}, err + } + return ClientSendToGroupResponse{}, nil +} + +// sendToGroupCreateRequest creates the SendToGroup request. +func (client *Client) sendToGroupCreateRequest(ctx context.Context, hub string, group string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToGroupOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/groups/{group}/:send" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if group == "" { + return nil, errors.New("parameter group cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{group}", url.PathEscape(group)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Excluded != nil { + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } + } + reqQP.Set("api-version", "2023-07-01") + if options != nil && options.Filter != nil { + reqQP.Set("filter", *options.Filter) + } + if options != nil && options.MessageTTLSeconds != nil { + reqQP.Set("messageTtlSeconds", strconv.FormatInt(int64(*options.MessageTTLSeconds), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Content-Type"] = []string{string(contentType)} + req.Raw().Header["Accept"] = []string{"application/json"} + if err := req.SetBody(message, string(contentType)); err != nil { + return nil, err +} + return req, nil +} + +// SendToUser - Send content inside request body to the specific user. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - userID - The user Id. +// - contentType - Upload file type +// - message - The payload body. +// - options - ClientSendToUserOptions contains the optional parameters for the Client.SendToUser method. +func (client *Client) SendToUser(ctx context.Context, hub string, userID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToUserOptions) (ClientSendToUserResponse, error) { + var err error + req, err := client.sendToUserCreateRequest(ctx, hub, userID, contentType, message, options) + if err != nil { + return ClientSendToUserResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientSendToUserResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { + err = runtime.NewResponseError(httpResp) + return ClientSendToUserResponse{}, err + } + return ClientSendToUserResponse{}, nil +} + +// sendToUserCreateRequest creates the SendToUser request. +func (client *Client) sendToUserCreateRequest(ctx context.Context, hub string, userID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToUserOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/users/{userId}/:send" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if userID == "" { + return nil, errors.New("parameter userID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{userId}", url.PathEscape(userID)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + if options != nil && options.Filter != nil { + reqQP.Set("filter", *options.Filter) + } + if options != nil && options.MessageTTLSeconds != nil { + reqQP.Set("messageTtlSeconds", strconv.FormatInt(int64(*options.MessageTTLSeconds), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Content-Type"] = []string{string(contentType)} + req.Raw().Header["Accept"] = []string{"application/json"} + if err := req.SetBody(message, string(contentType)); err != nil { + return nil, err +} + return req, nil +} + +// UserExists - Check if there are any client connections connected for the given user. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. +// - userID - Target user Id. +// - options - ClientUserExistsOptions contains the optional parameters for the Client.UserExists method. +func (client *Client) UserExists(ctx context.Context, hub string, userID string, options *ClientUserExistsOptions) (ClientUserExistsResponse, error) { + var err error + req, err := client.userExistsCreateRequest(ctx, hub, userID, options) + if err != nil { + return ClientUserExistsResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ClientUserExistsResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { + err = runtime.NewResponseError(httpResp) + return ClientUserExistsResponse{}, err + } + return ClientUserExistsResponse{}, nil +} + +// userExistsCreateRequest creates the UserExists request. +func (client *Client) userExistsCreateRequest(ctx context.Context, hub string, userID string, options *ClientUserExistsOptions) (*policy.Request, error) { + urlPath := "/api/hubs/{hub}/users/{userId}" + if hub == "" { + return nil, errors.New("parameter hub cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{hub}", url.PathEscape(hub)) + if userID == "" { + return nil, errors.New("parameter userID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{userId}", url.PathEscape(userID)) + req, err := runtime.NewRequest(ctx, http.MethodHead, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + return req, nil +} + diff --git a/sdk/messaging/azwebpubsub/constants.go b/sdk/messaging/azwebpubsub/constants.go new file mode 100644 index 000000000000..60df74220349 --- /dev/null +++ b/sdk/messaging/azwebpubsub/constants.go @@ -0,0 +1,46 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azwebpubsub + +// ContentType - Content type for upload +type ContentType string + +const ( + // ContentTypeApplicationJSON - Content Type 'application/json' + ContentTypeApplicationJSON ContentType = "application/json" + // ContentTypeApplicationOctetStream - Content Type 'application/octet-stream' + ContentTypeApplicationOctetStream ContentType = "application/octet-stream" + // ContentTypeTextPlain - Content Type 'text/plain' + ContentTypeTextPlain ContentType = "text/plain" +) + +// PossibleContentTypeValues returns the possible values for the ContentType const type. +func PossibleContentTypeValues() []ContentType { + return []ContentType{ + ContentTypeApplicationJSON, + ContentTypeApplicationOctetStream, + ContentTypeTextPlain, + } +} + +type WebPubSubPermission string + +const ( + WebPubSubPermissionJoinLeaveGroup WebPubSubPermission = "joinLeaveGroup" + WebPubSubPermissionSendToGroup WebPubSubPermission = "sendToGroup" +) + +// PossibleWebPubSubPermissionValues returns the possible values for the WebPubSubPermission const type. +func PossibleWebPubSubPermissionValues() []WebPubSubPermission { + return []WebPubSubPermission{ + WebPubSubPermissionJoinLeaveGroup, + WebPubSubPermissionSendToGroup, + } +} + diff --git a/sdk/messaging/azwebpubsub/go.mod b/sdk/messaging/azwebpubsub/go.mod new file mode 100644 index 000000000000..916914a98933 --- /dev/null +++ b/sdk/messaging/azwebpubsub/go.mod @@ -0,0 +1,21 @@ +module github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub + +go 1.18 + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect + github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/google/uuid v1.1.1 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect +) \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/go.sum b/sdk/messaging/azwebpubsub/go.sum new file mode 100644 index 000000000000..017306dd71e2 --- /dev/null +++ b/sdk/messaging/azwebpubsub/go.sum @@ -0,0 +1,14 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= diff --git a/sdk/messaging/azwebpubsub/healthapi_client.go b/sdk/messaging/azwebpubsub/healthapi_client.go new file mode 100644 index 000000000000..5dfe0ea2427b --- /dev/null +++ b/sdk/messaging/azwebpubsub/healthapi_client.go @@ -0,0 +1,61 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azwebpubsub + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" +) + +// HealthAPIClient contains the methods for the HealthAPI group. +// Don't use this type directly, use a constructor function instead. +type HealthAPIClient struct { + internal *azcore.Client + endpoint string +} + +// GetServiceStatus - Get service health status. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2023-07-01 +// - options - HealthAPIClientGetServiceStatusOptions contains the optional parameters for the HealthAPIClient.GetServiceStatus +// method. +func (client *HealthAPIClient) GetServiceStatus(ctx context.Context, options *HealthAPIClientGetServiceStatusOptions) (HealthAPIClientGetServiceStatusResponse, error) { + var err error + req, err := client.getServiceStatusCreateRequest(ctx, options) + if err != nil { + return HealthAPIClientGetServiceStatusResponse{}, err + } + httpResp, err := client.internal.Pipeline().Do(req) + if err != nil { + return HealthAPIClientGetServiceStatusResponse{}, err + } + if !runtime.HasStatusCode(httpResp, http.StatusOK) { + err = runtime.NewResponseError(httpResp) + return HealthAPIClientGetServiceStatusResponse{}, err + } + return HealthAPIClientGetServiceStatusResponse{}, nil +} + +// getServiceStatusCreateRequest creates the GetServiceStatus request. +func (client *HealthAPIClient) getServiceStatusCreateRequest(ctx context.Context, options *HealthAPIClientGetServiceStatusOptions) (*policy.Request, error) { + urlPath := "/api/health" + req, err := runtime.NewRequest(ctx, http.MethodHead, runtime.JoinPaths(client.endpoint, urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2023-07-01") + req.Raw().URL.RawQuery = reqQP.Encode() + return req, nil +} + diff --git a/sdk/messaging/azwebpubsub/internal/version.go b/sdk/messaging/azwebpubsub/internal/version.go new file mode 100644 index 000000000000..727f10b5246c --- /dev/null +++ b/sdk/messaging/azwebpubsub/internal/version.go @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package internal + +// Constants to identify the module +const ( + // ModuleName is the module name that shows in telemetry. + ModuleName = "azwebpubsub" + + // ModuleVersion is the semantic version (see http://semver.org) of this module. + ModuleVersion = "v0.1.1" +) diff --git a/sdk/messaging/azwebpubsub/models.go b/sdk/messaging/azwebpubsub/models.go new file mode 100644 index 000000000000..6d2dbc456ac4 --- /dev/null +++ b/sdk/messaging/azwebpubsub/models.go @@ -0,0 +1,56 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azwebpubsub + +// AddToGroupsRequest - The request object containing targets groups and a connection filter +type AddToGroupsRequest struct { + // An OData filter which target connections satisfy + Filter *string + + // A list of groups which target connections will be added into + Groups []*string +} + +// ClientTokenResponse - The response object containing the token for the client +type ClientTokenResponse struct { + // The token value for the WebSocket client to connect to the service + Token *string +} + +// ErrorDetail - The error object. +type ErrorDetail struct { + // One of a server-defined set of error codes. + Code *string + + // An array of details about specific errors that led to this reported error. + Details []*ErrorDetail + Inner *InnerError + + // A human-readable representation of the error. + Message *string + + // The target of the error. + Target *string +} + +type InnerError struct { + // A more specific error code than was provided by the containing error. + Code *string + Inner *InnerError +} + +// RemoveFromGroupsRequest - The request object containing targets groups and a connection filter +type RemoveFromGroupsRequest struct { + // An OData filter which target connections satisfy + Filter *string + + // A list of groups which target connections will be removed from + Groups []*string +} + diff --git a/sdk/messaging/azwebpubsub/models_serde.go b/sdk/messaging/azwebpubsub/models_serde.go new file mode 100644 index 000000000000..d81cc40c191b --- /dev/null +++ b/sdk/messaging/azwebpubsub/models_serde.go @@ -0,0 +1,200 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azwebpubsub + +import ( + "encoding/json" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "reflect" +) + +// MarshalJSON implements the json.Marshaller interface for type AddToGroupsRequest. +func (a AddToGroupsRequest) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "filter", a.Filter) + populate(objectMap, "groups", a.Groups) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type AddToGroupsRequest. +func (a *AddToGroupsRequest) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "filter": + err = unpopulate(val, "Filter", &a.Filter) + delete(rawMsg, key) + case "groups": + err = unpopulate(val, "Groups", &a.Groups) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type ClientTokenResponse. +func (c ClientTokenResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "token", c.Token) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type ClientTokenResponse. +func (c *ClientTokenResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "token": + err = unpopulate(val, "Token", &c.Token) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type ErrorDetail. +func (e ErrorDetail) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "code", e.Code) + populate(objectMap, "details", e.Details) + populate(objectMap, "inner", e.Inner) + populate(objectMap, "message", e.Message) + populate(objectMap, "target", e.Target) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type ErrorDetail. +func (e *ErrorDetail) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", e, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "code": + err = unpopulate(val, "Code", &e.Code) + delete(rawMsg, key) + case "details": + err = unpopulate(val, "Details", &e.Details) + delete(rawMsg, key) + case "inner": + err = unpopulate(val, "Inner", &e.Inner) + delete(rawMsg, key) + case "message": + err = unpopulate(val, "Message", &e.Message) + delete(rawMsg, key) + case "target": + err = unpopulate(val, "Target", &e.Target) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", e, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type InnerError. +func (i InnerError) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "code", i.Code) + populate(objectMap, "inner", i.Inner) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type InnerError. +func (i *InnerError) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", i, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "code": + err = unpopulate(val, "Code", &i.Code) + delete(rawMsg, key) + case "inner": + err = unpopulate(val, "Inner", &i.Inner) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", i, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type RemoveFromGroupsRequest. +func (r RemoveFromGroupsRequest) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "filter", r.Filter) + populate(objectMap, "groups", r.Groups) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type RemoveFromGroupsRequest. +func (r *RemoveFromGroupsRequest) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "filter": + err = unpopulate(val, "Filter", &r.Filter) + delete(rawMsg, key) + case "groups": + err = unpopulate(val, "Groups", &r.Groups) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + } + return nil +} + +func populate(m map[string]any, k string, v any) { + if v == nil { + return + } else if azcore.IsNullValue(v) { + m[k] = nil + } else if !reflect.ValueOf(v).IsNil() { + m[k] = v + } +} + +func unpopulate(data json.RawMessage, fn string, v any) error { + if data == nil { + return nil + } + if err := json.Unmarshal(data, v); err != nil { + return fmt.Errorf("struct field %s: %v", fn, err) + } + return nil +} + diff --git a/sdk/messaging/azwebpubsub/options.go b/sdk/messaging/azwebpubsub/options.go new file mode 100644 index 000000000000..d60c8643c758 --- /dev/null +++ b/sdk/messaging/azwebpubsub/options.go @@ -0,0 +1,191 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azwebpubsub + +// ClientAddConnectionToGroupOptions contains the optional parameters for the Client.AddConnectionToGroup method. +type ClientAddConnectionToGroupOptions struct { + // placeholder for future optional parameters +} + +// ClientAddConnectionsToGroupsOptions contains the optional parameters for the Client.AddConnectionsToGroups method. +type ClientAddConnectionsToGroupsOptions struct { + // placeholder for future optional parameters +} + +// ClientAddUserToGroupOptions contains the optional parameters for the Client.AddUserToGroup method. +type ClientAddUserToGroupOptions struct { + // placeholder for future optional parameters +} + +// ClientCheckPermissionOptions contains the optional parameters for the Client.CheckPermission method. +type ClientCheckPermissionOptions struct { + // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required +// parameter standing for the group name. + TargetName *string +} + +// ClientCloseAllConnectionsOptions contains the optional parameters for the Client.CloseAllConnections method. +type ClientCloseAllConnectionsOptions struct { + // Exclude these connectionIds when closing the connections in the hub. + Excluded []string + + // The reason closing the client connection. + Reason *string +} + +// ClientCloseConnectionOptions contains the optional parameters for the Client.CloseConnection method. +type ClientCloseConnectionOptions struct { + // The reason closing the client connection. + Reason *string +} + +// ClientCloseGroupConnectionsOptions contains the optional parameters for the Client.CloseGroupConnections method. +type ClientCloseGroupConnectionsOptions struct { + // Exclude these connectionIds when closing the connections in the group. + Excluded []string + + // The reason closing the client connection. + Reason *string +} + +// ClientCloseUserConnectionsOptions contains the optional parameters for the Client.CloseUserConnections method. +type ClientCloseUserConnectionsOptions struct { + // Exclude these connectionIds when closing the connections for the user. + Excluded []string + + // The reason closing the client connection. + Reason *string +} + +// ClientConnectionExistsOptions contains the optional parameters for the Client.ConnectionExists method. +type ClientConnectionExistsOptions struct { + // placeholder for future optional parameters +} + +// ClientGenerateClientTokenOptions contains the optional parameters for the Client.GenerateClientToken method. +type ClientGenerateClientTokenOptions struct { + // Groups that the connection will join when it connects. + Group []string + + // The expire time of the generated token. + MinutesToExpire *int32 + + // Roles that the connection with the generated token will have. + Role []string + + // User Id. + UserID *string +} + +// ClientGrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. +type ClientGrantPermissionOptions struct { + // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required +// parameter standing for the group name. + TargetName *string +} + +// ClientGroupExistsOptions contains the optional parameters for the Client.GroupExists method. +type ClientGroupExistsOptions struct { + // placeholder for future optional parameters +} + +// ClientRemoveConnectionFromAllGroupsOptions contains the optional parameters for the Client.RemoveConnectionFromAllGroups +// method. +type ClientRemoveConnectionFromAllGroupsOptions struct { + // placeholder for future optional parameters +} + +// ClientRemoveConnectionFromGroupOptions contains the optional parameters for the Client.RemoveConnectionFromGroup method. +type ClientRemoveConnectionFromGroupOptions struct { + // placeholder for future optional parameters +} + +// ClientRemoveConnectionsFromGroupsOptions contains the optional parameters for the Client.RemoveConnectionsFromGroups method. +type ClientRemoveConnectionsFromGroupsOptions struct { + // placeholder for future optional parameters +} + +// ClientRemoveUserFromAllGroupsOptions contains the optional parameters for the Client.RemoveUserFromAllGroups method. +type ClientRemoveUserFromAllGroupsOptions struct { + // placeholder for future optional parameters +} + +// ClientRemoveUserFromGroupOptions contains the optional parameters for the Client.RemoveUserFromGroup method. +type ClientRemoveUserFromGroupOptions struct { + // placeholder for future optional parameters +} + +// ClientRevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. +type ClientRevokePermissionOptions struct { + // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required +// parameter standing for the group name. + TargetName *string +} + +// ClientSendToAllOptions contains the optional parameters for the Client.SendToAll method. +type ClientSendToAllOptions struct { + // Excluded connection Ids. + Excluded []string + + // Following OData filter syntax to filter out the subscribers receiving the messages. + Filter *string + + // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message +// never expires. 300 is the maximum value. If this parameter is non-zero, +// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can +// help when the client's bandwidth is limited. + MessageTTLSeconds *int32 +} + +// ClientSendToConnectionOptions contains the optional parameters for the Client.SendToConnection method. +type ClientSendToConnectionOptions struct { + // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message +// never expires. 300 is the maximum value. If this parameter is non-zero, +// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can +// help when the client's bandwidth is limited. + MessageTTLSeconds *int32 +} + +// ClientSendToGroupOptions contains the optional parameters for the Client.SendToGroup method. +type ClientSendToGroupOptions struct { + // Excluded connection Ids + Excluded []string + + // Following OData filter syntax to filter out the subscribers receiving the messages. + Filter *string + + // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message +// never expires. 300 is the maximum value. If this parameter is non-zero, +// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can +// help when the client's bandwidth is limited. + MessageTTLSeconds *int32 +} + +// ClientSendToUserOptions contains the optional parameters for the Client.SendToUser method. +type ClientSendToUserOptions struct { + // Following OData filter syntax to filter out the subscribers receiving the messages. + Filter *string + + // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message +// never expires. 300 is the maximum value. If this parameter is non-zero, +// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can +// help when the client's bandwidth is limited. + MessageTTLSeconds *int32 +} + +// ClientUserExistsOptions contains the optional parameters for the Client.UserExists method. +type ClientUserExistsOptions struct { + // placeholder for future optional parameters +} + +// HealthAPIClientGetServiceStatusOptions contains the optional parameters for the HealthAPIClient.GetServiceStatus method. +type HealthAPIClientGetServiceStatusOptions struct { + // placeholder for future optional parameters +} + diff --git a/sdk/messaging/azwebpubsub/package-lock.json b/sdk/messaging/azwebpubsub/package-lock.json new file mode 100644 index 000000000000..e6b113e451b3 --- /dev/null +++ b/sdk/messaging/azwebpubsub/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "azwebpubsub", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/sdk/messaging/azwebpubsub/package.json b/sdk/messaging/azwebpubsub/package.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/sdk/messaging/azwebpubsub/package.json @@ -0,0 +1 @@ +{} diff --git a/sdk/messaging/azwebpubsub/response_types.go b/sdk/messaging/azwebpubsub/response_types.go new file mode 100644 index 000000000000..bdcabd1982be --- /dev/null +++ b/sdk/messaging/azwebpubsub/response_types.go @@ -0,0 +1,131 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package azwebpubsub + +// ClientAddConnectionToGroupResponse contains the response from method Client.AddConnectionToGroup. +type ClientAddConnectionToGroupResponse struct { + // placeholder for future response values +} + +// ClientAddConnectionsToGroupsResponse contains the response from method Client.AddConnectionsToGroups. +type ClientAddConnectionsToGroupsResponse struct { + // placeholder for future response values +} + +// ClientAddUserToGroupResponse contains the response from method Client.AddUserToGroup. +type ClientAddUserToGroupResponse struct { + // placeholder for future response values +} + +// ClientCheckPermissionResponse contains the response from method Client.CheckPermission. +type ClientCheckPermissionResponse struct { + // placeholder for future response values +} + +// ClientCloseAllConnectionsResponse contains the response from method Client.CloseAllConnections. +type ClientCloseAllConnectionsResponse struct { + // placeholder for future response values +} + +// ClientCloseConnectionResponse contains the response from method Client.CloseConnection. +type ClientCloseConnectionResponse struct { + // placeholder for future response values +} + +// ClientCloseGroupConnectionsResponse contains the response from method Client.CloseGroupConnections. +type ClientCloseGroupConnectionsResponse struct { + // placeholder for future response values +} + +// ClientCloseUserConnectionsResponse contains the response from method Client.CloseUserConnections. +type ClientCloseUserConnectionsResponse struct { + // placeholder for future response values +} + +// ClientConnectionExistsResponse contains the response from method Client.ConnectionExists. +type ClientConnectionExistsResponse struct { + // placeholder for future response values +} + +// ClientGenerateClientTokenResponse contains the response from method Client.GenerateClientToken. +type ClientGenerateClientTokenResponse struct { + // The response object containing the token for the client + ClientTokenResponse +} + +// ClientGrantPermissionResponse contains the response from method Client.GrantPermission. +type ClientGrantPermissionResponse struct { + // placeholder for future response values +} + +// ClientGroupExistsResponse contains the response from method Client.GroupExists. +type ClientGroupExistsResponse struct { + // placeholder for future response values +} + +// ClientRemoveConnectionFromAllGroupsResponse contains the response from method Client.RemoveConnectionFromAllGroups. +type ClientRemoveConnectionFromAllGroupsResponse struct { + // placeholder for future response values +} + +// ClientRemoveConnectionFromGroupResponse contains the response from method Client.RemoveConnectionFromGroup. +type ClientRemoveConnectionFromGroupResponse struct { + // placeholder for future response values +} + +// ClientRemoveConnectionsFromGroupsResponse contains the response from method Client.RemoveConnectionsFromGroups. +type ClientRemoveConnectionsFromGroupsResponse struct { + // placeholder for future response values +} + +// ClientRemoveUserFromAllGroupsResponse contains the response from method Client.RemoveUserFromAllGroups. +type ClientRemoveUserFromAllGroupsResponse struct { + // placeholder for future response values +} + +// ClientRemoveUserFromGroupResponse contains the response from method Client.RemoveUserFromGroup. +type ClientRemoveUserFromGroupResponse struct { + // placeholder for future response values +} + +// ClientRevokePermissionResponse contains the response from method Client.RevokePermission. +type ClientRevokePermissionResponse struct { + // placeholder for future response values +} + +// ClientSendToAllResponse contains the response from method Client.SendToAll. +type ClientSendToAllResponse struct { + // placeholder for future response values +} + +// ClientSendToConnectionResponse contains the response from method Client.SendToConnection. +type ClientSendToConnectionResponse struct { + // placeholder for future response values +} + +// ClientSendToGroupResponse contains the response from method Client.SendToGroup. +type ClientSendToGroupResponse struct { + // placeholder for future response values +} + +// ClientSendToUserResponse contains the response from method Client.SendToUser. +type ClientSendToUserResponse struct { + // placeholder for future response values +} + +// ClientUserExistsResponse contains the response from method Client.UserExists. +type ClientUserExistsResponse struct { + // placeholder for future response values +} + +// HealthAPIClientGetServiceStatusResponse contains the response from method HealthAPIClient.GetServiceStatus. +type HealthAPIClientGetServiceStatusResponse struct { + // placeholder for future response values +} + From d739152a1695ef594cfae1c4493cc6fd35aa8781 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Mon, 30 Oct 2023 16:16:36 +0800 Subject: [PATCH 02/28] Updating readme and autorest --- sdk/messaging/azwebpubsub/CHANGELOG.md | 4 +- sdk/messaging/azwebpubsub/README.md | 106 ++++++++++++++++++++++--- sdk/messaging/azwebpubsub/autorest.md | 2 +- 3 files changed, 98 insertions(+), 14 deletions(-) diff --git a/sdk/messaging/azwebpubsub/CHANGELOG.md b/sdk/messaging/azwebpubsub/CHANGELOG.md index ad4b95676df2..c30a5c273a8f 100644 --- a/sdk/messaging/azwebpubsub/CHANGELOG.md +++ b/sdk/messaging/azwebpubsub/CHANGELOG.md @@ -1,5 +1,5 @@ # Release History -## 0.1.0 (2023-xx-xx) +## 0.1.0 (Unreleased) -* Template package validating release pipeline \ No newline at end of file +* Initial version \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/README.md b/sdk/messaging/azwebpubsub/README.md index 76386ba402d6..e0ec5ec8c567 100644 --- a/sdk/messaging/azwebpubsub/README.md +++ b/sdk/messaging/azwebpubsub/README.md @@ -1,33 +1,110 @@ -# Azure Template Package client library for Go +# Azure Web PubSub service client library for Go -Azure Template Package client library for Go (`aztemplate`) matches necessary patterns that the development team has established to create a unified SDK written in the Go programming language. These libraries follow the Azure SDK Design Guidelines for Go. +[Azure Web PubSub service](https://aka.ms/awps/doc) is an Azure-managed service that helps developers easily build web applications with real-time features and publish-subscribe pattern. Any scenario that requires real-time publish-subscribe messaging between server and clients or among clients can use Azure Web PubSub service. Traditional real-time features that often require polling from server or submitting HTTP requests can also use Azure Web PubSub service. -The library allows client libraries to expose common functionality in a consistent fashion. Once you learn how to use these APIs in one client library, you will know how to use them in other client libraries. +You can use this library in your app server side to manage the WebSocket client connections, as shown in below diagram: + +![overflow](https://user-images.githubusercontent.com/668244/140014067-25a00959-04dc-47e8-ac25-6957bd0a71ce.png). + +- Send messages to hubs and groups. +- Send messages to particular users and connections. +- Organize users and connections into groups. +- Close connections +- Grant, revoke, and check permissions for an existing connection + +Details about the terms used here are described in [Key concepts](#key-concepts) section. + +Key links: +- [Source code][source] +- [API Reference Documentation][godoc] +- [Product documentation][product] +- [Samples][godoc_examples] ## Getting started -For a rich example of a well formatted readme, please check [here.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md) In addition, this is an [example readme](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-EXAMPLE.md) that should be emulated. Note that the top-level sections in this template align with that of the [template.](https://github.com/Azure/azure-sdk/blob/main/docs/policies/README-TEMPLATE.md) +### Install the package + +Install the Azure Web PubSub service client module for Go with `go get`: + +```bash +go get github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub +``` + +### Prerequisites + +- Go, version 1.18 or higher +- An [Azure subscription](https://azure.microsoft.com/free/) +- An existing Azure Web PubSub service instance. + + +### Authenticate the client + +Web PubSub service clients are created using a TokenCredential from the [Azure Identity package][azure_identity_pkg], like [DefaultAzureCredential][default_azure_credential]. +You can also create a client using a connection string. + +#### Using a service principal + +#### Using a connection string # Key concepts -Bullet point list of your library's main concepts. +### Connection + +A connection, also known as a client or a client connection, represents an individual WebSocket connection connected to the Web PubSub service. When successfully connected, a unique connection ID is assigned to this connection by the Web PubSub service. + +### Hub + +A hub is a logical concept for a set of client connections. Usually you use one hub for one purpose, for example, a chat hub, or a notification hub. When a client connection is created, it connects to a hub, and during its lifetime, it belongs to that hub. Different applications can share one Azure Web PubSub service by using different hub names. + +### Group + +A group is a subset of connections to the hub. You can add a client connection to a group, or remove the client connection from the group, anytime you want. For example, when a client joins a chat room, or when a client leaves the chat room, this chat room can be considered to be a group. A client can join multiple groups, and a group can contain multiple clients. + +### User + +Connections to Web PubSub can belong to one user. A user might have multiple connections, for example when a single user is connected across multiple devices or multiple browser tabs. + +### Message + +When the client is connected, it can send messages to the upstream application, or receive messages from the upstream application, through the WebSocket connection. # Examples -Examples of some of the key concepts for your library. +Examples for various scenarios can be found on [pkg.go.dev](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub#pkg-examples) or in the example*_test.go files in our GitHub repo for [azwebpubsub](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azwebpubsub). # Troubleshooting -Running into issues? This section should contain details as to what to do there. +### Live Trace + +Use **Live Trace** from the Web PubSub service portal to view the live traffic. + +### Logging + +This module uses the classification-based logging implementation in `azcore`. To enable console logging for all SDK modules, set the environment variable `AZURE_SDK_GO_LOGGING` to `all`. + +Use the `azcore/log` package to control log event output or to enable logs for `azwebpubsub` only. For example: + +```go +import ( + "fmt" + azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" +) -# Next steps +// print log output to stdout +azlog.SetListener(func(event azlog.Event, s string) { + fmt.Printf("[%s] %s\n", event, s) +}) -More sample code should go here, along with links out to the appropriate example tests. +// pick the set of events to log +azlog.SetEvents( + azwebpubsub +) +``` ## Contributing For details on contributing to this repository, see the [contributing guide][azure_sdk_for_go_contributing]. -This project welcomes contributions and suggestions. Most contributions require you to agree to a +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. @@ -66,4 +143,11 @@ Azure SDK for Go is licensed under the [MIT](https://github.com/Azure/azure-sdk- [azure_portal]: https://portal.azure.com [azure_sub]: https://azure.microsoft.com/free/ [cloud_shell]: https://docs.microsoft.com/azure/cloud-shell/overview -[cloud_shell_bash]: https://shell.azure.com/bash \ No newline at end of file +[cloud_shell_bash]: https://shell.azure.com/bash + +[azure_identity_pkg]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity +[default_azure_credential]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#NewDefaultAzureCredential +[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/messaging/azwebpubsub +[godoc]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub +[godoc_examples]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub#pkg-examples +[product]: https://aka.ms/awps/doc diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index 0cafde056c44..21afebc9eff7 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -6,7 +6,7 @@ description: Azure Web PubSub client clear-output-folder: false export-clients: true go: true -input-file: https://github.com/Azure/azure-rest-api-specs/blob/main/specification/webpubsub/data-plane/WebPubSub/stable/2023-07-01/webpubsub.json #TODO: change to hash for commit +input-file: https://github.com/Azure/azure-rest-api-specs/blob/052a4b8d50bfd5595a8b5b506015d18f2b65998d/specification/webpubsub/data-plane/WebPubSub/stable/2023-07-01/webpubsub.json license-header: MICROSOFT_MIT_NO_VERSION module: github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub openapi-type: "data-plane" From a0f15101e0650dadcfe38b0f6f367ec129c03602 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Tue, 31 Oct 2023 15:06:30 +0800 Subject: [PATCH 03/28] Adding custom client and test code --- sdk/messaging/azwebpubsub/client_custom.go | 65 ++++++ .../azwebpubsub/client_shared_test.go | 197 ++++++++++++++++++ sdk/messaging/azwebpubsub/client_test.go | 50 +++++ sdk/messaging/azwebpubsub/example_test.go | 53 +++++ sdk/messaging/azwebpubsub/go.mod | 28 ++- sdk/messaging/azwebpubsub/go.sum | 53 +++-- .../internal/policy_key_credential.go | 48 +++++ .../internal/policy_key_credential_test.go | 51 +++++ sdk/messaging/azwebpubsub/internal/util.go | 97 +++++++++ .../azwebpubsub/internal/util_test.go | 57 +++++ sdk/messaging/azwebpubsub/sample.env | 3 + 11 files changed, 678 insertions(+), 24 deletions(-) create mode 100644 sdk/messaging/azwebpubsub/client_custom.go create mode 100644 sdk/messaging/azwebpubsub/client_shared_test.go create mode 100644 sdk/messaging/azwebpubsub/client_test.go create mode 100644 sdk/messaging/azwebpubsub/example_test.go create mode 100644 sdk/messaging/azwebpubsub/internal/policy_key_credential.go create mode 100644 sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go create mode 100644 sdk/messaging/azwebpubsub/internal/util.go create mode 100644 sdk/messaging/azwebpubsub/internal/util_test.go create mode 100644 sdk/messaging/azwebpubsub/sample.env diff --git a/sdk/messaging/azwebpubsub/client_custom.go b/sdk/messaging/azwebpubsub/client_custom.go new file mode 100644 index 000000000000..e9685ab7b870 --- /dev/null +++ b/sdk/messaging/azwebpubsub/client_custom.go @@ -0,0 +1,65 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azwebpubsub + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" +) + +// ClientOptions contains optional settings for [Client] +type ClientOptions struct { + azcore.ClientOptions +} + +// NewLogsClient creates a client that accesses Azure Monitor logs data. +func NewClient(endpoint string, credential azcore.TokenCredential, options *ClientOptions) (*Client, error) { + if options == nil { + options = &ClientOptions{} + } + + authPolicy := runtime.NewBearerTokenPolicy(credential, []string{internal.TokenScope}, nil) + azcoreClient, err := azcore.NewClient(internal.ModuleName+".Client", internal.ModuleVersion, + runtime.PipelineOptions{PerRetry: []policy.Policy{authPolicy}}, &options.ClientOptions) + if err != nil { + return nil, err + } + return &Client{ + internal: azcoreClient, + endpoint: endpoint, + }, nil +} + +// NewClientFromConnectionString creates a Client from a connection string. +// +// Endpoint=https://.webpubsub.azure.com/;AccessKey=; +func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { + if options == nil { + options = &ClientOptions{} + } + + props, err := internal.ParseConnectionString(connectionString) + + if err != nil { + return nil, err + } + + azcoreClient, err := azcore.NewClient(internal.ModuleName+".Client", internal.ModuleVersion, runtime.PipelineOptions{ + PerRetry: []policy.Policy{internal.NewWebPubSubKeyCredentialPolicy(props.AccessKey)}, + }, &options.ClientOptions) + + if err != nil { + return nil, err + } + + return &Client{ + internal: azcoreClient, + endpoint: props.Endpoint, + }, nil +} diff --git a/sdk/messaging/azwebpubsub/client_shared_test.go b/sdk/messaging/azwebpubsub/client_shared_test.go new file mode 100644 index 000000000000..e8330c0ffc69 --- /dev/null +++ b/sdk/messaging/azwebpubsub/client_shared_test.go @@ -0,0 +1,197 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package azwebpubsub_test + +import ( + "crypto/tls" + "fmt" + "net/http" + "os" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" + "github.com/stretchr/testify/require" +) + +type clientWrapper struct { + *azwebpubsub.Client + TestVars testVars +} + +var fakeTestVars = testVars{ + Key: "key", + Endpoint: "https://fake.eastus-1.webpubsub.azure.net", + Subscription: "subscription", +} + +type testVars struct { + Key string + Endpoint string + Subscription string + ConnectionString string + + // KeyLogPath is the value of environment "SSLKEYLOGFILE_TEST", which + // points to a file on disk where we'll write the TLS pre-master-secret. + // This is useful if you want to trace parts of this test using Wireshark. + KeyLogPath string +} + +func loadEnv() (testVars, error) { + var missing []string + + get := func(n string) string { + if v := os.Getenv(n); v == "" { + missing = append(missing, n) + } + + return os.Getenv(n) + } + + tv := testVars{ + Key: get("WEBPUBSUB_KEY"), + Endpoint: get("WEBPUBSUB_ENDPOINT"), + ConnectionString: get("WEBPUBSUB_CONNECTIONSTRING"), + } + + if len(missing) == 3 { + return testVars{}, fmt.Errorf("Missing env variables: %s", strings.Join(missing, ",")) + } + + // Setting this variable will cause the test clients to dump out the pre-master-key + // for your HTTP connection. This allows you decrypt a packet capture from wireshark. + // + // If you want to do this just set SSLKEYLOGFILE env var to a path on disk and + // Go will write out the key. + tv.KeyLogPath = os.Getenv("SSLKEYLOGFILE") + return tv, nil +} + +func newClientWrapper(t *testing.T) clientWrapper { + var client *azwebpubsub.Client + var tv testVars + + if recording.GetRecordMode() != recording.PlaybackMode { + tmpTestVars, err := loadEnv() + require.NoError(t, err) + tv = tmpTestVars + } else { + tv = fakeTestVars + } + + if recording.GetRecordMode() == recording.LiveMode { + if tv.KeyLogPath != "" { + keyLogWriter, err := os.OpenFile(tv.KeyLogPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777) + require.NoError(t, err) + + t.Cleanup(func() { keyLogWriter.Close() }) + + tp := http.DefaultTransport.(*http.Transport).Clone() + tp.TLSClientConfig = &tls.Config{ + KeyLogWriter: keyLogWriter, + } + + httpClient := &http.Client{Transport: tp} + + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, &azwebpubsub.ClientOptions{ + ClientOptions: azcore.ClientOptions{ + Transport: httpClient, + }, + }) + require.NoError(t, err) + client = tmpClient + } else { + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, nil) + require.NoError(t, err) + client = tmpClient + } + + } else { + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, &azwebpubsub.ClientOptions{ + ClientOptions: azcore.ClientOptions{ + Transport: newRecordingTransporter(t, tv), + }, + }) + require.NoError(t, err) + client = tmpClient + } + + return clientWrapper{ + Client: client, + TestVars: tv, + } +} + +func newRecordingTransporter(t *testing.T, testVars testVars) policy.Transporter { + transport, err := recording.NewRecordingHTTPClient(t, nil) + require.NoError(t, err) + + err = recording.Start(t, "sdk/messaging/azwebpubsub/testdata", nil) + require.NoError(t, err) + + // err = recording.ResetProxy(nil) + // require.NoError(t, err) + + err = recording.AddURISanitizer(fakeTestVars.Endpoint, testVars.Endpoint, nil) + require.NoError(t, err) + + err = recording.AddURISanitizer(fakeTestVars.Subscription, testVars.Subscription, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer(`"time": "2023-10-31T00:33:32Z"`, `"time":".+?"`, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer( + `"id":"00000000-0000-0000-0000-000000000000"`, + `"id":"[^"]+"`, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer( + `"lockToken":"fake-lock-token"`, + `"lockToken":\s*"[^"]+"`, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer( + `"lockTokens": ["fake-lock-token"]`, + `"lockTokens":\s*\[\s*"[^"]+"\s*\]`, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer( + `"succeededLockTokens": ["fake-lock-token"]`, + `"succeededLockTokens":\s*\[\s*"[^"]+"\s*\]`, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer( + `"succeededLockTokens": ["fake-lock-token", "fake-lock-token", "fake-lock-token"]`, + `"succeededLockTokens":\s*`+ + `\[`+ + `(\s*"[^"]+"\s*\,){2}`+ + `\s*"[^"]+"\s*`+ + `\]`, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer( + `"lockTokens": ["fake-lock-token", "fake-lock-token"]`, + `"lockTokens":\s*\[\s*"[^"]+"\s*\,\s*"[^"]+"\s*\]`, nil) + require.NoError(t, err) + + err = recording.AddGeneralRegexSanitizer( + `"lockTokens": ["fake-lock-token", "fake-lock-token", "fake-lock-token"]`, + `"lockTokens":\s*`+ + `\[`+ + `(\s*"[^"]+"\s*\,){2}`+ + `\s*"[^"]+"\s*`+ + `\]`, nil) + require.NoError(t, err) + + t.Cleanup(func() { + err := recording.Stop(t, nil) + require.NoError(t, err) + }) + + return transport +} diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go new file mode 100644 index 000000000000..ed176ce2de6c --- /dev/null +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -0,0 +1,50 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package azwebpubsub_test + +import ( + "bytes" + "context" + "io" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" + "github.com/stretchr/testify/require" +) + +func TestClient_SendToAll(t *testing.T) { + if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { + t.Skip() + } + + client := newClientWrapper(t) + const hub = "chat" + + _, err := client.SendToAll(context.Background(), + hub, azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), + &azwebpubsub.ClientSendToAllOptions{}) + require.NoError(t, err) +} + +func TestClient_Exists(t *testing.T) { + if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { + t.Skip() + } + + client := newClientWrapper(t) + const hub = "chat" + + _, err := client.SendToAll(context.Background(), + hub, azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), + &azwebpubsub.ClientSendToAllOptions{}) + require.NoError(t, err) +} +func newStream(message string) io.ReadSeekCloser { + return streaming.NopCloser(bytes.NewReader([]byte(message))) +} diff --git a/sdk/messaging/azwebpubsub/example_test.go b/sdk/messaging/azwebpubsub/example_test.go new file mode 100644 index 000000000000..24039cdd5d6d --- /dev/null +++ b/sdk/messaging/azwebpubsub/example_test.go @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azwebpubsub_test + +import ( + "log" + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" +) + +func ExampleNewClientWithDefaultAzureCredential() { + + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + // handle error + } + + endpoint := os.Getenv("WEBPUBSUB_ENDPOINT") + + if endpoint == "" { + return + } + client, err := azwebpubsub.NewClient(endpoint, cred, nil) + + if err != nil { + // TODO: Update the following line with your application specific error handling logic + log.Fatalf("ERROR: %s", err) + } + + _ = client // ignore + + // Output: +} + +func ExampleNewClientWithConnectionString() *azwebpubsub.Client { + connectionString := os.Getenv("WEBPUBSUB_CONNECTIONSTRING") + + if connectionString == "" { + return nil + } + + client, err := azwebpubsub.NewClientFromConnectionString(connectionString, nil) + + if err != nil { + // TODO: Update the following line with your application specific error handling logic + log.Fatalf("ERROR: %s", err) + } + + return client +} diff --git a/sdk/messaging/azwebpubsub/go.mod b/sdk/messaging/azwebpubsub/go.mod index 916914a98933..11052c19271d 100644 --- a/sdk/messaging/azwebpubsub/go.mod +++ b/sdk/messaging/azwebpubsub/go.mod @@ -4,18 +4,24 @@ go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 + github.com/golang-jwt/jwt/v5 v5.0.0 + github.com/stretchr/testify v1.8.4 ) require ( - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect - github.com/google/uuid v1.1.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dnaeon/go-vcr v1.2.0 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect - golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect -) \ No newline at end of file + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/sdk/messaging/azwebpubsub/go.sum b/sdk/messaging/azwebpubsub/go.sum index 017306dd71e2..e4fa4d358fbc 100644 --- a/sdk/messaging/azwebpubsub/go.sum +++ b/sdk/messaging/azwebpubsub/go.sum @@ -1,14 +1,41 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 h1:TuEMD+E+1aTjjLICGQOW6vLe8UWES7kopac9mUXL56Y= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 h1:hVeq+yCyUi+MsoO/CU95yqCIcdzra5ovzk8Q2BBpV2M= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/messaging/azwebpubsub/internal/policy_key_credential.go b/sdk/messaging/azwebpubsub/internal/policy_key_credential.go new file mode 100644 index 000000000000..e75958d48b3b --- /dev/null +++ b/sdk/messaging/azwebpubsub/internal/policy_key_credential.go @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package internal + +import ( + "errors" + "net/http" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/golang-jwt/jwt/v5" +) + +type WebPubSubKeyCredentialPolicy struct { + key string +} + +func NewWebPubSubKeyCredentialPolicy(key string) *WebPubSubKeyCredentialPolicy { + return &WebPubSubKeyCredentialPolicy{ + key: key, + } +} + +// Do implementes the Do method on the [policy.Polilcy] interface. +func (k *WebPubSubKeyCredentialPolicy) Do(req *policy.Request) (*http.Response, error) { + val := k.key + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "aud": req.Raw().URL.String(), + "exp": time.Now().Add(time.Hour).Unix(), + }) + secretKey := []byte(val) // Replace with your secret key + tokenString, err := token.SignedString(secretKey) + if err != nil { + return nil, NonRetriableError(errors.New("error signing the token")) + } + req.Raw().Header.Add("Authorization", "Bearer "+tokenString) + return req.Next() +} + +// NonRetriableError marks the specified error as non-retriable. +func NonRetriableError(err error) error { + return &nonRetriableError{err} +} + +type nonRetriableError struct { + error +} diff --git a/sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go b/sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go new file mode 100644 index 000000000000..eec9dd6bf3fb --- /dev/null +++ b/sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package internal + +import ( + "context" + "net/http" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/golang-jwt/jwt/v5" + "github.com/stretchr/testify/require" +) + +func TestKeyCredentialPolicy(t *testing.T) { + const key = "foo" + const target = "http://abc/de" + keyPolicy := NewWebPubSubKeyCredentialPolicy(key) + require.NotNil(t, keyPolicy) + verifier := PolicyFunc(func(req *policy.Request) (*http.Response, error) { + token := req.Raw().Header.Get("Authorization") + + require.True(t, strings.HasPrefix(token, "Bearer ")) + token = strings.TrimPrefix(token, "Bearer ") + + claims, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { + return []byte(key), nil + }) + + require.NoError(t, err) + require.Equal(t, target, claims.Claims.(jwt.MapClaims)["aud"]) + return &http.Response{}, nil + }) + + pl := NewPipeline(runtime.PipelineOptions{PerCall: []policy.Policy{keyPolicy, verifier}}, + &policy.ClientOptions{}) + req, err := runtime.NewRequest(context.Background(), http.MethodGet, target) + require.NoError(t, err) + + _, err = pl.Do(req) + require.NoError(t, err) +} + +type PolicyFunc func(req *policy.Request) (*http.Response, error) + +func (f PolicyFunc) Do(req *policy.Request) (*http.Response, error) { + return f(req) +} diff --git a/sdk/messaging/azwebpubsub/internal/util.go b/sdk/messaging/azwebpubsub/internal/util.go new file mode 100644 index 000000000000..fa809f910856 --- /dev/null +++ b/sdk/messaging/azwebpubsub/internal/util.go @@ -0,0 +1,97 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package internal + +import ( + "errors" + "net/url" + "strings" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" +) + +const ( + TokenScope = "https://webpubsub.azure.com/.default" +) + +const ( + HeaderAuthorization = "Authorization" + HeaderXmsDate = "x-ms-date" + HeaderContentLength = "Content-Length" + HeaderContentEncoding = "Content-Encoding" + HeaderContentLanguage = "Content-Language" + HeaderContentType = "Content-Type" + HeaderContentMD5 = "Content-MD5" + HeaderIfModifiedSince = "If-Modified-Since" + HeaderIfMatch = "If-Match" + HeaderIfNoneMatch = "If-None-Match" + HeaderIfUnmodifiedSince = "If-Unmodified-Since" + HeaderRange = "Range" + HeaderXmsVersion = "x-ms-version" + HeaderXmsRequestID = "x-ms-request-id" +) + +func NewPipeline(plOpts runtime.PipelineOptions, options *policy.ClientOptions) runtime.Pipeline { + return runtime.NewPipeline(ModuleName+".Client", ModuleVersion, plOpts, options) +} + +var errConnectionString = errors.New("connection string is either blank or malformed. The expected connection string " + + "should contain key value pairs separated by semicolons. For example 'Endpoint=;AccessKey=;'") + +type ParsedConnectionString struct { + Endpoint string + AccessKey string +} + +func ParseConnectionString(connectionString string) (ParsedConnectionString, error) { + connStrMap := make(map[string]string) + connectionString = strings.TrimRight(connectionString, ";") + + splitString := strings.Split(connectionString, ";") + if len(splitString) == 0 { + return ParsedConnectionString{}, errConnectionString + } + for _, stringPart := range splitString { + parts := strings.SplitN(stringPart, "=", 2) + if len(parts) != 2 { + return ParsedConnectionString{}, errConnectionString + } + connStrMap[strings.ToLower(parts[0])] = parts[1] + } + + endpoint, ok := connStrMap["endpoint"] + if !ok { + return ParsedConnectionString{}, errConnectionString + } + + parsedURL, err := url.Parse(endpoint) + if err != nil { + return ParsedConnectionString{}, errors.New("endpoint is not a valid URL") + } + + port, has_port := connStrMap["port"] + if has_port { + parsedURL.Host = parsedURL.Hostname() + ":" + port + endpoint = parsedURL.String() + } + + if !strings.HasSuffix(endpoint, "/") { + // add a trailing slash to be consistent with the portal + endpoint += "/" + } + + key, ok := connStrMap["accesskey"] + if !ok { + return ParsedConnectionString{}, errConnectionString + } + + return ParsedConnectionString{ + Endpoint: endpoint, + AccessKey: key, + }, nil +} diff --git a/sdk/messaging/azwebpubsub/internal/util_test.go b/sdk/messaging/azwebpubsub/internal/util_test.go new file mode 100644 index 000000000000..52294f013705 --- /dev/null +++ b/sdk/messaging/azwebpubsub/internal/util_test.go @@ -0,0 +1,57 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package internal + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseConnectionStringInvalid(t *testing.T) { + badConnectionStrings := []string{ + "", + "foobar", + "foo;bar;baz", + "foo=;bar=;", + "=", + ";", + "=;==", + "foobar=baz=foo", + } + + for _, badConnStr := range badConnectionStrings { + parsed, err := ParseConnectionString(badConnStr) + require.Error(t, err) + require.Zero(t, parsed) + //require.Contains(t, err.Error(), errConnectionString.Error()) + } +} + +func TestParseConnectionString(t *testing.T) { + connStr := "Endpoint=http://abc.com;AccessKey=ABC;" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "http://abc.com/", parsed.Endpoint) + require.Equal(t, "ABC", parsed.AccessKey) +} + +func TestParseConnectionStringLowercase(t *testing.T) { + connStr := "Endpoint=http://abc.com;accessKey=ABC;" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "http://abc.com/", parsed.Endpoint) + require.Equal(t, "ABC", parsed.AccessKey) +} + +func TestParseConnectionStringWithPort(t *testing.T) { + connStr := "Endpoint=http://abc.com:8080;accessKey=ABC;Port=8088;" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "http://abc.com:8088/", parsed.Endpoint) + require.Equal(t, "ABC", parsed.AccessKey) +} diff --git a/sdk/messaging/azwebpubsub/sample.env b/sdk/messaging/azwebpubsub/sample.env new file mode 100644 index 000000000000..dcd4e3031976 --- /dev/null +++ b/sdk/messaging/azwebpubsub/sample.env @@ -0,0 +1,3 @@ +WEBPUBSUB_KEY= +WEBPUBSUB_ENDPOINT= +WEBPUBSUB_CONNECTIONSTRING= From f97c894cf86b629f43df3a6782e5ec0a286511a9 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Thu, 9 Nov 2023 15:59:07 +0800 Subject: [PATCH 04/28] Add GenerateClientAccessUrl --- sdk/messaging/azwebpubsub/autorest.md | 17 +++ sdk/messaging/azwebpubsub/client.go | 36 ++--- sdk/messaging/azwebpubsub/client_custom.go | 109 ++++++++++++++- .../azwebpubsub/client_shared_test.go | 31 ++--- sdk/messaging/azwebpubsub/client_test.go | 126 +++++++++++++++++- sdk/messaging/azwebpubsub/example_test.go | 10 +- sdk/messaging/azwebpubsub/go.mod | 1 + sdk/messaging/azwebpubsub/go.sum | 2 + sdk/messaging/azwebpubsub/sample.env | 3 +- 9 files changed, 287 insertions(+), 48 deletions(-) diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index 21afebc9eff7..9b9a7613ae3c 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -12,4 +12,21 @@ module: github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub openapi-type: "data-plane" output-folder: ../azwebpubsub use: "@autorest/go@4.0.0-preview.57" +directive: + # Make GenerateClientToken internal. + - from: client.go + where: $ + transform: return $.replace(/\bGenerateClientToken\b/g, "generateClientToken"); + # Make *Exists internal until SDK supports it. + - from: client.go + where: $ + transform: return $.replace(/\b(Group|Connection|User)Exists\b/g, function(match, group) { return group.toLowerCase() + "Exists";}); + # Add more properties to lient + - from: client.go + where: $ + transform: >- + return $.replace( + /(type Client struct[^}]+})/s, + "type Client struct {\n internal *azcore.Client\n endpoint string\n hub string\n key *string\n}") + ``` \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/client.go b/sdk/messaging/azwebpubsub/client.go index 46131bca8bfa..02dc357c8954 100644 --- a/sdk/messaging/azwebpubsub/client.go +++ b/sdk/messaging/azwebpubsub/client.go @@ -26,6 +26,8 @@ import ( type Client struct { internal *azcore.Client endpoint string + hub string + key *string; } // AddConnectionToGroup - Add a connection to the target group. @@ -434,14 +436,14 @@ func (client *Client) closeUserConnectionsCreateRequest(ctx context.Context, hub return req, nil } -// ConnectionExists - Check if the connection with the given connectionId exists. +// connectionExists - Check if the connection with the given connectionId exists. // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - connectionID - The connection Id. -// - options - ClientConnectionExistsOptions contains the optional parameters for the Client.ConnectionExists method. -func (client *Client) ConnectionExists(ctx context.Context, hub string, connectionID string, options *ClientConnectionExistsOptions) (ClientConnectionExistsResponse, error) { +// - options - ClientConnectionExistsOptions contains the optional parameters for the Client.connectionExists method. +func (client *Client) connectionExists(ctx context.Context, hub string, connectionID string, options *ClientConnectionExistsOptions) (ClientConnectionExistsResponse, error) { var err error req, err := client.connectionExistsCreateRequest(ctx, hub, connectionID, options) if err != nil { @@ -458,7 +460,7 @@ func (client *Client) ConnectionExists(ctx context.Context, hub string, connecti return ClientConnectionExistsResponse{}, nil } -// connectionExistsCreateRequest creates the ConnectionExists request. +// connectionExistsCreateRequest creates the connectionExists request. func (client *Client) connectionExistsCreateRequest(ctx context.Context, hub string, connectionID string, options *ClientConnectionExistsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/connections/{connectionId}" if hub == "" { @@ -479,13 +481,13 @@ func (client *Client) connectionExistsCreateRequest(ctx context.Context, hub str return req, nil } -// GenerateClientToken - Generate token for the client to connect Azure Web PubSub service. +// generateClientToken - Generate token for the client to connect Azure Web PubSub service. // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. -// - options - ClientGenerateClientTokenOptions contains the optional parameters for the Client.GenerateClientToken method. -func (client *Client) GenerateClientToken(ctx context.Context, hub string, options *ClientGenerateClientTokenOptions) (ClientGenerateClientTokenResponse, error) { +// - options - ClientGenerateClientTokenOptions contains the optional parameters for the Client.generateClientToken method. +func (client *Client) generateClientToken(ctx context.Context, hub string, options *ClientGenerateClientTokenOptions) (ClientGenerateClientTokenResponse, error) { var err error req, err := client.generateClientTokenCreateRequest(ctx, hub, options) if err != nil { @@ -503,7 +505,7 @@ func (client *Client) GenerateClientToken(ctx context.Context, hub string, optio return resp, err } -// generateClientTokenCreateRequest creates the GenerateClientToken request. +// generateClientTokenCreateRequest creates the generateClientToken request. func (client *Client) generateClientTokenCreateRequest(ctx context.Context, hub string, options *ClientGenerateClientTokenOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/:generateToken" if hub == "" { @@ -537,7 +539,7 @@ func (client *Client) generateClientTokenCreateRequest(ctx context.Context, hub return req, nil } -// generateClientTokenHandleResponse handles the GenerateClientToken response. +// generateClientTokenHandleResponse handles the generateClientToken response. func (client *Client) generateClientTokenHandleResponse(resp *http.Response) (ClientGenerateClientTokenResponse, error) { result := ClientGenerateClientTokenResponse{} if err := runtime.UnmarshalAsJSON(resp, &result.ClientTokenResponse); err != nil { @@ -600,14 +602,14 @@ func (client *Client) grantPermissionCreateRequest(ctx context.Context, hub stri return req, nil } -// GroupExists - Check if there are any client connections inside the given group +// groupExists - Check if there are any client connections inside the given group // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - group - Target group name, which length should be greater than 0 and less than 1025. -// - options - ClientGroupExistsOptions contains the optional parameters for the Client.GroupExists method. -func (client *Client) GroupExists(ctx context.Context, hub string, group string, options *ClientGroupExistsOptions) (ClientGroupExistsResponse, error) { +// - options - ClientGroupExistsOptions contains the optional parameters for the Client.groupExists method. +func (client *Client) groupExists(ctx context.Context, hub string, group string, options *ClientGroupExistsOptions) (ClientGroupExistsResponse, error) { var err error req, err := client.groupExistsCreateRequest(ctx, hub, group, options) if err != nil { @@ -624,7 +626,7 @@ func (client *Client) GroupExists(ctx context.Context, hub string, group string, return ClientGroupExistsResponse{}, nil } -// groupExistsCreateRequest creates the GroupExists request. +// groupExistsCreateRequest creates the groupExists request. func (client *Client) groupExistsCreateRequest(ctx context.Context, hub string, group string, options *ClientGroupExistsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/groups/{group}" if hub == "" { @@ -1176,14 +1178,14 @@ func (client *Client) sendToUserCreateRequest(ctx context.Context, hub string, u return req, nil } -// UserExists - Check if there are any client connections connected for the given user. +// userExists - Check if there are any client connections connected for the given user. // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - userID - Target user Id. -// - options - ClientUserExistsOptions contains the optional parameters for the Client.UserExists method. -func (client *Client) UserExists(ctx context.Context, hub string, userID string, options *ClientUserExistsOptions) (ClientUserExistsResponse, error) { +// - options - ClientUserExistsOptions contains the optional parameters for the Client.userExists method. +func (client *Client) userExists(ctx context.Context, hub string, userID string, options *ClientUserExistsOptions) (ClientUserExistsResponse, error) { var err error req, err := client.userExistsCreateRequest(ctx, hub, userID, options) if err != nil { @@ -1200,7 +1202,7 @@ func (client *Client) UserExists(ctx context.Context, hub string, userID string, return ClientUserExistsResponse{}, nil } -// userExistsCreateRequest creates the UserExists request. +// userExistsCreateRequest creates the userExists request. func (client *Client) userExistsCreateRequest(ctx context.Context, hub string, userID string, options *ClientUserExistsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/users/{userId}" if hub == "" { diff --git a/sdk/messaging/azwebpubsub/client_custom.go b/sdk/messaging/azwebpubsub/client_custom.go index e9685ab7b870..29adeb0ab085 100644 --- a/sdk/messaging/azwebpubsub/client_custom.go +++ b/sdk/messaging/azwebpubsub/client_custom.go @@ -7,10 +7,18 @@ package azwebpubsub import ( + "context" + "fmt" + "net/url" + "regexp" + "strings" + "time" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" + "github.com/golang-jwt/jwt" ) // ClientOptions contains optional settings for [Client] @@ -19,7 +27,7 @@ type ClientOptions struct { } // NewLogsClient creates a client that accesses Azure Monitor logs data. -func NewClient(endpoint string, credential azcore.TokenCredential, options *ClientOptions) (*Client, error) { +func NewClient(endpoint string, hub string, credential azcore.TokenCredential, options *ClientOptions) (*Client, error) { if options == nil { options = &ClientOptions{} } @@ -33,13 +41,14 @@ func NewClient(endpoint string, credential azcore.TokenCredential, options *Clie return &Client{ internal: azcoreClient, endpoint: endpoint, + hub: hub, }, nil } // NewClientFromConnectionString creates a Client from a connection string. // // Endpoint=https://.webpubsub.azure.com/;AccessKey=; -func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { +func NewClientFromConnectionString(connectionString string, hub string, options *ClientOptions) (*Client, error) { if options == nil { options = &ClientOptions{} } @@ -61,5 +70,101 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio return &Client{ internal: azcoreClient, endpoint: props.Endpoint, + hub: hub, + key: &props.AccessKey, + }, nil +} + +// GenerateClientAccessUrlOptions represents the options for generating a client token. +type GenerateClientAccessUrlOptions struct { + // UserID is the user ID for the client. + UserID *string + + // Roles are the roles that the connection with the generated token will have. + // Roles give the client initial permissions to leave, join, or publish to groups when using PubSub subprotocol. + // Possible role values: + // - webpubsub.joinLeaveGroup: the client can join or leave any group. + // - webpubsub.sendToGroup: the client can send messages to any group. + // - webpubsub.joinLeaveGroup.: the client can join or leave group . + // - webpubsub.sendToGroup.: the client can send messages to group . + // More info: https://azure.github.io/azure-webpubsub/references/pubsub-websocket-subprotocol#permissions + Roles []string + + // ExpirationTimeInMinutes is the number of minutes until the token expires. + ExpirationTimeInMinutes *int32 + + // Groups are the groups to join when the client connects. + Groups []string +} + +type GenerateClientAccessUrlResponse struct { + // The client token + Token string + // The base URL for the client to connect to + BaseURL string + // The URL client connects to with access_token query string + URL string +} + +func (c *Client) GenerateClientAccessUrl(ctx context.Context, options *GenerateClientAccessUrlOptions) (*GenerateClientAccessUrlResponse, error) { + endpoint := c.endpoint + hubName := c.hub + if !strings.HasSuffix(endpoint, "/") { + endpoint += "/" + } + clientEndpoint := regexp.MustCompile(`$(http)(s?://)`).ReplaceAllString(endpoint, "ws$2") + baseURL := fmt.Sprintf("%sclient/hubs/%s", clientEndpoint, hubName) + + var token string + var err error + if c.key != nil { + token, err = c.signJwtToken(baseURL, options) + if err != nil { + return nil, err + } + } else { + // Replace with your logic to generate the token using a webPubSub method + resp, err := c.generateClientToken(ctx, hubName, &ClientGenerateClientTokenOptions{UserID: options.UserID, Role: options.Roles, Group: options.Groups, MinutesToExpire: options.ExpirationTimeInMinutes}) + if err != nil { + return nil, err + } + + token = *resp.Token + } + + return &GenerateClientAccessUrlResponse{ + Token: token, + BaseURL: baseURL, + URL: fmt.Sprintf("%s?access_token=%s", baseURL, url.QueryEscape(token)), }, nil } + +func (c *Client) signJwtToken(baseURL string, options *GenerateClientAccessUrlOptions) (string, error) { + key := []byte(*c.key) + var exp int64 + if options == nil || options.ExpirationTimeInMinutes == nil { + exp = time.Now().Add(time.Hour).Unix() + } else { + exp = time.Now().Add(time.Minute * time.Duration(*options.ExpirationTimeInMinutes)).Unix() + } + claims := jwt.MapClaims{ + "aud": baseURL, + "exp": exp, + } + + if options != nil && options.UserID != nil { + claims["sub"] = *options.UserID + } + + if options != nil && options.Groups != nil && len(options.Groups) > 0 { + claims["webpubsub.group"] = options.Groups + } + + if options != nil && options.Roles != nil && len(options.Roles) > 0 { + claims["role"] = options.Roles + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + + return token.SignedString(key) +} diff --git a/sdk/messaging/azwebpubsub/client_shared_test.go b/sdk/messaging/azwebpubsub/client_shared_test.go index e8330c0ffc69..9a51e23d10d6 100644 --- a/sdk/messaging/azwebpubsub/client_shared_test.go +++ b/sdk/messaging/azwebpubsub/client_shared_test.go @@ -15,6 +15,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" "github.com/stretchr/testify/require" ) @@ -24,17 +25,13 @@ type clientWrapper struct { } var fakeTestVars = testVars{ - Key: "key", - Endpoint: "https://fake.eastus-1.webpubsub.azure.net", - Subscription: "subscription", + ConnectionString: "Endpoint=https://fake.eastus-1.webpubsub.azure.com;AccessKey=ABCDE;", + Hub: "chat", } type testVars struct { - Key string - Endpoint string - Subscription string ConnectionString string - + Hub string // KeyLogPath is the value of environment "SSLKEYLOGFILE_TEST", which // points to a file on disk where we'll write the TLS pre-master-secret. // This is useful if you want to trace parts of this test using Wireshark. @@ -53,12 +50,11 @@ func loadEnv() (testVars, error) { } tv := testVars{ - Key: get("WEBPUBSUB_KEY"), - Endpoint: get("WEBPUBSUB_ENDPOINT"), ConnectionString: get("WEBPUBSUB_CONNECTIONSTRING"), + Hub: get("WEBPUBSUB_HUB"), } - if len(missing) == 3 { + if len(missing) > 0 { return testVars{}, fmt.Errorf("Missing env variables: %s", strings.Join(missing, ",")) } @@ -97,7 +93,7 @@ func newClientWrapper(t *testing.T) clientWrapper { httpClient := &http.Client{Transport: tp} - tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, &azwebpubsub.ClientOptions{ + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, &azwebpubsub.ClientOptions{ ClientOptions: azcore.ClientOptions{ Transport: httpClient, }, @@ -105,13 +101,13 @@ func newClientWrapper(t *testing.T) clientWrapper { require.NoError(t, err) client = tmpClient } else { - tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, nil) + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, nil) require.NoError(t, err) client = tmpClient } } else { - tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, &azwebpubsub.ClientOptions{ + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, &azwebpubsub.ClientOptions{ ClientOptions: azcore.ClientOptions{ Transport: newRecordingTransporter(t, tv), }, @@ -135,14 +131,11 @@ func newRecordingTransporter(t *testing.T, testVars testVars) policy.Transporter // err = recording.ResetProxy(nil) // require.NoError(t, err) - - err = recording.AddURISanitizer(fakeTestVars.Endpoint, testVars.Endpoint, nil) - require.NoError(t, err) - - err = recording.AddURISanitizer(fakeTestVars.Subscription, testVars.Subscription, nil) + props, _ := internal.ParseConnectionString(testVars.ConnectionString) + err = recording.AddURISanitizer("https://fake_endpoint.com", props.Endpoint, nil) require.NoError(t, err) - err = recording.AddGeneralRegexSanitizer(`"time": "2023-10-31T00:33:32Z"`, `"time":".+?"`, nil) + err = recording.AddGeneralRegexSanitizer(`"time": "2023-11-31T00:33:32Z"`, `"time":".+?"`, nil) require.NoError(t, err) err = recording.AddGeneralRegexSanitizer( diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index ed176ce2de6c..a383f5a9ead2 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -10,11 +10,15 @@ import ( "bytes" "context" "io" + "net/url" + "regexp" "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" + "github.com/golang-jwt/jwt" "github.com/stretchr/testify/require" ) @@ -24,27 +28,137 @@ func TestClient_SendToAll(t *testing.T) { } client := newClientWrapper(t) - const hub = "chat" _, err := client.SendToAll(context.Background(), - hub, azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), + client.TestVars.Hub, azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), + &azwebpubsub.ClientSendToAllOptions{}) + require.NoError(t, err) + + _, err = client.SendToAll(context.Background(), + client.TestVars.Hub, azwebpubsub.ContentTypeApplicationJSON, newStream("true"), + &azwebpubsub.ClientSendToAllOptions{}) + require.NoError(t, err) + + _, err = client.SendToAll(context.Background(), + client.TestVars.Hub, azwebpubsub.ContentTypeApplicationOctetStream, newStream("true"), &azwebpubsub.ClientSendToAllOptions{}) require.NoError(t, err) } -func TestClient_Exists(t *testing.T) { +func TestClient_CloseConnections(t *testing.T) { if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { t.Skip() } client := newClientWrapper(t) const hub = "chat" + const conn1 = "conn1" + const group1 = "group1" + const user1 = "user1" + reason := "TestClient_CloseConnections" + _, err := client.CloseAllConnections(context.Background(), + hub, &azwebpubsub.ClientCloseAllConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) + require.NoError(t, err) + _, err = client.CloseConnection(context.Background(), + hub, conn1, &azwebpubsub.ClientCloseConnectionOptions{Reason: &reason}) + require.NoError(t, err) + _, err = client.CloseGroupConnections(context.Background(), + hub, group1, &azwebpubsub.ClientCloseGroupConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) + require.NoError(t, err) + _, err = client.CloseUserConnections(context.Background(), + hub, user1, &azwebpubsub.ClientCloseUserConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) + require.NoError(t, err) +} - _, err := client.SendToAll(context.Background(), - hub, azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), - &azwebpubsub.ClientSendToAllOptions{}) +func TestClient_GenerateClientAccessUrl(t *testing.T) { + if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { + t.Skip() + } + + client := newClientWrapper(t) + token, err := client.GenerateClientAccessUrl(context.Background(), nil) + require.NoError(t, err) + extract := extractToken(t, token, client) + require.Nil(t, extract.Roles) + require.Nil(t, extract.Groups) + require.Nil(t, extract.UserID) + + user1 := "user1" + token, err = client.GenerateClientAccessUrl(context.Background(), &azwebpubsub.GenerateClientAccessUrlOptions{ + UserID: &user1, + Roles: []string{"admin"}, + Groups: []string{"group1"}, + }) + require.NoError(t, err) + parsedURL, err := url.Parse(token.URL) require.NoError(t, err) + queryValues := parsedURL.Query() + accessToken := queryValues.Get("access_token") + require.NotEmpty(t, accessToken) + extract = extractToken(t, token, client) + require.Equal(t, user1, *extract.UserID) + require.Equal(t, "admin", extract.Roles[0]) + require.Equal(t, "group1", extract.Groups[0]) } + +func extractToken(t *testing.T, token *azwebpubsub.GenerateClientAccessUrlResponse, client clientWrapper) azwebpubsub.GenerateClientAccessUrlOptions { + key, err := internal.ParseConnectionString(client.TestVars.ConnectionString) + require.NoError(t, err) + expectedAudience := key.Endpoint + "client/hubs/" + client.TestVars.Hub + expectedBaseUrl := regexp.MustCompile(`$(http)(s?://)`).ReplaceAllString(expectedAudience, "ws$2") + + require.Equal(t, expectedBaseUrl, token.BaseURL) + parsed, err := jwt.Parse(token.Token, func(token *jwt.Token) (interface{}, error) { + // Provide the secret key for validation + return []byte(key.AccessKey), nil + }) + require.NoError(t, err) + require.True(t, parsed.Valid, "token is not valid") + claims, ok := parsed.Claims.(jwt.MapClaims) + require.True(t, ok, "claims is not valid") + audience, ok := claims["aud"].(string) + require.True(t, ok, "audience is not valid") + require.Equal(t, expectedAudience, audience) + subject, ok := claims["sub"].(string) + var userId *string + if ok { + userId = &subject + } else { + userId = nil + } + rawRoles, ok := claims["role"].([]interface{}) + var roles []string + if ok { + // Convert the interface slice to a slice of strings + for _, role := range rawRoles { + if r, ok := role.(string); ok { + roles = append(roles, r) + } + } + } else { + roles = nil + } + + rawGroups, ok := claims["webpubsub.group"].([]interface{}) + var groups []string + if ok { + // Convert the interface slice to a slice of strings + for _, group := range rawGroups { + if r, ok := group.(string); ok { + groups = append(groups, r) + } + } + } else { + groups = nil + } + + return azwebpubsub.GenerateClientAccessUrlOptions{ + UserID: userId, + Roles: roles, + Groups: groups, + } +} + func newStream(message string) io.ReadSeekCloser { return streaming.NopCloser(bytes.NewReader([]byte(message))) } diff --git a/sdk/messaging/azwebpubsub/example_test.go b/sdk/messaging/azwebpubsub/example_test.go index 24039cdd5d6d..ecd1fbd6aae5 100644 --- a/sdk/messaging/azwebpubsub/example_test.go +++ b/sdk/messaging/azwebpubsub/example_test.go @@ -23,7 +23,12 @@ func ExampleNewClientWithDefaultAzureCredential() { if endpoint == "" { return } - client, err := azwebpubsub.NewClient(endpoint, cred, nil) + + hub := os.Getenv("WEBPUBSUB_HUB") + if hub == "" { + return + } + client, err := azwebpubsub.NewClient(endpoint, hub, cred, nil) if err != nil { // TODO: Update the following line with your application specific error handling logic @@ -37,12 +42,13 @@ func ExampleNewClientWithDefaultAzureCredential() { func ExampleNewClientWithConnectionString() *azwebpubsub.Client { connectionString := os.Getenv("WEBPUBSUB_CONNECTIONSTRING") + hub := os.Getenv("WEBPUBSUB_HUB") if connectionString == "" { return nil } - client, err := azwebpubsub.NewClientFromConnectionString(connectionString, nil) + client, err := azwebpubsub.NewClientFromConnectionString(connectionString, hub, nil) if err != nil { // TODO: Update the following line with your application specific error handling logic diff --git a/sdk/messaging/azwebpubsub/go.mod b/sdk/messaging/azwebpubsub/go.mod index 11052c19271d..91700f0dcdbe 100644 --- a/sdk/messaging/azwebpubsub/go.mod +++ b/sdk/messaging/azwebpubsub/go.mod @@ -6,6 +6,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 + github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt/v5 v5.0.0 github.com/stretchr/testify v1.8.4 ) diff --git a/sdk/messaging/azwebpubsub/go.sum b/sdk/messaging/azwebpubsub/go.sum index e4fa4d358fbc..f21d38e62535 100644 --- a/sdk/messaging/azwebpubsub/go.sum +++ b/sdk/messaging/azwebpubsub/go.sum @@ -10,6 +10,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= diff --git a/sdk/messaging/azwebpubsub/sample.env b/sdk/messaging/azwebpubsub/sample.env index dcd4e3031976..574294285344 100644 --- a/sdk/messaging/azwebpubsub/sample.env +++ b/sdk/messaging/azwebpubsub/sample.env @@ -1,3 +1,2 @@ -WEBPUBSUB_KEY= -WEBPUBSUB_ENDPOINT= WEBPUBSUB_CONNECTIONSTRING= +WEBPUBSUB_HUB=chat From fa2629214e65fab894a523c18c7afd260e2e6306 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Fri, 10 Nov 2023 12:02:23 +0800 Subject: [PATCH 05/28] Resolve comments --- sdk/messaging/azwebpubsub/client_custom.go | 47 ++++++++++++------- sdk/messaging/azwebpubsub/client_test.go | 10 ++-- sdk/messaging/azwebpubsub/go.mod | 2 +- sdk/messaging/azwebpubsub/go.sum | 2 + .../internal/policy_key_credential.go | 12 +---- sdk/messaging/azwebpubsub/internal/util.go | 17 ------- 6 files changed, 41 insertions(+), 49 deletions(-) diff --git a/sdk/messaging/azwebpubsub/client_custom.go b/sdk/messaging/azwebpubsub/client_custom.go index 29adeb0ab085..b8759db534ea 100644 --- a/sdk/messaging/azwebpubsub/client_custom.go +++ b/sdk/messaging/azwebpubsub/client_custom.go @@ -8,9 +8,9 @@ package azwebpubsub import ( "context" + "errors" "fmt" "net/url" - "regexp" "strings" "time" @@ -26,7 +26,7 @@ type ClientOptions struct { azcore.ClientOptions } -// NewLogsClient creates a client that accesses Azure Monitor logs data. +// NewClient creates a client that manages Web PubSub service func NewClient(endpoint string, hub string, credential azcore.TokenCredential, options *ClientOptions) (*Client, error) { if options == nil { options = &ClientOptions{} @@ -45,9 +45,7 @@ func NewClient(endpoint string, hub string, credential azcore.TokenCredential, o }, nil } -// NewClientFromConnectionString creates a Client from a connection string. -// -// Endpoint=https://.webpubsub.azure.com/;AccessKey=; +// NewClientFromConnectionString creates a Client from a connection string func NewClientFromConnectionString(connectionString string, hub string, options *ClientOptions) (*Client, error) { if options == nil { options = &ClientOptions{} @@ -75,10 +73,10 @@ func NewClientFromConnectionString(connectionString string, hub string, options }, nil } -// GenerateClientAccessUrlOptions represents the options for generating a client token. +// GenerateClientAccessUrlOptions represents the options for generating a client access url type GenerateClientAccessUrlOptions struct { // UserID is the user ID for the client. - UserID *string + UserID string // Roles are the roles that the connection with the generated token will have. // Roles give the client initial permissions to leave, join, or publish to groups when using PubSub subprotocol. @@ -97,6 +95,7 @@ type GenerateClientAccessUrlOptions struct { Groups []string } +// GenerateClientAccessUrlResponse represents the response type for the generated client access url type GenerateClientAccessUrlResponse struct { // The client token Token string @@ -106,25 +105,36 @@ type GenerateClientAccessUrlResponse struct { URL string } +// GenerateClientAccessUrl - generate URL for the WebSocket clients +// - options - GenerateClientAccessUrlOptions contains the optional parameters for the Client.GenerateClientAccessUrl method. func (c *Client) GenerateClientAccessUrl(ctx context.Context, options *GenerateClientAccessUrlOptions) (*GenerateClientAccessUrlResponse, error) { endpoint := c.endpoint hubName := c.hub - if !strings.HasSuffix(endpoint, "/") { - endpoint += "/" + parsedURL, err := url.Parse(endpoint) + if err != nil { + return nil, errors.New("endpoint is not a valid URL") } - clientEndpoint := regexp.MustCompile(`$(http)(s?://)`).ReplaceAllString(endpoint, "ws$2") - baseURL := fmt.Sprintf("%sclient/hubs/%s", clientEndpoint, hubName) + + parsedURL.Scheme = strings.Replace(strings.ToLower(parsedURL.Scheme), "http", "ws", 1) + + clientEndpoint := parsedURL.String() + baseURL := fmt.Sprintf("%s/client/hubs/%s", clientEndpoint, hubName) var token string - var err error if c.key != nil { token, err = c.signJwtToken(baseURL, options) if err != nil { return nil, err } } else { + var userId *string + if options.UserID == "" { + userId = nil + } else { + userId = &options.UserID + } // Replace with your logic to generate the token using a webPubSub method - resp, err := c.generateClientToken(ctx, hubName, &ClientGenerateClientTokenOptions{UserID: options.UserID, Role: options.Roles, Group: options.Groups, MinutesToExpire: options.ExpirationTimeInMinutes}) + resp, err := c.generateClientToken(ctx, hubName, &ClientGenerateClientTokenOptions{UserID: userId, Role: options.Roles, Group: options.Groups, MinutesToExpire: options.ExpirationTimeInMinutes}) if err != nil { return nil, err } @@ -139,11 +149,16 @@ func (c *Client) GenerateClientAccessUrl(ctx context.Context, options *GenerateC }, nil } +const DefaultExpirationTime = time.Hour + func (c *Client) signJwtToken(baseURL string, options *GenerateClientAccessUrlOptions) (string, error) { + if c.key == nil { + return "", errors.New("key is nil") + } key := []byte(*c.key) var exp int64 if options == nil || options.ExpirationTimeInMinutes == nil { - exp = time.Now().Add(time.Hour).Unix() + exp = time.Now().Add(DefaultExpirationTime).Unix() } else { exp = time.Now().Add(time.Minute * time.Duration(*options.ExpirationTimeInMinutes)).Unix() } @@ -152,8 +167,8 @@ func (c *Client) signJwtToken(baseURL string, options *GenerateClientAccessUrlOp "exp": exp, } - if options != nil && options.UserID != nil { - claims["sub"] = *options.UserID + if options != nil && options.UserID != "" { + claims["sub"] = options.UserID } if options != nil && options.Groups != nil && len(options.Groups) > 0 { diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index a383f5a9ead2..6272f3849440 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -85,7 +85,7 @@ func TestClient_GenerateClientAccessUrl(t *testing.T) { user1 := "user1" token, err = client.GenerateClientAccessUrl(context.Background(), &azwebpubsub.GenerateClientAccessUrlOptions{ - UserID: &user1, + UserID: user1, Roles: []string{"admin"}, Groups: []string{"group1"}, }) @@ -96,7 +96,7 @@ func TestClient_GenerateClientAccessUrl(t *testing.T) { accessToken := queryValues.Get("access_token") require.NotEmpty(t, accessToken) extract = extractToken(t, token, client) - require.Equal(t, user1, *extract.UserID) + require.Equal(t, user1, extract.UserID) require.Equal(t, "admin", extract.Roles[0]) require.Equal(t, "group1", extract.Groups[0]) } @@ -120,11 +120,11 @@ func extractToken(t *testing.T, token *azwebpubsub.GenerateClientAccessUrlRespon require.True(t, ok, "audience is not valid") require.Equal(t, expectedAudience, audience) subject, ok := claims["sub"].(string) - var userId *string + var userId string if ok { - userId = &subject + userId = subject } else { - userId = nil + userId = "" } rawRoles, ok := claims["role"].([]interface{}) var roles []string diff --git a/sdk/messaging/azwebpubsub/go.mod b/sdk/messaging/azwebpubsub/go.mod index 91700f0dcdbe..e8214cdfe4a7 100644 --- a/sdk/messaging/azwebpubsub/go.mod +++ b/sdk/messaging/azwebpubsub/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt/v5 v5.0.0 github.com/stretchr/testify v1.8.4 diff --git a/sdk/messaging/azwebpubsub/go.sum b/sdk/messaging/azwebpubsub/go.sum index f21d38e62535..2ec0a84dc0e3 100644 --- a/sdk/messaging/azwebpubsub/go.sum +++ b/sdk/messaging/azwebpubsub/go.sum @@ -4,6 +4,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZM github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 h1:TuEMD+E+1aTjjLICGQOW6vLe8UWES7kopac9mUXL56Y= github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 h1:hVeq+yCyUi+MsoO/CU95yqCIcdzra5ovzk8Q2BBpV2M= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/sdk/messaging/azwebpubsub/internal/policy_key_credential.go b/sdk/messaging/azwebpubsub/internal/policy_key_credential.go index e75958d48b3b..489023f2ef78 100644 --- a/sdk/messaging/azwebpubsub/internal/policy_key_credential.go +++ b/sdk/messaging/azwebpubsub/internal/policy_key_credential.go @@ -9,6 +9,7 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo" "github.com/golang-jwt/jwt/v5" ) @@ -32,17 +33,8 @@ func (k *WebPubSubKeyCredentialPolicy) Do(req *policy.Request) (*http.Response, secretKey := []byte(val) // Replace with your secret key tokenString, err := token.SignedString(secretKey) if err != nil { - return nil, NonRetriableError(errors.New("error signing the token")) + return nil, errorinfo.NonRetriableError(errors.New("error signing the token")) } req.Raw().Header.Add("Authorization", "Bearer "+tokenString) return req.Next() } - -// NonRetriableError marks the specified error as non-retriable. -func NonRetriableError(err error) error { - return &nonRetriableError{err} -} - -type nonRetriableError struct { - error -} diff --git a/sdk/messaging/azwebpubsub/internal/util.go b/sdk/messaging/azwebpubsub/internal/util.go index fa809f910856..ea065635127c 100644 --- a/sdk/messaging/azwebpubsub/internal/util.go +++ b/sdk/messaging/azwebpubsub/internal/util.go @@ -19,23 +19,6 @@ const ( TokenScope = "https://webpubsub.azure.com/.default" ) -const ( - HeaderAuthorization = "Authorization" - HeaderXmsDate = "x-ms-date" - HeaderContentLength = "Content-Length" - HeaderContentEncoding = "Content-Encoding" - HeaderContentLanguage = "Content-Language" - HeaderContentType = "Content-Type" - HeaderContentMD5 = "Content-MD5" - HeaderIfModifiedSince = "If-Modified-Since" - HeaderIfMatch = "If-Match" - HeaderIfNoneMatch = "If-None-Match" - HeaderIfUnmodifiedSince = "If-Unmodified-Since" - HeaderRange = "Range" - HeaderXmsVersion = "x-ms-version" - HeaderXmsRequestID = "x-ms-request-id" -) - func NewPipeline(plOpts runtime.PipelineOptions, options *policy.ClientOptions) runtime.Pipeline { return runtime.NewPipeline(ModuleName+".Client", ModuleVersion, plOpts, options) } From 2d85a69a40cec29fc40a7396fd39b72c25ac7885 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Fri, 10 Nov 2023 14:58:45 +0800 Subject: [PATCH 06/28] resolve comments --- sdk/messaging/azwebpubsub/client_custom.go | 35 ++++++++++------- .../azwebpubsub/client_shared_test.go | 36 ++++++++++------- sdk/messaging/azwebpubsub/client_test.go | 39 ++++++++++--------- sdk/messaging/azwebpubsub/sample.env | 1 + 4 files changed, 67 insertions(+), 44 deletions(-) diff --git a/sdk/messaging/azwebpubsub/client_custom.go b/sdk/messaging/azwebpubsub/client_custom.go index b8759db534ea..0c2e91279fac 100644 --- a/sdk/messaging/azwebpubsub/client_custom.go +++ b/sdk/messaging/azwebpubsub/client_custom.go @@ -21,6 +21,8 @@ import ( "github.com/golang-jwt/jwt" ) +const defaultExpirationTime = time.Hour + // ClientOptions contains optional settings for [Client] type ClientOptions struct { azcore.ClientOptions @@ -28,6 +30,10 @@ type ClientOptions struct { // NewClient creates a client that manages Web PubSub service func NewClient(endpoint string, hub string, credential azcore.TokenCredential, options *ClientOptions) (*Client, error) { + if hub == "" { + return nil, errors.New("empty hub name is not allowed") + } + if options == nil { options = &ClientOptions{} } @@ -47,6 +53,10 @@ func NewClient(endpoint string, hub string, credential azcore.TokenCredential, o // NewClientFromConnectionString creates a Client from a connection string func NewClientFromConnectionString(connectionString string, hub string, options *ClientOptions) (*Client, error) { + if hub == "" { + return nil, errors.New("empty hub name is not allowed") + } + if options == nil { options = &ClientOptions{} } @@ -105,24 +115,25 @@ type GenerateClientAccessUrlResponse struct { URL string } -// GenerateClientAccessUrl - generate URL for the WebSocket clients -// - options - GenerateClientAccessUrlOptions contains the optional parameters for the Client.GenerateClientAccessUrl method. -func (c *Client) GenerateClientAccessUrl(ctx context.Context, options *GenerateClientAccessUrlOptions) (*GenerateClientAccessUrlResponse, error) { +// GenerateClientAccessURL - generate URL for the WebSocket clients +// - options - GenerateClientAccessUrlOptions contains the optional parameters for the Client.GenerateClientAccessURL method. +func (c *Client) GenerateClientAccessURL(ctx context.Context, options *GenerateClientAccessUrlOptions) (*GenerateClientAccessUrlResponse, error) { endpoint := c.endpoint hubName := c.hub + hubPath := url.PathEscape(hubName) parsedURL, err := url.Parse(endpoint) if err != nil { return nil, errors.New("endpoint is not a valid URL") } - parsedURL.Scheme = strings.Replace(strings.ToLower(parsedURL.Scheme), "http", "ws", 1) + audience := fmt.Sprintf("%sclient/hubs/%s", parsedURL.String(), hubPath) - clientEndpoint := parsedURL.String() - baseURL := fmt.Sprintf("%s/client/hubs/%s", clientEndpoint, hubName) + parsedURL.Scheme = strings.Replace(strings.ToLower(parsedURL.Scheme), "http", "ws", 1) + baseURL := fmt.Sprintf("%sclient/hubs/%s", parsedURL.String(), hubPath) var token string if c.key != nil { - token, err = c.signJwtToken(baseURL, options) + token, err = c.signJwtToken(audience, options) if err != nil { return nil, err } @@ -149,21 +160,19 @@ func (c *Client) GenerateClientAccessUrl(ctx context.Context, options *GenerateC }, nil } -const DefaultExpirationTime = time.Hour - -func (c *Client) signJwtToken(baseURL string, options *GenerateClientAccessUrlOptions) (string, error) { +func (c *Client) signJwtToken(audience string, options *GenerateClientAccessUrlOptions) (string, error) { if c.key == nil { return "", errors.New("key is nil") } key := []byte(*c.key) var exp int64 if options == nil || options.ExpirationTimeInMinutes == nil { - exp = time.Now().Add(DefaultExpirationTime).Unix() + exp = time.Now().Add(defaultExpirationTime).Unix() } else { exp = time.Now().Add(time.Minute * time.Duration(*options.ExpirationTimeInMinutes)).Unix() } claims := jwt.MapClaims{ - "aud": baseURL, + "aud": audience, "exp": exp, } @@ -171,7 +180,7 @@ func (c *Client) signJwtToken(baseURL string, options *GenerateClientAccessUrlOp claims["sub"] = options.UserID } - if options != nil && options.Groups != nil && len(options.Groups) > 0 { + if options != nil && len(options.Groups) > 0 { claims["webpubsub.group"] = options.Groups } diff --git a/sdk/messaging/azwebpubsub/client_shared_test.go b/sdk/messaging/azwebpubsub/client_shared_test.go index 9a51e23d10d6..3aa68e953453 100644 --- a/sdk/messaging/azwebpubsub/client_shared_test.go +++ b/sdk/messaging/azwebpubsub/client_shared_test.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" @@ -27,11 +28,14 @@ type clientWrapper struct { var fakeTestVars = testVars{ ConnectionString: "Endpoint=https://fake.eastus-1.webpubsub.azure.com;AccessKey=ABCDE;", Hub: "chat", + Endpoint: "https://fake.eastus-1.webpubsub.azure.com", } type testVars struct { + // NewClientFromConnectionString when ConnectionString is set ConnectionString string Hub string + Endpoint string // KeyLogPath is the value of environment "SSLKEYLOGFILE_TEST", which // points to a file on disk where we'll write the TLS pre-master-secret. // This is useful if you want to trace parts of this test using Wireshark. @@ -52,9 +56,10 @@ func loadEnv() (testVars, error) { tv := testVars{ ConnectionString: get("WEBPUBSUB_CONNECTIONSTRING"), Hub: get("WEBPUBSUB_HUB"), + Endpoint: get("WEBPUBSUB_ENDPOINT"), } - if len(missing) > 0 { + if len(missing) > 1 { return testVars{}, fmt.Errorf("Missing env variables: %s", strings.Join(missing, ",")) } @@ -70,7 +75,7 @@ func loadEnv() (testVars, error) { func newClientWrapper(t *testing.T) clientWrapper { var client *azwebpubsub.Client var tv testVars - + var options *azwebpubsub.ClientOptions if recording.GetRecordMode() != recording.PlaybackMode { tmpTestVars, err := loadEnv() require.NoError(t, err) @@ -92,26 +97,31 @@ func newClientWrapper(t *testing.T) clientWrapper { } httpClient := &http.Client{Transport: tp} - - tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, &azwebpubsub.ClientOptions{ + options = &azwebpubsub.ClientOptions{ ClientOptions: azcore.ClientOptions{ Transport: httpClient, }, - }) - require.NoError(t, err) - client = tmpClient + } } else { - tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, nil) - require.NoError(t, err) - client = tmpClient + options = nil } - } else { - tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, &azwebpubsub.ClientOptions{ + options = &azwebpubsub.ClientOptions{ ClientOptions: azcore.ClientOptions{ Transport: newRecordingTransporter(t, tv), }, - }) + } + } + + if tv.ConnectionString != "" { + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, options) + require.NoError(t, err) + client = tmpClient + } else { + cred, err := azidentity.NewDefaultAzureCredential(nil) + require.NoError(t, err) + + tmpClient, err := azwebpubsub.NewClient(tv.Endpoint, tv.Hub, cred, options) require.NoError(t, err) client = tmpClient } diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index 6272f3849440..7c39c92c2484 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -11,13 +11,12 @@ import ( "context" "io" "net/url" - "regexp" + "strings" "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" "github.com/golang-jwt/jwt" "github.com/stretchr/testify/require" ) @@ -70,21 +69,27 @@ func TestClient_CloseConnections(t *testing.T) { require.NoError(t, err) } -func TestClient_GenerateClientAccessUrl(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { - t.Skip() - } +func TestClient_GenerateClientAccessURLFromConnectionString(t *testing.T) { + _, err1 := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;;;;", "abc", nil) + require.ErrorContains(t, err1, "connection string is either blank or malformed.") - client := newClientWrapper(t) - token, err := client.GenerateClientAccessUrl(context.Background(), nil) + _, err1 = azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", "", nil) + require.ErrorContains(t, err1, "empty hub name is not allowed") + + hub := "chat/go" + client, err := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", hub, nil) require.NoError(t, err) - extract := extractToken(t, token, client) + + token, err := client.GenerateClientAccessURL(context.Background(), nil) + + require.NoError(t, err) + extract := extractToken(t, token, "http://test/subpath", "ABC", hub) require.Nil(t, extract.Roles) require.Nil(t, extract.Groups) - require.Nil(t, extract.UserID) + require.Empty(t, extract.UserID) user1 := "user1" - token, err = client.GenerateClientAccessUrl(context.Background(), &azwebpubsub.GenerateClientAccessUrlOptions{ + token, err = client.GenerateClientAccessURL(context.Background(), &azwebpubsub.GenerateClientAccessUrlOptions{ UserID: user1, Roles: []string{"admin"}, Groups: []string{"group1"}, @@ -95,22 +100,20 @@ func TestClient_GenerateClientAccessUrl(t *testing.T) { queryValues := parsedURL.Query() accessToken := queryValues.Get("access_token") require.NotEmpty(t, accessToken) - extract = extractToken(t, token, client) + extract = extractToken(t, token, "http://test/subpath", "ABC", hub) require.Equal(t, user1, extract.UserID) require.Equal(t, "admin", extract.Roles[0]) require.Equal(t, "group1", extract.Groups[0]) } -func extractToken(t *testing.T, token *azwebpubsub.GenerateClientAccessUrlResponse, client clientWrapper) azwebpubsub.GenerateClientAccessUrlOptions { - key, err := internal.ParseConnectionString(client.TestVars.ConnectionString) - require.NoError(t, err) - expectedAudience := key.Endpoint + "client/hubs/" + client.TestVars.Hub - expectedBaseUrl := regexp.MustCompile(`$(http)(s?://)`).ReplaceAllString(expectedAudience, "ws$2") +func extractToken(t *testing.T, token *azwebpubsub.GenerateClientAccessUrlResponse, endpoint string, key string, hub string) azwebpubsub.GenerateClientAccessUrlOptions { + expectedAudience := endpoint + "/client/hubs/" + url.PathEscape(hub) + expectedBaseUrl := strings.Replace(expectedAudience, "http", "ws", 1) require.Equal(t, expectedBaseUrl, token.BaseURL) parsed, err := jwt.Parse(token.Token, func(token *jwt.Token) (interface{}, error) { // Provide the secret key for validation - return []byte(key.AccessKey), nil + return []byte(key), nil }) require.NoError(t, err) require.True(t, parsed.Valid, "token is not valid") diff --git a/sdk/messaging/azwebpubsub/sample.env b/sdk/messaging/azwebpubsub/sample.env index 574294285344..9b2da97b31cf 100644 --- a/sdk/messaging/azwebpubsub/sample.env +++ b/sdk/messaging/azwebpubsub/sample.env @@ -1,2 +1,3 @@ WEBPUBSUB_CONNECTIONSTRING= WEBPUBSUB_HUB=chat +WEBPUBSUB_ENDPOINT= \ No newline at end of file From 9dc1a065b662e124d55903689366a8d73ef82b4f Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Fri, 10 Nov 2023 15:12:12 +0800 Subject: [PATCH 07/28] Update readme --- sdk/messaging/azwebpubsub/README.md | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/sdk/messaging/azwebpubsub/README.md b/sdk/messaging/azwebpubsub/README.md index e0ec5ec8c567..c1aea6b9145b 100644 --- a/sdk/messaging/azwebpubsub/README.md +++ b/sdk/messaging/azwebpubsub/README.md @@ -44,8 +44,47 @@ You can also create a client using a connection string. #### Using a service principal +Constructing the client requires your Web PubSub's endpoint URL, which you can get from the Azure Portal (`Host name` value on overview page with `https` scheme). + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" + "log" +) + +func main() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + + client, err := azwebpubsub.NewClient("", "", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } +} +``` + #### Using a connection string +ConnectionString can be found in the **Keys** tab from your Web PubSub resource portal. + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" + "log" +) + +func main() { + client, err := azwebpubsub.NewClientFromConnectionString("", "", nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } +} +``` + # Key concepts ### Connection From ea0ea0b048cb8ab82b090542de12e71b71140ff2 Mon Sep 17 00:00:00 2001 From: "Liangying.Wei" Date: Tue, 14 Nov 2023 03:28:50 +0000 Subject: [PATCH 08/28] fix some comments, remove hub parameter when constructing the client, and add HealthAPIClient constructions --- sdk/messaging/azwebpubsub/README.md | 4 +- sdk/messaging/azwebpubsub/autorest.md | 15 ++- sdk/messaging/azwebpubsub/build.go | 1 + sdk/messaging/azwebpubsub/client.go | 21 ++--- sdk/messaging/azwebpubsub/client_custom.go | 41 ++++----- .../azwebpubsub/client_shared_test.go | 7 +- sdk/messaging/azwebpubsub/client_test.go | 47 +++++++--- sdk/messaging/azwebpubsub/constants.go | 16 ++-- sdk/messaging/azwebpubsub/example_test.go | 16 ++-- sdk/messaging/azwebpubsub/go.mod | 2 +- sdk/messaging/azwebpubsub/go.sum | 6 +- .../azwebpubsub/healthapi_client_custom.go | 35 +++++++ .../azwebpubsub/healthapi_client_test.go | 92 +++++++++++++++++++ .../internal/policy_key_credential.go | 8 +- .../internal/policy_key_credential_test.go | 6 +- sdk/messaging/azwebpubsub/internal/util.go | 7 -- sdk/messaging/azwebpubsub/internal/version.go | 4 +- sdk/messaging/azwebpubsub/package-lock.json | 6 -- sdk/messaging/azwebpubsub/package.json | 1 - 19 files changed, 234 insertions(+), 101 deletions(-) create mode 100644 sdk/messaging/azwebpubsub/healthapi_client_custom.go create mode 100644 sdk/messaging/azwebpubsub/healthapi_client_test.go delete mode 100644 sdk/messaging/azwebpubsub/package-lock.json delete mode 100644 sdk/messaging/azwebpubsub/package.json diff --git a/sdk/messaging/azwebpubsub/README.md b/sdk/messaging/azwebpubsub/README.md index c1aea6b9145b..f6d36765ef9e 100644 --- a/sdk/messaging/azwebpubsub/README.md +++ b/sdk/messaging/azwebpubsub/README.md @@ -59,7 +59,7 @@ func main() { log.Fatalf("failed to obtain a credential: %v", err) } - client, err := azwebpubsub.NewClient("", "", cred, nil) + client, err := azwebpubsub.NewClient("", cred, nil) if err != nil { log.Fatalf("failed to create client: %v", err) } @@ -78,7 +78,7 @@ import ( ) func main() { - client, err := azwebpubsub.NewClientFromConnectionString("", "", nil) + client, err := azwebpubsub.NewClientFromConnectionString("", nil) if err != nil { log.Fatalf("failed to create client: %v", err) } diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index 9b9a7613ae3c..7dee89e40b55 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -4,15 +4,20 @@ title: WebPubSub description: Azure Web PubSub client clear-output-folder: false -export-clients: true go: true input-file: https://github.com/Azure/azure-rest-api-specs/blob/052a4b8d50bfd5595a8b5b506015d18f2b65998d/specification/webpubsub/data-plane/WebPubSub/stable/2023-07-01/webpubsub.json license-header: MICROSOFT_MIT_NO_VERSION module: github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub openapi-type: "data-plane" output-folder: ../azwebpubsub -use: "@autorest/go@4.0.0-preview.57" +use: "@autorest/go@4.0.0-preview.60" directive: + # Rename enum WebPubSubPermission to Permission since the package name already contains WebPubSub. + - from: + - constants.go + - client.go + where: $ + transform: return $.replace(/WebPubSubPermission/g, "Permission"); # Make GenerateClientToken internal. - from: client.go where: $ @@ -21,12 +26,16 @@ directive: - from: client.go where: $ transform: return $.replace(/\b(Group|Connection|User)Exists\b/g, function(match, group) { return group.toLowerCase() + "Exists";}); + # Make CheckPermission internal until SDK supports it, since it leverage 404 status code + - from: client.go + where: $ + transform: return $.replace(/\bCheckPermission\b/g, "checkPermission"); # Add more properties to lient - from: client.go where: $ transform: >- return $.replace( /(type Client struct[^}]+})/s, - "type Client struct {\n internal *azcore.Client\n endpoint string\n hub string\n key *string\n}") + "type Client struct {\n internal *azcore.Client\n endpoint string\n key *string\n}") ``` \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/build.go b/sdk/messaging/azwebpubsub/build.go index cd74dd14c0c9..565585be5005 100644 --- a/sdk/messaging/azwebpubsub/build.go +++ b/sdk/messaging/azwebpubsub/build.go @@ -5,5 +5,6 @@ //go:generate autorest ./autorest.md //go:generate goimports -w . +//go:generate gofmt -w . package azwebpubsub diff --git a/sdk/messaging/azwebpubsub/client.go b/sdk/messaging/azwebpubsub/client.go index 02dc357c8954..eecf592ff20a 100644 --- a/sdk/messaging/azwebpubsub/client.go +++ b/sdk/messaging/azwebpubsub/client.go @@ -26,8 +26,7 @@ import ( type Client struct { internal *azcore.Client endpoint string - hub string - key *string; + key *string } // AddConnectionToGroup - Add a connection to the target group. @@ -177,15 +176,15 @@ func (client *Client) addUserToGroupCreateRequest(ctx context.Context, hub strin return req, nil } -// CheckPermission - Check if a connection has permission to the specified action. +// checkPermission - Check if a connection has permission to the specified action. // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. // - connectionID - Target connection Id. -// - options - ClientCheckPermissionOptions contains the optional parameters for the Client.CheckPermission method. -func (client *Client) CheckPermission(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientCheckPermissionOptions) (ClientCheckPermissionResponse, error) { +// - options - ClientCheckPermissionOptions contains the optional parameters for the Client.checkPermission method. +func (client *Client) checkPermission(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientCheckPermissionOptions) (ClientCheckPermissionResponse, error) { var err error req, err := client.checkPermissionCreateRequest(ctx, hub, permission, connectionID, options) if err != nil { @@ -202,8 +201,8 @@ func (client *Client) CheckPermission(ctx context.Context, hub string, permissio return ClientCheckPermissionResponse{}, nil } -// checkPermissionCreateRequest creates the CheckPermission request. -func (client *Client) checkPermissionCreateRequest(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientCheckPermissionOptions) (*policy.Request, error) { +// checkPermissionCreateRequest creates the checkPermission request. +func (client *Client) checkPermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientCheckPermissionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -556,7 +555,7 @@ func (client *Client) generateClientTokenHandleResponse(resp *http.Response) (Cl // - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. // - connectionID - Target connection Id. // - options - ClientGrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. -func (client *Client) GrantPermission(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientGrantPermissionOptions) (ClientGrantPermissionResponse, error) { +func (client *Client) GrantPermission(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientGrantPermissionOptions) (ClientGrantPermissionResponse, error) { var err error req, err := client.grantPermissionCreateRequest(ctx, hub, permission, connectionID, options) if err != nil { @@ -574,7 +573,7 @@ func (client *Client) GrantPermission(ctx context.Context, hub string, permissio } // grantPermissionCreateRequest creates the GrantPermission request. -func (client *Client) grantPermissionCreateRequest(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientGrantPermissionOptions) (*policy.Request, error) { +func (client *Client) grantPermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientGrantPermissionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -898,7 +897,7 @@ func (client *Client) removeUserFromGroupCreateRequest(ctx context.Context, hub // - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. // - connectionID - Target connection Id. // - options - ClientRevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. -func (client *Client) RevokePermission(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientRevokePermissionOptions) (ClientRevokePermissionResponse, error) { +func (client *Client) RevokePermission(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientRevokePermissionOptions) (ClientRevokePermissionResponse, error) { var err error req, err := client.revokePermissionCreateRequest(ctx, hub, permission, connectionID, options) if err != nil { @@ -916,7 +915,7 @@ func (client *Client) RevokePermission(ctx context.Context, hub string, permissi } // revokePermissionCreateRequest creates the RevokePermission request. -func (client *Client) revokePermissionCreateRequest(ctx context.Context, hub string, permission WebPubSubPermission, connectionID string, options *ClientRevokePermissionOptions) (*policy.Request, error) { +func (client *Client) revokePermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientRevokePermissionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") diff --git a/sdk/messaging/azwebpubsub/client_custom.go b/sdk/messaging/azwebpubsub/client_custom.go index 0c2e91279fac..f87ebc77191e 100644 --- a/sdk/messaging/azwebpubsub/client_custom.go +++ b/sdk/messaging/azwebpubsub/client_custom.go @@ -29,17 +29,13 @@ type ClientOptions struct { } // NewClient creates a client that manages Web PubSub service -func NewClient(endpoint string, hub string, credential azcore.TokenCredential, options *ClientOptions) (*Client, error) { - if hub == "" { - return nil, errors.New("empty hub name is not allowed") - } - +func NewClient(endpoint string, credential azcore.TokenCredential, options *ClientOptions) (*Client, error) { if options == nil { options = &ClientOptions{} } authPolicy := runtime.NewBearerTokenPolicy(credential, []string{internal.TokenScope}, nil) - azcoreClient, err := azcore.NewClient(internal.ModuleName+".Client", internal.ModuleVersion, + azcoreClient, err := azcore.NewClient(internal.ModuleName, internal.ModuleVersion, runtime.PipelineOptions{PerRetry: []policy.Policy{authPolicy}}, &options.ClientOptions) if err != nil { return nil, err @@ -47,16 +43,11 @@ func NewClient(endpoint string, hub string, credential azcore.TokenCredential, o return &Client{ internal: azcoreClient, endpoint: endpoint, - hub: hub, }, nil } // NewClientFromConnectionString creates a Client from a connection string -func NewClientFromConnectionString(connectionString string, hub string, options *ClientOptions) (*Client, error) { - if hub == "" { - return nil, errors.New("empty hub name is not allowed") - } - +func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { if options == nil { options = &ClientOptions{} } @@ -67,7 +58,7 @@ func NewClientFromConnectionString(connectionString string, hub string, options return nil, err } - azcoreClient, err := azcore.NewClient(internal.ModuleName+".Client", internal.ModuleVersion, runtime.PipelineOptions{ + azcoreClient, err := azcore.NewClient(internal.ModuleName, internal.ModuleVersion, runtime.PipelineOptions{ PerRetry: []policy.Policy{internal.NewWebPubSubKeyCredentialPolicy(props.AccessKey)}, }, &options.ClientOptions) @@ -78,13 +69,12 @@ func NewClientFromConnectionString(connectionString string, hub string, options return &Client{ internal: azcoreClient, endpoint: props.Endpoint, - hub: hub, key: &props.AccessKey, }, nil } -// GenerateClientAccessUrlOptions represents the options for generating a client access url -type GenerateClientAccessUrlOptions struct { +// GenerateClientAccessURLOptions represents the options for generating a client access url +type GenerateClientAccessURLOptions struct { // UserID is the user ID for the client. UserID string @@ -105,8 +95,8 @@ type GenerateClientAccessUrlOptions struct { Groups []string } -// GenerateClientAccessUrlResponse represents the response type for the generated client access url -type GenerateClientAccessUrlResponse struct { +// GenerateClientAccessURLResponse represents the response type for the generated client access url +type GenerateClientAccessURLResponse struct { // The client token Token string // The base URL for the client to connect to @@ -116,11 +106,14 @@ type GenerateClientAccessUrlResponse struct { } // GenerateClientAccessURL - generate URL for the WebSocket clients +// - hub - The hub name. // - options - GenerateClientAccessUrlOptions contains the optional parameters for the Client.GenerateClientAccessURL method. -func (c *Client) GenerateClientAccessURL(ctx context.Context, options *GenerateClientAccessUrlOptions) (*GenerateClientAccessUrlResponse, error) { +func (c *Client) GenerateClientAccessURL(ctx context.Context, hub string, options *GenerateClientAccessURLOptions) (*GenerateClientAccessURLResponse, error) { endpoint := c.endpoint - hubName := c.hub - hubPath := url.PathEscape(hubName) + if hub == "" { + return nil, errors.New("empty hub name is not allowed") + } + hubPath := url.PathEscape(hub) parsedURL, err := url.Parse(endpoint) if err != nil { return nil, errors.New("endpoint is not a valid URL") @@ -145,7 +138,7 @@ func (c *Client) GenerateClientAccessURL(ctx context.Context, options *GenerateC userId = &options.UserID } // Replace with your logic to generate the token using a webPubSub method - resp, err := c.generateClientToken(ctx, hubName, &ClientGenerateClientTokenOptions{UserID: userId, Role: options.Roles, Group: options.Groups, MinutesToExpire: options.ExpirationTimeInMinutes}) + resp, err := c.generateClientToken(ctx, hub, &ClientGenerateClientTokenOptions{UserID: userId, Role: options.Roles, Group: options.Groups, MinutesToExpire: options.ExpirationTimeInMinutes}) if err != nil { return nil, err } @@ -153,14 +146,14 @@ func (c *Client) GenerateClientAccessURL(ctx context.Context, options *GenerateC token = *resp.Token } - return &GenerateClientAccessUrlResponse{ + return &GenerateClientAccessURLResponse{ Token: token, BaseURL: baseURL, URL: fmt.Sprintf("%s?access_token=%s", baseURL, url.QueryEscape(token)), }, nil } -func (c *Client) signJwtToken(audience string, options *GenerateClientAccessUrlOptions) (string, error) { +func (c *Client) signJwtToken(audience string, options *GenerateClientAccessURLOptions) (string, error) { if c.key == nil { return "", errors.New("key is nil") } diff --git a/sdk/messaging/azwebpubsub/client_shared_test.go b/sdk/messaging/azwebpubsub/client_shared_test.go index 3aa68e953453..c2b872a82fc5 100644 --- a/sdk/messaging/azwebpubsub/client_shared_test.go +++ b/sdk/messaging/azwebpubsub/client_shared_test.go @@ -27,14 +27,12 @@ type clientWrapper struct { var fakeTestVars = testVars{ ConnectionString: "Endpoint=https://fake.eastus-1.webpubsub.azure.com;AccessKey=ABCDE;", - Hub: "chat", Endpoint: "https://fake.eastus-1.webpubsub.azure.com", } type testVars struct { // NewClientFromConnectionString when ConnectionString is set ConnectionString string - Hub string Endpoint string // KeyLogPath is the value of environment "SSLKEYLOGFILE_TEST", which // points to a file on disk where we'll write the TLS pre-master-secret. @@ -55,7 +53,6 @@ func loadEnv() (testVars, error) { tv := testVars{ ConnectionString: get("WEBPUBSUB_CONNECTIONSTRING"), - Hub: get("WEBPUBSUB_HUB"), Endpoint: get("WEBPUBSUB_ENDPOINT"), } @@ -114,14 +111,14 @@ func newClientWrapper(t *testing.T) clientWrapper { } if tv.ConnectionString != "" { - tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, tv.Hub, options) + tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, options) require.NoError(t, err) client = tmpClient } else { cred, err := azidentity.NewDefaultAzureCredential(nil) require.NoError(t, err) - tmpClient, err := azwebpubsub.NewClient(tv.Endpoint, tv.Hub, cred, options) + tmpClient, err := azwebpubsub.NewClient(tv.Endpoint, cred, options) require.NoError(t, err) client = tmpClient } diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index 7c39c92c2484..39dd210be0c8 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -27,23 +27,42 @@ func TestClient_SendToAll(t *testing.T) { } client := newClientWrapper(t) - - _, err := client.SendToAll(context.Background(), - client.TestVars.Hub, azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), + hub := "hub1" + _, err := client.SendToAll(context.Background(), hub, + azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), &azwebpubsub.ClientSendToAllOptions{}) require.NoError(t, err) - _, err = client.SendToAll(context.Background(), - client.TestVars.Hub, azwebpubsub.ContentTypeApplicationJSON, newStream("true"), + _, err = client.SendToAll(context.Background(), hub, + azwebpubsub.ContentTypeApplicationJSON, newStream("true"), &azwebpubsub.ClientSendToAllOptions{}) require.NoError(t, err) - _, err = client.SendToAll(context.Background(), - client.TestVars.Hub, azwebpubsub.ContentTypeApplicationOctetStream, newStream("true"), + _, err = client.SendToAll(context.Background(), hub, + azwebpubsub.ContentTypeApplicationOctetStream, newStream("true"), &azwebpubsub.ClientSendToAllOptions{}) require.NoError(t, err) } +func TestClient_ManagePermissions(t *testing.T) { + if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { + t.Skip() + } + + client := newClientWrapper(t) + const hub = "chat" + const conn1 = "conn1" + group := "group1" + _, err := client.GrantPermission(context.Background(), hub, azwebpubsub.PermissionJoinLeaveGroup, conn1, &azwebpubsub.ClientGrantPermissionOptions{ + TargetName: &group, + }) + require.ErrorContains(t, err, "404 Not Found") + _, err = client.RevokePermission(context.Background(), hub, azwebpubsub.PermissionJoinLeaveGroup, conn1, &azwebpubsub.ClientRevokePermissionOptions{ + TargetName: &group, + }) + require.NoError(t, err) +} + func TestClient_CloseConnections(t *testing.T) { if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { t.Skip() @@ -70,17 +89,17 @@ func TestClient_CloseConnections(t *testing.T) { } func TestClient_GenerateClientAccessURLFromConnectionString(t *testing.T) { - _, err1 := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;;;;", "abc", nil) + _, err1 := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;;;;", nil) require.ErrorContains(t, err1, "connection string is either blank or malformed.") - _, err1 = azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", "", nil) + _, err1 = azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", nil) require.ErrorContains(t, err1, "empty hub name is not allowed") hub := "chat/go" - client, err := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", hub, nil) + client, err := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", nil) require.NoError(t, err) - token, err := client.GenerateClientAccessURL(context.Background(), nil) + token, err := client.GenerateClientAccessURL(context.Background(), hub, nil) require.NoError(t, err) extract := extractToken(t, token, "http://test/subpath", "ABC", hub) @@ -89,7 +108,7 @@ func TestClient_GenerateClientAccessURLFromConnectionString(t *testing.T) { require.Empty(t, extract.UserID) user1 := "user1" - token, err = client.GenerateClientAccessURL(context.Background(), &azwebpubsub.GenerateClientAccessUrlOptions{ + token, err = client.GenerateClientAccessURL(context.Background(), hub, &azwebpubsub.GenerateClientAccessURLOptions{ UserID: user1, Roles: []string{"admin"}, Groups: []string{"group1"}, @@ -106,7 +125,7 @@ func TestClient_GenerateClientAccessURLFromConnectionString(t *testing.T) { require.Equal(t, "group1", extract.Groups[0]) } -func extractToken(t *testing.T, token *azwebpubsub.GenerateClientAccessUrlResponse, endpoint string, key string, hub string) azwebpubsub.GenerateClientAccessUrlOptions { +func extractToken(t *testing.T, token *azwebpubsub.GenerateClientAccessURLResponse, endpoint string, key string, hub string) azwebpubsub.GenerateClientAccessURLOptions { expectedAudience := endpoint + "/client/hubs/" + url.PathEscape(hub) expectedBaseUrl := strings.Replace(expectedAudience, "http", "ws", 1) @@ -155,7 +174,7 @@ func extractToken(t *testing.T, token *azwebpubsub.GenerateClientAccessUrlRespon groups = nil } - return azwebpubsub.GenerateClientAccessUrlOptions{ + return azwebpubsub.GenerateClientAccessURLOptions{ UserID: userId, Roles: roles, Groups: groups, diff --git a/sdk/messaging/azwebpubsub/constants.go b/sdk/messaging/azwebpubsub/constants.go index 60df74220349..4102b36d3800 100644 --- a/sdk/messaging/azwebpubsub/constants.go +++ b/sdk/messaging/azwebpubsub/constants.go @@ -29,18 +29,18 @@ func PossibleContentTypeValues() []ContentType { } } -type WebPubSubPermission string +type Permission string const ( - WebPubSubPermissionJoinLeaveGroup WebPubSubPermission = "joinLeaveGroup" - WebPubSubPermissionSendToGroup WebPubSubPermission = "sendToGroup" + PermissionJoinLeaveGroup Permission = "joinLeaveGroup" + PermissionSendToGroup Permission = "sendToGroup" ) -// PossibleWebPubSubPermissionValues returns the possible values for the WebPubSubPermission const type. -func PossibleWebPubSubPermissionValues() []WebPubSubPermission { - return []WebPubSubPermission{ - WebPubSubPermissionJoinLeaveGroup, - WebPubSubPermissionSendToGroup, +// PossiblePermissionValues returns the possible values for the Permission const type. +func PossiblePermissionValues() []Permission { + return []Permission{ + PermissionJoinLeaveGroup, + PermissionSendToGroup, } } diff --git a/sdk/messaging/azwebpubsub/example_test.go b/sdk/messaging/azwebpubsub/example_test.go index ecd1fbd6aae5..f3a2585654cb 100644 --- a/sdk/messaging/azwebpubsub/example_test.go +++ b/sdk/messaging/azwebpubsub/example_test.go @@ -11,7 +11,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" ) -func ExampleNewClientWithDefaultAzureCredential() { +func Example_NewClientWithDefaultAzureCredential() { cred, err := azidentity.NewDefaultAzureCredential(nil) if err != nil { @@ -28,7 +28,7 @@ func ExampleNewClientWithDefaultAzureCredential() { if hub == "" { return } - client, err := azwebpubsub.NewClient(endpoint, hub, cred, nil) + client, err := azwebpubsub.NewClient(endpoint, cred, nil) if err != nil { // TODO: Update the following line with your application specific error handling logic @@ -40,20 +40,20 @@ func ExampleNewClientWithDefaultAzureCredential() { // Output: } -func ExampleNewClientWithConnectionString() *azwebpubsub.Client { +func Example_NewClientWithConnectionString() { connectionString := os.Getenv("WEBPUBSUB_CONNECTIONSTRING") - hub := os.Getenv("WEBPUBSUB_HUB") - if connectionString == "" { - return nil + return } - client, err := azwebpubsub.NewClientFromConnectionString(connectionString, hub, nil) + client, err := azwebpubsub.NewClientFromConnectionString(connectionString, nil) if err != nil { // TODO: Update the following line with your application specific error handling logic log.Fatalf("ERROR: %s", err) } - return client + _ = client // ignore + + // Output: } diff --git a/sdk/messaging/azwebpubsub/go.mod b/sdk/messaging/azwebpubsub/go.mod index e8214cdfe4a7..bdecf0454ab1 100644 --- a/sdk/messaging/azwebpubsub/go.mod +++ b/sdk/messaging/azwebpubsub/go.mod @@ -3,7 +3,7 @@ module github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 github.com/golang-jwt/jwt v3.2.2+incompatible diff --git a/sdk/messaging/azwebpubsub/go.sum b/sdk/messaging/azwebpubsub/go.sum index 2ec0a84dc0e3..111b006fb5de 100644 --- a/sdk/messaging/azwebpubsub/go.sum +++ b/sdk/messaging/azwebpubsub/go.sum @@ -1,9 +1,7 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 h1:TuEMD+E+1aTjjLICGQOW6vLe8UWES7kopac9mUXL56Y= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 h1:hVeq+yCyUi+MsoO/CU95yqCIcdzra5ovzk8Q2BBpV2M= diff --git a/sdk/messaging/azwebpubsub/healthapi_client_custom.go b/sdk/messaging/azwebpubsub/healthapi_client_custom.go new file mode 100644 index 000000000000..02bfa34ee9e4 --- /dev/null +++ b/sdk/messaging/azwebpubsub/healthapi_client_custom.go @@ -0,0 +1,35 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azwebpubsub + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" +) + +// HealthAPIClientOptions contains optional settings for [HealthAPIClient] +type HealthAPIClientOptions struct { + azcore.ClientOptions +} + +// NewHealthAPIClient creates a client that checks the healthy status of Web PubSub service +func NewHealthAPIClient(endpoint string, options *HealthAPIClientOptions) (*HealthAPIClient, error) { + if options == nil { + options = &HealthAPIClientOptions{} + } + + azcoreClient, err := azcore.NewClient(internal.ModuleName, internal.ModuleVersion, runtime.PipelineOptions{}, &options.ClientOptions) + if err != nil { + return nil, err + } + + return &HealthAPIClient{ + internal: azcoreClient, + endpoint: endpoint, + }, nil +} diff --git a/sdk/messaging/azwebpubsub/healthapi_client_test.go b/sdk/messaging/azwebpubsub/healthapi_client_test.go new file mode 100644 index 000000000000..9726aff1d583 --- /dev/null +++ b/sdk/messaging/azwebpubsub/healthapi_client_test.go @@ -0,0 +1,92 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package azwebpubsub_test + +import ( + "context" + "crypto/tls" + "net/http" + "os" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" + "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" + "github.com/stretchr/testify/require" +) + +func TestHealthAPIClient_GetServiceStatus(t *testing.T) { + if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { + t.Skip() + } + + client := getHealthAPIClient(t) + _, err := client.GetServiceStatus(context.Background(), &azwebpubsub.HealthAPIClientGetServiceStatusOptions{}) + require.NoError(t, err) +} + +func loadEndpointFromEnv() (string, error) { + if v := os.Getenv("WEBPUBSUB_ENDPOINT"); v != "" { + return v, nil + } + if v := os.Getenv("WEBPUBSUB_CONNECTIONSTRING"); v != "" { + props, err := internal.ParseConnectionString(v) + if err != nil { + return "", err + } + return props.Endpoint, nil + } + return "", nil +} + +func getHealthAPIClient(t *testing.T) *azwebpubsub.HealthAPIClient { + var options *azwebpubsub.HealthAPIClientOptions + var endpoint string + if recording.GetRecordMode() != recording.PlaybackMode { + tmpEndpoint, err := loadEndpointFromEnv() + require.NoError(t, err) + require.NotEmpty(t, tmpEndpoint) + endpoint = tmpEndpoint + } else { + endpoint = "https://fake.eastus-1.webpubsub.azure.com" + } + + if recording.GetRecordMode() == recording.LiveMode { + keyLogPath := os.Getenv("SSLKEYLOGFILE") + if keyLogPath != "" { + keyLogWriter, err := os.OpenFile(keyLogPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777) + require.NoError(t, err) + + t.Cleanup(func() { keyLogWriter.Close() }) + + tp := http.DefaultTransport.(*http.Transport).Clone() + tp.TLSClientConfig = &tls.Config{ + KeyLogWriter: keyLogWriter, + } + + httpClient := &http.Client{Transport: tp} + options = &azwebpubsub.HealthAPIClientOptions{ + ClientOptions: azcore.ClientOptions{ + Transport: httpClient, + }, + } + } else { + options = nil + } + } else { + options = &azwebpubsub.HealthAPIClientOptions{ + ClientOptions: azcore.ClientOptions{ + Transport: newRecordingTransporter(t, testVars{Endpoint: endpoint}), + }, + } + } + + client, err := azwebpubsub.NewHealthAPIClient("https://lianwei-test-1.webpubsub.azure.com", options) + require.NoError(t, err) + return client +} diff --git a/sdk/messaging/azwebpubsub/internal/policy_key_credential.go b/sdk/messaging/azwebpubsub/internal/policy_key_credential.go index 489023f2ef78..acee5b3c3de9 100644 --- a/sdk/messaging/azwebpubsub/internal/policy_key_credential.go +++ b/sdk/messaging/azwebpubsub/internal/policy_key_credential.go @@ -13,18 +13,18 @@ import ( "github.com/golang-jwt/jwt/v5" ) -type WebPubSubKeyCredentialPolicy struct { +type KeyCredentialPolicy struct { key string } -func NewWebPubSubKeyCredentialPolicy(key string) *WebPubSubKeyCredentialPolicy { - return &WebPubSubKeyCredentialPolicy{ +func NewWebPubSubKeyCredentialPolicy(key string) *KeyCredentialPolicy { + return &KeyCredentialPolicy{ key: key, } } // Do implementes the Do method on the [policy.Polilcy] interface. -func (k *WebPubSubKeyCredentialPolicy) Do(req *policy.Request) (*http.Response, error) { +func (k *KeyCredentialPolicy) Do(req *policy.Request) (*http.Response, error) { val := k.key token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "aud": req.Raw().URL.String(), diff --git a/sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go b/sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go index eec9dd6bf3fb..77833ca65d31 100644 --- a/sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go +++ b/sdk/messaging/azwebpubsub/internal/policy_key_credential_test.go @@ -35,7 +35,7 @@ func TestKeyCredentialPolicy(t *testing.T) { return &http.Response{}, nil }) - pl := NewPipeline(runtime.PipelineOptions{PerCall: []policy.Policy{keyPolicy, verifier}}, + pl := newPipeline(runtime.PipelineOptions{PerCall: []policy.Policy{keyPolicy, verifier}}, &policy.ClientOptions{}) req, err := runtime.NewRequest(context.Background(), http.MethodGet, target) require.NoError(t, err) @@ -49,3 +49,7 @@ type PolicyFunc func(req *policy.Request) (*http.Response, error) func (f PolicyFunc) Do(req *policy.Request) (*http.Response, error) { return f(req) } + +func newPipeline(plOpts runtime.PipelineOptions, options *policy.ClientOptions) runtime.Pipeline { + return runtime.NewPipeline(ModuleName+".Client", ModuleVersion, plOpts, options) +} diff --git a/sdk/messaging/azwebpubsub/internal/util.go b/sdk/messaging/azwebpubsub/internal/util.go index ea065635127c..ac77d2384736 100644 --- a/sdk/messaging/azwebpubsub/internal/util.go +++ b/sdk/messaging/azwebpubsub/internal/util.go @@ -10,19 +10,12 @@ import ( "errors" "net/url" "strings" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" ) const ( TokenScope = "https://webpubsub.azure.com/.default" ) -func NewPipeline(plOpts runtime.PipelineOptions, options *policy.ClientOptions) runtime.Pipeline { - return runtime.NewPipeline(ModuleName+".Client", ModuleVersion, plOpts, options) -} - var errConnectionString = errors.New("connection string is either blank or malformed. The expected connection string " + "should contain key value pairs separated by semicolons. For example 'Endpoint=;AccessKey=;'") diff --git a/sdk/messaging/azwebpubsub/internal/version.go b/sdk/messaging/azwebpubsub/internal/version.go index 727f10b5246c..e0cba87ea360 100644 --- a/sdk/messaging/azwebpubsub/internal/version.go +++ b/sdk/messaging/azwebpubsub/internal/version.go @@ -11,8 +11,8 @@ package internal // Constants to identify the module const ( // ModuleName is the module name that shows in telemetry. - ModuleName = "azwebpubsub" + ModuleName = "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" // ModuleVersion is the semantic version (see http://semver.org) of this module. - ModuleVersion = "v0.1.1" + ModuleVersion = "v0.1.0" ) diff --git a/sdk/messaging/azwebpubsub/package-lock.json b/sdk/messaging/azwebpubsub/package-lock.json deleted file mode 100644 index e6b113e451b3..000000000000 --- a/sdk/messaging/azwebpubsub/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "azwebpubsub", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/sdk/messaging/azwebpubsub/package.json b/sdk/messaging/azwebpubsub/package.json deleted file mode 100644 index 0967ef424bce..000000000000 --- a/sdk/messaging/azwebpubsub/package.json +++ /dev/null @@ -1 +0,0 @@ -{} From 9cd024cccf797d06bdd2c1e23e972f54fc35860a Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Tue, 14 Nov 2023 16:09:45 +0800 Subject: [PATCH 09/28] Fix go vet error --- sdk/messaging/azwebpubsub/example_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/messaging/azwebpubsub/example_test.go b/sdk/messaging/azwebpubsub/example_test.go index f3a2585654cb..c6243c413968 100644 --- a/sdk/messaging/azwebpubsub/example_test.go +++ b/sdk/messaging/azwebpubsub/example_test.go @@ -11,7 +11,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" ) -func Example_NewClientWithDefaultAzureCredential() { +// ExampleNewClient demonstrates how to create a new client with default Azure credentials. +func ExampleNewClient() { cred, err := azidentity.NewDefaultAzureCredential(nil) if err != nil { @@ -40,7 +41,8 @@ func Example_NewClientWithDefaultAzureCredential() { // Output: } -func Example_NewClientWithConnectionString() { +// ExampleNewClientFromConnectionString demonstrates how to create a new client with connection string. +func ExampleNewClientFromConnectionString() { connectionString := os.Getenv("WEBPUBSUB_CONNECTIONSTRING") if connectionString == "" { return From abb89b64fd5b5cce888cd05fbef57c0da5def522 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Tue, 14 Nov 2023 16:16:44 +0800 Subject: [PATCH 10/28] Fix test failure --- sdk/messaging/azwebpubsub/client_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index 39dd210be0c8..a41982ef2c6e 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -92,9 +92,6 @@ func TestClient_GenerateClientAccessURLFromConnectionString(t *testing.T) { _, err1 := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;;;;", nil) require.ErrorContains(t, err1, "connection string is either blank or malformed.") - _, err1 = azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", nil) - require.ErrorContains(t, err1, "empty hub name is not allowed") - hub := "chat/go" client, err := azwebpubsub.NewClientFromConnectionString("Endpoint=http://test/subpath;AccessKey=ABC;;;", nil) require.NoError(t, err) From 0af1a219bf19c4f77cb09c580581120e69195084 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Wed, 15 Nov 2023 11:35:58 +0800 Subject: [PATCH 11/28] Fix comments --- sdk/messaging/azwebpubsub/autorest.md | 4 ++++ sdk/messaging/azwebpubsub/client_custom.go | 14 +++++++++----- .../{healthapi_client.go => health_client.go} | 19 +++++++++---------- ...ient_custom.go => health_client_custom.go} | 12 ++++++------ ...i_client_test.go => health_client_test.go} | 16 ++++++++-------- sdk/messaging/azwebpubsub/options.go | 4 ++-- sdk/messaging/azwebpubsub/response_types.go | 4 ++-- 7 files changed, 40 insertions(+), 33 deletions(-) rename sdk/messaging/azwebpubsub/{healthapi_client.go => health_client.go} (65%) rename sdk/messaging/azwebpubsub/{healthapi_client_custom.go => health_client_custom.go} (62%) rename sdk/messaging/azwebpubsub/{healthapi_client_test.go => health_client_test.go} (82%) diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index 7dee89e40b55..9fb0220898c5 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -12,6 +12,10 @@ openapi-type: "data-plane" output-folder: ../azwebpubsub use: "@autorest/go@4.0.0-preview.60" directive: + # Rename HealthAPI to Health + - from: swagger-document + where: '$.paths["/api/health"].head' + transform: $.operationId = "Health_GetServiceStatus"; # Rename enum WebPubSubPermission to Permission since the package name already contains WebPubSub. - from: - constants.go diff --git a/sdk/messaging/azwebpubsub/client_custom.go b/sdk/messaging/azwebpubsub/client_custom.go index f87ebc77191e..122f237c286f 100644 --- a/sdk/messaging/azwebpubsub/client_custom.go +++ b/sdk/messaging/azwebpubsub/client_custom.go @@ -88,8 +88,8 @@ type GenerateClientAccessURLOptions struct { // More info: https://azure.github.io/azure-webpubsub/references/pubsub-websocket-subprotocol#permissions Roles []string - // ExpirationTimeInMinutes is the number of minutes until the token expires. - ExpirationTimeInMinutes *int32 + // ExpirationTimeInMinutes is the number of minutes until the token expires. Default value(60 minutes) is used if the value is 0. + ExpirationTimeInMinutes int32 // Groups are the groups to join when the client connects. Groups []string @@ -138,7 +138,7 @@ func (c *Client) GenerateClientAccessURL(ctx context.Context, hub string, option userId = &options.UserID } // Replace with your logic to generate the token using a webPubSub method - resp, err := c.generateClientToken(ctx, hub, &ClientGenerateClientTokenOptions{UserID: userId, Role: options.Roles, Group: options.Groups, MinutesToExpire: options.ExpirationTimeInMinutes}) + resp, err := c.generateClientToken(ctx, hub, &ClientGenerateClientTokenOptions{UserID: userId, Role: options.Roles, Group: options.Groups, MinutesToExpire: &options.ExpirationTimeInMinutes}) if err != nil { return nil, err } @@ -159,10 +159,14 @@ func (c *Client) signJwtToken(audience string, options *GenerateClientAccessURLO } key := []byte(*c.key) var exp int64 - if options == nil || options.ExpirationTimeInMinutes == nil { + + if options == nil || options.ExpirationTimeInMinutes == 0 { exp = time.Now().Add(defaultExpirationTime).Unix() } else { - exp = time.Now().Add(time.Minute * time.Duration(*options.ExpirationTimeInMinutes)).Unix() + if options.ExpirationTimeInMinutes < 0 { + return "", errors.New("the value of ExpirationTimeInMinutes is out of range") + } + exp = time.Now().Add(time.Minute * time.Duration(options.ExpirationTimeInMinutes)).Unix() } claims := jwt.MapClaims{ "aud": audience, diff --git a/sdk/messaging/azwebpubsub/healthapi_client.go b/sdk/messaging/azwebpubsub/health_client.go similarity index 65% rename from sdk/messaging/azwebpubsub/healthapi_client.go rename to sdk/messaging/azwebpubsub/health_client.go index 5dfe0ea2427b..54750152742f 100644 --- a/sdk/messaging/azwebpubsub/healthapi_client.go +++ b/sdk/messaging/azwebpubsub/health_client.go @@ -16,9 +16,9 @@ import ( "net/http" ) -// HealthAPIClient contains the methods for the HealthAPI group. +// HealthClient contains the methods for the Health group. // Don't use this type directly, use a constructor function instead. -type HealthAPIClient struct { +type HealthClient struct { internal *azcore.Client endpoint string } @@ -27,27 +27,26 @@ type HealthAPIClient struct { // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2023-07-01 -// - options - HealthAPIClientGetServiceStatusOptions contains the optional parameters for the HealthAPIClient.GetServiceStatus -// method. -func (client *HealthAPIClient) GetServiceStatus(ctx context.Context, options *HealthAPIClientGetServiceStatusOptions) (HealthAPIClientGetServiceStatusResponse, error) { +// - options - HealthClientGetServiceStatusOptions contains the optional parameters for the HealthClient.GetServiceStatus method. +func (client *HealthClient) GetServiceStatus(ctx context.Context, options *HealthClientGetServiceStatusOptions) (HealthClientGetServiceStatusResponse, error) { var err error req, err := client.getServiceStatusCreateRequest(ctx, options) if err != nil { - return HealthAPIClientGetServiceStatusResponse{}, err + return HealthClientGetServiceStatusResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return HealthAPIClientGetServiceStatusResponse{}, err + return HealthClientGetServiceStatusResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK) { err = runtime.NewResponseError(httpResp) - return HealthAPIClientGetServiceStatusResponse{}, err + return HealthClientGetServiceStatusResponse{}, err } - return HealthAPIClientGetServiceStatusResponse{}, nil + return HealthClientGetServiceStatusResponse{}, nil } // getServiceStatusCreateRequest creates the GetServiceStatus request. -func (client *HealthAPIClient) getServiceStatusCreateRequest(ctx context.Context, options *HealthAPIClientGetServiceStatusOptions) (*policy.Request, error) { +func (client *HealthClient) getServiceStatusCreateRequest(ctx context.Context, options *HealthClientGetServiceStatusOptions) (*policy.Request, error) { urlPath := "/api/health" req, err := runtime.NewRequest(ctx, http.MethodHead, runtime.JoinPaths(client.endpoint, urlPath)) if err != nil { diff --git a/sdk/messaging/azwebpubsub/healthapi_client_custom.go b/sdk/messaging/azwebpubsub/health_client_custom.go similarity index 62% rename from sdk/messaging/azwebpubsub/healthapi_client_custom.go rename to sdk/messaging/azwebpubsub/health_client_custom.go index 02bfa34ee9e4..e98f06ac2564 100644 --- a/sdk/messaging/azwebpubsub/healthapi_client_custom.go +++ b/sdk/messaging/azwebpubsub/health_client_custom.go @@ -12,15 +12,15 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" ) -// HealthAPIClientOptions contains optional settings for [HealthAPIClient] -type HealthAPIClientOptions struct { +// HealthClientOptions contains optional settings for [HealthClient] +type HealthClientOptions struct { azcore.ClientOptions } -// NewHealthAPIClient creates a client that checks the healthy status of Web PubSub service -func NewHealthAPIClient(endpoint string, options *HealthAPIClientOptions) (*HealthAPIClient, error) { +// NewHealthClientWithNoCredentials creates a client that checks the healthy status of Web PubSub service +func NewHealthClientWithNoCredentials(endpoint string, options *HealthClientOptions) (*HealthClient, error) { if options == nil { - options = &HealthAPIClientOptions{} + options = &HealthClientOptions{} } azcoreClient, err := azcore.NewClient(internal.ModuleName, internal.ModuleVersion, runtime.PipelineOptions{}, &options.ClientOptions) @@ -28,7 +28,7 @@ func NewHealthAPIClient(endpoint string, options *HealthAPIClientOptions) (*Heal return nil, err } - return &HealthAPIClient{ + return &HealthClient{ internal: azcoreClient, endpoint: endpoint, }, nil diff --git a/sdk/messaging/azwebpubsub/healthapi_client_test.go b/sdk/messaging/azwebpubsub/health_client_test.go similarity index 82% rename from sdk/messaging/azwebpubsub/healthapi_client_test.go rename to sdk/messaging/azwebpubsub/health_client_test.go index 9726aff1d583..421f113e15f7 100644 --- a/sdk/messaging/azwebpubsub/healthapi_client_test.go +++ b/sdk/messaging/azwebpubsub/health_client_test.go @@ -20,13 +20,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestHealthAPIClient_GetServiceStatus(t *testing.T) { +func TestHealthClient_GetServiceStatus(t *testing.T) { if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { t.Skip() } - client := getHealthAPIClient(t) - _, err := client.GetServiceStatus(context.Background(), &azwebpubsub.HealthAPIClientGetServiceStatusOptions{}) + client := getHealthClient(t) + _, err := client.GetServiceStatus(context.Background(), &azwebpubsub.HealthClientGetServiceStatusOptions{}) require.NoError(t, err) } @@ -44,8 +44,8 @@ func loadEndpointFromEnv() (string, error) { return "", nil } -func getHealthAPIClient(t *testing.T) *azwebpubsub.HealthAPIClient { - var options *azwebpubsub.HealthAPIClientOptions +func getHealthClient(t *testing.T) *azwebpubsub.HealthClient { + var options *azwebpubsub.HealthClientOptions var endpoint string if recording.GetRecordMode() != recording.PlaybackMode { tmpEndpoint, err := loadEndpointFromEnv() @@ -70,7 +70,7 @@ func getHealthAPIClient(t *testing.T) *azwebpubsub.HealthAPIClient { } httpClient := &http.Client{Transport: tp} - options = &azwebpubsub.HealthAPIClientOptions{ + options = &azwebpubsub.HealthClientOptions{ ClientOptions: azcore.ClientOptions{ Transport: httpClient, }, @@ -79,14 +79,14 @@ func getHealthAPIClient(t *testing.T) *azwebpubsub.HealthAPIClient { options = nil } } else { - options = &azwebpubsub.HealthAPIClientOptions{ + options = &azwebpubsub.HealthClientOptions{ ClientOptions: azcore.ClientOptions{ Transport: newRecordingTransporter(t, testVars{Endpoint: endpoint}), }, } } - client, err := azwebpubsub.NewHealthAPIClient("https://lianwei-test-1.webpubsub.azure.com", options) + client, err := azwebpubsub.NewHealthClientWithNoCredentials("https://lianwei-test-1.webpubsub.azure.com", options) require.NoError(t, err) return client } diff --git a/sdk/messaging/azwebpubsub/options.go b/sdk/messaging/azwebpubsub/options.go index d60c8643c758..9c6fc5bf3962 100644 --- a/sdk/messaging/azwebpubsub/options.go +++ b/sdk/messaging/azwebpubsub/options.go @@ -184,8 +184,8 @@ type ClientUserExistsOptions struct { // placeholder for future optional parameters } -// HealthAPIClientGetServiceStatusOptions contains the optional parameters for the HealthAPIClient.GetServiceStatus method. -type HealthAPIClientGetServiceStatusOptions struct { +// HealthClientGetServiceStatusOptions contains the optional parameters for the HealthClient.GetServiceStatus method. +type HealthClientGetServiceStatusOptions struct { // placeholder for future optional parameters } diff --git a/sdk/messaging/azwebpubsub/response_types.go b/sdk/messaging/azwebpubsub/response_types.go index bdcabd1982be..e384ffad4596 100644 --- a/sdk/messaging/azwebpubsub/response_types.go +++ b/sdk/messaging/azwebpubsub/response_types.go @@ -124,8 +124,8 @@ type ClientUserExistsResponse struct { // placeholder for future response values } -// HealthAPIClientGetServiceStatusResponse contains the response from method HealthAPIClient.GetServiceStatus. -type HealthAPIClientGetServiceStatusResponse struct { +// HealthClientGetServiceStatusResponse contains the response from method HealthClient.GetServiceStatus. +type HealthClientGetServiceStatusResponse struct { // placeholder for future response values } From be5c1006e21494b54d4cbfb1475b7b9cfdfc9c99 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Wed, 15 Nov 2023 17:05:37 +0800 Subject: [PATCH 12/28] Adding recording --- .../azwebpubsub/client_shared_test.go | 44 ++++++---- sdk/messaging/azwebpubsub/client_test.go | 1 - .../azwebpubsub/health_client_test.go | 69 ++------------- .../testdata/recordings/TestDummy.json | 4 + .../TestClient_CloseConnections.json | 84 +++++++++++++++++++ .../TestClient_ManagePermissions.json | 53 ++++++++++++ .../recordings/TestClient_SendToAll.json | 71 ++++++++++++++++ .../TestHealthClient_GetServiceStatus.json | 20 +++++ 8 files changed, 265 insertions(+), 81 deletions(-) create mode 100644 sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json create mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json create mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json create mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json create mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json diff --git a/sdk/messaging/azwebpubsub/client_shared_test.go b/sdk/messaging/azwebpubsub/client_shared_test.go index c2b872a82fc5..a5abc7d405b5 100644 --- a/sdk/messaging/azwebpubsub/client_shared_test.go +++ b/sdk/messaging/azwebpubsub/client_shared_test.go @@ -27,7 +27,6 @@ type clientWrapper struct { var fakeTestVars = testVars{ ConnectionString: "Endpoint=https://fake.eastus-1.webpubsub.azure.com;AccessKey=ABCDE;", - Endpoint: "https://fake.eastus-1.webpubsub.azure.com", } type testVars struct { @@ -69,10 +68,9 @@ func loadEnv() (testVars, error) { return tv, nil } -func newClientWrapper(t *testing.T) clientWrapper { - var client *azwebpubsub.Client +func loadClientOptions(t *testing.T) (testVars, *azcore.ClientOptions) { var tv testVars - var options *azwebpubsub.ClientOptions + var options *azcore.ClientOptions if recording.GetRecordMode() != recording.PlaybackMode { tmpTestVars, err := loadEnv() require.NoError(t, err) @@ -81,6 +79,15 @@ func newClientWrapper(t *testing.T) clientWrapper { tv = fakeTestVars } + if tv.ConnectionString != "" { + props, err := internal.ParseConnectionString(tv.ConnectionString) + require.NoError(t, err) + // always use ConnectionString's Endpoint if it is set + tv.Endpoint = props.Endpoint + } + + require.NotEmpty(t, tv.Endpoint) + if recording.GetRecordMode() == recording.LiveMode { if tv.KeyLogPath != "" { keyLogWriter, err := os.OpenFile(tv.KeyLogPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777) @@ -94,22 +101,27 @@ func newClientWrapper(t *testing.T) clientWrapper { } httpClient := &http.Client{Transport: tp} - options = &azwebpubsub.ClientOptions{ - ClientOptions: azcore.ClientOptions{ - Transport: httpClient, - }, + options = &azcore.ClientOptions{ + Transport: httpClient, } } else { options = nil } } else { - options = &azwebpubsub.ClientOptions{ - ClientOptions: azcore.ClientOptions{ - Transport: newRecordingTransporter(t, tv), - }, + options = &azcore.ClientOptions{ + Transport: newRecordingTransporter(t, tv), } } + return tv, options +} + +func newClientWrapper(t *testing.T) clientWrapper { + var client *azwebpubsub.Client + tv, coreOptions := loadClientOptions(t) + options := &azwebpubsub.ClientOptions{ + ClientOptions: *coreOptions, + } if tv.ConnectionString != "" { tmpClient, err := azwebpubsub.NewClientFromConnectionString(tv.ConnectionString, options) require.NoError(t, err) @@ -135,14 +147,10 @@ func newRecordingTransporter(t *testing.T, testVars testVars) policy.Transporter err = recording.Start(t, "sdk/messaging/azwebpubsub/testdata", nil) require.NoError(t, err) - - // err = recording.ResetProxy(nil) - // require.NoError(t, err) - props, _ := internal.ParseConnectionString(testVars.ConnectionString) - err = recording.AddURISanitizer("https://fake_endpoint.com", props.Endpoint, nil) + err = recording.AddURISanitizer("https://fake_endpoint.com/", testVars.Endpoint, nil) require.NoError(t, err) - err = recording.AddGeneralRegexSanitizer(`"time": "2023-11-31T00:33:32Z"`, `"time":".+?"`, nil) + err = recording.AddGeneralRegexSanitizer(`"Date": "Wed, 15 Nov 2023 08:00:00 GMT"`, `"Date":".+?"`, nil) require.NoError(t, err) err = recording.AddGeneralRegexSanitizer( diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index a41982ef2c6e..31de67c81ebc 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -48,7 +48,6 @@ func TestClient_ManagePermissions(t *testing.T) { if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { t.Skip() } - client := newClientWrapper(t) const hub = "chat" const conn1 = "conn1" diff --git a/sdk/messaging/azwebpubsub/health_client_test.go b/sdk/messaging/azwebpubsub/health_client_test.go index 421f113e15f7..7bb712ef728b 100644 --- a/sdk/messaging/azwebpubsub/health_client_test.go +++ b/sdk/messaging/azwebpubsub/health_client_test.go @@ -8,15 +8,10 @@ package azwebpubsub_test import ( "context" - "crypto/tls" - "net/http" - "os" "testing" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" "github.com/stretchr/testify/require" ) @@ -25,68 +20,18 @@ func TestHealthClient_GetServiceStatus(t *testing.T) { t.Skip() } - client := getHealthClient(t) + client := newHealthClient(t) _, err := client.GetServiceStatus(context.Background(), &azwebpubsub.HealthClientGetServiceStatusOptions{}) require.NoError(t, err) } -func loadEndpointFromEnv() (string, error) { - if v := os.Getenv("WEBPUBSUB_ENDPOINT"); v != "" { - return v, nil +func newHealthClient(t *testing.T) *azwebpubsub.HealthClient { + tv, coreOptions := loadClientOptions(t) + options := &azwebpubsub.HealthClientOptions{ + ClientOptions: *coreOptions, } - if v := os.Getenv("WEBPUBSUB_CONNECTIONSTRING"); v != "" { - props, err := internal.ParseConnectionString(v) - if err != nil { - return "", err - } - return props.Endpoint, nil - } - return "", nil -} - -func getHealthClient(t *testing.T) *azwebpubsub.HealthClient { - var options *azwebpubsub.HealthClientOptions - var endpoint string - if recording.GetRecordMode() != recording.PlaybackMode { - tmpEndpoint, err := loadEndpointFromEnv() - require.NoError(t, err) - require.NotEmpty(t, tmpEndpoint) - endpoint = tmpEndpoint - } else { - endpoint = "https://fake.eastus-1.webpubsub.azure.com" - } - - if recording.GetRecordMode() == recording.LiveMode { - keyLogPath := os.Getenv("SSLKEYLOGFILE") - if keyLogPath != "" { - keyLogWriter, err := os.OpenFile(keyLogPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777) - require.NoError(t, err) - - t.Cleanup(func() { keyLogWriter.Close() }) - - tp := http.DefaultTransport.(*http.Transport).Clone() - tp.TLSClientConfig = &tls.Config{ - KeyLogWriter: keyLogWriter, - } - - httpClient := &http.Client{Transport: tp} - options = &azwebpubsub.HealthClientOptions{ - ClientOptions: azcore.ClientOptions{ - Transport: httpClient, - }, - } - } else { - options = nil - } - } else { - options = &azwebpubsub.HealthClientOptions{ - ClientOptions: azcore.ClientOptions{ - Transport: newRecordingTransporter(t, testVars{Endpoint: endpoint}), - }, - } - } - - client, err := azwebpubsub.NewHealthClientWithNoCredentials("https://lianwei-test-1.webpubsub.azure.com", options) + println(tv.Endpoint) + client, err := azwebpubsub.NewHealthClientWithNoCredentials(tv.Endpoint, options) require.NoError(t, err) return client } diff --git a/sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json b/sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json new file mode 100644 index 000000000000..f721723386d8 --- /dev/null +++ b/sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json @@ -0,0 +1,4 @@ +{ + "Entries": [], + "Variables": {} +} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json new file mode 100644 index 000000000000..4f652e6f7bcb --- /dev/null +++ b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json @@ -0,0 +1,84 @@ +{ + "Entries": [ + { + "RequestUri": "https://fake_endpoint.com/api/hubs/chat/:closeConnections?api-version=2023-07-01\u0026excluded=conn1\u0026reason=TestClient_CloseConnections", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "Content-Length": "0", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": null, + "StatusCode": 204, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Date": "Wed, 15 Nov 2023 08:03:57 GMT", + "Server": "nginx" + }, + "ResponseBody": null + }, + { + "RequestUri": "https://fake_endpoint.com/api/hubs/chat/connections/conn1?api-version=2023-07-01\u0026reason=TestClient_CloseConnections", + "RequestMethod": "DELETE", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": null, + "StatusCode": 204, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Date": "Wed, 15 Nov 2023 08:03:58 GMT", + "Server": "nginx" + }, + "ResponseBody": null + }, + { + "RequestUri": "https://fake_endpoint.com/api/hubs/chat/groups/group1/:closeConnections?api-version=2023-07-01\u0026excluded=conn1\u0026reason=TestClient_CloseConnections", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "Content-Length": "0", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": null, + "StatusCode": 204, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Date": "Wed, 15 Nov 2023 08:03:58 GMT", + "Server": "nginx" + }, + "ResponseBody": null + }, + { + "RequestUri": "https://fake_endpoint.com/api/hubs/chat/users/user1/:closeConnections?api-version=2023-07-01\u0026excluded=conn1\u0026reason=TestClient_CloseConnections", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "Content-Length": "0", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": null, + "StatusCode": 204, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Date": "Wed, 15 Nov 2023 08:03:58 GMT", + "Server": "nginx" + }, + "ResponseBody": null + } + ], + "Variables": {} +} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json new file mode 100644 index 000000000000..17444a0babbf --- /dev/null +++ b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json @@ -0,0 +1,53 @@ +{ + "Entries": [ + { + "RequestUri": "https://fake_endpoint.com/api/hubs/chat/permissions/joinLeaveGroup/connections/conn1?api-version=2023-07-01\u0026targetName=group1", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "Content-Length": "0", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": null, + "StatusCode": 404, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Content-Length": "137", + "Content-Type": "application/json; charset=utf-8", + "Date": "Wed, 15 Nov 2023 08:03:57 GMT", + "Server": "nginx", + "x-ms-error-code": "Info.Connection.NotExisted" + }, + "ResponseBody": { + "code": "Info.Connection.NotExisted", + "message": "Connection \u0060conn1\u0060 is not found.", + "target": "Connection", + "details": null, + "innererror": null + } + }, + { + "RequestUri": "https://fake_endpoint.com/api/hubs/chat/permissions/joinLeaveGroup/connections/conn1?api-version=2023-07-01\u0026targetName=group1", + "RequestMethod": "DELETE", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": null, + "StatusCode": 204, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Date": "Wed, 15 Nov 2023 08:03:57 GMT", + "Server": "nginx" + }, + "ResponseBody": null + } + ], + "Variables": {} +} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json new file mode 100644 index 000000000000..31da4879d847 --- /dev/null +++ b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json @@ -0,0 +1,71 @@ +{ + "Entries": [ + { + "RequestUri": "https://fake_endpoint.com/api/hubs/hub1/:send?api-version=2023-07-01", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "Content-Length": "12", + "Content-Type": "text/plain", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": "Hello world!", + "StatusCode": 202, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Content-Length": "0", + "Date": "Wed, 15 Nov 2023 08:03:54 GMT", + "Server": "nginx" + }, + "ResponseBody": null + }, + { + "RequestUri": "https://fake_endpoint.com/api/hubs/hub1/:send?api-version=2023-07-01", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "Content-Length": "4", + "Content-Type": "application/json", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": true, + "StatusCode": 202, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Content-Length": "0", + "Date": "Wed, 15 Nov 2023 08:03:55 GMT", + "Server": "nginx" + }, + "ResponseBody": null + }, + { + "RequestUri": "https://fake_endpoint.com/api/hubs/hub1/:send?api-version=2023-07-01", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "Authorization": "Sanitized", + "Content-Length": "4", + "Content-Type": "application/octet-stream", + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": "dHJ1ZQ==", + "StatusCode": 202, + "ResponseHeaders": { + "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", + "Connection": "keep-alive", + "Content-Length": "0", + "Date": "Wed, 15 Nov 2023 08:03:55 GMT", + "Server": "nginx" + }, + "ResponseBody": null + } + ], + "Variables": {} +} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json new file mode 100644 index 000000000000..46432d7606d6 --- /dev/null +++ b/sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json @@ -0,0 +1,20 @@ +{ + "Entries": [ + { + "RequestUri": "https://fake_endpoint.com/api/health?api-version=2023-07-01", + "RequestMethod": "HEAD", + "RequestHeaders": { + "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Connection": "keep-alive", + "Date": "Wed, 15 Nov 2023 08:03:59 GMT", + "Server": "nginx" + }, + "ResponseBody": null + } + ], + "Variables": {} +} From 9abb7daaa8c311b7c5789019a7431847db2118e0 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Thu, 16 Nov 2023 16:43:26 +0800 Subject: [PATCH 13/28] Use asset repo --- sdk/messaging/azwebpubsub/assets.json | 6 ++ .../testdata/recordings/TestDummy.json | 4 - .../TestClient_CloseConnections.json | 84 ------------------- .../TestClient_ManagePermissions.json | 53 ------------ .../recordings/TestClient_SendToAll.json | 71 ---------------- .../TestHealthClient_GetServiceStatus.json | 20 ----- 6 files changed, 6 insertions(+), 232 deletions(-) create mode 100644 sdk/messaging/azwebpubsub/assets.json delete mode 100644 sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json delete mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json delete mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json delete mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json delete mode 100644 sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json diff --git a/sdk/messaging/azwebpubsub/assets.json b/sdk/messaging/azwebpubsub/assets.json new file mode 100644 index 000000000000..22cfa27c00cf --- /dev/null +++ b/sdk/messaging/azwebpubsub/assets.json @@ -0,0 +1,6 @@ +{ + "AssetsRepo": "Azure/azure-sdk-assets", + "AssetsRepoPrefixPath": "go", + "TagPrefix": "go/messaging/azwebpubsub", + "Tag": "go/messaging/azwebpubsub_94be93d99b" +} diff --git a/sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json b/sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json deleted file mode 100644 index f721723386d8..000000000000 --- a/sdk/messaging/azwebpubsub/sdk/messaging/azwebpubsub/testdata/recordings/TestDummy.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Entries": [], - "Variables": {} -} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json deleted file mode 100644 index 4f652e6f7bcb..000000000000 --- a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_CloseConnections.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "Entries": [ - { - "RequestUri": "https://fake_endpoint.com/api/hubs/chat/:closeConnections?api-version=2023-07-01\u0026excluded=conn1\u0026reason=TestClient_CloseConnections", - "RequestMethod": "POST", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "Content-Length": "0", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": null, - "StatusCode": 204, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Date": "Wed, 15 Nov 2023 08:03:57 GMT", - "Server": "nginx" - }, - "ResponseBody": null - }, - { - "RequestUri": "https://fake_endpoint.com/api/hubs/chat/connections/conn1?api-version=2023-07-01\u0026reason=TestClient_CloseConnections", - "RequestMethod": "DELETE", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": null, - "StatusCode": 204, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Date": "Wed, 15 Nov 2023 08:03:58 GMT", - "Server": "nginx" - }, - "ResponseBody": null - }, - { - "RequestUri": "https://fake_endpoint.com/api/hubs/chat/groups/group1/:closeConnections?api-version=2023-07-01\u0026excluded=conn1\u0026reason=TestClient_CloseConnections", - "RequestMethod": "POST", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "Content-Length": "0", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": null, - "StatusCode": 204, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Date": "Wed, 15 Nov 2023 08:03:58 GMT", - "Server": "nginx" - }, - "ResponseBody": null - }, - { - "RequestUri": "https://fake_endpoint.com/api/hubs/chat/users/user1/:closeConnections?api-version=2023-07-01\u0026excluded=conn1\u0026reason=TestClient_CloseConnections", - "RequestMethod": "POST", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "Content-Length": "0", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": null, - "StatusCode": 204, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Date": "Wed, 15 Nov 2023 08:03:58 GMT", - "Server": "nginx" - }, - "ResponseBody": null - } - ], - "Variables": {} -} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json deleted file mode 100644 index 17444a0babbf..000000000000 --- a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_ManagePermissions.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "Entries": [ - { - "RequestUri": "https://fake_endpoint.com/api/hubs/chat/permissions/joinLeaveGroup/connections/conn1?api-version=2023-07-01\u0026targetName=group1", - "RequestMethod": "PUT", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "Content-Length": "0", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": null, - "StatusCode": 404, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Content-Length": "137", - "Content-Type": "application/json; charset=utf-8", - "Date": "Wed, 15 Nov 2023 08:03:57 GMT", - "Server": "nginx", - "x-ms-error-code": "Info.Connection.NotExisted" - }, - "ResponseBody": { - "code": "Info.Connection.NotExisted", - "message": "Connection \u0060conn1\u0060 is not found.", - "target": "Connection", - "details": null, - "innererror": null - } - }, - { - "RequestUri": "https://fake_endpoint.com/api/hubs/chat/permissions/joinLeaveGroup/connections/conn1?api-version=2023-07-01\u0026targetName=group1", - "RequestMethod": "DELETE", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": null, - "StatusCode": 204, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Date": "Wed, 15 Nov 2023 08:03:57 GMT", - "Server": "nginx" - }, - "ResponseBody": null - } - ], - "Variables": {} -} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json deleted file mode 100644 index 31da4879d847..000000000000 --- a/sdk/messaging/azwebpubsub/testdata/recordings/TestClient_SendToAll.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "Entries": [ - { - "RequestUri": "https://fake_endpoint.com/api/hubs/hub1/:send?api-version=2023-07-01", - "RequestMethod": "POST", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "Content-Length": "12", - "Content-Type": "text/plain", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": "Hello world!", - "StatusCode": 202, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Content-Length": "0", - "Date": "Wed, 15 Nov 2023 08:03:54 GMT", - "Server": "nginx" - }, - "ResponseBody": null - }, - { - "RequestUri": "https://fake_endpoint.com/api/hubs/hub1/:send?api-version=2023-07-01", - "RequestMethod": "POST", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "Content-Length": "4", - "Content-Type": "application/json", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": true, - "StatusCode": 202, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Content-Length": "0", - "Date": "Wed, 15 Nov 2023 08:03:55 GMT", - "Server": "nginx" - }, - "ResponseBody": null - }, - { - "RequestUri": "https://fake_endpoint.com/api/hubs/hub1/:send?api-version=2023-07-01", - "RequestMethod": "POST", - "RequestHeaders": { - "Accept": "application/json", - "Accept-Encoding": "gzip", - "Authorization": "Sanitized", - "Content-Length": "4", - "Content-Type": "application/octet-stream", - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": "dHJ1ZQ==", - "StatusCode": 202, - "ResponseHeaders": { - "api-supported-versions": "2021-10-01, 2022-11-01, 2023-07-01", - "Connection": "keep-alive", - "Content-Length": "0", - "Date": "Wed, 15 Nov 2023 08:03:55 GMT", - "Server": "nginx" - }, - "ResponseBody": null - } - ], - "Variables": {} -} diff --git a/sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json b/sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json deleted file mode 100644 index 46432d7606d6..000000000000 --- a/sdk/messaging/azwebpubsub/testdata/recordings/TestHealthClient_GetServiceStatus.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "Entries": [ - { - "RequestUri": "https://fake_endpoint.com/api/health?api-version=2023-07-01", - "RequestMethod": "HEAD", - "RequestHeaders": { - "User-Agent": "azsdk-go-azwebpubsub/v0.1.0 (go1.21.0; Windows_NT)" - }, - "RequestBody": null, - "StatusCode": 200, - "ResponseHeaders": { - "Connection": "keep-alive", - "Date": "Wed, 15 Nov 2023 08:03:59 GMT", - "Server": "nginx" - }, - "ResponseBody": null - } - ], - "Variables": {} -} From ee72d15d6338c1e8f26064fe615af2c1ae1b2eff Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Fri, 17 Nov 2023 10:32:59 +0800 Subject: [PATCH 14/28] Remove skip --- sdk/messaging/azwebpubsub/client_test.go | 12 ------------ sdk/messaging/azwebpubsub/health_client_test.go | 5 ----- 2 files changed, 17 deletions(-) diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index 31de67c81ebc..ccf185a16610 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -15,17 +15,12 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" - "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" "github.com/golang-jwt/jwt" "github.com/stretchr/testify/require" ) func TestClient_SendToAll(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { - t.Skip() - } - client := newClientWrapper(t) hub := "hub1" _, err := client.SendToAll(context.Background(), hub, @@ -45,9 +40,6 @@ func TestClient_SendToAll(t *testing.T) { } func TestClient_ManagePermissions(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { - t.Skip() - } client := newClientWrapper(t) const hub = "chat" const conn1 = "conn1" @@ -63,10 +55,6 @@ func TestClient_ManagePermissions(t *testing.T) { } func TestClient_CloseConnections(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { - t.Skip() - } - client := newClientWrapper(t) const hub = "chat" const conn1 = "conn1" diff --git a/sdk/messaging/azwebpubsub/health_client_test.go b/sdk/messaging/azwebpubsub/health_client_test.go index 7bb712ef728b..9515fd70c79d 100644 --- a/sdk/messaging/azwebpubsub/health_client_test.go +++ b/sdk/messaging/azwebpubsub/health_client_test.go @@ -10,16 +10,11 @@ import ( "context" "testing" - "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" "github.com/stretchr/testify/require" ) func TestHealthClient_GetServiceStatus(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode || testing.Short() { - t.Skip() - } - client := newHealthClient(t) _, err := client.GetServiceStatus(context.Background(), &azwebpubsub.HealthClientGetServiceStatusOptions{}) require.NoError(t, err) From 273311aec8c0b797d7d66915a17d023b05b48323 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Fri, 17 Nov 2023 10:48:05 +0800 Subject: [PATCH 15/28] Fix comment --- sdk/messaging/azwebpubsub/health_client_custom.go | 4 ++-- sdk/messaging/azwebpubsub/health_client_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/messaging/azwebpubsub/health_client_custom.go b/sdk/messaging/azwebpubsub/health_client_custom.go index e98f06ac2564..4e5f647c1653 100644 --- a/sdk/messaging/azwebpubsub/health_client_custom.go +++ b/sdk/messaging/azwebpubsub/health_client_custom.go @@ -17,8 +17,8 @@ type HealthClientOptions struct { azcore.ClientOptions } -// NewHealthClientWithNoCredentials creates a client that checks the healthy status of Web PubSub service -func NewHealthClientWithNoCredentials(endpoint string, options *HealthClientOptions) (*HealthClient, error) { +// NewHealthClientWithNoCredential creates a client that checks the healthy status of Web PubSub service +func NewHealthClientWithNoCredential(endpoint string, options *HealthClientOptions) (*HealthClient, error) { if options == nil { options = &HealthClientOptions{} } diff --git a/sdk/messaging/azwebpubsub/health_client_test.go b/sdk/messaging/azwebpubsub/health_client_test.go index 9515fd70c79d..4cfd13ccbd72 100644 --- a/sdk/messaging/azwebpubsub/health_client_test.go +++ b/sdk/messaging/azwebpubsub/health_client_test.go @@ -26,7 +26,7 @@ func newHealthClient(t *testing.T) *azwebpubsub.HealthClient { ClientOptions: *coreOptions, } println(tv.Endpoint) - client, err := azwebpubsub.NewHealthClientWithNoCredentials(tv.Endpoint, options) + client, err := azwebpubsub.NewHealthClientWithNoCredential(tv.Endpoint, options) require.NoError(t, err) return client } From 7aa5b0e50555b47e4df418d929306a37ad1f5917 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Fri, 17 Nov 2023 23:17:23 +0800 Subject: [PATCH 16/28] adding main test logic to start the test-proxy --- sdk/messaging/azwebpubsub/main_test.go | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 sdk/messaging/azwebpubsub/main_test.go diff --git a/sdk/messaging/azwebpubsub/main_test.go b/sdk/messaging/azwebpubsub/main_test.go new file mode 100644 index 000000000000..fe69c91d60c6 --- /dev/null +++ b/sdk/messaging/azwebpubsub/main_test.go @@ -0,0 +1,41 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package azwebpubsub_test + +import ( + "os" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" +) + +const recordingDirectory = "sdk/messaging/azwebpubsub/testdata" + +func TestMain(m *testing.M) { + code := run(m) + os.Exit(code) +} + +func run(m *testing.M) int { + var proxy *recording.TestProxyInstance + if recording.GetRecordMode() == recording.PlaybackMode || recording.GetRecordMode() == recording.RecordingMode { + var err error + proxy, err = recording.StartTestProxy(recordingDirectory, nil) + if err != nil { + panic(err) + } + + defer func() { + err := recording.StopTestProxy(proxy) + if err != nil { + panic(err) + } + }() + } + code := m.Run() + return code +} From 89a59930a3c7a21ee0f278f3a52ecc772a6d95d6 Mon Sep 17 00:00:00 2001 From: "Liangying.Wei" Date: Thu, 30 Nov 2023 09:22:16 +0800 Subject: [PATCH 17/28] update CI settings --- sdk/messaging/azwebpubsub/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/messaging/azwebpubsub/ci.yml b/sdk/messaging/azwebpubsub/ci.yml index 09cc844ff4f1..698ce0feb10e 100644 --- a/sdk/messaging/azwebpubsub/ci.yml +++ b/sdk/messaging/azwebpubsub/ci.yml @@ -21,10 +21,10 @@ pr: paths: include: - sdk/messaging/azwebpubsub/ - - eng/ stages: - template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml parameters: - ServiceDirectory: 'messaging/azwebpubsub/' \ No newline at end of file + ServiceDirectory: 'messaging/azwebpubsub/' + UsePipelineProxy: false \ No newline at end of file From 7ddb1a2da89ec6fa8e8828a8c827c66e12b9750c Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Tue, 5 Dec 2023 13:58:43 +0800 Subject: [PATCH 18/28] Fix test failure --- sdk/messaging/azwebpubsub/autorest.md | 2 +- sdk/messaging/azwebpubsub/client.go | 76 ++++++++++----------- sdk/messaging/azwebpubsub/constants.go | 7 +- sdk/messaging/azwebpubsub/health_client.go | 4 +- sdk/messaging/azwebpubsub/models.go | 5 +- sdk/messaging/azwebpubsub/models_serde.go | 28 ++++---- sdk/messaging/azwebpubsub/options.go | 31 ++++----- sdk/messaging/azwebpubsub/response_types.go | 1 - 8 files changed, 75 insertions(+), 79 deletions(-) diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index 9fb0220898c5..d864342389ca 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -40,6 +40,6 @@ directive: transform: >- return $.replace( /(type Client struct[^}]+})/s, - "type Client struct {\n internal *azcore.Client\n endpoint string\n key *string\n}") + "type Client struct {\n internal *azcore.Client\n endpoint string\n key *string\n}") ``` \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/client.go b/sdk/messaging/azwebpubsub/client.go index eecf592ff20a..f71b0e4883d2 100644 --- a/sdk/messaging/azwebpubsub/client.go +++ b/sdk/messaging/azwebpubsub/client.go @@ -11,14 +11,15 @@ package azwebpubsub import ( "context" "errors" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "io" "net/http" "net/url" "strconv" "strings" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" ) // Client contains the methods for the WebPubSub group. @@ -26,7 +27,7 @@ import ( type Client struct { internal *azcore.Client endpoint string - key *string + key *string } // AddConnectionToGroup - Add a connection to the target group. @@ -120,8 +121,8 @@ func (client *Client) addConnectionsToGroupsCreateRequest(ctx context.Context, h req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, groupsToAdd); err != nil { - return nil, err -} + return nil, err + } return req, nil } @@ -265,9 +266,9 @@ func (client *Client) closeAllConnectionsCreateRequest(ctx context.Context, hub } reqQP := req.Raw().URL.Query() if options != nil && options.Excluded != nil { - for _, qv := range options.Excluded { - reqQP.Add("excluded", qv) - } + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } } if options != nil && options.Reason != nil { reqQP.Set("reason", *options.Reason) @@ -368,9 +369,9 @@ func (client *Client) closeGroupConnectionsCreateRequest(ctx context.Context, hu } reqQP := req.Raw().URL.Query() if options != nil && options.Excluded != nil { - for _, qv := range options.Excluded { - reqQP.Add("excluded", qv) - } + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } } if options != nil && options.Reason != nil { reqQP.Set("reason", *options.Reason) @@ -422,9 +423,9 @@ func (client *Client) closeUserConnectionsCreateRequest(ctx context.Context, hub } reqQP := req.Raw().URL.Query() if options != nil && options.Excluded != nil { - for _, qv := range options.Excluded { - reqQP.Add("excluded", qv) - } + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } } if options != nil && options.Reason != nil { reqQP.Set("reason", *options.Reason) @@ -520,18 +521,18 @@ func (client *Client) generateClientTokenCreateRequest(ctx context.Context, hub reqQP.Set("userId", *options.UserID) } if options != nil && options.Role != nil { - for _, qv := range options.Role { - reqQP.Add("role", qv) - } + for _, qv := range options.Role { + reqQP.Add("role", qv) + } } if options != nil && options.MinutesToExpire != nil { reqQP.Set("minutesToExpire", strconv.FormatInt(int64(*options.MinutesToExpire), 10)) } reqQP.Set("api-version", "2023-07-01") if options != nil && options.Group != nil { - for _, qv := range options.Group { - reqQP.Add("group", qv) - } + for _, qv := range options.Group { + reqQP.Add("group", qv) + } } req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json, text/json"} @@ -786,8 +787,8 @@ func (client *Client) removeConnectionsFromGroupsCreateRequest(ctx context.Conte req.Raw().URL.RawQuery = reqQP.Encode() req.Raw().Header["Accept"] = []string{"application/json"} if err := runtime.MarshalAsJSON(req, groupsToRemove); err != nil { - return nil, err -} + return nil, err + } return req, nil } @@ -981,9 +982,9 @@ func (client *Client) sendToAllCreateRequest(ctx context.Context, hub string, co } reqQP := req.Raw().URL.Query() if options != nil && options.Excluded != nil { - for _, qv := range options.Excluded { - reqQP.Add("excluded", qv) - } + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } } reqQP.Set("api-version", "2023-07-01") if options != nil && options.Filter != nil { @@ -996,8 +997,8 @@ func (client *Client) sendToAllCreateRequest(ctx context.Context, hub string, co req.Raw().Header["Content-Type"] = []string{string(contentType)} req.Raw().Header["Accept"] = []string{"application/json"} if err := req.SetBody(message, string(contentType)); err != nil { - return nil, err -} + return nil, err + } return req, nil } @@ -1051,8 +1052,8 @@ func (client *Client) sendToConnectionCreateRequest(ctx context.Context, hub str req.Raw().Header["Content-Type"] = []string{string(contentType)} req.Raw().Header["Accept"] = []string{"application/json"} if err := req.SetBody(message, string(contentType)); err != nil { - return nil, err -} + return nil, err + } return req, nil } @@ -1099,9 +1100,9 @@ func (client *Client) sendToGroupCreateRequest(ctx context.Context, hub string, } reqQP := req.Raw().URL.Query() if options != nil && options.Excluded != nil { - for _, qv := range options.Excluded { - reqQP.Add("excluded", qv) - } + for _, qv := range options.Excluded { + reqQP.Add("excluded", qv) + } } reqQP.Set("api-version", "2023-07-01") if options != nil && options.Filter != nil { @@ -1114,8 +1115,8 @@ func (client *Client) sendToGroupCreateRequest(ctx context.Context, hub string, req.Raw().Header["Content-Type"] = []string{string(contentType)} req.Raw().Header["Accept"] = []string{"application/json"} if err := req.SetBody(message, string(contentType)); err != nil { - return nil, err -} + return nil, err + } return req, nil } @@ -1172,8 +1173,8 @@ func (client *Client) sendToUserCreateRequest(ctx context.Context, hub string, u req.Raw().Header["Content-Type"] = []string{string(contentType)} req.Raw().Header["Accept"] = []string{"application/json"} if err := req.SetBody(message, string(contentType)); err != nil { - return nil, err -} + return nil, err + } return req, nil } @@ -1221,4 +1222,3 @@ func (client *Client) userExistsCreateRequest(ctx context.Context, hub string, u req.Raw().URL.RawQuery = reqQP.Encode() return req, nil } - diff --git a/sdk/messaging/azwebpubsub/constants.go b/sdk/messaging/azwebpubsub/constants.go index 4102b36d3800..966b883a4842 100644 --- a/sdk/messaging/azwebpubsub/constants.go +++ b/sdk/messaging/azwebpubsub/constants.go @@ -22,7 +22,7 @@ const ( // PossibleContentTypeValues returns the possible values for the ContentType const type. func PossibleContentTypeValues() []ContentType { - return []ContentType{ + return []ContentType{ ContentTypeApplicationJSON, ContentTypeApplicationOctetStream, ContentTypeTextPlain, @@ -33,14 +33,13 @@ type Permission string const ( PermissionJoinLeaveGroup Permission = "joinLeaveGroup" - PermissionSendToGroup Permission = "sendToGroup" + PermissionSendToGroup Permission = "sendToGroup" ) // PossiblePermissionValues returns the possible values for the Permission const type. func PossiblePermissionValues() []Permission { - return []Permission{ + return []Permission{ PermissionJoinLeaveGroup, PermissionSendToGroup, } } - diff --git a/sdk/messaging/azwebpubsub/health_client.go b/sdk/messaging/azwebpubsub/health_client.go index 54750152742f..f91987c9cbc9 100644 --- a/sdk/messaging/azwebpubsub/health_client.go +++ b/sdk/messaging/azwebpubsub/health_client.go @@ -10,10 +10,11 @@ package azwebpubsub import ( "context" + "net/http" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "net/http" ) // HealthClient contains the methods for the Health group. @@ -57,4 +58,3 @@ func (client *HealthClient) getServiceStatusCreateRequest(ctx context.Context, o req.Raw().URL.RawQuery = reqQP.Encode() return req, nil } - diff --git a/sdk/messaging/azwebpubsub/models.go b/sdk/messaging/azwebpubsub/models.go index 6d2dbc456ac4..0239a812c6ec 100644 --- a/sdk/messaging/azwebpubsub/models.go +++ b/sdk/messaging/azwebpubsub/models.go @@ -30,7 +30,7 @@ type ErrorDetail struct { // An array of details about specific errors that led to this reported error. Details []*ErrorDetail - Inner *InnerError + Inner *InnerError // A human-readable representation of the error. Message *string @@ -41,7 +41,7 @@ type ErrorDetail struct { type InnerError struct { // A more specific error code than was provided by the containing error. - Code *string + Code *string Inner *InnerError } @@ -53,4 +53,3 @@ type RemoveFromGroupsRequest struct { // A list of groups which target connections will be removed from Groups []*string } - diff --git a/sdk/messaging/azwebpubsub/models_serde.go b/sdk/messaging/azwebpubsub/models_serde.go index d81cc40c191b..b641794efe8b 100644 --- a/sdk/messaging/azwebpubsub/models_serde.go +++ b/sdk/messaging/azwebpubsub/models_serde.go @@ -11,8 +11,9 @@ package azwebpubsub import ( "encoding/json" "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "reflect" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" ) // MarshalJSON implements the json.Marshaller interface for type AddToGroupsRequest. @@ -33,10 +34,10 @@ func (a *AddToGroupsRequest) UnmarshalJSON(data []byte) error { var err error switch key { case "filter": - err = unpopulate(val, "Filter", &a.Filter) + err = unpopulate(val, "Filter", &a.Filter) delete(rawMsg, key) case "groups": - err = unpopulate(val, "Groups", &a.Groups) + err = unpopulate(val, "Groups", &a.Groups) delete(rawMsg, key) } if err != nil { @@ -63,7 +64,7 @@ func (c *ClientTokenResponse) UnmarshalJSON(data []byte) error { var err error switch key { case "token": - err = unpopulate(val, "Token", &c.Token) + err = unpopulate(val, "Token", &c.Token) delete(rawMsg, key) } if err != nil { @@ -94,19 +95,19 @@ func (e *ErrorDetail) UnmarshalJSON(data []byte) error { var err error switch key { case "code": - err = unpopulate(val, "Code", &e.Code) + err = unpopulate(val, "Code", &e.Code) delete(rawMsg, key) case "details": - err = unpopulate(val, "Details", &e.Details) + err = unpopulate(val, "Details", &e.Details) delete(rawMsg, key) case "inner": - err = unpopulate(val, "Inner", &e.Inner) + err = unpopulate(val, "Inner", &e.Inner) delete(rawMsg, key) case "message": - err = unpopulate(val, "Message", &e.Message) + err = unpopulate(val, "Message", &e.Message) delete(rawMsg, key) case "target": - err = unpopulate(val, "Target", &e.Target) + err = unpopulate(val, "Target", &e.Target) delete(rawMsg, key) } if err != nil { @@ -134,10 +135,10 @@ func (i *InnerError) UnmarshalJSON(data []byte) error { var err error switch key { case "code": - err = unpopulate(val, "Code", &i.Code) + err = unpopulate(val, "Code", &i.Code) delete(rawMsg, key) case "inner": - err = unpopulate(val, "Inner", &i.Inner) + err = unpopulate(val, "Inner", &i.Inner) delete(rawMsg, key) } if err != nil { @@ -165,10 +166,10 @@ func (r *RemoveFromGroupsRequest) UnmarshalJSON(data []byte) error { var err error switch key { case "filter": - err = unpopulate(val, "Filter", &r.Filter) + err = unpopulate(val, "Filter", &r.Filter) delete(rawMsg, key) case "groups": - err = unpopulate(val, "Groups", &r.Groups) + err = unpopulate(val, "Groups", &r.Groups) delete(rawMsg, key) } if err != nil { @@ -197,4 +198,3 @@ func unpopulate(data json.RawMessage, fn string, v any) error { } return nil } - diff --git a/sdk/messaging/azwebpubsub/options.go b/sdk/messaging/azwebpubsub/options.go index 9c6fc5bf3962..89adb69e5ff4 100644 --- a/sdk/messaging/azwebpubsub/options.go +++ b/sdk/messaging/azwebpubsub/options.go @@ -26,7 +26,7 @@ type ClientAddUserToGroupOptions struct { // ClientCheckPermissionOptions contains the optional parameters for the Client.CheckPermission method. type ClientCheckPermissionOptions struct { // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required -// parameter standing for the group name. + // parameter standing for the group name. TargetName *string } @@ -86,7 +86,7 @@ type ClientGenerateClientTokenOptions struct { // ClientGrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. type ClientGrantPermissionOptions struct { // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required -// parameter standing for the group name. + // parameter standing for the group name. TargetName *string } @@ -124,7 +124,7 @@ type ClientRemoveUserFromGroupOptions struct { // ClientRevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. type ClientRevokePermissionOptions struct { // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required -// parameter standing for the group name. + // parameter standing for the group name. TargetName *string } @@ -137,18 +137,18 @@ type ClientSendToAllOptions struct { Filter *string // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message -// never expires. 300 is the maximum value. If this parameter is non-zero, -// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can -// help when the client's bandwidth is limited. + // never expires. 300 is the maximum value. If this parameter is non-zero, + // messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can + // help when the client's bandwidth is limited. MessageTTLSeconds *int32 } // ClientSendToConnectionOptions contains the optional parameters for the Client.SendToConnection method. type ClientSendToConnectionOptions struct { // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message -// never expires. 300 is the maximum value. If this parameter is non-zero, -// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can -// help when the client's bandwidth is limited. + // never expires. 300 is the maximum value. If this parameter is non-zero, + // messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can + // help when the client's bandwidth is limited. MessageTTLSeconds *int32 } @@ -161,9 +161,9 @@ type ClientSendToGroupOptions struct { Filter *string // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message -// never expires. 300 is the maximum value. If this parameter is non-zero, -// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can -// help when the client's bandwidth is limited. + // never expires. 300 is the maximum value. If this parameter is non-zero, + // messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can + // help when the client's bandwidth is limited. MessageTTLSeconds *int32 } @@ -173,9 +173,9 @@ type ClientSendToUserOptions struct { Filter *string // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message -// never expires. 300 is the maximum value. If this parameter is non-zero, -// messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can -// help when the client's bandwidth is limited. + // never expires. 300 is the maximum value. If this parameter is non-zero, + // messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can + // help when the client's bandwidth is limited. MessageTTLSeconds *int32 } @@ -188,4 +188,3 @@ type ClientUserExistsOptions struct { type HealthClientGetServiceStatusOptions struct { // placeholder for future optional parameters } - diff --git a/sdk/messaging/azwebpubsub/response_types.go b/sdk/messaging/azwebpubsub/response_types.go index e384ffad4596..548734ac7d65 100644 --- a/sdk/messaging/azwebpubsub/response_types.go +++ b/sdk/messaging/azwebpubsub/response_types.go @@ -128,4 +128,3 @@ type ClientUserExistsResponse struct { type HealthClientGetServiceStatusResponse struct { // placeholder for future response values } - From 9374f1c51f72ada236497bbf6b7be6a31ae5dbb0 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Thu, 7 Dec 2023 10:23:37 +0800 Subject: [PATCH 19/28] Update link to temp URL to pass CI --- sdk/messaging/azwebpubsub/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/messaging/azwebpubsub/README.md b/sdk/messaging/azwebpubsub/README.md index f6d36765ef9e..376c40aec973 100644 --- a/sdk/messaging/azwebpubsub/README.md +++ b/sdk/messaging/azwebpubsub/README.md @@ -109,7 +109,7 @@ When the client is connected, it can send messages to the upstream application, # Examples -Examples for various scenarios can be found on [pkg.go.dev](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub#pkg-examples) or in the example*_test.go files in our GitHub repo for [azwebpubsub](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azwebpubsub). +Examples for various scenarios can be found on [pkg.go.dev][godoc_examples] or in the example*_test.go files in our GitHub repo for [azwebpubsub][source]. # Troubleshooting @@ -186,7 +186,7 @@ Azure SDK for Go is licensed under the [MIT](https://github.com/Azure/azure-sdk- [azure_identity_pkg]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity [default_azure_credential]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#NewDefaultAzureCredential -[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/messaging/azwebpubsub -[godoc]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub -[godoc_examples]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub#pkg-examples +[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk +[godoc]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk +[godoc_examples]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go#pkg-examples [product]: https://aka.ms/awps/doc From e3f864241e471faf7989e5143a9f8808f5275179 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Thu, 7 Dec 2023 10:57:12 +0800 Subject: [PATCH 20/28] Fix doc comment --- sdk/messaging/azwebpubsub/autorest.md | 16 +++++++++++++++- sdk/messaging/azwebpubsub/constants.go | 1 + sdk/messaging/azwebpubsub/models.go | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index d864342389ca..c0b349bd4aae 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -34,12 +34,26 @@ directive: - from: client.go where: $ transform: return $.replace(/\bCheckPermission\b/g, "checkPermission"); - # Add more properties to lient + # Add more properties to the client - from: client.go where: $ transform: >- return $.replace( /(type Client struct[^}]+})/s, "type Client struct {\n internal *azcore.Client\n endpoint string\n key *string\n}") + # Add comments to type Permission + - from: constants.go + where: $ + transform: >- + return $.replace( + /type Permission string/s, + "// Permission contains the allowed permissions\ntype Permission string") + # Add comments to InnerError + - from: models.go + where: $ + transform: >- + return $.replace( + /type InnerError struct/s, + "// InnerError - The inner error object\ntype InnerError struct") ``` \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/constants.go b/sdk/messaging/azwebpubsub/constants.go index 966b883a4842..9be3082eb405 100644 --- a/sdk/messaging/azwebpubsub/constants.go +++ b/sdk/messaging/azwebpubsub/constants.go @@ -29,6 +29,7 @@ func PossibleContentTypeValues() []ContentType { } } +// Permission contains the allowed permissions type Permission string const ( diff --git a/sdk/messaging/azwebpubsub/models.go b/sdk/messaging/azwebpubsub/models.go index 0239a812c6ec..99d83fb6e1be 100644 --- a/sdk/messaging/azwebpubsub/models.go +++ b/sdk/messaging/azwebpubsub/models.go @@ -39,6 +39,7 @@ type ErrorDetail struct { Target *string } +// InnerError - The inner error object type InnerError struct { // A more specific error code than was provided by the containing error. Code *string From 92a21964257fa72149503905dff9c23b81d8b4d4 Mon Sep 17 00:00:00 2001 From: "Liangying.Wei" Date: Mon, 11 Dec 2023 13:51:44 +0800 Subject: [PATCH 21/28] Update CHANGELOG.md --- sdk/messaging/azwebpubsub/CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/messaging/azwebpubsub/CHANGELOG.md b/sdk/messaging/azwebpubsub/CHANGELOG.md index c30a5c273a8f..e67b791c431e 100644 --- a/sdk/messaging/azwebpubsub/CHANGELOG.md +++ b/sdk/messaging/azwebpubsub/CHANGELOG.md @@ -1,5 +1,7 @@ # Release History -## 0.1.0 (Unreleased) +## 0.1.0 (2023-12-11) -* Initial version \ No newline at end of file +### Features Added + +- Initial preview for the Web PubSub Service From fe3a152013ac558662e332ddd3a3807f8a80e2fb Mon Sep 17 00:00:00 2001 From: "Liangying.Wei" Date: Wed, 13 Dec 2023 14:37:53 +0800 Subject: [PATCH 22/28] resolve comments --- sdk/messaging/azwebpubsub/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/messaging/azwebpubsub/ci.yml b/sdk/messaging/azwebpubsub/ci.yml index 698ce0feb10e..522941e89fb7 100644 --- a/sdk/messaging/azwebpubsub/ci.yml +++ b/sdk/messaging/azwebpubsub/ci.yml @@ -9,7 +9,6 @@ trigger: paths: include: - sdk/messaging/azwebpubsub/ - - eng/ pr: branches: @@ -26,5 +25,5 @@ pr: stages: - template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml parameters: - ServiceDirectory: 'messaging/azwebpubsub/' + ServiceDirectory: 'messaging/azwebpubsub' UsePipelineProxy: false \ No newline at end of file From 6f47a7b180942b2b371620acc409dc055a4e45a1 Mon Sep 17 00:00:00 2001 From: "Liangying.Wei" Date: Thu, 14 Dec 2023 10:02:14 +0800 Subject: [PATCH 23/28] Update sdk/messaging/azwebpubsub/ci.yml Co-authored-by: Rick Winter --- sdk/messaging/azwebpubsub/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/messaging/azwebpubsub/ci.yml b/sdk/messaging/azwebpubsub/ci.yml index 522941e89fb7..8710e949d058 100644 --- a/sdk/messaging/azwebpubsub/ci.yml +++ b/sdk/messaging/azwebpubsub/ci.yml @@ -26,4 +26,5 @@ stages: - template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml parameters: ServiceDirectory: 'messaging/azwebpubsub' - UsePipelineProxy: false \ No newline at end of file + UsePipelineProxy: false + \ No newline at end of file From eb2a69da5c0af6145a0a443dda0c404d076359b5 Mon Sep 17 00:00:00 2001 From: "Liangying.Wei" Date: Thu, 14 Dec 2023 10:02:24 +0800 Subject: [PATCH 24/28] Update sdk/messaging/azwebpubsub/sample.env Co-authored-by: Rick Winter --- sdk/messaging/azwebpubsub/sample.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/messaging/azwebpubsub/sample.env b/sdk/messaging/azwebpubsub/sample.env index 9b2da97b31cf..4b5a9bb95a71 100644 --- a/sdk/messaging/azwebpubsub/sample.env +++ b/sdk/messaging/azwebpubsub/sample.env @@ -1,3 +1,3 @@ WEBPUBSUB_CONNECTIONSTRING= WEBPUBSUB_HUB=chat -WEBPUBSUB_ENDPOINT= \ No newline at end of file +WEBPUBSUB_ENDPOINT= From e15adaf006d685c5dabe59dc7605dc5b49fc3a66 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Wed, 3 Jan 2024 15:03:51 +0800 Subject: [PATCH 25/28] Resolving comments --- sdk/messaging/azwebpubsub/autorest.md | 2 ++ sdk/messaging/azwebpubsub/models.go | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index c0b349bd4aae..c2f9d75f365f 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -4,6 +4,8 @@ title: WebPubSub description: Azure Web PubSub client clear-output-folder: false +slice-elements-byval: true +remove-non-reference-schema: true go: true input-file: https://github.com/Azure/azure-rest-api-specs/blob/052a4b8d50bfd5595a8b5b506015d18f2b65998d/specification/webpubsub/data-plane/WebPubSub/stable/2023-07-01/webpubsub.json license-header: MICROSOFT_MIT_NO_VERSION diff --git a/sdk/messaging/azwebpubsub/models.go b/sdk/messaging/azwebpubsub/models.go index 99d83fb6e1be..3c9bda441c35 100644 --- a/sdk/messaging/azwebpubsub/models.go +++ b/sdk/messaging/azwebpubsub/models.go @@ -14,7 +14,7 @@ type AddToGroupsRequest struct { Filter *string // A list of groups which target connections will be added into - Groups []*string + Groups []string } // ClientTokenResponse - The response object containing the token for the client @@ -29,7 +29,7 @@ type ErrorDetail struct { Code *string // An array of details about specific errors that led to this reported error. - Details []*ErrorDetail + Details []ErrorDetail Inner *InnerError // A human-readable representation of the error. @@ -52,5 +52,5 @@ type RemoveFromGroupsRequest struct { Filter *string // A list of groups which target connections will be removed from - Groups []*string + Groups []string } From 00af5018f595978b05591335b3520ab6bb47b142 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Wed, 17 Jan 2024 16:15:23 +0800 Subject: [PATCH 26/28] resolve comments --- sdk/messaging/azwebpubsub/autorest.md | 8 +- .../azwebpubsub/health_client_custom.go | 9 +-- .../azwebpubsub/health_client_test.go | 2 +- sdk/messaging/azwebpubsub/models.go | 23 ------ sdk/messaging/azwebpubsub/models_serde.go | 74 ------------------- 5 files changed, 10 insertions(+), 106 deletions(-) diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index c2f9d75f365f..fa113945a2cd 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -57,5 +57,11 @@ directive: return $.replace( /type InnerError struct/s, "// InnerError - The inner error object\ntype InnerError struct") - + # delete unused error models + - from: models.go + where: $ + transform: return $.replace(/(?:\/\/.*\s)+type (?:ErrorDetail|InnerError).+\{(?:\s.+\s)+\}\s/g, ""); + - from: models_serde.go + where: $ + transform: return $.replace(/(?:\/\/.*\s)+func \(\w \*?(?:ErrorDetail|InnerError)\).*\{\s(?:.+\s)+\}\s/g, ""); ``` \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/health_client_custom.go b/sdk/messaging/azwebpubsub/health_client_custom.go index 4e5f647c1653..a5192b77c50b 100644 --- a/sdk/messaging/azwebpubsub/health_client_custom.go +++ b/sdk/messaging/azwebpubsub/health_client_custom.go @@ -12,15 +12,10 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" ) -// HealthClientOptions contains optional settings for [HealthClient] -type HealthClientOptions struct { - azcore.ClientOptions -} - // NewHealthClientWithNoCredential creates a client that checks the healthy status of Web PubSub service -func NewHealthClientWithNoCredential(endpoint string, options *HealthClientOptions) (*HealthClient, error) { +func NewHealthClientWithNoCredential(endpoint string, options *ClientOptions) (*HealthClient, error) { if options == nil { - options = &HealthClientOptions{} + options = &ClientOptions{} } azcoreClient, err := azcore.NewClient(internal.ModuleName, internal.ModuleVersion, runtime.PipelineOptions{}, &options.ClientOptions) diff --git a/sdk/messaging/azwebpubsub/health_client_test.go b/sdk/messaging/azwebpubsub/health_client_test.go index 4cfd13ccbd72..00afe6fb6a03 100644 --- a/sdk/messaging/azwebpubsub/health_client_test.go +++ b/sdk/messaging/azwebpubsub/health_client_test.go @@ -22,7 +22,7 @@ func TestHealthClient_GetServiceStatus(t *testing.T) { func newHealthClient(t *testing.T) *azwebpubsub.HealthClient { tv, coreOptions := loadClientOptions(t) - options := &azwebpubsub.HealthClientOptions{ + options := &azwebpubsub.ClientOptions{ ClientOptions: *coreOptions, } println(tv.Endpoint) diff --git a/sdk/messaging/azwebpubsub/models.go b/sdk/messaging/azwebpubsub/models.go index 3c9bda441c35..4f7ab8911964 100644 --- a/sdk/messaging/azwebpubsub/models.go +++ b/sdk/messaging/azwebpubsub/models.go @@ -23,29 +23,6 @@ type ClientTokenResponse struct { Token *string } -// ErrorDetail - The error object. -type ErrorDetail struct { - // One of a server-defined set of error codes. - Code *string - - // An array of details about specific errors that led to this reported error. - Details []ErrorDetail - Inner *InnerError - - // A human-readable representation of the error. - Message *string - - // The target of the error. - Target *string -} - -// InnerError - The inner error object -type InnerError struct { - // A more specific error code than was provided by the containing error. - Code *string - Inner *InnerError -} - // RemoveFromGroupsRequest - The request object containing targets groups and a connection filter type RemoveFromGroupsRequest struct { // An OData filter which target connections satisfy diff --git a/sdk/messaging/azwebpubsub/models_serde.go b/sdk/messaging/azwebpubsub/models_serde.go index b641794efe8b..735c72aa4664 100644 --- a/sdk/messaging/azwebpubsub/models_serde.go +++ b/sdk/messaging/azwebpubsub/models_serde.go @@ -74,80 +74,6 @@ func (c *ClientTokenResponse) UnmarshalJSON(data []byte) error { return nil } -// MarshalJSON implements the json.Marshaller interface for type ErrorDetail. -func (e ErrorDetail) MarshalJSON() ([]byte, error) { - objectMap := make(map[string]any) - populate(objectMap, "code", e.Code) - populate(objectMap, "details", e.Details) - populate(objectMap, "inner", e.Inner) - populate(objectMap, "message", e.Message) - populate(objectMap, "target", e.Target) - return json.Marshal(objectMap) -} - -// UnmarshalJSON implements the json.Unmarshaller interface for type ErrorDetail. -func (e *ErrorDetail) UnmarshalJSON(data []byte) error { - var rawMsg map[string]json.RawMessage - if err := json.Unmarshal(data, &rawMsg); err != nil { - return fmt.Errorf("unmarshalling type %T: %v", e, err) - } - for key, val := range rawMsg { - var err error - switch key { - case "code": - err = unpopulate(val, "Code", &e.Code) - delete(rawMsg, key) - case "details": - err = unpopulate(val, "Details", &e.Details) - delete(rawMsg, key) - case "inner": - err = unpopulate(val, "Inner", &e.Inner) - delete(rawMsg, key) - case "message": - err = unpopulate(val, "Message", &e.Message) - delete(rawMsg, key) - case "target": - err = unpopulate(val, "Target", &e.Target) - delete(rawMsg, key) - } - if err != nil { - return fmt.Errorf("unmarshalling type %T: %v", e, err) - } - } - return nil -} - -// MarshalJSON implements the json.Marshaller interface for type InnerError. -func (i InnerError) MarshalJSON() ([]byte, error) { - objectMap := make(map[string]any) - populate(objectMap, "code", i.Code) - populate(objectMap, "inner", i.Inner) - return json.Marshal(objectMap) -} - -// UnmarshalJSON implements the json.Unmarshaller interface for type InnerError. -func (i *InnerError) UnmarshalJSON(data []byte) error { - var rawMsg map[string]json.RawMessage - if err := json.Unmarshal(data, &rawMsg); err != nil { - return fmt.Errorf("unmarshalling type %T: %v", i, err) - } - for key, val := range rawMsg { - var err error - switch key { - case "code": - err = unpopulate(val, "Code", &i.Code) - delete(rawMsg, key) - case "inner": - err = unpopulate(val, "Inner", &i.Inner) - delete(rawMsg, key) - } - if err != nil { - return fmt.Errorf("unmarshalling type %T: %v", i, err) - } - } - return nil -} - // MarshalJSON implements the json.Marshaller interface for type RemoveFromGroupsRequest. func (r RemoveFromGroupsRequest) MarshalJSON() ([]byte, error) { objectMap := make(map[string]any) From e8fb8ccf463343e4529ea2e73b4054d64738e181 Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Wed, 24 Jan 2024 10:29:22 +0800 Subject: [PATCH 27/28] remove healthclient --- sdk/messaging/azwebpubsub/CHANGELOG.md | 2 +- sdk/messaging/azwebpubsub/autorest.md | 7 +-- sdk/messaging/azwebpubsub/health_client.go | 60 ------------------- .../azwebpubsub/health_client_custom.go | 30 ---------- .../azwebpubsub/health_client_test.go | 32 ---------- sdk/messaging/azwebpubsub/options.go | 5 -- sdk/messaging/azwebpubsub/response_types.go | 5 -- 7 files changed, 4 insertions(+), 137 deletions(-) delete mode 100644 sdk/messaging/azwebpubsub/health_client.go delete mode 100644 sdk/messaging/azwebpubsub/health_client_custom.go delete mode 100644 sdk/messaging/azwebpubsub/health_client_test.go diff --git a/sdk/messaging/azwebpubsub/CHANGELOG.md b/sdk/messaging/azwebpubsub/CHANGELOG.md index e67b791c431e..37a1ea328c2c 100644 --- a/sdk/messaging/azwebpubsub/CHANGELOG.md +++ b/sdk/messaging/azwebpubsub/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 0.1.0 (2023-12-11) +## 0.1.0 (2024-01-21) ### Features Added diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index fa113945a2cd..e57985974e1c 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -14,10 +14,9 @@ openapi-type: "data-plane" output-folder: ../azwebpubsub use: "@autorest/go@4.0.0-preview.60" directive: - # Rename HealthAPI to Health - - from: swagger-document - where: '$.paths["/api/health"].head' - transform: $.operationId = "Health_GetServiceStatus"; + # Remove HealthAPI + - from: swagger-document + remove-operation: 'HealthApi_GetServiceStatus' # Rename enum WebPubSubPermission to Permission since the package name already contains WebPubSub. - from: - constants.go diff --git a/sdk/messaging/azwebpubsub/health_client.go b/sdk/messaging/azwebpubsub/health_client.go deleted file mode 100644 index f91987c9cbc9..000000000000 --- a/sdk/messaging/azwebpubsub/health_client.go +++ /dev/null @@ -1,60 +0,0 @@ -//go:build go1.18 -// +build go1.18 - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT. -// Changes may cause incorrect behavior and will be lost if the code is regenerated. - -package azwebpubsub - -import ( - "context" - "net/http" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" -) - -// HealthClient contains the methods for the Health group. -// Don't use this type directly, use a constructor function instead. -type HealthClient struct { - internal *azcore.Client - endpoint string -} - -// GetServiceStatus - Get service health status. -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2023-07-01 -// - options - HealthClientGetServiceStatusOptions contains the optional parameters for the HealthClient.GetServiceStatus method. -func (client *HealthClient) GetServiceStatus(ctx context.Context, options *HealthClientGetServiceStatusOptions) (HealthClientGetServiceStatusResponse, error) { - var err error - req, err := client.getServiceStatusCreateRequest(ctx, options) - if err != nil { - return HealthClientGetServiceStatusResponse{}, err - } - httpResp, err := client.internal.Pipeline().Do(req) - if err != nil { - return HealthClientGetServiceStatusResponse{}, err - } - if !runtime.HasStatusCode(httpResp, http.StatusOK) { - err = runtime.NewResponseError(httpResp) - return HealthClientGetServiceStatusResponse{}, err - } - return HealthClientGetServiceStatusResponse{}, nil -} - -// getServiceStatusCreateRequest creates the GetServiceStatus request. -func (client *HealthClient) getServiceStatusCreateRequest(ctx context.Context, options *HealthClientGetServiceStatusOptions) (*policy.Request, error) { - urlPath := "/api/health" - req, err := runtime.NewRequest(ctx, http.MethodHead, runtime.JoinPaths(client.endpoint, urlPath)) - if err != nil { - return nil, err - } - reqQP := req.Raw().URL.Query() - reqQP.Set("api-version", "2023-07-01") - req.Raw().URL.RawQuery = reqQP.Encode() - return req, nil -} diff --git a/sdk/messaging/azwebpubsub/health_client_custom.go b/sdk/messaging/azwebpubsub/health_client_custom.go deleted file mode 100644 index a5192b77c50b..000000000000 --- a/sdk/messaging/azwebpubsub/health_client_custom.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build go1.18 -// +build go1.18 - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azwebpubsub - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub/internal" -) - -// NewHealthClientWithNoCredential creates a client that checks the healthy status of Web PubSub service -func NewHealthClientWithNoCredential(endpoint string, options *ClientOptions) (*HealthClient, error) { - if options == nil { - options = &ClientOptions{} - } - - azcoreClient, err := azcore.NewClient(internal.ModuleName, internal.ModuleVersion, runtime.PipelineOptions{}, &options.ClientOptions) - if err != nil { - return nil, err - } - - return &HealthClient{ - internal: azcoreClient, - endpoint: endpoint, - }, nil -} diff --git a/sdk/messaging/azwebpubsub/health_client_test.go b/sdk/messaging/azwebpubsub/health_client_test.go deleted file mode 100644 index 00afe6fb6a03..000000000000 --- a/sdk/messaging/azwebpubsub/health_client_test.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build go1.18 -// +build go1.18 - -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -package azwebpubsub_test - -import ( - "context" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azwebpubsub" - "github.com/stretchr/testify/require" -) - -func TestHealthClient_GetServiceStatus(t *testing.T) { - client := newHealthClient(t) - _, err := client.GetServiceStatus(context.Background(), &azwebpubsub.HealthClientGetServiceStatusOptions{}) - require.NoError(t, err) -} - -func newHealthClient(t *testing.T) *azwebpubsub.HealthClient { - tv, coreOptions := loadClientOptions(t) - options := &azwebpubsub.ClientOptions{ - ClientOptions: *coreOptions, - } - println(tv.Endpoint) - client, err := azwebpubsub.NewHealthClientWithNoCredential(tv.Endpoint, options) - require.NoError(t, err) - return client -} diff --git a/sdk/messaging/azwebpubsub/options.go b/sdk/messaging/azwebpubsub/options.go index 89adb69e5ff4..ea4b1b0e5069 100644 --- a/sdk/messaging/azwebpubsub/options.go +++ b/sdk/messaging/azwebpubsub/options.go @@ -183,8 +183,3 @@ type ClientSendToUserOptions struct { type ClientUserExistsOptions struct { // placeholder for future optional parameters } - -// HealthClientGetServiceStatusOptions contains the optional parameters for the HealthClient.GetServiceStatus method. -type HealthClientGetServiceStatusOptions struct { - // placeholder for future optional parameters -} diff --git a/sdk/messaging/azwebpubsub/response_types.go b/sdk/messaging/azwebpubsub/response_types.go index 548734ac7d65..b3c28b485b5b 100644 --- a/sdk/messaging/azwebpubsub/response_types.go +++ b/sdk/messaging/azwebpubsub/response_types.go @@ -123,8 +123,3 @@ type ClientSendToUserResponse struct { type ClientUserExistsResponse struct { // placeholder for future response values } - -// HealthClientGetServiceStatusResponse contains the response from method HealthClient.GetServiceStatus. -type HealthClientGetServiceStatusResponse struct { - // placeholder for future response values -} From a029bdc6f723b5907e404fc16b5e2037fa51298a Mon Sep 17 00:00:00 2001 From: Liangying Wei Date: Fri, 26 Jan 2024 13:03:48 +0800 Subject: [PATCH 28/28] Resolve comments --- sdk/messaging/azwebpubsub/autorest.md | 9 + sdk/messaging/azwebpubsub/client.go | 332 ++++++++++---------- sdk/messaging/azwebpubsub/client_custom.go | 2 +- sdk/messaging/azwebpubsub/client_test.go | 18 +- sdk/messaging/azwebpubsub/models.go | 4 +- sdk/messaging/azwebpubsub/models_serde.go | 8 +- sdk/messaging/azwebpubsub/options.go | 92 +++--- sdk/messaging/azwebpubsub/response_types.go | 94 +++--- 8 files changed, 284 insertions(+), 275 deletions(-) diff --git a/sdk/messaging/azwebpubsub/autorest.md b/sdk/messaging/azwebpubsub/autorest.md index e57985974e1c..8f81fd590e2c 100644 --- a/sdk/messaging/azwebpubsub/autorest.md +++ b/sdk/messaging/azwebpubsub/autorest.md @@ -63,4 +63,13 @@ directive: - from: models_serde.go where: $ transform: return $.replace(/(?:\/\/.*\s)+func \(\w \*?(?:ErrorDetail|InnerError)\).*\{\s(?:.+\s)+\}\s/g, ""); + # delete client name prefix from method options and response types + - from: + - client.go + - models.go + - models_serde.go + - options.go + - response_types.go + where: $ + transform: return $.replace(/Client(\w+)((?:Options|Response))/g, "$1$2"); ``` \ No newline at end of file diff --git a/sdk/messaging/azwebpubsub/client.go b/sdk/messaging/azwebpubsub/client.go index f71b0e4883d2..5d3b0ec64a2e 100644 --- a/sdk/messaging/azwebpubsub/client.go +++ b/sdk/messaging/azwebpubsub/client.go @@ -37,26 +37,26 @@ type Client struct { // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - group - Target group name, which length should be greater than 0 and less than 1025. // - connectionID - Target connection Id -// - options - ClientAddConnectionToGroupOptions contains the optional parameters for the Client.AddConnectionToGroup method. -func (client *Client) AddConnectionToGroup(ctx context.Context, hub string, group string, connectionID string, options *ClientAddConnectionToGroupOptions) (ClientAddConnectionToGroupResponse, error) { +// - options - AddConnectionToGroupOptions contains the optional parameters for the Client.AddConnectionToGroup method. +func (client *Client) AddConnectionToGroup(ctx context.Context, hub string, group string, connectionID string, options *AddConnectionToGroupOptions) (AddConnectionToGroupResponse, error) { var err error req, err := client.addConnectionToGroupCreateRequest(ctx, hub, group, connectionID, options) if err != nil { - return ClientAddConnectionToGroupResponse{}, err + return AddConnectionToGroupResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientAddConnectionToGroupResponse{}, err + return AddConnectionToGroupResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK) { err = runtime.NewResponseError(httpResp) - return ClientAddConnectionToGroupResponse{}, err + return AddConnectionToGroupResponse{}, err } - return ClientAddConnectionToGroupResponse{}, nil + return AddConnectionToGroupResponse{}, nil } // addConnectionToGroupCreateRequest creates the AddConnectionToGroup request. -func (client *Client) addConnectionToGroupCreateRequest(ctx context.Context, hub string, group string, connectionID string, options *ClientAddConnectionToGroupOptions) (*policy.Request, error) { +func (client *Client) addConnectionToGroupCreateRequest(ctx context.Context, hub string, group string, connectionID string, options *AddConnectionToGroupOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/groups/{group}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -87,26 +87,26 @@ func (client *Client) addConnectionToGroupCreateRequest(ctx context.Context, hub // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - groupsToAdd - Target groups and connection filter. -// - options - ClientAddConnectionsToGroupsOptions contains the optional parameters for the Client.AddConnectionsToGroups method. -func (client *Client) AddConnectionsToGroups(ctx context.Context, hub string, groupsToAdd AddToGroupsRequest, options *ClientAddConnectionsToGroupsOptions) (ClientAddConnectionsToGroupsResponse, error) { +// - options - AddConnectionsToGroupsOptions contains the optional parameters for the Client.AddConnectionsToGroups method. +func (client *Client) AddConnectionsToGroups(ctx context.Context, hub string, groupsToAdd AddToGroupsRequest, options *AddConnectionsToGroupsOptions) (AddConnectionsToGroupsResponse, error) { var err error req, err := client.addConnectionsToGroupsCreateRequest(ctx, hub, groupsToAdd, options) if err != nil { - return ClientAddConnectionsToGroupsResponse{}, err + return AddConnectionsToGroupsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientAddConnectionsToGroupsResponse{}, err + return AddConnectionsToGroupsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK) { err = runtime.NewResponseError(httpResp) - return ClientAddConnectionsToGroupsResponse{}, err + return AddConnectionsToGroupsResponse{}, err } - return ClientAddConnectionsToGroupsResponse{}, nil + return AddConnectionsToGroupsResponse{}, nil } // addConnectionsToGroupsCreateRequest creates the AddConnectionsToGroups request. -func (client *Client) addConnectionsToGroupsCreateRequest(ctx context.Context, hub string, groupsToAdd AddToGroupsRequest, options *ClientAddConnectionsToGroupsOptions) (*policy.Request, error) { +func (client *Client) addConnectionsToGroupsCreateRequest(ctx context.Context, hub string, groupsToAdd AddToGroupsRequest, options *AddConnectionsToGroupsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/:addToGroups" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -133,26 +133,26 @@ func (client *Client) addConnectionsToGroupsCreateRequest(ctx context.Context, h // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - group - Target group name, which length should be greater than 0 and less than 1025. // - userID - Target user Id. -// - options - ClientAddUserToGroupOptions contains the optional parameters for the Client.AddUserToGroup method. -func (client *Client) AddUserToGroup(ctx context.Context, hub string, group string, userID string, options *ClientAddUserToGroupOptions) (ClientAddUserToGroupResponse, error) { +// - options - AddUserToGroupOptions contains the optional parameters for the Client.AddUserToGroup method. +func (client *Client) AddUserToGroup(ctx context.Context, hub string, group string, userID string, options *AddUserToGroupOptions) (AddUserToGroupResponse, error) { var err error req, err := client.addUserToGroupCreateRequest(ctx, hub, group, userID, options) if err != nil { - return ClientAddUserToGroupResponse{}, err + return AddUserToGroupResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientAddUserToGroupResponse{}, err + return AddUserToGroupResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK) { err = runtime.NewResponseError(httpResp) - return ClientAddUserToGroupResponse{}, err + return AddUserToGroupResponse{}, err } - return ClientAddUserToGroupResponse{}, nil + return AddUserToGroupResponse{}, nil } // addUserToGroupCreateRequest creates the AddUserToGroup request. -func (client *Client) addUserToGroupCreateRequest(ctx context.Context, hub string, group string, userID string, options *ClientAddUserToGroupOptions) (*policy.Request, error) { +func (client *Client) addUserToGroupCreateRequest(ctx context.Context, hub string, group string, userID string, options *AddUserToGroupOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/users/{userId}/groups/{group}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -184,26 +184,26 @@ func (client *Client) addUserToGroupCreateRequest(ctx context.Context, hub strin // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. // - connectionID - Target connection Id. -// - options - ClientCheckPermissionOptions contains the optional parameters for the Client.checkPermission method. -func (client *Client) checkPermission(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientCheckPermissionOptions) (ClientCheckPermissionResponse, error) { +// - options - CheckPermissionOptions contains the optional parameters for the Client.checkPermission method. +func (client *Client) checkPermission(ctx context.Context, hub string, permission Permission, connectionID string, options *CheckPermissionOptions) (CheckPermissionResponse, error) { var err error req, err := client.checkPermissionCreateRequest(ctx, hub, permission, connectionID, options) if err != nil { - return ClientCheckPermissionResponse{}, err + return CheckPermissionResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientCheckPermissionResponse{}, err + return CheckPermissionResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { err = runtime.NewResponseError(httpResp) - return ClientCheckPermissionResponse{}, err + return CheckPermissionResponse{}, err } - return ClientCheckPermissionResponse{}, nil + return CheckPermissionResponse{}, nil } // checkPermissionCreateRequest creates the checkPermission request. -func (client *Client) checkPermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientCheckPermissionOptions) (*policy.Request, error) { +func (client *Client) checkPermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *CheckPermissionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -235,26 +235,26 @@ func (client *Client) checkPermissionCreateRequest(ctx context.Context, hub stri // // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. -// - options - ClientCloseAllConnectionsOptions contains the optional parameters for the Client.CloseAllConnections method. -func (client *Client) CloseAllConnections(ctx context.Context, hub string, options *ClientCloseAllConnectionsOptions) (ClientCloseAllConnectionsResponse, error) { +// - options - CloseAllConnectionsOptions contains the optional parameters for the Client.CloseAllConnections method. +func (client *Client) CloseAllConnections(ctx context.Context, hub string, options *CloseAllConnectionsOptions) (CloseAllConnectionsResponse, error) { var err error req, err := client.closeAllConnectionsCreateRequest(ctx, hub, options) if err != nil { - return ClientCloseAllConnectionsResponse{}, err + return CloseAllConnectionsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientCloseAllConnectionsResponse{}, err + return CloseAllConnectionsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientCloseAllConnectionsResponse{}, err + return CloseAllConnectionsResponse{}, err } - return ClientCloseAllConnectionsResponse{}, nil + return CloseAllConnectionsResponse{}, nil } // closeAllConnectionsCreateRequest creates the CloseAllConnections request. -func (client *Client) closeAllConnectionsCreateRequest(ctx context.Context, hub string, options *ClientCloseAllConnectionsOptions) (*policy.Request, error) { +func (client *Client) closeAllConnectionsCreateRequest(ctx context.Context, hub string, options *CloseAllConnectionsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/:closeConnections" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -285,26 +285,26 @@ func (client *Client) closeAllConnectionsCreateRequest(ctx context.Context, hub // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - connectionID - Target connection Id. -// - options - ClientCloseConnectionOptions contains the optional parameters for the Client.CloseConnection method. -func (client *Client) CloseConnection(ctx context.Context, hub string, connectionID string, options *ClientCloseConnectionOptions) (ClientCloseConnectionResponse, error) { +// - options - CloseConnectionOptions contains the optional parameters for the Client.CloseConnection method. +func (client *Client) CloseConnection(ctx context.Context, hub string, connectionID string, options *CloseConnectionOptions) (CloseConnectionResponse, error) { var err error req, err := client.closeConnectionCreateRequest(ctx, hub, connectionID, options) if err != nil { - return ClientCloseConnectionResponse{}, err + return CloseConnectionResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientCloseConnectionResponse{}, err + return CloseConnectionResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientCloseConnectionResponse{}, err + return CloseConnectionResponse{}, err } - return ClientCloseConnectionResponse{}, nil + return CloseConnectionResponse{}, nil } // closeConnectionCreateRequest creates the CloseConnection request. -func (client *Client) closeConnectionCreateRequest(ctx context.Context, hub string, connectionID string, options *ClientCloseConnectionOptions) (*policy.Request, error) { +func (client *Client) closeConnectionCreateRequest(ctx context.Context, hub string, connectionID string, options *CloseConnectionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -334,26 +334,26 @@ func (client *Client) closeConnectionCreateRequest(ctx context.Context, hub stri // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - group - Target group name, which length should be greater than 0 and less than 1025. -// - options - ClientCloseGroupConnectionsOptions contains the optional parameters for the Client.CloseGroupConnections method. -func (client *Client) CloseGroupConnections(ctx context.Context, hub string, group string, options *ClientCloseGroupConnectionsOptions) (ClientCloseGroupConnectionsResponse, error) { +// - options - CloseGroupConnectionsOptions contains the optional parameters for the Client.CloseGroupConnections method. +func (client *Client) CloseGroupConnections(ctx context.Context, hub string, group string, options *CloseGroupConnectionsOptions) (CloseGroupConnectionsResponse, error) { var err error req, err := client.closeGroupConnectionsCreateRequest(ctx, hub, group, options) if err != nil { - return ClientCloseGroupConnectionsResponse{}, err + return CloseGroupConnectionsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientCloseGroupConnectionsResponse{}, err + return CloseGroupConnectionsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientCloseGroupConnectionsResponse{}, err + return CloseGroupConnectionsResponse{}, err } - return ClientCloseGroupConnectionsResponse{}, nil + return CloseGroupConnectionsResponse{}, nil } // closeGroupConnectionsCreateRequest creates the CloseGroupConnections request. -func (client *Client) closeGroupConnectionsCreateRequest(ctx context.Context, hub string, group string, options *ClientCloseGroupConnectionsOptions) (*policy.Request, error) { +func (client *Client) closeGroupConnectionsCreateRequest(ctx context.Context, hub string, group string, options *CloseGroupConnectionsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/groups/{group}/:closeConnections" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -388,26 +388,26 @@ func (client *Client) closeGroupConnectionsCreateRequest(ctx context.Context, hu // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - userID - The user Id. -// - options - ClientCloseUserConnectionsOptions contains the optional parameters for the Client.CloseUserConnections method. -func (client *Client) CloseUserConnections(ctx context.Context, hub string, userID string, options *ClientCloseUserConnectionsOptions) (ClientCloseUserConnectionsResponse, error) { +// - options - CloseUserConnectionsOptions contains the optional parameters for the Client.CloseUserConnections method. +func (client *Client) CloseUserConnections(ctx context.Context, hub string, userID string, options *CloseUserConnectionsOptions) (CloseUserConnectionsResponse, error) { var err error req, err := client.closeUserConnectionsCreateRequest(ctx, hub, userID, options) if err != nil { - return ClientCloseUserConnectionsResponse{}, err + return CloseUserConnectionsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientCloseUserConnectionsResponse{}, err + return CloseUserConnectionsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientCloseUserConnectionsResponse{}, err + return CloseUserConnectionsResponse{}, err } - return ClientCloseUserConnectionsResponse{}, nil + return CloseUserConnectionsResponse{}, nil } // closeUserConnectionsCreateRequest creates the CloseUserConnections request. -func (client *Client) closeUserConnectionsCreateRequest(ctx context.Context, hub string, userID string, options *ClientCloseUserConnectionsOptions) (*policy.Request, error) { +func (client *Client) closeUserConnectionsCreateRequest(ctx context.Context, hub string, userID string, options *CloseUserConnectionsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/users/{userId}/:closeConnections" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -442,26 +442,26 @@ func (client *Client) closeUserConnectionsCreateRequest(ctx context.Context, hub // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - connectionID - The connection Id. -// - options - ClientConnectionExistsOptions contains the optional parameters for the Client.connectionExists method. -func (client *Client) connectionExists(ctx context.Context, hub string, connectionID string, options *ClientConnectionExistsOptions) (ClientConnectionExistsResponse, error) { +// - options - ConnectionExistsOptions contains the optional parameters for the Client.connectionExists method. +func (client *Client) connectionExists(ctx context.Context, hub string, connectionID string, options *ConnectionExistsOptions) (ConnectionExistsResponse, error) { var err error req, err := client.connectionExistsCreateRequest(ctx, hub, connectionID, options) if err != nil { - return ClientConnectionExistsResponse{}, err + return ConnectionExistsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientConnectionExistsResponse{}, err + return ConnectionExistsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { err = runtime.NewResponseError(httpResp) - return ClientConnectionExistsResponse{}, err + return ConnectionExistsResponse{}, err } - return ClientConnectionExistsResponse{}, nil + return ConnectionExistsResponse{}, nil } // connectionExistsCreateRequest creates the connectionExists request. -func (client *Client) connectionExistsCreateRequest(ctx context.Context, hub string, connectionID string, options *ClientConnectionExistsOptions) (*policy.Request, error) { +func (client *Client) connectionExistsCreateRequest(ctx context.Context, hub string, connectionID string, options *ConnectionExistsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -486,27 +486,27 @@ func (client *Client) connectionExistsCreateRequest(ctx context.Context, hub str // // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. -// - options - ClientGenerateClientTokenOptions contains the optional parameters for the Client.generateClientToken method. -func (client *Client) generateClientToken(ctx context.Context, hub string, options *ClientGenerateClientTokenOptions) (ClientGenerateClientTokenResponse, error) { +// - options - GenerateClientTokenOptions contains the optional parameters for the Client.generateClientToken method. +func (client *Client) generateClientToken(ctx context.Context, hub string, options *GenerateClientTokenOptions) (GenerateClientTokenResponse, error) { var err error req, err := client.generateClientTokenCreateRequest(ctx, hub, options) if err != nil { - return ClientGenerateClientTokenResponse{}, err + return GenerateClientTokenResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientGenerateClientTokenResponse{}, err + return GenerateClientTokenResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK) { err = runtime.NewResponseError(httpResp) - return ClientGenerateClientTokenResponse{}, err + return GenerateClientTokenResponse{}, err } - resp, err := client.generateClientTokenHandleResponse(httpResp) + resp, err := client.generateTokenHandleResponse(httpResp) return resp, err } // generateClientTokenCreateRequest creates the generateClientToken request. -func (client *Client) generateClientTokenCreateRequest(ctx context.Context, hub string, options *ClientGenerateClientTokenOptions) (*policy.Request, error) { +func (client *Client) generateClientTokenCreateRequest(ctx context.Context, hub string, options *GenerateClientTokenOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/:generateToken" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -539,11 +539,11 @@ func (client *Client) generateClientTokenCreateRequest(ctx context.Context, hub return req, nil } -// generateClientTokenHandleResponse handles the generateClientToken response. -func (client *Client) generateClientTokenHandleResponse(resp *http.Response) (ClientGenerateClientTokenResponse, error) { - result := ClientGenerateClientTokenResponse{} - if err := runtime.UnmarshalAsJSON(resp, &result.ClientTokenResponse); err != nil { - return ClientGenerateClientTokenResponse{}, err +// generateTokenHandleResponse handles the generateClientToken response. +func (client *Client) generateTokenHandleResponse(resp *http.Response) (GenerateClientTokenResponse, error) { + result := GenerateClientTokenResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.TokenResponse); err != nil { + return GenerateClientTokenResponse{}, err } return result, nil } @@ -555,26 +555,26 @@ func (client *Client) generateClientTokenHandleResponse(resp *http.Response) (Cl // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. // - connectionID - Target connection Id. -// - options - ClientGrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. -func (client *Client) GrantPermission(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientGrantPermissionOptions) (ClientGrantPermissionResponse, error) { +// - options - GrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. +func (client *Client) GrantPermission(ctx context.Context, hub string, permission Permission, connectionID string, options *GrantPermissionOptions) (GrantPermissionResponse, error) { var err error req, err := client.grantPermissionCreateRequest(ctx, hub, permission, connectionID, options) if err != nil { - return ClientGrantPermissionResponse{}, err + return GrantPermissionResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientGrantPermissionResponse{}, err + return GrantPermissionResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK) { err = runtime.NewResponseError(httpResp) - return ClientGrantPermissionResponse{}, err + return GrantPermissionResponse{}, err } - return ClientGrantPermissionResponse{}, nil + return GrantPermissionResponse{}, nil } // grantPermissionCreateRequest creates the GrantPermission request. -func (client *Client) grantPermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientGrantPermissionOptions) (*policy.Request, error) { +func (client *Client) grantPermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *GrantPermissionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -608,26 +608,26 @@ func (client *Client) grantPermissionCreateRequest(ctx context.Context, hub stri // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - group - Target group name, which length should be greater than 0 and less than 1025. -// - options - ClientGroupExistsOptions contains the optional parameters for the Client.groupExists method. -func (client *Client) groupExists(ctx context.Context, hub string, group string, options *ClientGroupExistsOptions) (ClientGroupExistsResponse, error) { +// - options - GroupExistsOptions contains the optional parameters for the Client.groupExists method. +func (client *Client) groupExists(ctx context.Context, hub string, group string, options *GroupExistsOptions) (GroupExistsResponse, error) { var err error req, err := client.groupExistsCreateRequest(ctx, hub, group, options) if err != nil { - return ClientGroupExistsResponse{}, err + return GroupExistsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientGroupExistsResponse{}, err + return GroupExistsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { err = runtime.NewResponseError(httpResp) - return ClientGroupExistsResponse{}, err + return GroupExistsResponse{}, err } - return ClientGroupExistsResponse{}, nil + return GroupExistsResponse{}, nil } // groupExistsCreateRequest creates the groupExists request. -func (client *Client) groupExistsCreateRequest(ctx context.Context, hub string, group string, options *ClientGroupExistsOptions) (*policy.Request, error) { +func (client *Client) groupExistsCreateRequest(ctx context.Context, hub string, group string, options *GroupExistsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/groups/{group}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -653,27 +653,27 @@ func (client *Client) groupExistsCreateRequest(ctx context.Context, hub string, // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - connectionID - Target connection Id. -// - options - ClientRemoveConnectionFromAllGroupsOptions contains the optional parameters for the Client.RemoveConnectionFromAllGroups +// - options - RemoveConnectionFromAllGroupsOptions contains the optional parameters for the Client.RemoveConnectionFromAllGroups // method. -func (client *Client) RemoveConnectionFromAllGroups(ctx context.Context, hub string, connectionID string, options *ClientRemoveConnectionFromAllGroupsOptions) (ClientRemoveConnectionFromAllGroupsResponse, error) { +func (client *Client) RemoveConnectionFromAllGroups(ctx context.Context, hub string, connectionID string, options *RemoveConnectionFromAllGroupsOptions) (RemoveConnectionFromAllGroupsResponse, error) { var err error req, err := client.removeConnectionFromAllGroupsCreateRequest(ctx, hub, connectionID, options) if err != nil { - return ClientRemoveConnectionFromAllGroupsResponse{}, err + return RemoveConnectionFromAllGroupsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientRemoveConnectionFromAllGroupsResponse{}, err + return RemoveConnectionFromAllGroupsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientRemoveConnectionFromAllGroupsResponse{}, err + return RemoveConnectionFromAllGroupsResponse{}, err } - return ClientRemoveConnectionFromAllGroupsResponse{}, nil + return RemoveConnectionFromAllGroupsResponse{}, nil } // removeConnectionFromAllGroupsCreateRequest creates the RemoveConnectionFromAllGroups request. -func (client *Client) removeConnectionFromAllGroupsCreateRequest(ctx context.Context, hub string, connectionID string, options *ClientRemoveConnectionFromAllGroupsOptions) (*policy.Request, error) { +func (client *Client) removeConnectionFromAllGroupsCreateRequest(ctx context.Context, hub string, connectionID string, options *RemoveConnectionFromAllGroupsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/connections/{connectionId}/groups" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -701,27 +701,27 @@ func (client *Client) removeConnectionFromAllGroupsCreateRequest(ctx context.Con // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - group - Target group name, which length should be greater than 0 and less than 1025. // - connectionID - Target connection Id. -// - options - ClientRemoveConnectionFromGroupOptions contains the optional parameters for the Client.RemoveConnectionFromGroup +// - options - RemoveConnectionFromGroupOptions contains the optional parameters for the Client.RemoveConnectionFromGroup // method. -func (client *Client) RemoveConnectionFromGroup(ctx context.Context, hub string, group string, connectionID string, options *ClientRemoveConnectionFromGroupOptions) (ClientRemoveConnectionFromGroupResponse, error) { +func (client *Client) RemoveConnectionFromGroup(ctx context.Context, hub string, group string, connectionID string, options *RemoveConnectionFromGroupOptions) (RemoveConnectionFromGroupResponse, error) { var err error req, err := client.removeConnectionFromGroupCreateRequest(ctx, hub, group, connectionID, options) if err != nil { - return ClientRemoveConnectionFromGroupResponse{}, err + return RemoveConnectionFromGroupResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientRemoveConnectionFromGroupResponse{}, err + return RemoveConnectionFromGroupResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientRemoveConnectionFromGroupResponse{}, err + return RemoveConnectionFromGroupResponse{}, err } - return ClientRemoveConnectionFromGroupResponse{}, nil + return RemoveConnectionFromGroupResponse{}, nil } // removeConnectionFromGroupCreateRequest creates the RemoveConnectionFromGroup request. -func (client *Client) removeConnectionFromGroupCreateRequest(ctx context.Context, hub string, group string, connectionID string, options *ClientRemoveConnectionFromGroupOptions) (*policy.Request, error) { +func (client *Client) removeConnectionFromGroupCreateRequest(ctx context.Context, hub string, group string, connectionID string, options *RemoveConnectionFromGroupOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/groups/{group}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -752,27 +752,27 @@ func (client *Client) removeConnectionFromGroupCreateRequest(ctx context.Context // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - groupsToRemove - Target groups and connection filter. -// - options - ClientRemoveConnectionsFromGroupsOptions contains the optional parameters for the Client.RemoveConnectionsFromGroups +// - options - RemoveConnectionsFromGroupsOptions contains the optional parameters for the Client.RemoveConnectionsFromGroups // method. -func (client *Client) RemoveConnectionsFromGroups(ctx context.Context, hub string, groupsToRemove RemoveFromGroupsRequest, options *ClientRemoveConnectionsFromGroupsOptions) (ClientRemoveConnectionsFromGroupsResponse, error) { +func (client *Client) RemoveConnectionsFromGroups(ctx context.Context, hub string, groupsToRemove RemoveFromGroupsRequest, options *RemoveConnectionsFromGroupsOptions) (RemoveConnectionsFromGroupsResponse, error) { var err error req, err := client.removeConnectionsFromGroupsCreateRequest(ctx, hub, groupsToRemove, options) if err != nil { - return ClientRemoveConnectionsFromGroupsResponse{}, err + return RemoveConnectionsFromGroupsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientRemoveConnectionsFromGroupsResponse{}, err + return RemoveConnectionsFromGroupsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK) { err = runtime.NewResponseError(httpResp) - return ClientRemoveConnectionsFromGroupsResponse{}, err + return RemoveConnectionsFromGroupsResponse{}, err } - return ClientRemoveConnectionsFromGroupsResponse{}, nil + return RemoveConnectionsFromGroupsResponse{}, nil } // removeConnectionsFromGroupsCreateRequest creates the RemoveConnectionsFromGroups request. -func (client *Client) removeConnectionsFromGroupsCreateRequest(ctx context.Context, hub string, groupsToRemove RemoveFromGroupsRequest, options *ClientRemoveConnectionsFromGroupsOptions) (*policy.Request, error) { +func (client *Client) removeConnectionsFromGroupsCreateRequest(ctx context.Context, hub string, groupsToRemove RemoveFromGroupsRequest, options *RemoveConnectionsFromGroupsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/:removeFromGroups" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -798,27 +798,27 @@ func (client *Client) removeConnectionsFromGroupsCreateRequest(ctx context.Conte // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - userID - Target user Id. -// - options - ClientRemoveUserFromAllGroupsOptions contains the optional parameters for the Client.RemoveUserFromAllGroups +// - options - RemoveUserFromAllGroupsOptions contains the optional parameters for the Client.RemoveUserFromAllGroups // method. -func (client *Client) RemoveUserFromAllGroups(ctx context.Context, hub string, userID string, options *ClientRemoveUserFromAllGroupsOptions) (ClientRemoveUserFromAllGroupsResponse, error) { +func (client *Client) RemoveUserFromAllGroups(ctx context.Context, hub string, userID string, options *RemoveUserFromAllGroupsOptions) (RemoveUserFromAllGroupsResponse, error) { var err error req, err := client.removeUserFromAllGroupsCreateRequest(ctx, hub, userID, options) if err != nil { - return ClientRemoveUserFromAllGroupsResponse{}, err + return RemoveUserFromAllGroupsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientRemoveUserFromAllGroupsResponse{}, err + return RemoveUserFromAllGroupsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientRemoveUserFromAllGroupsResponse{}, err + return RemoveUserFromAllGroupsResponse{}, err } - return ClientRemoveUserFromAllGroupsResponse{}, nil + return RemoveUserFromAllGroupsResponse{}, nil } // removeUserFromAllGroupsCreateRequest creates the RemoveUserFromAllGroups request. -func (client *Client) removeUserFromAllGroupsCreateRequest(ctx context.Context, hub string, userID string, options *ClientRemoveUserFromAllGroupsOptions) (*policy.Request, error) { +func (client *Client) removeUserFromAllGroupsCreateRequest(ctx context.Context, hub string, userID string, options *RemoveUserFromAllGroupsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/users/{userId}/groups" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -846,26 +846,26 @@ func (client *Client) removeUserFromAllGroupsCreateRequest(ctx context.Context, // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - group - Target group name, which length should be greater than 0 and less than 1025. // - userID - Target user Id. -// - options - ClientRemoveUserFromGroupOptions contains the optional parameters for the Client.RemoveUserFromGroup method. -func (client *Client) RemoveUserFromGroup(ctx context.Context, hub string, group string, userID string, options *ClientRemoveUserFromGroupOptions) (ClientRemoveUserFromGroupResponse, error) { +// - options - RemoveUserFromGroupOptions contains the optional parameters for the Client.RemoveUserFromGroup method. +func (client *Client) RemoveUserFromGroup(ctx context.Context, hub string, group string, userID string, options *RemoveUserFromGroupOptions) (RemoveUserFromGroupResponse, error) { var err error req, err := client.removeUserFromGroupCreateRequest(ctx, hub, group, userID, options) if err != nil { - return ClientRemoveUserFromGroupResponse{}, err + return RemoveUserFromGroupResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientRemoveUserFromGroupResponse{}, err + return RemoveUserFromGroupResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientRemoveUserFromGroupResponse{}, err + return RemoveUserFromGroupResponse{}, err } - return ClientRemoveUserFromGroupResponse{}, nil + return RemoveUserFromGroupResponse{}, nil } // removeUserFromGroupCreateRequest creates the RemoveUserFromGroup request. -func (client *Client) removeUserFromGroupCreateRequest(ctx context.Context, hub string, group string, userID string, options *ClientRemoveUserFromGroupOptions) (*policy.Request, error) { +func (client *Client) removeUserFromGroupCreateRequest(ctx context.Context, hub string, group string, userID string, options *RemoveUserFromGroupOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/users/{userId}/groups/{group}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -897,26 +897,26 @@ func (client *Client) removeUserFromGroupCreateRequest(ctx context.Context, hub // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - permission - The permission: current supported actions are joinLeaveGroup and sendToGroup. // - connectionID - Target connection Id. -// - options - ClientRevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. -func (client *Client) RevokePermission(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientRevokePermissionOptions) (ClientRevokePermissionResponse, error) { +// - options - RevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. +func (client *Client) RevokePermission(ctx context.Context, hub string, permission Permission, connectionID string, options *RevokePermissionOptions) (RevokePermissionResponse, error) { var err error req, err := client.revokePermissionCreateRequest(ctx, hub, permission, connectionID, options) if err != nil { - return ClientRevokePermissionResponse{}, err + return RevokePermissionResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientRevokePermissionResponse{}, err + return RevokePermissionResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusNoContent) { err = runtime.NewResponseError(httpResp) - return ClientRevokePermissionResponse{}, err + return RevokePermissionResponse{}, err } - return ClientRevokePermissionResponse{}, nil + return RevokePermissionResponse{}, nil } // revokePermissionCreateRequest creates the RevokePermission request. -func (client *Client) revokePermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *ClientRevokePermissionOptions) (*policy.Request, error) { +func (client *Client) revokePermissionCreateRequest(ctx context.Context, hub string, permission Permission, connectionID string, options *RevokePermissionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/permissions/{permission}/connections/{connectionId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -951,26 +951,26 @@ func (client *Client) revokePermissionCreateRequest(ctx context.Context, hub str // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - contentType - Upload file type // - message - The payload body. -// - options - ClientSendToAllOptions contains the optional parameters for the Client.SendToAll method. -func (client *Client) SendToAll(ctx context.Context, hub string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToAllOptions) (ClientSendToAllResponse, error) { +// - options - SendToAllOptions contains the optional parameters for the Client.SendToAll method. +func (client *Client) SendToAll(ctx context.Context, hub string, contentType ContentType, message io.ReadSeekCloser, options *SendToAllOptions) (SendToAllResponse, error) { var err error req, err := client.sendToAllCreateRequest(ctx, hub, contentType, message, options) if err != nil { - return ClientSendToAllResponse{}, err + return SendToAllResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientSendToAllResponse{}, err + return SendToAllResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { err = runtime.NewResponseError(httpResp) - return ClientSendToAllResponse{}, err + return SendToAllResponse{}, err } - return ClientSendToAllResponse{}, nil + return SendToAllResponse{}, nil } // sendToAllCreateRequest creates the SendToAll request. -func (client *Client) sendToAllCreateRequest(ctx context.Context, hub string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToAllOptions) (*policy.Request, error) { +func (client *Client) sendToAllCreateRequest(ctx context.Context, hub string, contentType ContentType, message io.ReadSeekCloser, options *SendToAllOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/:send" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -1010,26 +1010,26 @@ func (client *Client) sendToAllCreateRequest(ctx context.Context, hub string, co // - connectionID - The connection Id. // - contentType - Upload file type // - message - The payload body. -// - options - ClientSendToConnectionOptions contains the optional parameters for the Client.SendToConnection method. -func (client *Client) SendToConnection(ctx context.Context, hub string, connectionID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToConnectionOptions) (ClientSendToConnectionResponse, error) { +// - options - SendToConnectionOptions contains the optional parameters for the Client.SendToConnection method. +func (client *Client) SendToConnection(ctx context.Context, hub string, connectionID string, contentType ContentType, message io.ReadSeekCloser, options *SendToConnectionOptions) (SendToConnectionResponse, error) { var err error req, err := client.sendToConnectionCreateRequest(ctx, hub, connectionID, contentType, message, options) if err != nil { - return ClientSendToConnectionResponse{}, err + return SendToConnectionResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientSendToConnectionResponse{}, err + return SendToConnectionResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { err = runtime.NewResponseError(httpResp) - return ClientSendToConnectionResponse{}, err + return SendToConnectionResponse{}, err } - return ClientSendToConnectionResponse{}, nil + return SendToConnectionResponse{}, nil } // sendToConnectionCreateRequest creates the SendToConnection request. -func (client *Client) sendToConnectionCreateRequest(ctx context.Context, hub string, connectionID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToConnectionOptions) (*policy.Request, error) { +func (client *Client) sendToConnectionCreateRequest(ctx context.Context, hub string, connectionID string, contentType ContentType, message io.ReadSeekCloser, options *SendToConnectionOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/connections/{connectionId}/:send" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -1065,26 +1065,26 @@ func (client *Client) sendToConnectionCreateRequest(ctx context.Context, hub str // - group - Target group name, which length should be greater than 0 and less than 1025. // - contentType - Upload file type // - message - The payload body. -// - options - ClientSendToGroupOptions contains the optional parameters for the Client.SendToGroup method. -func (client *Client) SendToGroup(ctx context.Context, hub string, group string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToGroupOptions) (ClientSendToGroupResponse, error) { +// - options - SendToGroupOptions contains the optional parameters for the Client.SendToGroup method. +func (client *Client) SendToGroup(ctx context.Context, hub string, group string, contentType ContentType, message io.ReadSeekCloser, options *SendToGroupOptions) (SendToGroupResponse, error) { var err error req, err := client.sendToGroupCreateRequest(ctx, hub, group, contentType, message, options) if err != nil { - return ClientSendToGroupResponse{}, err + return SendToGroupResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientSendToGroupResponse{}, err + return SendToGroupResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { err = runtime.NewResponseError(httpResp) - return ClientSendToGroupResponse{}, err + return SendToGroupResponse{}, err } - return ClientSendToGroupResponse{}, nil + return SendToGroupResponse{}, nil } // sendToGroupCreateRequest creates the SendToGroup request. -func (client *Client) sendToGroupCreateRequest(ctx context.Context, hub string, group string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToGroupOptions) (*policy.Request, error) { +func (client *Client) sendToGroupCreateRequest(ctx context.Context, hub string, group string, contentType ContentType, message io.ReadSeekCloser, options *SendToGroupOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/groups/{group}/:send" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -1128,26 +1128,26 @@ func (client *Client) sendToGroupCreateRequest(ctx context.Context, hub string, // - userID - The user Id. // - contentType - Upload file type // - message - The payload body. -// - options - ClientSendToUserOptions contains the optional parameters for the Client.SendToUser method. -func (client *Client) SendToUser(ctx context.Context, hub string, userID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToUserOptions) (ClientSendToUserResponse, error) { +// - options - SendToUserOptions contains the optional parameters for the Client.SendToUser method. +func (client *Client) SendToUser(ctx context.Context, hub string, userID string, contentType ContentType, message io.ReadSeekCloser, options *SendToUserOptions) (SendToUserResponse, error) { var err error req, err := client.sendToUserCreateRequest(ctx, hub, userID, contentType, message, options) if err != nil { - return ClientSendToUserResponse{}, err + return SendToUserResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientSendToUserResponse{}, err + return SendToUserResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusAccepted) { err = runtime.NewResponseError(httpResp) - return ClientSendToUserResponse{}, err + return SendToUserResponse{}, err } - return ClientSendToUserResponse{}, nil + return SendToUserResponse{}, nil } // sendToUserCreateRequest creates the SendToUser request. -func (client *Client) sendToUserCreateRequest(ctx context.Context, hub string, userID string, contentType ContentType, message io.ReadSeekCloser, options *ClientSendToUserOptions) (*policy.Request, error) { +func (client *Client) sendToUserCreateRequest(ctx context.Context, hub string, userID string, contentType ContentType, message io.ReadSeekCloser, options *SendToUserOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/users/{userId}/:send" if hub == "" { return nil, errors.New("parameter hub cannot be empty") @@ -1184,26 +1184,26 @@ func (client *Client) sendToUserCreateRequest(ctx context.Context, hub string, u // Generated from API version 2023-07-01 // - hub - Target hub name, which should start with alphabetic characters and only contain alpha-numeric characters or underscore. // - userID - Target user Id. -// - options - ClientUserExistsOptions contains the optional parameters for the Client.userExists method. -func (client *Client) userExists(ctx context.Context, hub string, userID string, options *ClientUserExistsOptions) (ClientUserExistsResponse, error) { +// - options - UserExistsOptions contains the optional parameters for the Client.userExists method. +func (client *Client) userExists(ctx context.Context, hub string, userID string, options *UserExistsOptions) (UserExistsResponse, error) { var err error req, err := client.userExistsCreateRequest(ctx, hub, userID, options) if err != nil { - return ClientUserExistsResponse{}, err + return UserExistsResponse{}, err } httpResp, err := client.internal.Pipeline().Do(req) if err != nil { - return ClientUserExistsResponse{}, err + return UserExistsResponse{}, err } if !runtime.HasStatusCode(httpResp, http.StatusOK, http.StatusNotFound) { err = runtime.NewResponseError(httpResp) - return ClientUserExistsResponse{}, err + return UserExistsResponse{}, err } - return ClientUserExistsResponse{}, nil + return UserExistsResponse{}, nil } // userExistsCreateRequest creates the userExists request. -func (client *Client) userExistsCreateRequest(ctx context.Context, hub string, userID string, options *ClientUserExistsOptions) (*policy.Request, error) { +func (client *Client) userExistsCreateRequest(ctx context.Context, hub string, userID string, options *UserExistsOptions) (*policy.Request, error) { urlPath := "/api/hubs/{hub}/users/{userId}" if hub == "" { return nil, errors.New("parameter hub cannot be empty") diff --git a/sdk/messaging/azwebpubsub/client_custom.go b/sdk/messaging/azwebpubsub/client_custom.go index 122f237c286f..590db8c95e4c 100644 --- a/sdk/messaging/azwebpubsub/client_custom.go +++ b/sdk/messaging/azwebpubsub/client_custom.go @@ -138,7 +138,7 @@ func (c *Client) GenerateClientAccessURL(ctx context.Context, hub string, option userId = &options.UserID } // Replace with your logic to generate the token using a webPubSub method - resp, err := c.generateClientToken(ctx, hub, &ClientGenerateClientTokenOptions{UserID: userId, Role: options.Roles, Group: options.Groups, MinutesToExpire: &options.ExpirationTimeInMinutes}) + resp, err := c.generateClientToken(ctx, hub, &GenerateClientTokenOptions{UserID: userId, Role: options.Roles, Group: options.Groups, MinutesToExpire: &options.ExpirationTimeInMinutes}) if err != nil { return nil, err } diff --git a/sdk/messaging/azwebpubsub/client_test.go b/sdk/messaging/azwebpubsub/client_test.go index ccf185a16610..f8bfd409e43c 100644 --- a/sdk/messaging/azwebpubsub/client_test.go +++ b/sdk/messaging/azwebpubsub/client_test.go @@ -25,17 +25,17 @@ func TestClient_SendToAll(t *testing.T) { hub := "hub1" _, err := client.SendToAll(context.Background(), hub, azwebpubsub.ContentTypeTextPlain, newStream("Hello world!"), - &azwebpubsub.ClientSendToAllOptions{}) + &azwebpubsub.SendToAllOptions{}) require.NoError(t, err) _, err = client.SendToAll(context.Background(), hub, azwebpubsub.ContentTypeApplicationJSON, newStream("true"), - &azwebpubsub.ClientSendToAllOptions{}) + &azwebpubsub.SendToAllOptions{}) require.NoError(t, err) _, err = client.SendToAll(context.Background(), hub, azwebpubsub.ContentTypeApplicationOctetStream, newStream("true"), - &azwebpubsub.ClientSendToAllOptions{}) + &azwebpubsub.SendToAllOptions{}) require.NoError(t, err) } @@ -44,11 +44,11 @@ func TestClient_ManagePermissions(t *testing.T) { const hub = "chat" const conn1 = "conn1" group := "group1" - _, err := client.GrantPermission(context.Background(), hub, azwebpubsub.PermissionJoinLeaveGroup, conn1, &azwebpubsub.ClientGrantPermissionOptions{ + _, err := client.GrantPermission(context.Background(), hub, azwebpubsub.PermissionJoinLeaveGroup, conn1, &azwebpubsub.GrantPermissionOptions{ TargetName: &group, }) require.ErrorContains(t, err, "404 Not Found") - _, err = client.RevokePermission(context.Background(), hub, azwebpubsub.PermissionJoinLeaveGroup, conn1, &azwebpubsub.ClientRevokePermissionOptions{ + _, err = client.RevokePermission(context.Background(), hub, azwebpubsub.PermissionJoinLeaveGroup, conn1, &azwebpubsub.RevokePermissionOptions{ TargetName: &group, }) require.NoError(t, err) @@ -62,16 +62,16 @@ func TestClient_CloseConnections(t *testing.T) { const user1 = "user1" reason := "TestClient_CloseConnections" _, err := client.CloseAllConnections(context.Background(), - hub, &azwebpubsub.ClientCloseAllConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) + hub, &azwebpubsub.CloseAllConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) require.NoError(t, err) _, err = client.CloseConnection(context.Background(), - hub, conn1, &azwebpubsub.ClientCloseConnectionOptions{Reason: &reason}) + hub, conn1, &azwebpubsub.CloseConnectionOptions{Reason: &reason}) require.NoError(t, err) _, err = client.CloseGroupConnections(context.Background(), - hub, group1, &azwebpubsub.ClientCloseGroupConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) + hub, group1, &azwebpubsub.CloseGroupConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) require.NoError(t, err) _, err = client.CloseUserConnections(context.Background(), - hub, user1, &azwebpubsub.ClientCloseUserConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) + hub, user1, &azwebpubsub.CloseUserConnectionsOptions{Excluded: []string{conn1}, Reason: &reason}) require.NoError(t, err) } diff --git a/sdk/messaging/azwebpubsub/models.go b/sdk/messaging/azwebpubsub/models.go index 4f7ab8911964..e1b345e4d9cf 100644 --- a/sdk/messaging/azwebpubsub/models.go +++ b/sdk/messaging/azwebpubsub/models.go @@ -17,8 +17,8 @@ type AddToGroupsRequest struct { Groups []string } -// ClientTokenResponse - The response object containing the token for the client -type ClientTokenResponse struct { +// TokenResponse - The response object containing the token for the client +type TokenResponse struct { // The token value for the WebSocket client to connect to the service Token *string } diff --git a/sdk/messaging/azwebpubsub/models_serde.go b/sdk/messaging/azwebpubsub/models_serde.go index 735c72aa4664..f6081a5ed268 100644 --- a/sdk/messaging/azwebpubsub/models_serde.go +++ b/sdk/messaging/azwebpubsub/models_serde.go @@ -47,15 +47,15 @@ func (a *AddToGroupsRequest) UnmarshalJSON(data []byte) error { return nil } -// MarshalJSON implements the json.Marshaller interface for type ClientTokenResponse. -func (c ClientTokenResponse) MarshalJSON() ([]byte, error) { +// MarshalJSON implements the json.Marshaller interface for type TokenResponse. +func (c TokenResponse) MarshalJSON() ([]byte, error) { objectMap := make(map[string]any) populate(objectMap, "token", c.Token) return json.Marshal(objectMap) } -// UnmarshalJSON implements the json.Unmarshaller interface for type ClientTokenResponse. -func (c *ClientTokenResponse) UnmarshalJSON(data []byte) error { +// UnmarshalJSON implements the json.Unmarshaller interface for type TokenResponse. +func (c *TokenResponse) UnmarshalJSON(data []byte) error { var rawMsg map[string]json.RawMessage if err := json.Unmarshal(data, &rawMsg); err != nil { return fmt.Errorf("unmarshalling type %T: %v", c, err) diff --git a/sdk/messaging/azwebpubsub/options.go b/sdk/messaging/azwebpubsub/options.go index ea4b1b0e5069..4dcf245e4b72 100644 --- a/sdk/messaging/azwebpubsub/options.go +++ b/sdk/messaging/azwebpubsub/options.go @@ -8,30 +8,30 @@ package azwebpubsub -// ClientAddConnectionToGroupOptions contains the optional parameters for the Client.AddConnectionToGroup method. -type ClientAddConnectionToGroupOptions struct { +// AddConnectionToGroupOptions contains the optional parameters for the Client.AddConnectionToGroup method. +type AddConnectionToGroupOptions struct { // placeholder for future optional parameters } -// ClientAddConnectionsToGroupsOptions contains the optional parameters for the Client.AddConnectionsToGroups method. -type ClientAddConnectionsToGroupsOptions struct { +// AddConnectionsToGroupsOptions contains the optional parameters for the Client.AddConnectionsToGroups method. +type AddConnectionsToGroupsOptions struct { // placeholder for future optional parameters } -// ClientAddUserToGroupOptions contains the optional parameters for the Client.AddUserToGroup method. -type ClientAddUserToGroupOptions struct { +// AddUserToGroupOptions contains the optional parameters for the Client.AddUserToGroup method. +type AddUserToGroupOptions struct { // placeholder for future optional parameters } -// ClientCheckPermissionOptions contains the optional parameters for the Client.CheckPermission method. -type ClientCheckPermissionOptions struct { +// CheckPermissionOptions contains the optional parameters for the Client.CheckPermission method. +type CheckPermissionOptions struct { // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required // parameter standing for the group name. TargetName *string } -// ClientCloseAllConnectionsOptions contains the optional parameters for the Client.CloseAllConnections method. -type ClientCloseAllConnectionsOptions struct { +// CloseAllConnectionsOptions contains the optional parameters for the Client.CloseAllConnections method. +type CloseAllConnectionsOptions struct { // Exclude these connectionIds when closing the connections in the hub. Excluded []string @@ -39,14 +39,14 @@ type ClientCloseAllConnectionsOptions struct { Reason *string } -// ClientCloseConnectionOptions contains the optional parameters for the Client.CloseConnection method. -type ClientCloseConnectionOptions struct { +// CloseConnectionOptions contains the optional parameters for the Client.CloseConnection method. +type CloseConnectionOptions struct { // The reason closing the client connection. Reason *string } -// ClientCloseGroupConnectionsOptions contains the optional parameters for the Client.CloseGroupConnections method. -type ClientCloseGroupConnectionsOptions struct { +// CloseGroupConnectionsOptions contains the optional parameters for the Client.CloseGroupConnections method. +type CloseGroupConnectionsOptions struct { // Exclude these connectionIds when closing the connections in the group. Excluded []string @@ -54,8 +54,8 @@ type ClientCloseGroupConnectionsOptions struct { Reason *string } -// ClientCloseUserConnectionsOptions contains the optional parameters for the Client.CloseUserConnections method. -type ClientCloseUserConnectionsOptions struct { +// CloseUserConnectionsOptions contains the optional parameters for the Client.CloseUserConnections method. +type CloseUserConnectionsOptions struct { // Exclude these connectionIds when closing the connections for the user. Excluded []string @@ -63,13 +63,13 @@ type ClientCloseUserConnectionsOptions struct { Reason *string } -// ClientConnectionExistsOptions contains the optional parameters for the Client.ConnectionExists method. -type ClientConnectionExistsOptions struct { +// ConnectionExistsOptions contains the optional parameters for the Client.ConnectionExists method. +type ConnectionExistsOptions struct { // placeholder for future optional parameters } -// ClientGenerateClientTokenOptions contains the optional parameters for the Client.GenerateClientToken method. -type ClientGenerateClientTokenOptions struct { +// GenerateClientTokenOptions contains the optional parameters for the Client.GenerateClientToken method. +type GenerateClientTokenOptions struct { // Groups that the connection will join when it connects. Group []string @@ -83,53 +83,53 @@ type ClientGenerateClientTokenOptions struct { UserID *string } -// ClientGrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. -type ClientGrantPermissionOptions struct { +// GrantPermissionOptions contains the optional parameters for the Client.GrantPermission method. +type GrantPermissionOptions struct { // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required // parameter standing for the group name. TargetName *string } -// ClientGroupExistsOptions contains the optional parameters for the Client.GroupExists method. -type ClientGroupExistsOptions struct { +// GroupExistsOptions contains the optional parameters for the Client.GroupExists method. +type GroupExistsOptions struct { // placeholder for future optional parameters } -// ClientRemoveConnectionFromAllGroupsOptions contains the optional parameters for the Client.RemoveConnectionFromAllGroups +// RemoveConnectionFromAllGroupsOptions contains the optional parameters for the Client.RemoveConnectionFromAllGroups // method. -type ClientRemoveConnectionFromAllGroupsOptions struct { +type RemoveConnectionFromAllGroupsOptions struct { // placeholder for future optional parameters } -// ClientRemoveConnectionFromGroupOptions contains the optional parameters for the Client.RemoveConnectionFromGroup method. -type ClientRemoveConnectionFromGroupOptions struct { +// RemoveConnectionFromGroupOptions contains the optional parameters for the Client.RemoveConnectionFromGroup method. +type RemoveConnectionFromGroupOptions struct { // placeholder for future optional parameters } -// ClientRemoveConnectionsFromGroupsOptions contains the optional parameters for the Client.RemoveConnectionsFromGroups method. -type ClientRemoveConnectionsFromGroupsOptions struct { +// RemoveConnectionsFromGroupsOptions contains the optional parameters for the Client.RemoveConnectionsFromGroups method. +type RemoveConnectionsFromGroupsOptions struct { // placeholder for future optional parameters } -// ClientRemoveUserFromAllGroupsOptions contains the optional parameters for the Client.RemoveUserFromAllGroups method. -type ClientRemoveUserFromAllGroupsOptions struct { +// RemoveUserFromAllGroupsOptions contains the optional parameters for the Client.RemoveUserFromAllGroups method. +type RemoveUserFromAllGroupsOptions struct { // placeholder for future optional parameters } -// ClientRemoveUserFromGroupOptions contains the optional parameters for the Client.RemoveUserFromGroup method. -type ClientRemoveUserFromGroupOptions struct { +// RemoveUserFromGroupOptions contains the optional parameters for the Client.RemoveUserFromGroup method. +type RemoveUserFromGroupOptions struct { // placeholder for future optional parameters } -// ClientRevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. -type ClientRevokePermissionOptions struct { +// RevokePermissionOptions contains the optional parameters for the Client.RevokePermission method. +type RevokePermissionOptions struct { // The meaning of the target depends on the specific permission. For joinLeaveGroup and sendToGroup, targetName is a required // parameter standing for the group name. TargetName *string } -// ClientSendToAllOptions contains the optional parameters for the Client.SendToAll method. -type ClientSendToAllOptions struct { +// SendToAllOptions contains the optional parameters for the Client.SendToAll method. +type SendToAllOptions struct { // Excluded connection Ids. Excluded []string @@ -143,8 +143,8 @@ type ClientSendToAllOptions struct { MessageTTLSeconds *int32 } -// ClientSendToConnectionOptions contains the optional parameters for the Client.SendToConnection method. -type ClientSendToConnectionOptions struct { +// SendToConnectionOptions contains the optional parameters for the Client.SendToConnection method. +type SendToConnectionOptions struct { // The time-to-live (TTL) value in seconds for messages sent to the service. 0 is the default value, which means the message // never expires. 300 is the maximum value. If this parameter is non-zero, // messages that are not consumed by the client within the specified TTL will be dropped by the service. This parameter can @@ -152,8 +152,8 @@ type ClientSendToConnectionOptions struct { MessageTTLSeconds *int32 } -// ClientSendToGroupOptions contains the optional parameters for the Client.SendToGroup method. -type ClientSendToGroupOptions struct { +// SendToGroupOptions contains the optional parameters for the Client.SendToGroup method. +type SendToGroupOptions struct { // Excluded connection Ids Excluded []string @@ -167,8 +167,8 @@ type ClientSendToGroupOptions struct { MessageTTLSeconds *int32 } -// ClientSendToUserOptions contains the optional parameters for the Client.SendToUser method. -type ClientSendToUserOptions struct { +// SendToUserOptions contains the optional parameters for the Client.SendToUser method. +type SendToUserOptions struct { // Following OData filter syntax to filter out the subscribers receiving the messages. Filter *string @@ -179,7 +179,7 @@ type ClientSendToUserOptions struct { MessageTTLSeconds *int32 } -// ClientUserExistsOptions contains the optional parameters for the Client.UserExists method. -type ClientUserExistsOptions struct { +// UserExistsOptions contains the optional parameters for the Client.UserExists method. +type UserExistsOptions struct { // placeholder for future optional parameters } diff --git a/sdk/messaging/azwebpubsub/response_types.go b/sdk/messaging/azwebpubsub/response_types.go index b3c28b485b5b..2381808231fd 100644 --- a/sdk/messaging/azwebpubsub/response_types.go +++ b/sdk/messaging/azwebpubsub/response_types.go @@ -8,118 +8,118 @@ package azwebpubsub -// ClientAddConnectionToGroupResponse contains the response from method Client.AddConnectionToGroup. -type ClientAddConnectionToGroupResponse struct { +// AddConnectionToGroupResponse contains the response from method Client.AddConnectionToGroup. +type AddConnectionToGroupResponse struct { // placeholder for future response values } -// ClientAddConnectionsToGroupsResponse contains the response from method Client.AddConnectionsToGroups. -type ClientAddConnectionsToGroupsResponse struct { +// AddConnectionsToGroupsResponse contains the response from method Client.AddConnectionsToGroups. +type AddConnectionsToGroupsResponse struct { // placeholder for future response values } -// ClientAddUserToGroupResponse contains the response from method Client.AddUserToGroup. -type ClientAddUserToGroupResponse struct { +// AddUserToGroupResponse contains the response from method Client.AddUserToGroup. +type AddUserToGroupResponse struct { // placeholder for future response values } -// ClientCheckPermissionResponse contains the response from method Client.CheckPermission. -type ClientCheckPermissionResponse struct { +// CheckPermissionResponse contains the response from method Client.CheckPermission. +type CheckPermissionResponse struct { // placeholder for future response values } -// ClientCloseAllConnectionsResponse contains the response from method Client.CloseAllConnections. -type ClientCloseAllConnectionsResponse struct { +// CloseAllConnectionsResponse contains the response from method Client.CloseAllConnections. +type CloseAllConnectionsResponse struct { // placeholder for future response values } -// ClientCloseConnectionResponse contains the response from method Client.CloseConnection. -type ClientCloseConnectionResponse struct { +// CloseConnectionResponse contains the response from method Client.CloseConnection. +type CloseConnectionResponse struct { // placeholder for future response values } -// ClientCloseGroupConnectionsResponse contains the response from method Client.CloseGroupConnections. -type ClientCloseGroupConnectionsResponse struct { +// CloseGroupConnectionsResponse contains the response from method Client.CloseGroupConnections. +type CloseGroupConnectionsResponse struct { // placeholder for future response values } -// ClientCloseUserConnectionsResponse contains the response from method Client.CloseUserConnections. -type ClientCloseUserConnectionsResponse struct { +// CloseUserConnectionsResponse contains the response from method Client.CloseUserConnections. +type CloseUserConnectionsResponse struct { // placeholder for future response values } -// ClientConnectionExistsResponse contains the response from method Client.ConnectionExists. -type ClientConnectionExistsResponse struct { +// ConnectionExistsResponse contains the response from method Client.ConnectionExists. +type ConnectionExistsResponse struct { // placeholder for future response values } -// ClientGenerateClientTokenResponse contains the response from method Client.GenerateClientToken. -type ClientGenerateClientTokenResponse struct { +// GenerateClientTokenResponse contains the response from method Client.GenerateClientToken. +type GenerateClientTokenResponse struct { // The response object containing the token for the client - ClientTokenResponse + TokenResponse } -// ClientGrantPermissionResponse contains the response from method Client.GrantPermission. -type ClientGrantPermissionResponse struct { +// GrantPermissionResponse contains the response from method Client.GrantPermission. +type GrantPermissionResponse struct { // placeholder for future response values } -// ClientGroupExistsResponse contains the response from method Client.GroupExists. -type ClientGroupExistsResponse struct { +// GroupExistsResponse contains the response from method Client.GroupExists. +type GroupExistsResponse struct { // placeholder for future response values } -// ClientRemoveConnectionFromAllGroupsResponse contains the response from method Client.RemoveConnectionFromAllGroups. -type ClientRemoveConnectionFromAllGroupsResponse struct { +// RemoveConnectionFromAllGroupsResponse contains the response from method Client.RemoveConnectionFromAllGroups. +type RemoveConnectionFromAllGroupsResponse struct { // placeholder for future response values } -// ClientRemoveConnectionFromGroupResponse contains the response from method Client.RemoveConnectionFromGroup. -type ClientRemoveConnectionFromGroupResponse struct { +// RemoveConnectionFromGroupResponse contains the response from method Client.RemoveConnectionFromGroup. +type RemoveConnectionFromGroupResponse struct { // placeholder for future response values } -// ClientRemoveConnectionsFromGroupsResponse contains the response from method Client.RemoveConnectionsFromGroups. -type ClientRemoveConnectionsFromGroupsResponse struct { +// RemoveConnectionsFromGroupsResponse contains the response from method Client.RemoveConnectionsFromGroups. +type RemoveConnectionsFromGroupsResponse struct { // placeholder for future response values } -// ClientRemoveUserFromAllGroupsResponse contains the response from method Client.RemoveUserFromAllGroups. -type ClientRemoveUserFromAllGroupsResponse struct { +// RemoveUserFromAllGroupsResponse contains the response from method Client.RemoveUserFromAllGroups. +type RemoveUserFromAllGroupsResponse struct { // placeholder for future response values } -// ClientRemoveUserFromGroupResponse contains the response from method Client.RemoveUserFromGroup. -type ClientRemoveUserFromGroupResponse struct { +// RemoveUserFromGroupResponse contains the response from method Client.RemoveUserFromGroup. +type RemoveUserFromGroupResponse struct { // placeholder for future response values } -// ClientRevokePermissionResponse contains the response from method Client.RevokePermission. -type ClientRevokePermissionResponse struct { +// RevokePermissionResponse contains the response from method Client.RevokePermission. +type RevokePermissionResponse struct { // placeholder for future response values } -// ClientSendToAllResponse contains the response from method Client.SendToAll. -type ClientSendToAllResponse struct { +// SendToAllResponse contains the response from method Client.SendToAll. +type SendToAllResponse struct { // placeholder for future response values } -// ClientSendToConnectionResponse contains the response from method Client.SendToConnection. -type ClientSendToConnectionResponse struct { +// SendToConnectionResponse contains the response from method Client.SendToConnection. +type SendToConnectionResponse struct { // placeholder for future response values } -// ClientSendToGroupResponse contains the response from method Client.SendToGroup. -type ClientSendToGroupResponse struct { +// SendToGroupResponse contains the response from method Client.SendToGroup. +type SendToGroupResponse struct { // placeholder for future response values } -// ClientSendToUserResponse contains the response from method Client.SendToUser. -type ClientSendToUserResponse struct { +// SendToUserResponse contains the response from method Client.SendToUser. +type SendToUserResponse struct { // placeholder for future response values } -// ClientUserExistsResponse contains the response from method Client.UserExists. -type ClientUserExistsResponse struct { +// UserExistsResponse contains the response from method Client.UserExists. +type UserExistsResponse struct { // placeholder for future response values }