From f64f87d152356a219ed58476ac91c2ddb8c2bae6 Mon Sep 17 00:00:00 2001 From: Lorna Jane Mitchell Date: Wed, 25 Nov 2020 15:34:47 +0000 Subject: [PATCH 1/7] Initial codegen from Account API definition --- internal/account/api_balance.go | 203 +++++++ internal/account/api_configuration.go | 120 ++++ internal/account/api_secret_management.go | 428 ++++++++++++++ internal/account/client.go | 548 ++++++++++++++++++ internal/account/configuration.go | 130 +++++ internal/account/model_account_balance.go | 17 + internal/account/model_account_settings.go | 23 + .../account/model_account_settings_request.go | 17 + .../account/model_create_secret_request.go | 15 + .../account/model_error_api_key_not_found.go | 21 + .../model_error_authentication_failed.go | 15 + ...r_authentication_failed_account_balance.go | 15 + .../model_error_auto_reload_not_enabled.go | 15 + .../model_error_secret_id_not_found.go | 21 + internal/account/model_secret_info.go | 18 + internal/account/model_secret_mgmt_links.go | 14 + .../account/model_secret_mgmt_links_self.go | 15 + internal/account/model_success.go | 15 + internal/account/model_topup_request.go | 15 + internal/account/response.go | 46 ++ 20 files changed, 1711 insertions(+) create mode 100644 internal/account/api_balance.go create mode 100644 internal/account/api_configuration.go create mode 100644 internal/account/api_secret_management.go create mode 100644 internal/account/client.go create mode 100644 internal/account/configuration.go create mode 100644 internal/account/model_account_balance.go create mode 100644 internal/account/model_account_settings.go create mode 100644 internal/account/model_account_settings_request.go create mode 100644 internal/account/model_create_secret_request.go create mode 100644 internal/account/model_error_api_key_not_found.go create mode 100644 internal/account/model_error_authentication_failed.go create mode 100644 internal/account/model_error_authentication_failed_account_balance.go create mode 100644 internal/account/model_error_auto_reload_not_enabled.go create mode 100644 internal/account/model_error_secret_id_not_found.go create mode 100644 internal/account/model_secret_info.go create mode 100644 internal/account/model_secret_mgmt_links.go create mode 100644 internal/account/model_secret_mgmt_links_self.go create mode 100644 internal/account/model_success.go create mode 100644 internal/account/model_topup_request.go create mode 100644 internal/account/response.go diff --git a/internal/account/api_balance.go b/internal/account/api_balance.go new file mode 100644 index 0000000..1069adf --- /dev/null +++ b/internal/account/api_balance.go @@ -0,0 +1,203 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account + +import ( + _context "context" + _ioutil "io/ioutil" + _nethttp "net/http" + _neturl "net/url" +) + +// Linger please +var ( + _ _context.Context +) + +// BalanceApiService BalanceApi service +type BalanceApiService service + +/* +GetAccountBalance Get Account Balance +Retrieve the current balance of your Vonage API account + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param apiKey Your Vonage API key. You can find this in the [dashboard](https://dashboard.nexmo.com) + * @param apiSecret Your Vonage API secret. You can find this in the [dashboard](https://dashboard.nexmo.com) +@return AccountBalance +*/ +func (a *BalanceApiService) GetAccountBalance(ctx _context.Context, apiKey string, apiSecret string) (AccountBalance, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue AccountBalance + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/account/get-balance" + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + localVarQueryParams.Add("api_key", parameterToString(apiKey, "")) + localVarQueryParams.Add("api_secret", parameterToString(apiSecret, "")) + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json", "application/xml"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v ErrorAuthenticationFailedAccountBalance + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +/* +TopUpAccountBalance Top Up Account Balance +You can top up your account using this API when you have enabled auto-reload in the dashboard. The amount added by the top-up operation will be the same amount as was added in the payment when auto-reload was enabled. Your account balance is checked every 5-10 minutes and if it falls below the threshold and auto-reload is enabled, then it will be topped up automatically. Use this endpoint if you need to top up at times when your credit may be exhausted more quickly than the auto-reload may occur. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param apiKey Your Vonage API key. You can find this in the [dashboard](https://dashboard.nexmo.com) + * @param apiSecret Your Vonage API secret. You can find this in the [dashboard](https://dashboard.nexmo.com) + * @param trx The transaction reference of the transaction when balance was added and auto-reload was enabled on your account. +@return Success +*/ +func (a *BalanceApiService) TopUpAccountBalance(ctx _context.Context, apiKey string, apiSecret string, trx string) (Success, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Success + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/account/top-up" + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + localVarQueryParams.Add("api_key", parameterToString(apiKey, "")) + localVarQueryParams.Add("api_secret", parameterToString(apiSecret, "")) + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/x-www-form-urlencoded"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json", "application/xml"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + localVarFormParams.Add("trx", parameterToString(trx, "")) + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v OneOfErrorAuthenticationFailedErrorAutoReloadNotEnabled + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/internal/account/api_configuration.go b/internal/account/api_configuration.go new file mode 100644 index 0000000..70a3429 --- /dev/null +++ b/internal/account/api_configuration.go @@ -0,0 +1,120 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account + +import ( + _context "context" + _ioutil "io/ioutil" + _nethttp "net/http" + _neturl "net/url" + "github.com/antihax/optional" +) + +// Linger please +var ( + _ _context.Context +) + +// ConfigurationApiService ConfigurationApi service +type ConfigurationApiService service + +// ChangeAccountSettingsOpts Optional parameters for the method 'ChangeAccountSettings' +type ChangeAccountSettingsOpts struct { + MoCallBackUrl optional.String + DrCallBackUrl optional.String +} + +/* +ChangeAccountSettings Change Account Settings +Update the default callback URLs (where the webhooks are sent to) associated with your account: * Callback URL for incoming SMS messages * Callback URL for delivery receipts Note that the URLs you provide must be valid and active. Vonage will check that they return a 200 OK response before the setting is saved. + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param apiKey Your Vonage API key. You can find this in the [dashboard](https://dashboard.nexmo.com) + * @param apiSecret Your Vonage API secret. You can find this in the [dashboard](https://dashboard.nexmo.com) + * @param optional nil or *ChangeAccountSettingsOpts - Optional Parameters: + * @param "MoCallBackUrl" (optional.String) - The URL where Vonage will send a webhook when an SMS is received to a Vonage number that does not have SMS handling configured. Send an empty string to unset this value. + * @param "DrCallBackUrl" (optional.String) - The URL where Vonage will send a webhook when an delivery receipt is received without a specific callback URL configured. Send an empty string to unset this value. +@return AccountSettings +*/ +func (a *ConfigurationApiService) ChangeAccountSettings(ctx _context.Context, apiKey string, apiSecret string, localVarOptionals *ChangeAccountSettingsOpts) (AccountSettings, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue AccountSettings + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/account/settings" + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + localVarQueryParams.Add("api_key", parameterToString(apiKey, "")) + localVarQueryParams.Add("api_secret", parameterToString(apiSecret, "")) + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/x-www-form-urlencoded"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json", "application/xml"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if localVarOptionals != nil && localVarOptionals.MoCallBackUrl.IsSet() { + localVarFormParams.Add("moCallBackUrl", parameterToString(localVarOptionals.MoCallBackUrl.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.DrCallBackUrl.IsSet() { + localVarFormParams.Add("drCallBackUrl", parameterToString(localVarOptionals.DrCallBackUrl.Value(), "")) + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/internal/account/api_secret_management.go b/internal/account/api_secret_management.go new file mode 100644 index 0000000..1005806 --- /dev/null +++ b/internal/account/api_secret_management.go @@ -0,0 +1,428 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account + +import ( + _context "context" + _ioutil "io/ioutil" + _nethttp "net/http" + _neturl "net/url" + "strings" +) + +// Linger please +var ( + _ _context.Context +) + +// SecretManagementApiService SecretManagementApi service +type SecretManagementApiService service + +/* +CreateAPISecret Create API Secret + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param apiKey The API key to manage secrets for + * @param createSecretRequest +@return SecretInfo +*/ +func (a *SecretManagementApiService) CreateAPISecret(ctx _context.Context, apiKey string, createSecretRequest CreateSecretRequest) (SecretInfo, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue SecretInfo + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets" + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = &createSecretRequest + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 400 { + var v map[string]interface{} + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 401 { + var v map[string]interface{} + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v ErrorApiKeyNotFound + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +/* +RetrieveAPISecret Retrieve one API Secret + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param apiKey The API key to manage secrets for + * @param secretId ID of the API Secret +@return SecretInfo +*/ +func (a *SecretManagementApiService) RetrieveAPISecret(ctx _context.Context, apiKey string, secretId string) (SecretInfo, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue SecretInfo + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets/{secret_id}" + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + + localVarPath = strings.Replace(localVarPath, "{"+"secret_id"+"}", _neturl.QueryEscape(parameterToString(secretId, "")) , -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v map[string]interface{} + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v OneOfErrorApiKeyNotFoundErrorSecretIdNotFound + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +/* +RetrieveAPISecrets Retrieve API Secrets + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param apiKey The API key to manage secrets for +@return map[string]interface{} +*/ +func (a *SecretManagementApiService) RetrieveAPISecrets(ctx _context.Context, apiKey string) (map[string]interface{}, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue map[string]interface{} + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets" + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v map[string]interface{} + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v ErrorApiKeyNotFound + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +/* +RevokeAPISecret Revoke an API Secret + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param apiKey The API key to manage secrets for + * @param secretId ID of the API Secret +*/ +func (a *SecretManagementApiService) RevokeAPISecret(ctx _context.Context, apiKey string, secretId string) (*_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodDelete + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets/{secret_id}" + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + + localVarPath = strings.Replace(localVarPath, "{"+"secret_id"+"}", _neturl.QueryEscape(parameterToString(secretId, "")) , -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(r) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 401 { + var v map[string]interface{} + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 403 { + var v map[string]interface{} + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + return localVarHTTPResponse, newErr + } + if localVarHTTPResponse.StatusCode == 404 { + var v OneOfErrorApiKeyNotFoundErrorSecretIdNotFound + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = v + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/internal/account/client.go b/internal/account/client.go new file mode 100644 index 0000000..a08dff0 --- /dev/null +++ b/internal/account/client.go @@ -0,0 +1,548 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account + +import ( + "bytes" + "context" + "encoding/json" + "encoding/xml" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "mime/multipart" + "net/http" + "net/http/httputil" + "net/url" + "os" + "path/filepath" + "reflect" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" + + "golang.org/x/oauth2" +) + +var ( + jsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:vnd\.[^;]+\+)?json)`) + xmlCheck = regexp.MustCompile(`(?i:(?:application|text)/xml)`) +) + +// APIClient manages communication with the Account API API v1.0.3 +// In most cases there should be only one, shared, APIClient. +type APIClient struct { + cfg *Configuration + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // API Services + + BalanceApi *BalanceApiService + + ConfigurationApi *ConfigurationApiService + + SecretManagementApi *SecretManagementApiService +} + +type service struct { + client *APIClient +} + +// NewAPIClient creates a new API client. Requires a userAgent string describing your application. +// optionally a custom http.Client to allow for advanced features such as caching. +func NewAPIClient(cfg *Configuration) *APIClient { + if cfg.HTTPClient == nil { + cfg.HTTPClient = http.DefaultClient + } + + c := &APIClient{} + c.cfg = cfg + c.common.client = c + + // API Services + c.BalanceApi = (*BalanceApiService)(&c.common) + c.ConfigurationApi = (*ConfigurationApiService)(&c.common) + c.SecretManagementApi = (*SecretManagementApiService)(&c.common) + + return c +} + +func atoi(in string) (int, error) { + return strconv.Atoi(in) +} + +// selectHeaderContentType select a content type from the available list. +func selectHeaderContentType(contentTypes []string) string { + if len(contentTypes) == 0 { + return "" + } + if contains(contentTypes, "application/json") { + return "application/json" + } + return contentTypes[0] // use the first content type specified in 'consumes' +} + +// selectHeaderAccept join all accept types and return +func selectHeaderAccept(accepts []string) string { + if len(accepts) == 0 { + return "" + } + + if contains(accepts, "application/json") { + return "application/json" + } + + return strings.Join(accepts, ",") +} + +// contains is a case insenstive match, finding needle in a haystack +func contains(haystack []string, needle string) bool { + for _, a := range haystack { + if strings.ToLower(a) == strings.ToLower(needle) { + return true + } + } + return false +} + +// Verify optional parameters are of the correct type. +func typeCheckParameter(obj interface{}, expected string, name string) error { + // Make sure there is an object. + if obj == nil { + return nil + } + + // Check the type is as expected. + if reflect.TypeOf(obj).String() != expected { + return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String()) + } + return nil +} + +// parameterToString convert interface{} parameters to string, using a delimiter if format is provided. +func parameterToString(obj interface{}, collectionFormat string) string { + var delimiter string + + switch collectionFormat { + case "pipes": + delimiter = "|" + case "ssv": + delimiter = " " + case "tsv": + delimiter = "\t" + case "csv": + delimiter = "," + } + + if reflect.TypeOf(obj).Kind() == reflect.Slice { + return strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]") + } else if t, ok := obj.(time.Time); ok { + return t.Format(time.RFC3339) + } + + return fmt.Sprintf("%v", obj) +} + +// helper for converting interface{} parameters to json strings +func parameterToJson(obj interface{}) (string, error) { + jsonBuf, err := json.Marshal(obj) + if err != nil { + return "", err + } + return string(jsonBuf), err +} + + +// callAPI do the request. +func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) { + if c.cfg.Debug { + dump, err := httputil.DumpRequestOut(request, true) + if err != nil { + return nil, err + } + log.Printf("\n%s\n", string(dump)) + } + + resp, err := c.cfg.HTTPClient.Do(request) + if err != nil { + return resp, err + } + + if c.cfg.Debug { + dump, err := httputil.DumpResponse(resp, true) + if err != nil { + return resp, err + } + log.Printf("\n%s\n", string(dump)) + } + + return resp, err +} + +// ChangeBasePath changes base path to allow switching to mocks +func (c *APIClient) ChangeBasePath(path string) { + c.cfg.BasePath = path +} + +// Allow modification of underlying config for alternate implementations and testing +// Caution: modifying the configuration while live can cause data races and potentially unwanted behavior +func (c *APIClient) GetConfig() *Configuration { + return c.cfg +} + +// prepareRequest build the request +func (c *APIClient) prepareRequest( + ctx context.Context, + path string, method string, + postBody interface{}, + headerParams map[string]string, + queryParams url.Values, + formParams url.Values, + formFileName string, + fileName string, + fileBytes []byte) (localVarRequest *http.Request, err error) { + + var body *bytes.Buffer + + // Detect postBody type and post. + if postBody != nil { + contentType := headerParams["Content-Type"] + if contentType == "" { + contentType = detectContentType(postBody) + headerParams["Content-Type"] = contentType + } + + body, err = setBody(postBody, contentType) + if err != nil { + return nil, err + } + } + + // add form parameters and file if available. + if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(fileBytes) > 0 && fileName != "") { + if body != nil { + return nil, errors.New("Cannot specify postBody and multipart form at the same time.") + } + body = &bytes.Buffer{} + w := multipart.NewWriter(body) + + for k, v := range formParams { + for _, iv := range v { + if strings.HasPrefix(k, "@") { // file + err = addFile(w, k[1:], iv) + if err != nil { + return nil, err + } + } else { // form value + w.WriteField(k, iv) + } + } + } + if len(fileBytes) > 0 && fileName != "" { + w.Boundary() + //_, fileNm := filepath.Split(fileName) + part, err := w.CreateFormFile(formFileName, filepath.Base(fileName)) + if err != nil { + return nil, err + } + _, err = part.Write(fileBytes) + if err != nil { + return nil, err + } + } + + // Set the Boundary in the Content-Type + headerParams["Content-Type"] = w.FormDataContentType() + + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + w.Close() + } + + if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 { + if body != nil { + return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.") + } + body = &bytes.Buffer{} + body.WriteString(formParams.Encode()) + // Set Content-Length + headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len()) + } + + // Setup path and query parameters + url, err := url.Parse(path) + if err != nil { + return nil, err + } + + // Override request host, if applicable + if c.cfg.Host != "" { + url.Host = c.cfg.Host + } + + // Override request scheme, if applicable + if c.cfg.Scheme != "" { + url.Scheme = c.cfg.Scheme + } + + // Adding Query Param + query := url.Query() + for k, v := range queryParams { + for _, iv := range v { + query.Add(k, iv) + } + } + + // Encode the parameters. + url.RawQuery = query.Encode() + + // Generate a new request + if body != nil { + localVarRequest, err = http.NewRequest(method, url.String(), body) + } else { + localVarRequest, err = http.NewRequest(method, url.String(), nil) + } + if err != nil { + return nil, err + } + + // add header parameters, if any + if len(headerParams) > 0 { + headers := http.Header{} + for h, v := range headerParams { + headers.Set(h, v) + } + localVarRequest.Header = headers + } + + // Add the user agent to the request. + localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent) + + if ctx != nil { + // add context to the request + localVarRequest = localVarRequest.WithContext(ctx) + + // Walk through any authentication. + + // OAuth2 authentication + if tok, ok := ctx.Value(ContextOAuth2).(oauth2.TokenSource); ok { + // We were able to grab an oauth2 token from the context + var latestToken *oauth2.Token + if latestToken, err = tok.Token(); err != nil { + return nil, err + } + + latestToken.SetAuthHeader(localVarRequest) + } + + // Basic HTTP Authentication + if auth, ok := ctx.Value(ContextBasicAuth).(BasicAuth); ok { + localVarRequest.SetBasicAuth(auth.UserName, auth.Password) + } + + // AccessToken Authentication + if auth, ok := ctx.Value(ContextAccessToken).(string); ok { + localVarRequest.Header.Add("Authorization", "Bearer "+auth) + } + + } + + for header, value := range c.cfg.DefaultHeader { + localVarRequest.Header.Add(header, value) + } + + return localVarRequest, nil +} + +func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { + if len(b) == 0 { + return nil + } + if s, ok := v.(*string); ok { + *s = string(b) + return nil + } + if f, ok := v.(**os.File); ok { + *f, err = ioutil.TempFile("", "HttpClientFile") + if err != nil { + return + } + _, err = (*f).Write(b) + _, err = (*f).Seek(0, io.SeekStart) + return + } + if xmlCheck.MatchString(contentType) { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } + if jsonCheck.MatchString(contentType) { + if err = json.Unmarshal(b, v); err != nil { + return err + } + return nil + } + return errors.New("undefined response type") +} + +// Add a file to the multipart request +func addFile(w *multipart.Writer, fieldName, path string) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + part, err := w.CreateFormFile(fieldName, filepath.Base(path)) + if err != nil { + return err + } + _, err = io.Copy(part, file) + + return err +} + +// Prevent trying to import "fmt" +func reportError(format string, a ...interface{}) error { + return fmt.Errorf(format, a...) +} + +// Set request body from an interface{} +func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { + if bodyBuf == nil { + bodyBuf = &bytes.Buffer{} + } + + if reader, ok := body.(io.Reader); ok { + _, err = bodyBuf.ReadFrom(reader) + } else if b, ok := body.([]byte); ok { + _, err = bodyBuf.Write(b) + } else if s, ok := body.(string); ok { + _, err = bodyBuf.WriteString(s) + } else if s, ok := body.(*string); ok { + _, err = bodyBuf.WriteString(*s) + } else if jsonCheck.MatchString(contentType) { + err = json.NewEncoder(bodyBuf).Encode(body) + } else if xmlCheck.MatchString(contentType) { + err = xml.NewEncoder(bodyBuf).Encode(body) + } + + if err != nil { + return nil, err + } + + if bodyBuf.Len() == 0 { + err = fmt.Errorf("Invalid body type %s\n", contentType) + return nil, err + } + return bodyBuf, nil +} + +// detectContentType method is used to figure out `Request.Body` content type for request header +func detectContentType(body interface{}) string { + contentType := "text/plain; charset=utf-8" + kind := reflect.TypeOf(body).Kind() + + switch kind { + case reflect.Struct, reflect.Map, reflect.Ptr: + contentType = "application/json; charset=utf-8" + case reflect.String: + contentType = "text/plain; charset=utf-8" + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = "application/json; charset=utf-8" + } + } + + return contentType +} + +// Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// CacheExpires helper function to determine remaining time before repeating a request. +func CacheExpires(r *http.Response) time.Time { + // Figure out when the cache expires. + var expires time.Time + now, err := time.Parse(time.RFC1123, r.Header.Get("date")) + if err != nil { + return time.Now() + } + respCacheControl := parseCacheControl(r.Header) + + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err := time.ParseDuration(maxAge + "s") + if err != nil { + expires = now + } else { + expires = now.Add(lifetime) + } + } else { + expiresHeader := r.Header.Get("Expires") + if expiresHeader != "" { + expires, err = time.Parse(time.RFC1123, expiresHeader) + if err != nil { + expires = now + } + } + } + return expires +} + +func strlen(s string) int { + return utf8.RuneCountInString(s) +} + +// GenericOpenAPIError Provides access to the body, error and model on returned errors. +type GenericOpenAPIError struct { + body []byte + error string + model interface{} +} + +// Error returns non-empty string if there was an error. +func (e GenericOpenAPIError) Error() string { + return e.error +} + +// Body returns the raw bytes of the response +func (e GenericOpenAPIError) Body() []byte { + return e.body +} + +// Model returns the unpacked model of the error +func (e GenericOpenAPIError) Model() interface{} { + return e.model +} diff --git a/internal/account/configuration.go b/internal/account/configuration.go new file mode 100644 index 0000000..9b08660 --- /dev/null +++ b/internal/account/configuration.go @@ -0,0 +1,130 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account + +import ( + "fmt" + "net/http" + "strings" +) + +// contextKeys are used to identify the type of value in the context. +// Since these are string, it is possible to get a short description of the +// context key for logging and debugging using key.String(). + +type contextKey string + +func (c contextKey) String() string { + return "auth " + string(c) +} + +var ( + // ContextOAuth2 takes an oauth2.TokenSource as authentication for the request. + ContextOAuth2 = contextKey("token") + + // ContextBasicAuth takes BasicAuth as authentication for the request. + ContextBasicAuth = contextKey("basic") + + // ContextAccessToken takes a string oauth2 access token as authentication for the request. + ContextAccessToken = contextKey("accesstoken") + + // ContextAPIKey takes an APIKey as authentication for the request + ContextAPIKey = contextKey("apikey") + +) + +// BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth +type BasicAuth struct { + UserName string `json:"userName,omitempty"` + Password string `json:"password,omitempty"` +} + +// APIKey provides API key based authentication to a request passed via context using ContextAPIKey +type APIKey struct { + Key string + Prefix string +} + + +// ServerVariable stores the information about a server variable +type ServerVariable struct { + Description string + DefaultValue string + EnumValues []string +} + +// ServerConfiguration stores the information about a server +type ServerConfiguration struct { + Url string + Description string + Variables map[string]ServerVariable +} + +// Configuration stores the configuration of the API client +type Configuration struct { + BasePath string `json:"basePath,omitempty"` + Host string `json:"host,omitempty"` + Scheme string `json:"scheme,omitempty"` + DefaultHeader map[string]string `json:"defaultHeader,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + Debug bool `json:"debug,omitempty"` + Servers []ServerConfiguration + HTTPClient *http.Client +} + +// NewConfiguration returns a new Configuration object +func NewConfiguration() *Configuration { + cfg := &Configuration{ + BasePath: "https://api.nexmo.com", + DefaultHeader: make(map[string]string), + UserAgent: "OpenAPI-Generator/1.0.0/go", + Debug: false, + Servers: []ServerConfiguration{ + { + Url: "https://api.nexmo.com", + Description: "No description provided", + }, + }, + } + return cfg +} + +// AddDefaultHeader adds a new HTTP header to the default header in the request +func (c *Configuration) AddDefaultHeader(key string, value string) { + c.DefaultHeader[key] = value +} + +// ServerUrl returns URL based on server settings +func (c *Configuration) ServerUrl(index int, variables map[string]string) (string, error) { + if index < 0 || len(c.Servers) <= index { + return "", fmt.Errorf("Index %v out of range %v", index, len(c.Servers) - 1) + } + server := c.Servers[index] + url := server.Url + + // go through variables and replace placeholders + for name, variable := range server.Variables { + if value, ok := variables[name]; ok { + found := bool(len(variable.EnumValues) == 0) + for _, enumValue := range variable.EnumValues { + if value == enumValue { + found = true + } + } + if !found { + return "", fmt.Errorf("The variable %s in the server URL has invalid value %v. Must be %v", name, value, variable.EnumValues) + } + url = strings.Replace(url, "{"+name+"}", value, -1) + } else { + url = strings.Replace(url, "{"+name+"}", variable.DefaultValue, -1) + } + } + return url, nil +} diff --git a/internal/account/model_account_balance.go b/internal/account/model_account_balance.go new file mode 100644 index 0000000..67e215a --- /dev/null +++ b/internal/account/model_account_balance.go @@ -0,0 +1,17 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// AccountBalance struct for AccountBalance +type AccountBalance struct { + // The balance of the account, in EUR + Value float32 `json:"value,omitempty"` + // Whether the account has auto-reloading enabled + AutoReload bool `json:"autoReload,omitempty"` +} diff --git a/internal/account/model_account_settings.go b/internal/account/model_account_settings.go new file mode 100644 index 0000000..dc1bfd6 --- /dev/null +++ b/internal/account/model_account_settings.go @@ -0,0 +1,23 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// AccountSettings struct for AccountSettings +type AccountSettings struct { + // The current or updated inbound message URI + MoCallbackUrl string `json:"mo-callback-url,omitempty"` + // The current or updated delivery receipt URI + DrCallbackUrl string `json:"dr-callback-url,omitempty"` + // The maximum number of outbound messages per second. + MaxOutboundRequest int32 `json:"max-outbound-request,omitempty"` + // The maximum number of inbound messages per second. + MaxInboundRequest int32 `json:"max-inbound-request,omitempty"` + // The maximum number of API calls per second. + MaxCallsPerSecond int32 `json:"max-calls-per-second,omitempty"` +} diff --git a/internal/account/model_account_settings_request.go b/internal/account/model_account_settings_request.go new file mode 100644 index 0000000..d1ce94c --- /dev/null +++ b/internal/account/model_account_settings_request.go @@ -0,0 +1,17 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// AccountSettingsRequest struct for AccountSettingsRequest +type AccountSettingsRequest struct { + // The URL where Vonage will send a webhook when an SMS is received to a Vonage number that does not have SMS handling configured. Send an empty string to unset this value. + MoCallBackUrl string `json:"moCallBackUrl,omitempty"` + // The URL where Vonage will send a webhook when an delivery receipt is received without a specific callback URL configured. Send an empty string to unset this value. + DrCallBackUrl string `json:"drCallBackUrl,omitempty"` +} diff --git a/internal/account/model_create_secret_request.go b/internal/account/model_create_secret_request.go new file mode 100644 index 0000000..cff211a --- /dev/null +++ b/internal/account/model_create_secret_request.go @@ -0,0 +1,15 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// CreateSecretRequest struct for CreateSecretRequest +type CreateSecretRequest struct { + // The new secret must follow these rules: * minimum 8 characters * maximum 25 characters * minimum 1 lower case character * minimum 1 upper case character * minimum 1 digit + Secret string `json:"secret"` +} diff --git a/internal/account/model_error_api_key_not_found.go b/internal/account/model_error_api_key_not_found.go new file mode 100644 index 0000000..3759ce8 --- /dev/null +++ b/internal/account/model_error_api_key_not_found.go @@ -0,0 +1,21 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// ErrorApiKeyNotFound This API key was not recognised +type ErrorApiKeyNotFound struct { + // URL for further information + Type string `json:"type"` + // Description of the error + Title string `json:"title"` + // More detail regarding this error, including the API key supplied + Detail string `json:"detail"` + // Internal Trace ID + Instance string `json:"instance"` +} diff --git a/internal/account/model_error_authentication_failed.go b/internal/account/model_error_authentication_failed.go new file mode 100644 index 0000000..2614db3 --- /dev/null +++ b/internal/account/model_error_authentication_failed.go @@ -0,0 +1,15 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// ErrorAuthenticationFailed Authentication Failed +type ErrorAuthenticationFailed struct { + ErrorCode *interface{} `json:"error-code,omitempty"` + ErrorCodeLabel *interface{} `json:"error-code-label,omitempty"` +} diff --git a/internal/account/model_error_authentication_failed_account_balance.go b/internal/account/model_error_authentication_failed_account_balance.go new file mode 100644 index 0000000..f37924e --- /dev/null +++ b/internal/account/model_error_authentication_failed_account_balance.go @@ -0,0 +1,15 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// ErrorAuthenticationFailedAccountBalance Authentication Failed +type ErrorAuthenticationFailedAccountBalance struct { + ErrorCode *interface{} `json:"error-code,omitempty"` + ErrorCodeLabel *interface{} `json:"error-code-label,omitempty"` +} diff --git a/internal/account/model_error_auto_reload_not_enabled.go b/internal/account/model_error_auto_reload_not_enabled.go new file mode 100644 index 0000000..f718862 --- /dev/null +++ b/internal/account/model_error_auto_reload_not_enabled.go @@ -0,0 +1,15 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// ErrorAutoReloadNotEnabled Auto-Reload not enabled +type ErrorAutoReloadNotEnabled struct { + ErrorCode *interface{} `json:"error-code,omitempty"` + ErrorCodeLabel *interface{} `json:"error-code-label,omitempty"` +} diff --git a/internal/account/model_error_secret_id_not_found.go b/internal/account/model_error_secret_id_not_found.go new file mode 100644 index 0000000..2bf69ac --- /dev/null +++ b/internal/account/model_error_secret_id_not_found.go @@ -0,0 +1,21 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// ErrorSecretIdNotFound This secret ID was not recognised +type ErrorSecretIdNotFound struct { + // URL for further information + Type string `json:"type"` + // Description of the error + Title string `json:"title"` + // More detail regarding this error, including the secret ID supplied + Detail string `json:"detail"` + // Internal Trace ID + Instance string `json:"instance"` +} diff --git a/internal/account/model_secret_info.go b/internal/account/model_secret_info.go new file mode 100644 index 0000000..995a547 --- /dev/null +++ b/internal/account/model_secret_info.go @@ -0,0 +1,18 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// SecretInfo struct for SecretInfo +type SecretInfo struct { + Links SecretMgmtLinks `json:"_links,omitempty"` + // Secret ID + Id string `json:"id,omitempty"` + // Creation date/time for this secret + CreatedAt string `json:"created_at,omitempty"` +} diff --git a/internal/account/model_secret_mgmt_links.go b/internal/account/model_secret_mgmt_links.go new file mode 100644 index 0000000..fde286a --- /dev/null +++ b/internal/account/model_secret_mgmt_links.go @@ -0,0 +1,14 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// SecretMgmtLinks Links related to this resource +type SecretMgmtLinks struct { + Self SecretMgmtLinksSelf `json:"self,omitempty"` +} diff --git a/internal/account/model_secret_mgmt_links_self.go b/internal/account/model_secret_mgmt_links_self.go new file mode 100644 index 0000000..047df15 --- /dev/null +++ b/internal/account/model_secret_mgmt_links_self.go @@ -0,0 +1,15 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// SecretMgmtLinksSelf This resource +type SecretMgmtLinksSelf struct { + // The URI for this resource + Href string `json:"href,omitempty"` +} diff --git a/internal/account/model_success.go b/internal/account/model_success.go new file mode 100644 index 0000000..5441aac --- /dev/null +++ b/internal/account/model_success.go @@ -0,0 +1,15 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// Success struct for Success +type Success struct { + ErrorCode *interface{} `json:"error-code,omitempty"` + ErrorCodeLabel *interface{} `json:"error-code-label,omitempty"` +} diff --git a/internal/account/model_topup_request.go b/internal/account/model_topup_request.go new file mode 100644 index 0000000..d942ed3 --- /dev/null +++ b/internal/account/model_topup_request.go @@ -0,0 +1,15 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account +// TopupRequest struct for TopupRequest +type TopupRequest struct { + // The transaction reference of the transaction when balance was added and auto-reload was enabled on your account. + Trx string `json:"trx"` +} diff --git a/internal/account/response.go b/internal/account/response.go new file mode 100644 index 0000000..2210df4 --- /dev/null +++ b/internal/account/response.go @@ -0,0 +1,46 @@ +/* + * Account API + * + * Enables users to manage their Vonage API Account by programmable means. More information is available here: . + * + * API version: 1.0.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package account + +import ( + "net/http" +) + +// APIResponse stores the API response returned by the server. +type APIResponse struct { + *http.Response `json:"-"` + Message string `json:"message,omitempty"` + // Operation is the name of the OpenAPI operation. + Operation string `json:"operation,omitempty"` + // RequestURL is the request URL. This value is always available, even if the + // embedded *http.Response is nil. + RequestURL string `json:"url,omitempty"` + // Method is the HTTP method used for the request. This value is always + // available, even if the embedded *http.Response is nil. + Method string `json:"method,omitempty"` + // Payload holds the contents of the response body (which may be nil or empty). + // This is provided here as the raw response.Body() reader will have already + // been drained. + Payload []byte `json:"-"` +} + +// NewAPIResponse returns a new APIResonse object. +func NewAPIResponse(r *http.Response) *APIResponse { + + response := &APIResponse{Response: r} + return response +} + +// NewAPIResponseWithError returns a new APIResponse object with the provided error message. +func NewAPIResponseWithError(errorMessage string) *APIResponse { + + response := &APIResponse{Message: errorMessage} + return response +} From 258ffb5b395fbefc6145773b3427776a52228964 Mon Sep 17 00:00:00 2001 From: Lorna Jane Mitchell Date: Wed, 25 Nov 2020 16:34:12 +0000 Subject: [PATCH 2/7] Work around the problems caused by OneOf and the code generator --- internal/account/api_balance.go | 2 +- internal/account/api_secret_management.go | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/account/api_balance.go b/internal/account/api_balance.go index 1069adf..07815a5 100644 --- a/internal/account/api_balance.go +++ b/internal/account/api_balance.go @@ -179,7 +179,7 @@ func (a *BalanceApiService) TopUpAccountBalance(ctx _context.Context, apiKey str error: localVarHTTPResponse.Status, } if localVarHTTPResponse.StatusCode == 401 { - var v OneOfErrorAuthenticationFailedErrorAutoReloadNotEnabled + var v ErrorAuthenticationFailed err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() diff --git a/internal/account/api_secret_management.go b/internal/account/api_secret_management.go index 1005806..de550e2 100644 --- a/internal/account/api_secret_management.go +++ b/internal/account/api_secret_management.go @@ -44,7 +44,7 @@ func (a *SecretManagementApiService) CreateAPISecret(ctx _context.Context, apiKe // create path and map variables localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets" - localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := _neturl.Values{} @@ -153,9 +153,9 @@ func (a *SecretManagementApiService) RetrieveAPISecret(ctx _context.Context, api // create path and map variables localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets/{secret_id}" - localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"secret_id"+"}", _neturl.QueryEscape(parameterToString(secretId, "")) , -1) + localVarPath = strings.Replace(localVarPath, "{"+"secret_id"+"}", _neturl.QueryEscape(parameterToString(secretId, "")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := _neturl.Values{} @@ -210,7 +210,7 @@ func (a *SecretManagementApiService) RetrieveAPISecret(ctx _context.Context, api return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 404 { - var v OneOfErrorApiKeyNotFoundErrorSecretIdNotFound + var v ErrorApiKeyNotFound err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() @@ -251,7 +251,7 @@ func (a *SecretManagementApiService) RetrieveAPISecrets(ctx _context.Context, ap // create path and map variables localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets" - localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := _neturl.Values{} @@ -346,9 +346,9 @@ func (a *SecretManagementApiService) RevokeAPISecret(ctx _context.Context, apiKe // create path and map variables localVarPath := a.client.cfg.BasePath + "/accounts/{api_key}/secrets/{secret_id}" - localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")) , -1) + localVarPath = strings.Replace(localVarPath, "{"+"api_key"+"}", _neturl.QueryEscape(parameterToString(apiKey, "")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"secret_id"+"}", _neturl.QueryEscape(parameterToString(secretId, "")) , -1) + localVarPath = strings.Replace(localVarPath, "{"+"secret_id"+"}", _neturl.QueryEscape(parameterToString(secretId, "")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := _neturl.Values{} @@ -413,7 +413,7 @@ func (a *SecretManagementApiService) RevokeAPISecret(ctx _context.Context, apiKe return localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 404 { - var v OneOfErrorApiKeyNotFoundErrorSecretIdNotFound + var v ErrorApiKeyNotFound err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() From 299fa64cec5f651133622b9c6dcffafa26f08c61 Mon Sep 17 00:00:00 2001 From: Lorna Jane Mitchell Date: Wed, 25 Nov 2020 16:35:31 +0000 Subject: [PATCH 3/7] Add get balance for account with docs and a test --- account.go | 57 ++++++++++++++++++++++++++++++++++++++++ account_test.go | 42 +++++++++++++++++++++++++++++ docs/examples/account.md | 32 ++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 account.go create mode 100644 account_test.go create mode 100644 docs/examples/account.md diff --git a/account.go b/account.go new file mode 100644 index 0000000..1ca9651 --- /dev/null +++ b/account.go @@ -0,0 +1,57 @@ +package vonage + +import ( + "context" + + "github.com/vonage/vonage-go-sdk/internal/account" +) + +// AccountClient for working with the SMS API +type AccountClient struct { + Config *account.Configuration + apiKey string + apiSecret string +} + +// NewAccountClient Creates a new Account Client, supplying an Auth to work with +func NewAccountClient(Auth Auth) *AccountClient { + client := new(AccountClient) + creds := Auth.GetCreds() + client.apiKey = creds[0] + client.apiSecret = creds[1] + + // Use a default set of config but make it accessible + client.Config = account.NewConfiguration() + client.Config.UserAgent = GetUserAgent() + + // Does not pick up correct server URL from OpenAPI description + client.Config.BasePath = "https://rest.nexmo.com" + return client +} + +type AccountBalance struct { + Value float32 + AutoReload bool +} + +type AccountBalanceErrorResponse struct { + ErrorCode string + ErrorCodeLabel string +} + +// GetBalance fetches the current balance of the authenticated account, in Euros +func (client *AccountClient) GetBalance() (AccountBalance, AccountBalanceErrorResponse, error) { + + accountClient := account.NewAPIClient(client.Config) + + ctx := context.Background() + + // fetch the balance + result, _, err := accountClient.BalanceApi.GetAccountBalance(ctx, client.apiKey, client.apiSecret) + + if err != nil { + return AccountBalance{}, AccountBalanceErrorResponse{}, err + } + + return AccountBalance(result), AccountBalanceErrorResponse{}, nil +} diff --git a/account_test.go b/account_test.go new file mode 100644 index 0000000..c09c8cb --- /dev/null +++ b/account_test.go @@ -0,0 +1,42 @@ +package vonage + +import ( + "net/http" + "testing" + + "github.com/jarcoal/httpmock" +) + +func TestAccountNewAccountClient(*testing.T) { + auth := CreateAuthFromKeySecret("123", "456") + NewAccountClient(auth) +} + +func TestAccountGetBalance(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("GET", "https://rest.nexmo.com/account/get-balance", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(200, ` +{ + "value": 10.28, + "autoReload": false +} + `, + ) + + resp.Header.Add("Content-Type", "application/json") + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("12345678", "456") + client := NewAccountClient(auth) + result, _, _ := client.GetBalance() + + balance := result.Value + if balance != 10.28 { + t.Error("Test account get balance failed") + } +} diff --git a/docs/examples/account.md b/docs/examples/account.md new file mode 100644 index 0000000..28c5dee --- /dev/null +++ b/docs/examples/account.md @@ -0,0 +1,32 @@ +--- +title: Account API +permalink: examples/account +--- + +Account API gives access to check your balance, rotate your account secrets and configure the default behaviour of your account. Check out the [documentation](https://developer.nexmo.com/account/overview) and [API reference](https://developer.nexmo.com/api/account) for more details. + +## Get Account Balance + +Check the current balance on your account. + +```golang +package main + +import ( + "fmt" + + "github.com/vonage/vonage-go-sdk" +) + +func main() { + auth := vonage.CreateAuthFromKeySecret(API_KEY, API_SECRET) + accountClient := vonage.NewAccountClient(auth) + response, _, err := accountClient.GetBalance() + + if err != nil { + panic(err) + } + + fmt.Printf("Account balance: %f EUR", response.Value) +} +``` From 0ca2a18c8f96e69bab5739adc74e61b7214691e0 Mon Sep 17 00:00:00 2001 From: Lorna Jane Mitchell Date: Tue, 15 Dec 2020 16:45:43 +0000 Subject: [PATCH 4/7] Add Account config setting with test and docs --- account.go | 60 ++++++++++++++++++++++++++++++++++++---- account_test.go | 56 +++++++++++++++++++++++++++++++++++++ docs/examples/account.md | 32 +++++++++++++++++++++ 3 files changed, 142 insertions(+), 6 deletions(-) diff --git a/account.go b/account.go index 1ca9651..dd2b7af 100644 --- a/account.go +++ b/account.go @@ -2,7 +2,9 @@ package vonage import ( "context" + "encoding/json" + "github.com/antihax/optional" "github.com/vonage/vonage-go-sdk/internal/account" ) @@ -34,13 +36,13 @@ type AccountBalance struct { AutoReload bool } -type AccountBalanceErrorResponse struct { - ErrorCode string - ErrorCodeLabel string +type AccountErrorResponse struct { + ErrorCode string `json:"error-code,omitempty"` + ErrorCodeLabel string `json:"error-code-label,omitempty"` } // GetBalance fetches the current balance of the authenticated account, in Euros -func (client *AccountClient) GetBalance() (AccountBalance, AccountBalanceErrorResponse, error) { +func (client *AccountClient) GetBalance() (AccountBalance, AccountErrorResponse, error) { accountClient := account.NewAPIClient(client.Config) @@ -50,8 +52,54 @@ func (client *AccountClient) GetBalance() (AccountBalance, AccountBalanceErrorRe result, _, err := accountClient.BalanceApi.GetAccountBalance(ctx, client.apiKey, client.apiSecret) if err != nil { - return AccountBalance{}, AccountBalanceErrorResponse{}, err + return AccountBalance{}, AccountErrorResponse{}, err } - return AccountBalance(result), AccountBalanceErrorResponse{}, nil + return AccountBalance(result), AccountErrorResponse{}, nil +} + +type AccountConfigSettings struct { + MoCallbackUrl string + DrCallbackUrl string +} + +type AccountConfigResponse struct { + MoCallbackUrl string + DrCallbackUrl string + MaxOutboundRequest int32 + MaxInboundRequest int32 + MaxCallsPerSecond int32 +} + +// SetConfig allows the user to set the URLs for incoming SMS (mo) and delivery receipt (dr) payloads +func (client *AccountClient) SetConfig(config AccountConfigSettings) (AccountConfigResponse, AccountErrorResponse, error) { + + accountClient := account.NewAPIClient(client.Config) + + ctx := context.Background() + + opts := account.ChangeAccountSettingsOpts{} + if config.MoCallbackUrl != "" { + opts.MoCallBackUrl = optional.NewString(config.MoCallbackUrl) + } + if config.DrCallbackUrl != "" { + opts.DrCallBackUrl = optional.NewString(config.DrCallbackUrl) + } + + // update Account settings + result, _, err := accountClient.ConfigurationApi.ChangeAccountSettings(ctx, client.apiKey, client.apiSecret, &opts) + + if err != nil { + e := err.(account.GenericOpenAPIError) + data := e.Body() + + var errResp AccountErrorResponse + jsonErr := json.Unmarshal(data, &errResp) + if jsonErr == nil { + return AccountConfigResponse{}, errResp, err + } + + } + + return AccountConfigResponse(result), AccountErrorResponse{}, nil } diff --git a/account_test.go b/account_test.go index c09c8cb..579e197 100644 --- a/account_test.go +++ b/account_test.go @@ -40,3 +40,59 @@ func TestAccountGetBalance(t *testing.T) { t.Error("Test account get balance failed") } } + +func TestAccountSetConfig(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("POST", "https://rest.nexmo.com/account/settings", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(200, ` +{ + "mo-callback-url": "https://example.com/webhooks/inbound-sms", + "dr-callback-url": "https://example.com/webhooks/delivery-receipt", + "max-outbound-request": 30, + "max-inbound-request": 30, + "max-calls-per-second": 30 +} + `, + ) + + resp.Header.Add("Content-Type", "application/json") + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("12345678", "456") + client := NewAccountClient(auth) + result, _, _ := client.SetConfig(AccountConfigSettings{}) + + if result.MoCallbackUrl != "https://example.com/webhooks/inbound-sms" { + t.Error("Test account set config failed") + } +} + +func TestAccountSetConfigNoAuth(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("POST", "https://rest.nexmo.com/account/settings", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(420, ` +{"max-outbound-request":0,"max-inbound-request":0,"max-calls-per-second":0,"error-code":"420","error-code-label":"API key is required"} + `, + ) + + resp.Header.Add("Content-Type", "application/json") + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("", "") + client := NewAccountClient(auth) + _, resp, _ := client.SetConfig(AccountConfigSettings{}) + + if resp.ErrorCode != "420" { + t.Error("Test account set config missing auth behaviour failed") + } +} diff --git a/docs/examples/account.md b/docs/examples/account.md index 28c5dee..c40e22d 100644 --- a/docs/examples/account.md +++ b/docs/examples/account.md @@ -30,3 +30,35 @@ func main() { fmt.Printf("Account balance: %f EUR", response.Value) } ``` + +## Configure Account + +Set the default URLs for incoming SMS and delivery receipt payloads to be sent to. If the number has settings, that will be used but otherwise we fall back to this account API setting. + +```go +package main + +import ( + "fmt" + + "github.com/vonage/vonage-go-sdk" +) + +func main() { + auth := vonage.CreateAuthFromKeySecret(API_KEY, API_SECRET) + accountClient := vonage.NewAccountClient(auth) + + opts := vonage.AccountConfigSettings{ + MoCallbackUrl: "https://example.com/webhooks/inbound-sms", + DrCallbackUrl: "https://example.com/webhooks/delivery-receipt" + } + response, _, err := accountClient.SetConfig(opts) + + if err != nil { + panic(err) + } + + fmt.Println("Incoming SMS sent to: " + response.MoCallbackUrl) +} +``` + From 90446ee4b841bd20702bdcb7e16bcb7daf1e2182 Mon Sep 17 00:00:00 2001 From: Lorna Jane Mitchell Date: Wed, 16 Dec 2020 11:25:39 +0000 Subject: [PATCH 5/7] Enable listing all secrets via Account API --- account.go | 75 ++++++++++++++++++++++++++++++++++++++-- account_test.go | 44 +++++++++++++++++++++++ docs/examples/account.md | 29 ++++++++++++++++ 3 files changed, 146 insertions(+), 2 deletions(-) diff --git a/account.go b/account.go index dd2b7af..335253a 100644 --- a/account.go +++ b/account.go @@ -3,6 +3,7 @@ package vonage import ( "context" "encoding/json" + "time" "github.com/antihax/optional" "github.com/vonage/vonage-go-sdk/internal/account" @@ -26,8 +27,6 @@ func NewAccountClient(Auth Auth) *AccountClient { client.Config = account.NewConfiguration() client.Config.UserAgent = GetUserAgent() - // Does not pick up correct server URL from OpenAPI description - client.Config.BasePath = "https://rest.nexmo.com" return client } @@ -43,6 +42,12 @@ type AccountErrorResponse struct { // GetBalance fetches the current balance of the authenticated account, in Euros func (client *AccountClient) GetBalance() (AccountBalance, AccountErrorResponse, error) { + // default config is not correct + // so override if it's still using the default setting. + defaultConfig := account.NewConfiguration() + if defaultConfig.BasePath == client.Config.BasePath { + client.Config.BasePath = "https://rest.nexmo.com" + } accountClient := account.NewAPIClient(client.Config) @@ -73,6 +78,12 @@ type AccountConfigResponse struct { // SetConfig allows the user to set the URLs for incoming SMS (mo) and delivery receipt (dr) payloads func (client *AccountClient) SetConfig(config AccountConfigSettings) (AccountConfigResponse, AccountErrorResponse, error) { + // default config is not correct + // so override if it's still using the default setting. + defaultConfig := account.NewConfiguration() + if defaultConfig.BasePath == client.Config.BasePath { + client.Config.BasePath = "https://rest.nexmo.com" + } accountClient := account.NewAPIClient(client.Config) @@ -103,3 +114,63 @@ func (client *AccountClient) SetConfig(config AccountConfigSettings) (AccountCon return AccountConfigResponse(result), AccountErrorResponse{}, nil } + +type AccountSecret struct { + ID string + CreatedAt time.Time +} + +type AccountSecretCollection struct { + Secrets []AccountSecret +} + +type AccountSecretErrorResponse struct { + Type string `json:"type,omitempty"` + Title string `json:"title,omitempty"` + Detail string `json:"detail,omitempty"` + Instance string `json:"instance,omitempty"` +} + +func (client *AccountClient) ListSecrets() (AccountSecretCollection, AccountSecretErrorResponse, error) { + accountClient := account.NewAPIClient(client.Config) + + ctx := context.WithValue(context.Background(), account.ContextBasicAuth, account.BasicAuth{ + UserName: client.apiKey, + Password: client.apiSecret, + }) + + // get secrets + result, _, err := accountClient.SecretManagementApi.RetrieveAPISecrets(ctx, client.apiKey) + + if err != nil { + e, ok := err.(account.GenericOpenAPIError) + if ok { + data := e.Body() + + var errResp AccountSecretErrorResponse + jsonErr := json.Unmarshal(data, &errResp) + if jsonErr == nil { + return AccountSecretCollection{}, errResp, err + } + // if we didn't get the expected format but it was an openapi error + return AccountSecretCollection{}, AccountSecretErrorResponse{}, e + } + // something else went wrong + return AccountSecretCollection{}, AccountSecretErrorResponse{}, err + } + + // lots and lots of type assertions needed here because of how the API description is structured + data := result["_embedded"].(map[string]interface{}) + list := data["secrets"].([]interface{}) + var collection AccountSecretCollection + + for i := 0; i < len(list); i++ { + secret := list[i].(map[string]interface{}) + createdAt, _ := time.Parse(time.RFC3339, secret["created_at"].(string)) + collection.Secrets = append( + collection.Secrets, + AccountSecret{ID: secret["id"].(string), CreatedAt: createdAt}, + ) + } + return collection, AccountSecretErrorResponse{}, nil +} diff --git a/account_test.go b/account_test.go index 579e197..156d169 100644 --- a/account_test.go +++ b/account_test.go @@ -96,3 +96,47 @@ func TestAccountSetConfigNoAuth(t *testing.T) { t.Error("Test account set config missing auth behaviour failed") } } + +func TestAccountListSecrets(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("GET", "https://api.nexmo.com/accounts/12345678/secrets", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(200, ` +{ + "_links": { + "self": { + "href": "abc123" + } + }, + "_embedded": { + "secrets": [ + { + "_links": { + "self": { + "href": "abc123" + } + }, + "id": "ad6dc56f-07b5-46e1-a527-85530e625800", + "created_at": "2017-03-02T16:34:49Z" + } + ] + } +} + `, + ) + + resp.Header.Add("Content-Type", "application/json") + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("12345678", "456") + client := NewAccountClient(auth) + result, _, _ := client.ListSecrets() + + if result.Secrets[0].ID != "ad6dc56f-07b5-46e1-a527-85530e625800" { + t.Error("Test account list secrets failed") + } +} diff --git a/docs/examples/account.md b/docs/examples/account.md index c40e22d..6007bd1 100644 --- a/docs/examples/account.md +++ b/docs/examples/account.md @@ -62,3 +62,32 @@ func main() { } ``` +## Fetch All Account Secrets + +This endpoint returns the secret ID (needed to identify the secret for deletion) and creation date for all the secrets on this account. + +```go +package main + +import ( + "fmt" + + "github.com/vonage/vonage-go-sdk" +) + +func main() { + auth := vonage.CreateAuthFromKeySecret(API_KEY, API_SECRET) + accountClient := vonage.NewAccountClient(auth) + + response, _, err := accountClient.ListSecrets() + + if err != nil { + panic(err) + } + + for i := 0; i < len(response.Secrets); i++ { + date := response.Secrets[i].CreatedAt.Format("Jan 2 2006") + fmt.Println("Secret " + response.Secrets[i].ID + " created " + date) + } +} +``` \ No newline at end of file From 276d5f9465a37c4edee75ad17e933f881197c080 Mon Sep 17 00:00:00 2001 From: Lorna Jane Mitchell Date: Wed, 16 Dec 2020 15:59:08 +0000 Subject: [PATCH 6/7] Add support for getting one secret from the Account API --- account.go | 34 +++++++++++++++++++++ account_test.go | 64 ++++++++++++++++++++++++++++++++++++++++ docs/examples/account.md | 32 +++++++++++++++++++- 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/account.go b/account.go index 335253a..104903a 100644 --- a/account.go +++ b/account.go @@ -174,3 +174,37 @@ func (client *AccountClient) ListSecrets() (AccountSecretCollection, AccountSecr } return collection, AccountSecretErrorResponse{}, nil } + +// GetSecret retrieves data about a single account secret +func (client *AccountClient) GetSecret(id string) (AccountSecret, AccountSecretErrorResponse, error) { + accountClient := account.NewAPIClient(client.Config) + + ctx := context.WithValue(context.Background(), account.ContextBasicAuth, account.BasicAuth{ + UserName: client.apiKey, + Password: client.apiSecret, + }) + + // get secrets + result, _, err := accountClient.SecretManagementApi.RetrieveAPISecret(ctx, client.apiKey, id) + + if err != nil { + e, ok := err.(account.GenericOpenAPIError) + if ok { + data := e.Body() + + var errResp AccountSecretErrorResponse + jsonErr := json.Unmarshal(data, &errResp) + if jsonErr == nil { + return AccountSecret{}, errResp, err + } + // if we didn't get the expected format but it was an openapi error + return AccountSecret{}, AccountSecretErrorResponse{}, e + } + // something else went wrong + return AccountSecret{}, AccountSecretErrorResponse{}, err + } + + createdAt, _ := time.Parse(time.RFC3339, result.CreatedAt) + secret := AccountSecret{ID: result.Id, CreatedAt: createdAt} + return secret, AccountSecretErrorResponse{}, nil +} diff --git a/account_test.go b/account_test.go index 156d169..320ffdc 100644 --- a/account_test.go +++ b/account_test.go @@ -140,3 +140,67 @@ func TestAccountListSecrets(t *testing.T) { t.Error("Test account list secrets failed") } } + +func TestAccountGetSecret(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("GET", "https://api.nexmo.com/accounts/12345678/secrets/ad6dc56f-07b5-46e1-a527-85530e625800", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(200, ` +{ + "_links": { + "self": { + "href": "abc123" + } + }, + "id": "ad6dc56f-07b5-46e1-a527-85530e625800", + "created_at": "2017-03-02T16:34:49Z" +} + `, + ) + + resp.Header.Add("Content-Type", "application/json") + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("12345678", "456") + client := NewAccountClient(auth) + result, _, _ := client.GetSecret("ad6dc56f-07b5-46e1-a527-85530e625800") + + if result.ID != "ad6dc56f-07b5-46e1-a527-85530e625800" { + t.Error("Test account get one failed") + } +} +func TestAccountGetMissingSecret(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("GET", "https://api.nexmo.com/accounts/12345678/secrets/does-not-exist", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(404, ` +{ + "_links": { + "self": { + "href": "abc123" + } + }, + "id": "ad6dc56f-07b5-46e1-a527-85530e625800", + "created_at": "2017-03-02T16:34:49Z" +} + `, + ) + + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("12345678", "456") + client := NewAccountClient(auth) + _, _, err := client.GetSecret("does-not-exist") + + if err == nil { + t.Error("Test account get one missing secret failed") + } +} diff --git a/docs/examples/account.md b/docs/examples/account.md index 6007bd1..6ebd4a2 100644 --- a/docs/examples/account.md +++ b/docs/examples/account.md @@ -90,4 +90,34 @@ func main() { fmt.Println("Secret " + response.Secrets[i].ID + " created " + date) } } -``` \ No newline at end of file +``` + +## Fetch One Account Secret + +This endpoint returns the secret ID and creation date for the secret requested. + +```go +package main + +import ( + "fmt" + + "github.com/vonage/vonage-go-sdk" +) + +func main() { + auth := vonage.CreateAuthFromKeySecret(API_KEY, API_SECRET) + accountClient := vonage.NewAccountClient(auth) + + response, _, err := accountClient.GetSecret("abcdefab-0000-1111-2222-0123456789ef") + + if err != nil { + panic(err) + } + + if response.ID != "" { + date := response.CreatedAt.Format("Jan 2 2006") + fmt.Println("Secret " + response.ID + " created " + date) + } +} +``` From 4e49701f35567475c21355619133dc6407d46ac9 Mon Sep 17 00:00:00 2001 From: Lorna Jane Mitchell Date: Fri, 18 Dec 2020 13:45:01 +0000 Subject: [PATCH 7/7] Add create/delete secret for account API --- account.go | 67 ++++++++++++++++++++++++++++++++++++++ account_test.go | 56 +++++++++++++++++++++++++++++++- docs/examples/account.md | 69 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/account.go b/account.go index 104903a..36406ce 100644 --- a/account.go +++ b/account.go @@ -208,3 +208,70 @@ func (client *AccountClient) GetSecret(id string) (AccountSecret, AccountSecretE secret := AccountSecret{ID: result.Id, CreatedAt: createdAt} return secret, AccountSecretErrorResponse{}, nil } + +// CreateSecret adds an additional secret to the account (the number of secrets allowed is limited) +func (client *AccountClient) CreateSecret(secret string) (AccountSecret, AccountSecretErrorResponse, error) { + accountClient := account.NewAPIClient(client.Config) + + ctx := context.WithValue(context.Background(), account.ContextBasicAuth, account.BasicAuth{ + UserName: client.apiKey, + Password: client.apiSecret, + }) + + request := account.CreateSecretRequest{Secret: secret} + + result, _, err := accountClient.SecretManagementApi.CreateAPISecret(ctx, client.apiKey, request) + + if err != nil { + e, ok := err.(account.GenericOpenAPIError) + if ok { + data := e.Body() + + var errResp AccountSecretErrorResponse + jsonErr := json.Unmarshal(data, &errResp) + if jsonErr == nil { + return AccountSecret{}, errResp, err + } + // if we didn't get the expected format but it was an openapi error + return AccountSecret{}, AccountSecretErrorResponse{}, e + } + // something else went wrong + return AccountSecret{}, AccountSecretErrorResponse{}, err + } + + createdAt, _ := time.Parse(time.RFC3339, result.CreatedAt) + new_secret := AccountSecret{ID: result.Id, CreatedAt: createdAt} + return new_secret, AccountSecretErrorResponse{}, nil +} + +// DeleteSecret adds an additional secret to the account (the number of secrets allowed is limited) +func (client *AccountClient) DeleteSecret(id string) (bool, AccountSecretErrorResponse, error) { + accountClient := account.NewAPIClient(client.Config) + + ctx := context.WithValue(context.Background(), account.ContextBasicAuth, account.BasicAuth{ + UserName: client.apiKey, + Password: client.apiSecret, + }) + + // this one only returns two values because it's a 204 so no actual response + _, err := accountClient.SecretManagementApi.RevokeAPISecret(ctx, client.apiKey, id) + + if err != nil { + e, ok := err.(account.GenericOpenAPIError) + if ok { + data := e.Body() + + var errResp AccountSecretErrorResponse + jsonErr := json.Unmarshal(data, &errResp) + if jsonErr == nil { + return false, errResp, err + } + // if we didn't get the expected format but it was an openapi error + return false, AccountSecretErrorResponse{}, e + } + // something else went wrong + return false, AccountSecretErrorResponse{}, err + } + + return true, AccountSecretErrorResponse{}, nil +} diff --git a/account_test.go b/account_test.go index 320ffdc..290536d 100644 --- a/account_test.go +++ b/account_test.go @@ -170,7 +170,7 @@ func TestAccountGetSecret(t *testing.T) { result, _, _ := client.GetSecret("ad6dc56f-07b5-46e1-a527-85530e625800") if result.ID != "ad6dc56f-07b5-46e1-a527-85530e625800" { - t.Error("Test account get one failed") + t.Error("Test account get one secret failed") } } func TestAccountGetMissingSecret(t *testing.T) { @@ -204,3 +204,57 @@ func TestAccountGetMissingSecret(t *testing.T) { t.Error("Test account get one missing secret failed") } } + +func TestAccountCreateSecret(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("POST", "https://api.nexmo.com/accounts/12345678/secrets", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(201, ` +{ + "_links": { + "self": { + "href": "/accounts/12345678/secrets/c07c0604-dc5b-4520-94df-dc4964b2fbca" + } + }, + "id": "c07c0604-dc5b-4520-94df-dc4964b2fbca", + "created_at": "2020-10-18T13:37:15Z" +} + `, + ) + + resp.Header.Add("Content-Type", "application/json") + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("12345678", "456") + client := NewAccountClient(auth) + result, _, _ := client.CreateSecret("V3ryS3cr3t!") + + if result.ID != "c07c0604-dc5b-4520-94df-dc4964b2fbca" { + t.Error("Test account create secret failed") + } +} + +func TestAccountDeleteSecret(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + httpmock.RegisterResponder("DELETE", "https://api.nexmo.com/accounts/12345678/secrets/ad6dc56f-07b5-46e1-a527-85530e625800", + func(req *http.Request) (*http.Response, error) { + resp := httpmock.NewStringResponse(204, "") + + return resp, nil + }, + ) + + auth := CreateAuthFromKeySecret("12345678", "456") + client := NewAccountClient(auth) + result, _, _ := client.DeleteSecret("ad6dc56f-07b5-46e1-a527-85530e625800") + + if result != true { + t.Error("Test account delete secret failed") + } +} diff --git a/docs/examples/account.md b/docs/examples/account.md index 6ebd4a2..52008e7 100644 --- a/docs/examples/account.md +++ b/docs/examples/account.md @@ -5,6 +5,13 @@ permalink: examples/account Account API gives access to check your balance, rotate your account secrets and configure the default behaviour of your account. Check out the [documentation](https://developer.nexmo.com/account/overview) and [API reference](https://developer.nexmo.com/api/account) for more details. +- [Get Account Balance](#get-account-balance) +- [Configure Account](#configure-account) +- [Fetch All Account Secrets](#fetch-all-account-secrets) +- [Fetch One Account Secret](#fetch-one-account-secret) +- [Create Account Secret](#create-account-secret) +- [Revoke Account Secret](#revoke-account-secret) + ## Get Account Balance Check the current balance on your account. @@ -121,3 +128,65 @@ func main() { } } ``` + +## Create Account Secret + +To change account secrets, first add a new secret. Then update your application and when it's using the new secret, revoke the old secret. + +```go +package main + +import ( + "fmt" + + "github.com/vonage/vonage-go-sdk" +) + +func main() { + auth := vonage.CreateAuthFromKeySecret(API_KEY, API_SECRET) + accountClient := vonage.NewAccountClient(auth) + + response, errResp, err := accountClient.CreateSecret("T0pS3cr3t!") + + if err != nil { + fmt.Println("ERROR: " + errResp.Title + ": " + errResp.Detail) + } + + if response.ID != "" { + date := response.CreatedAt.Format("Jan 2 2006") + fmt.Println("Secret " + response.ID + " created " + date) + } +} +``` + +## Revoke Account Secret + +Revoke an account secret by its ID. Note that you can't revoke the only secret you have, so add a new one before attempting to delete the existing one. + +This method returns a boolean to indicate if the deletion was successful. + +```go +package main + +import ( + "fmt" + + "github.com/vonage/vonage-go-sdk" +) + +func main() { + auth := vonage.CreateAuthFromKeySecret(API_KEY, API_SECRET) + accountClient := vonage.NewAccountClient(auth) + + ok, errResp, err := accountClient.DeleteSecret("abcdefab-0000-1111-2222-0123456789ef") + + if err != nil { + fmt.Println("ERROR: " + errResp.Title + ": " + errResp.Detail) + } + + if ok { + fmt.Println("Secret deleted") + } + +} +```