diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 8b11ed43..9cbf5158 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,8 +1,8 @@ [package] -distribution = "2201.8.0" +distribution = "2201.10.0" org = "ballerinax" name = "twilio" -version = "4.0.1" +version = "5.0.0" authors = ["Ballerina"] repository = "https://github.com/ballerina-platform/module-ballerinax-twilio" keywords = ["Communication/Call & SMS", "Cost/Paid"] @@ -10,4 +10,4 @@ icon = "icon.png" license = ["Apache-2.0"] [build-options] -observabilityIncluded = false +observabilityIncluded = true diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 67d7de2f..b04de546 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,12 +5,12 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.8.4" +distribution-version = "2201.10.0" [[package]] org = "ballerina" name = "auth" -version = "2.10.0" +version = "2.12.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "jballerina.java"}, @@ -22,7 +22,7 @@ dependencies = [ [[package]] org = "ballerina" name = "cache" -version = "3.7.1" +version = "3.8.0" dependencies = [ {org = "ballerina", name = "constraint"}, {org = "ballerina", name = "jballerina.java"}, @@ -44,7 +44,7 @@ modules = [ [[package]] org = "ballerina" name = "crypto" -version = "2.5.0" +version = "2.7.2" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "time"} @@ -53,7 +53,7 @@ dependencies = [ [[package]] org = "ballerina" name = "file" -version = "1.9.0" +version = "1.10.0" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -64,7 +64,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.10.7" +version = "2.12.2" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -96,7 +96,7 @@ modules = [ [[package]] org = "ballerina" name = "io" -version = "1.6.0" +version = "1.6.1" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} @@ -110,10 +110,11 @@ version = "0.0.0" [[package]] org = "ballerina" name = "jwt" -version = "2.10.0" +version = "2.13.0" dependencies = [ {org = "ballerina", name = "cache"}, {org = "ballerina", name = "crypto"}, + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.int"}, {org = "ballerina", name = "lang.string"}, @@ -207,7 +208,7 @@ dependencies = [ [[package]] org = "ballerina" name = "log" -version = "2.9.0" +version = "2.10.0" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -221,17 +222,18 @@ modules = [ [[package]] org = "ballerina" name = "mime" -version = "2.9.0" +version = "2.10.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.int"} + {org = "ballerina", name = "lang.int"}, + {org = "ballerina", name = "log"} ] [[package]] org = "ballerina" name = "oauth2" -version = "2.10.0" +version = "2.12.0" dependencies = [ {org = "ballerina", name = "cache"}, {org = "ballerina", name = "crypto"}, @@ -244,7 +246,7 @@ dependencies = [ [[package]] org = "ballerina" name = "observe" -version = "1.2.2" +version = "1.3.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] @@ -277,6 +279,7 @@ version = "0.0.0" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.array"}, {org = "ballerina", name = "lang.error"} ] modules = [ @@ -286,7 +289,7 @@ modules = [ [[package]] org = "ballerina" name = "time" -version = "2.4.0" +version = "2.5.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] @@ -317,7 +320,7 @@ modules = [ [[package]] org = "ballerinax" name = "twilio" -version = "4.0.1" +version = "5.0.0" dependencies = [ {org = "ballerina", name = "constraint"}, {org = "ballerina", name = "http"}, diff --git a/ballerina/client.bal b/ballerina/client.bal index 7984b00a..e3e4e04e 100644 --- a/ballerina/client.bal +++ b/ballerina/client.bal @@ -27,8 +27,9 @@ public isolated client class Client { # + serviceUrl - URL of the target service # + return - An error if connector initialization failed public isolated function init(ConnectionConfig config, string serviceUrl = "https://api.twilio.com") returns error? { - self.accountSid = config.auth.username; - self.generatedClient = check new (config, serviceUrl); + self.accountSid = config.auth.accountSid; + oas:ConnectionConfig oasConnectionConfig = getOasConnectionConfig(config); + self.generatedClient = check new (oasConnectionConfig, serviceUrl); } # Retrieves a collection of Accounts belonging to the account used to make the request # @@ -2097,3 +2098,34 @@ public isolated client class Client { return self.generatedClient->deleteUserDefinedMessageSubscription(accountSid ?: self.accountSid, callSid, sid); } } + +isolated function getOasConnectionConfig(ConnectionConfig config) returns oas:ConnectionConfig => { + auth: getAuthConfig(config.auth), + httpVersion: config.httpVersion, + http1Settings: config.http1Settings, + http2Settings: config.http2Settings, + timeout: config.timeout, + forwarded: config.forwarded, + poolConfig: config.poolConfig, + cache: config.cache, + circuitBreaker: config.circuitBreaker, + compression: config.compression, + retryConfig: config.retryConfig, + responseLimits: config.responseLimits, + secureSocket: config.secureSocket, + proxy: config.proxy, + validation: config.validation +}; + +isolated function getAuthConfig(AuthTokenConfig|ApiKeyConfig config) returns http:CredentialsConfig { + if config is AuthTokenConfig { + return { + username: config.accountSid, + password: config.authToken + }; + } + return { + username: config.apiKey, + password: config.apiSecret + }; +} diff --git a/ballerina/tests/README.md b/ballerina/tests/README.md index aa2813ce..656d074d 100644 --- a/ballerina/tests/README.md +++ b/ballerina/tests/README.md @@ -57,6 +57,8 @@ accountSid="" authToken="" toPhoneNumber="" fromPhoneNumber="" +apiKey="" +apiSecret="" ``` #### Using Environment Variables @@ -68,6 +70,8 @@ export ACCOUNT_SID="" export AUTH_TOKEN="" export TO_PHONE="" export TWILIO_PHONE="" +export API_KEY="" +export API_SECRET="" ``` Then, run the following command to run the tests: diff --git a/ballerina/tests/tests.bal b/ballerina/tests/tests.bal index 8250702f..8a7d1f01 100644 --- a/ballerina/tests/tests.bal +++ b/ballerina/tests/tests.bal @@ -73,10 +73,10 @@ CreateMessageRequest msgReq = { function initializeClientsForTwilioServer () returns error? { if (isTestOnLiveServer) { log:printInfo("Running tests on actual server"); - twilio = check new ({auth: {username: accountSid, password: authToken}}); + twilio = check new ({auth: {accountSid: accountSid, authToken: authToken}}); } else { log:printInfo("Running tests on mock server"); - twilio = check new ({auth: {username: accountSid, password: authToken}}, serviceUrl = "http://localhost:9090/"); + twilio = check new ({auth: {accountSid: accountSid, authToken: authToken}}, serviceUrl = "http://localhost:9090/"); } } @test:Config { diff --git a/ballerina/types.bal b/ballerina/types.bal index 669fb71e..1b94a029 100644 --- a/ballerina/types.bal +++ b/ballerina/types.bal @@ -24,7 +24,7 @@ import ballerina/http; @display {label: "Connection Config"} public type ConnectionConfig record {| # Configurations related to client authentication - http:CredentialsConfig auth; + AuthTokenConfig|ApiKeyConfig auth; # The HTTP version understood by the client http:HttpVersion httpVersion = http:HTTP_2_0; # Configurations related to HTTP/1.x protocol @@ -55,6 +55,28 @@ public type ConnectionConfig record {| boolean validation = true; |}; +# Twilio Auth token Based Authentication configuration. +# +# + accountSid - Twilio account SID +# + authToken - Twilio authentication token of the account +@display{label: "Auth token based authentication config"} +public type AuthTokenConfig record {| + string accountSid; + string authToken; +|}; + +# Twilio API Key Based Authentication configurations. +# +# + apiKey - Twilio API key SID +# + apiSecret - Twilio API key Secret +# + accountSid - Twilio account SID +@display{label: "API Key Based authentication config"} +public type ApiKeyConfig record {| + string apiKey; + string apiSecret; + string accountSid; +|}; + # Provides settings related to HTTP/1.x protocol. public type ClientHttp1Settings record {| # Specifies whether to reuse a connection for multiple requests diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index f5355539..98ad863d 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -1,5 +1,5 @@ [package] -distribution = "2201.8.0" +distribution = "2201.10.0" org = "ballerinax" name = "twilio" version = "@toml.version@" diff --git a/examples/accounts/create-sub-account/main.bal b/examples/accounts/create-sub-account/main.bal index 0f3fd07b..b0a4da7a 100644 --- a/examples/accounts/create-sub-account/main.bal +++ b/examples/accounts/create-sub-account/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/accounts/fetch-account/main.bal b/examples/accounts/fetch-account/main.bal index 30a89d10..de3e0d0c 100644 --- a/examples/accounts/fetch-account/main.bal +++ b/examples/accounts/fetch-account/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/accounts/fetch-balance/main.bal b/examples/accounts/fetch-balance/main.bal index d001525b..bdc64cd7 100644 --- a/examples/accounts/fetch-balance/main.bal +++ b/examples/accounts/fetch-balance/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/accounts/list-accounts/main.bal b/examples/accounts/list-accounts/main.bal index dd3b9642..12209b38 100644 --- a/examples/accounts/list-accounts/main.bal +++ b/examples/accounts/list-accounts/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/accounts/update-account/main.bal b/examples/accounts/update-account/main.bal index 41ff96da..70943a5e 100644 --- a/examples/accounts/update-account/main.bal +++ b/examples/accounts/update-account/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/authentication/api-key-auth/API key authentication.md b/examples/authentication/api-key-auth/API key authentication.md new file mode 100644 index 00000000..c5cf4dfe --- /dev/null +++ b/examples/authentication/api-key-auth/API key authentication.md @@ -0,0 +1,26 @@ +# API Key Based Authentication in Ballerina Twilio Connector + +This example demonstrates how to authenticate your requests to Twilio Account using API Key based authentication in Ballerina Twilio Connector. + +## Prerequisites + +### 1. Set up +Refer to the setup guide in [ReadMe](../../../README.md) for necessary credentials. + +### 2. Configuration + +Configure Twilio API credentials in `Config.toml` in the example directory: + +```toml +API_KEY="" +API_SECRET="" +ACCOUNT_SID="" +``` + +## Run the Example + +Execute the following command to run the example: + +```bash +bal run +``` \ No newline at end of file diff --git a/examples/authentication/api-key-auth/Ballerina.toml b/examples/authentication/api-key-auth/Ballerina.toml new file mode 100644 index 00000000..3a99d3d5 --- /dev/null +++ b/examples/authentication/api-key-auth/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "twilio_samples" +name = "api_key_auth" +version = "0.1.0" +distribution = "2201.10.1" + +[build-options] +observabilityIncluded = true diff --git a/examples/authentication/api-key-auth/main.bal b/examples/authentication/api-key-auth/main.bal new file mode 100644 index 00000000..da388b7b --- /dev/null +++ b/examples/authentication/api-key-auth/main.bal @@ -0,0 +1,46 @@ +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.org). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/io; +import ballerina/os; +import ballerinax/twilio; + +configurable string accountSid = os:getEnv("ACCOUNT_SID"); +configurable string apiKey = os:getEnv("API_KEY"); +configurable string apiSecret = os:getEnv("API_SECRET"); + +// Twilio API Key based authentication configurations +twilio:ConnectionConfig twilioConfig = { + auth: { + apiKey, + apiSecret, + accountSid + } +}; + +// This sample demonstrates a scenario where Twilio connector is used to send a text message to a number. +public function main() returns error? { + twilio:Client twilio = check new (twilioConfig); + + twilio:CreateMessageRequest messageRequest = { + To: "+00123456789", + From: "+00123456789", + Body: "Hello from Ballerina" + }; + + twilio:Message response = check twilio->createMessage(messageRequest); + io:print("Message Status: ",response?.status); +} diff --git a/examples/calls/create-call/main.bal b/examples/calls/create-call/main.bal index 15d2f078..50c6e396 100644 --- a/examples/calls/create-call/main.bal +++ b/examples/calls/create-call/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/calls/delete-call-log/main.bal b/examples/calls/delete-call-log/main.bal index dbfd1860..6401b16a 100644 --- a/examples/calls/delete-call-log/main.bal +++ b/examples/calls/delete-call-log/main.bal @@ -25,8 +25,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/calls/fetch-call-log/main.bal b/examples/calls/fetch-call-log/main.bal index b750b315..8dd52b5f 100644 --- a/examples/calls/fetch-call-log/main.bal +++ b/examples/calls/fetch-call-log/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/calls/list-call-logs/main.bal b/examples/calls/list-call-logs/main.bal index eb1d82fe..c4ca82d3 100644 --- a/examples/calls/list-call-logs/main.bal +++ b/examples/calls/list-call-logs/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/messages/create-sms-message/main.bal b/examples/messages/create-sms-message/main.bal index 6f5364ce..5e3a1531 100644 --- a/examples/messages/create-sms-message/main.bal +++ b/examples/messages/create-sms-message/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/messages/create-whatsapp-message/main.bal b/examples/messages/create-whatsapp-message/main.bal index 0dc0093c..01014b2b 100644 --- a/examples/messages/create-whatsapp-message/main.bal +++ b/examples/messages/create-whatsapp-message/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/messages/delete-message-log/main.bal b/examples/messages/delete-message-log/main.bal index a38552f2..2472775e 100644 --- a/examples/messages/delete-message-log/main.bal +++ b/examples/messages/delete-message-log/main.bal @@ -25,8 +25,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/messages/fetch-message-log/main.bal b/examples/messages/fetch-message-log/main.bal index c045e209..a5174532 100644 --- a/examples/messages/fetch-message-log/main.bal +++ b/examples/messages/fetch-message-log/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/examples/messages/list-message-logs/main.bal b/examples/messages/list-message-logs/main.bal index 5d282b42..ae0e1776 100644 --- a/examples/messages/list-message-logs/main.bal +++ b/examples/messages/list-message-logs/main.bal @@ -24,8 +24,8 @@ configurable string authToken = os:getEnv("AUTH_TOKEN"); // Twilio configurations twilio:ConnectionConfig twilioConfig = { auth: { - username: accountSid, - password: authToken + accountSid, + authToken } }; diff --git a/gradle.properties b/gradle.properties index 0465ac50..922f1bff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.caching=true group=io.ballerina.stdlib -version=4.0.2-SNAPSHOT -ballerinaLangVersion=2201.8.4 +version=5.0.0-SNAPSHOT +ballerinaLangVersion=2201.10.0 checkstylePluginVersion=10.12.0 spotbugsPluginVersion=5.0.14