From 8ef8ece3907d85b5a11fa364008f4bf8cb66da8e Mon Sep 17 00:00:00 2001 From: maxkahan Date: Thu, 13 Jun 2024 00:44:05 +0100 Subject: [PATCH] add network packages --- application/tests/test_application.py | 3 +- camara_auth/README.md | 34 --- .../src/vonage_camara_auth/__init__.py | 4 - camara_auth/tests/BUILD | 1 - camara_auth/tests/test_camara_auth.py | 86 ------ gnp_sim_swap/README.md | 34 --- .../src/vonage_gnp_sim_swap/__init__.py | 4 - gnp_sim_swap/tests/BUILD | 1 - gnp_sim_swap/tests/_test_camara_auth.py | 86 ------ {camara_auth => network_auth}/BUILD | 4 +- {camara_auth => network_auth}/CHANGES.md | 0 network_auth/README.md | 34 +++ {camara_auth => network_auth}/pyproject.toml | 4 +- .../src/vonage_network_auth}/BUILD | 0 .../src/vonage_network_auth/__init__.py | 4 + .../src/vonage_network_auth/network_auth.py | 44 ++- .../src/vonage_network_auth}/responses.py | 0 network_auth/tests/BUILD | 1 + .../tests/data/oidc_request.json | 0 .../tests/data/token_request.json | 0 network_auth/tests/test_network_auth.py | 91 ++++++ {gnp_sim_swap => network_sim_swap}/BUILD | 4 +- {gnp_sim_swap => network_sim_swap}/CHANGES.md | 0 network_sim_swap/README.md | 38 +++ .../pyproject.toml | 6 +- .../src/vonage_network_sim_swap}/BUILD | 0 .../src/vonage_network_sim_swap/__init__.py | 4 + .../src/vonage_network_sim_swap}/responses.py | 0 .../src/vonage_network_sim_swap}/sim_swap.py | 13 +- network_sim_swap/tests/BUILD | 1 + .../tests/data/check_sim_swap.json | 0 .../tests/data/get_swap_date.json | 0 .../tests/test_sim_swap.py | 0 pants.toml | 2 +- vonage/README.md | 8 +- vonage/pyproject.toml | 1 - vonage/src/vonage/__init__.py | 2 - vonage/src/vonage/vonage.py | 2 - vonage_gnp/CHANGES.md | 267 ------------------ vonage_gnp/src/gnp/BUILD | 1 - vonage_gnp/src/gnp/__init__.py | 5 - {vonage_gnp => vonage_network}/BUILD | 4 +- vonage_network/CHANGES.md | 2 + {vonage_gnp => vonage_network}/README.md | 0 {vonage_gnp => vonage_network}/pyproject.toml | 18 +- vonage_network/src/vonage_network/BUILD | 1 + vonage_network/src/vonage_network/__init__.py | 18 ++ .../src/vonage_network}/_version.py | 0 .../src/vonage_network/vonage_network.py | 23 +- {vonage_gnp => vonage_network}/tests/BUILD | 0 .../tests/test_vonage_network.py | 7 +- 51 files changed, 273 insertions(+), 589 deletions(-) delete mode 100644 camara_auth/README.md delete mode 100644 camara_auth/src/vonage_camara_auth/__init__.py delete mode 100644 camara_auth/tests/BUILD delete mode 100644 camara_auth/tests/test_camara_auth.py delete mode 100644 gnp_sim_swap/README.md delete mode 100644 gnp_sim_swap/src/vonage_gnp_sim_swap/__init__.py delete mode 100644 gnp_sim_swap/tests/BUILD delete mode 100644 gnp_sim_swap/tests/_test_camara_auth.py rename {camara_auth => network_auth}/BUILD (79%) rename {camara_auth => network_auth}/CHANGES.md (100%) create mode 100644 network_auth/README.md rename {camara_auth => network_auth}/pyproject.toml (86%) rename {camara_auth/src/vonage_camara_auth => network_auth/src/vonage_network_auth}/BUILD (100%) create mode 100644 network_auth/src/vonage_network_auth/__init__.py rename camara_auth/src/vonage_camara_auth/camara_auth.py => network_auth/src/vonage_network_auth/network_auth.py (59%) rename {camara_auth/src/vonage_camara_auth => network_auth/src/vonage_network_auth}/responses.py (100%) create mode 100644 network_auth/tests/BUILD rename {camara_auth => network_auth}/tests/data/oidc_request.json (100%) rename {camara_auth => network_auth}/tests/data/token_request.json (100%) create mode 100644 network_auth/tests/test_network_auth.py rename {gnp_sim_swap => network_sim_swap}/BUILD (76%) rename {gnp_sim_swap => network_sim_swap}/CHANGES.md (100%) create mode 100644 network_sim_swap/README.md rename {gnp_sim_swap => network_sim_swap}/pyproject.toml (84%) rename {gnp_sim_swap/src/vonage_gnp_sim_swap => network_sim_swap/src/vonage_network_sim_swap}/BUILD (100%) create mode 100644 network_sim_swap/src/vonage_network_sim_swap/__init__.py rename {gnp_sim_swap/src/vonage_gnp_sim_swap => network_sim_swap/src/vonage_network_sim_swap}/responses.py (100%) rename {gnp_sim_swap/src/vonage_gnp_sim_swap => network_sim_swap/src/vonage_network_sim_swap}/sim_swap.py (84%) create mode 100644 network_sim_swap/tests/BUILD rename {gnp_sim_swap => network_sim_swap}/tests/data/check_sim_swap.json (100%) rename {gnp_sim_swap => network_sim_swap}/tests/data/get_swap_date.json (100%) rename {gnp_sim_swap => network_sim_swap}/tests/test_sim_swap.py (100%) delete mode 100644 vonage_gnp/CHANGES.md delete mode 100644 vonage_gnp/src/gnp/BUILD delete mode 100644 vonage_gnp/src/gnp/__init__.py rename {vonage_gnp => vonage_network}/BUILD (65%) create mode 100644 vonage_network/CHANGES.md rename {vonage_gnp => vonage_network}/README.md (100%) rename {vonage_gnp => vonage_network}/pyproject.toml (65%) create mode 100644 vonage_network/src/vonage_network/BUILD create mode 100644 vonage_network/src/vonage_network/__init__.py rename {vonage_gnp/src/gnp => vonage_network/src/vonage_network}/_version.py (100%) rename vonage_gnp/src/gnp/gnp.py => vonage_network/src/vonage_network/vonage_network.py (54%) rename {vonage_gnp => vonage_network}/tests/BUILD (100%) rename vonage_gnp/tests/test_vonage.py => vonage_network/tests/test_vonage_network.py (59%) diff --git a/application/tests/test_application.py b/application/tests/test_application.py index 675f61f8..6c14a4c6 100644 --- a/application/tests/test_application.py +++ b/application/tests/test_application.py @@ -2,7 +2,6 @@ import responses from pytest import raises -from testutils import build_response, get_mock_api_key_auth from vonage_application.application import Application from vonage_application.common import ( ApplicationUrl, @@ -25,6 +24,8 @@ from vonage_application.requests import ApplicationConfig, ListApplicationsFilter from vonage_http_client.http_client import HttpClient +from testutils import build_response, get_mock_api_key_auth + path = abspath(__file__) application = Application(HttpClient(get_mock_api_key_auth())) diff --git a/camara_auth/README.md b/camara_auth/README.md deleted file mode 100644 index c3373d21..00000000 --- a/camara_auth/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Camara API Authentication Client - -This package (`vonage-camara-auth`) provides a client for authenticating Camara APIs that require Oauth2 authentcation. Using it, it is possible to generate authenticated JWTs for use with GNP APIs, e.g. Sim Swap, Number Verification. - -This package is not intended to be used directly, but will be called by Camara-based APIs that require it. Thus, it doesn't require manual installation or configuration unless you're using this package independently of an SDK. - -For full API documentation, refer to the [Vonage developer documentation](https://developer.vonage.com). - -## Installation - -Install from the Python Package Index with pip: - -```bash -pip install vonage-camara-auth -``` - -## Usage - -### Create a `CamaraAuth` Object - -```python -from vonage_camara_auth import CamaraAuth -from vonage_http_client import HttpClient, Auth - -camara_auth = CamaraAuth(HttpClient(Auth(application_id='application-id', private_key='private-key'))) -``` - -### Generate an Authenticated Access Token - -```python -token = camara_auth.get_oauth2_user_token( - number='447700900000', scope='dpv:FraudPreventionAndDetection#check-sim-swap' -) -``` diff --git a/camara_auth/src/vonage_camara_auth/__init__.py b/camara_auth/src/vonage_camara_auth/__init__.py deleted file mode 100644 index 4f0d2db2..00000000 --- a/camara_auth/src/vonage_camara_auth/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .camara_auth import CamaraAuth -from .responses import OidcResponse, TokenResponse - -__all__ = ['CamaraAuth', 'OidcResponse', 'TokenResponse'] diff --git a/camara_auth/tests/BUILD b/camara_auth/tests/BUILD deleted file mode 100644 index f88f88b2..00000000 --- a/camara_auth/tests/BUILD +++ /dev/null @@ -1 +0,0 @@ -python_tests(dependencies=['camara_auth', 'testutils']) diff --git a/camara_auth/tests/test_camara_auth.py b/camara_auth/tests/test_camara_auth.py deleted file mode 100644 index 2d1d92a1..00000000 --- a/camara_auth/tests/test_camara_auth.py +++ /dev/null @@ -1,86 +0,0 @@ -from os.path import abspath - -import responses -from vonage_camara_auth import CamaraAuth, camara_auth -from vonage_camara_auth.responses import OidcResponse -from vonage_http_client.http_client import HttpClient - -from testutils import build_response, get_mock_jwt_auth - -path = abspath(__file__) - - -camara_auth = CamaraAuth(HttpClient(get_mock_jwt_auth())) - - -def test_http_client_property(): - http_client = camara_auth.http_client - assert isinstance(http_client, HttpClient) - - -@responses.activate -def test_oidc_request(): - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/bc-authorize', - 'oidc_request.json', - ) - - response = camara_auth._make_oidc_request( - number='447700900000', - scope='dpv:FraudPreventionAndDetection#check-sim-swap', - ) - - assert response.auth_req_id == '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537' - assert response.expires_in == '120' - assert response.interval == '2' - - -@responses.activate -def test_request_camara_access_token(): - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/token', - 'token_request.json', - ) - - oidc_response_dict = { - 'auth_req_id': '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537', - 'expires_in': '120', - 'interval': '2', - } - oidc_response = OidcResponse(**oidc_response_dict) - response = camara_auth._request_camara_token(oidc_response.auth_req_id) - - assert ( - response.access_token - == 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkZWZhdWx0IiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3wWzV6t8bFJUZ6k0WJ9kY3J2kNw9v5zXJ8x1J5g1v2k' - ) - assert response.token_type == 'A-VALID-TOKEN-TYPE' - assert response.refresh_token == 'A-VALID-REFRESH-TOKEN' - - -@responses.activate -def test_whole_oauth2_flow(): - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/bc-authorize', - 'oidc_request.json', - ) - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/token', - 'token_request.json', - ) - - access_token = camara_auth.get_oauth2_user_token( - number='447700900000', scope='dpv:FraudPreventionAndDetection#check-sim-swap' - ) - assert ( - access_token - == 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkZWZhdWx0IiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3wWzV6t8bFJUZ6k0WJ9kY3J2kNw9v5zXJ8x1J5g1v2k' - ) diff --git a/gnp_sim_swap/README.md b/gnp_sim_swap/README.md deleted file mode 100644 index c3373d21..00000000 --- a/gnp_sim_swap/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Camara API Authentication Client - -This package (`vonage-camara-auth`) provides a client for authenticating Camara APIs that require Oauth2 authentcation. Using it, it is possible to generate authenticated JWTs for use with GNP APIs, e.g. Sim Swap, Number Verification. - -This package is not intended to be used directly, but will be called by Camara-based APIs that require it. Thus, it doesn't require manual installation or configuration unless you're using this package independently of an SDK. - -For full API documentation, refer to the [Vonage developer documentation](https://developer.vonage.com). - -## Installation - -Install from the Python Package Index with pip: - -```bash -pip install vonage-camara-auth -``` - -## Usage - -### Create a `CamaraAuth` Object - -```python -from vonage_camara_auth import CamaraAuth -from vonage_http_client import HttpClient, Auth - -camara_auth = CamaraAuth(HttpClient(Auth(application_id='application-id', private_key='private-key'))) -``` - -### Generate an Authenticated Access Token - -```python -token = camara_auth.get_oauth2_user_token( - number='447700900000', scope='dpv:FraudPreventionAndDetection#check-sim-swap' -) -``` diff --git a/gnp_sim_swap/src/vonage_gnp_sim_swap/__init__.py b/gnp_sim_swap/src/vonage_gnp_sim_swap/__init__.py deleted file mode 100644 index 6314dbef..00000000 --- a/gnp_sim_swap/src/vonage_gnp_sim_swap/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .responses import LastSwapDate, SwapStatus -from .sim_swap import SimSwap - -__all__ = ['SimSwap', 'LastSwapDate', 'SwapStatus'] diff --git a/gnp_sim_swap/tests/BUILD b/gnp_sim_swap/tests/BUILD deleted file mode 100644 index 88d3016e..00000000 --- a/gnp_sim_swap/tests/BUILD +++ /dev/null @@ -1 +0,0 @@ -python_tests(dependencies=['gnp_sim_swap', 'testutils']) diff --git a/gnp_sim_swap/tests/_test_camara_auth.py b/gnp_sim_swap/tests/_test_camara_auth.py deleted file mode 100644 index f4c7926a..00000000 --- a/gnp_sim_swap/tests/_test_camara_auth.py +++ /dev/null @@ -1,86 +0,0 @@ -from os.path import abspath - -import responses - -from testutils import build_response, get_mock_jwt_auth -from vonage_camara_auth import CamaraAuth, camara_auth -from vonage_camara_auth.responses import OidcResponse -from vonage_http_client.http_client import HttpClient - -path = abspath(__file__) - - -camara_auth = CamaraAuth(HttpClient(get_mock_jwt_auth())) - - -def test_http_client_property(): - http_client = camara_auth.http_client - assert isinstance(http_client, HttpClient) - - -@responses.activate -def test_oidc_request(): - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/bc-authorize', - 'oidc_request.json', - ) - - response = camara_auth._make_oidc_request( - number='447700900000', - scope='dpv:FraudPreventionAndDetection#check-sim-swap', - ) - - assert response.auth_req_id == '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537' - assert response.expires_in == '120' - assert response.interval == '2' - - -@responses.activate -def test_request_camara_access_token(): - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/token', - 'token_request.json', - ) - - oidc_response_dict = { - 'auth_req_id': '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537', - 'expires_in': '120', - 'interval': '2', - } - oidc_response = OidcResponse(**oidc_response_dict) - response = camara_auth._request_camara_token(oidc_response.auth_req_id) - - assert ( - response.access_token - == 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkZWZhdWx0IiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3wWzV6t8bFJUZ6k0WJ9kY3J2kNw9v5zXJ8x1J5g1v2k' - ) - assert response.token_type == 'A-VALID-TOKEN-TYPE' - assert response.refresh_token == 'A-VALID-REFRESH-TOKEN' - - -@responses.activate -def test_whole_oauth2_flow(): - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/bc-authorize', - 'oidc_request.json', - ) - build_response( - path, - 'POST', - 'https://api-eu.vonage.com/oauth2/token', - 'token_request.json', - ) - - access_token = camara_auth.get_oauth2_user_token( - number='447700900000', scope='dpv:FraudPreventionAndDetection#check-sim-swap' - ) - assert ( - access_token - == 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkZWZhdWx0IiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3wWzV6t8bFJUZ6k0WJ9kY3J2kNw9v5zXJ8x1J5g1v2k' - ) diff --git a/camara_auth/BUILD b/network_auth/BUILD similarity index 79% rename from camara_auth/BUILD rename to network_auth/BUILD index a725bc0b..8487b434 100644 --- a/camara_auth/BUILD +++ b/network_auth/BUILD @@ -4,11 +4,11 @@ file(name='readme', source='README.md') files(sources=['tests/data/*']) python_distribution( - name='vonage-camara-auth', + name='vonage-network-auth', dependencies=[ ':pyproject', ':readme', - 'camara_auth/src/vonage_camara_auth', + 'network_auth/src/vonage_network_auth', ], provides=python_artifact(), generate_setup=False, diff --git a/camara_auth/CHANGES.md b/network_auth/CHANGES.md similarity index 100% rename from camara_auth/CHANGES.md rename to network_auth/CHANGES.md diff --git a/network_auth/README.md b/network_auth/README.md new file mode 100644 index 00000000..b7ad9af7 --- /dev/null +++ b/network_auth/README.md @@ -0,0 +1,34 @@ +# Vonage Network API Authentication Client + +This package (`vonage-network-auth`) provides a client for authenticating Network APIs that require Oauth2 authentcation. Using it, it is possible to generate authenticated JWTs for use with GNP APIs, e.g. Sim Swap, Number Verification. + +This package is intended to be used as part of an SDK, accessing required methods through the SDK instead of directly. Thus, it doesn't require manual installation or configuration unless you're using this package independently of an SDK. + +For full API documentation, refer to the [Vonage developer documentation](https://developer.vonage.com). + +## Installation + +Install from the Python Package Index with pip: + +```bash +pip install vonage-network-auth +``` + +## Usage + +### Create a `NetworkAuth` Object + +```python +from vonage_network_auth import NetworkAuth +from vonage_http_client import HttpClient, Auth + +network_auth = NetworkAuth(HttpClient(Auth(application_id='application-id', private_key='private-key'))) +``` + +### Generate an Authenticated Access Token + +```python +token = camara_auth.get_oauth2_user_token( + number='447700900000', scope='dpv:FraudPreventionAndDetection#check-sim-swap' +) +``` diff --git a/camara_auth/pyproject.toml b/network_auth/pyproject.toml similarity index 86% rename from camara_auth/pyproject.toml rename to network_auth/pyproject.toml index 1edb88c6..1173d26f 100644 --- a/camara_auth/pyproject.toml +++ b/network_auth/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "vonage-camara-auth" +name = "vonage-network-auth" version = "1.0.0" -description = "Package for working with Camara APIs that require Oauth2 in Python." +description = "Package for working with Network APIs that require Oauth2 in Python." readme = "README.md" authors = [{ name = "Vonage", email = "devrel@vonage.com" }] requires-python = ">=3.8" diff --git a/camara_auth/src/vonage_camara_auth/BUILD b/network_auth/src/vonage_network_auth/BUILD similarity index 100% rename from camara_auth/src/vonage_camara_auth/BUILD rename to network_auth/src/vonage_network_auth/BUILD diff --git a/network_auth/src/vonage_network_auth/__init__.py b/network_auth/src/vonage_network_auth/__init__.py new file mode 100644 index 00000000..e321e403 --- /dev/null +++ b/network_auth/src/vonage_network_auth/__init__.py @@ -0,0 +1,4 @@ +from .network_auth import NetworkAuth +from .responses import OidcResponse, TokenResponse + +__all__ = ['NetworkAuth', 'OidcResponse', 'TokenResponse'] diff --git a/camara_auth/src/vonage_camara_auth/camara_auth.py b/network_auth/src/vonage_network_auth/network_auth.py similarity index 59% rename from camara_auth/src/vonage_camara_auth/camara_auth.py rename to network_auth/src/vonage_network_auth/network_auth.py index 977a5e51..ba100fe0 100644 --- a/camara_auth/src/vonage_camara_auth/camara_auth.py +++ b/network_auth/src/vonage_network_auth/network_auth.py @@ -4,8 +4,8 @@ from .responses import OidcResponse, TokenResponse -class CamaraAuth: - """Class containing methods for authenticating APIs following Camara standards.""" +class NetworkAuth: + """Class containing methods for authenticating Network APIs following Camara standards.""" def __init__(self, http_client: HttpClient): self._http_client = http_client @@ -33,18 +33,23 @@ def get_oauth2_user_token(self, number: str, scope: str) -> str: Returns: str: The OAuth2 user token. """ - oidc_response = self._make_oidc_request(number, scope) - token_response = self._request_camara_token(oidc_response.auth_req_id) + oidc_response = self.make_oidc_request(number, scope) + token_response = self.request_access_token(oidc_response.auth_req_id) return token_response.access_token - def _make_oidc_request(self, number: str, scope: str) -> OidcResponse: + @validate_call + def make_oidc_request(self, number: str, scope: str) -> OidcResponse: """Make an OIDC request to authenticate a user. - Returns a code that can be used to request a Camara token. - """ + Args: + number (str): The phone number to authenticate. + scope (str): The scope of the token. - login_hint = f'tel:+{number}' - params = {'login_hint': login_hint, 'scope': scope} + Returns: + OidcResponse: A response containing the authentication request ID. + """ + number = self._ensure_plus_prefix(number) + params = {'login_hint': number, 'scope': scope} response = self._http_client.post( self._host, @@ -55,12 +60,12 @@ def _make_oidc_request(self, number: str, scope: str) -> OidcResponse: ) return OidcResponse(**response) - def _request_camara_token( + @validate_call + def request_access_token( self, auth_req_id: str, grant_type: str = 'urn:openid:params:grant-type:ciba' ) -> TokenResponse: - """Request a Camara token using an authentication request ID given as a response - to the OIDC request. - """ + """Request a Camara access token using an authentication request ID given as a response to + an OIDC request.""" params = {'auth_req_id': auth_req_id, 'grant_type': grant_type} response = self._http_client.post( @@ -71,3 +76,16 @@ def _request_camara_token( self._sent_data_type, ) return TokenResponse(**response) + + def _ensure_plus_prefix(self, number: str) -> str: + """Ensure that the number has a plus prefix. + + Args: + number (str): The phone number to check. + + Returns: + str: The phone number with a plus prefix. + """ + if number.startswith('+'): + return number + return f'+{number}' diff --git a/camara_auth/src/vonage_camara_auth/responses.py b/network_auth/src/vonage_network_auth/responses.py similarity index 100% rename from camara_auth/src/vonage_camara_auth/responses.py rename to network_auth/src/vonage_network_auth/responses.py diff --git a/network_auth/tests/BUILD b/network_auth/tests/BUILD new file mode 100644 index 00000000..0f917372 --- /dev/null +++ b/network_auth/tests/BUILD @@ -0,0 +1 @@ +python_tests(dependencies=['network_auth', 'testutils']) diff --git a/camara_auth/tests/data/oidc_request.json b/network_auth/tests/data/oidc_request.json similarity index 100% rename from camara_auth/tests/data/oidc_request.json rename to network_auth/tests/data/oidc_request.json diff --git a/camara_auth/tests/data/token_request.json b/network_auth/tests/data/token_request.json similarity index 100% rename from camara_auth/tests/data/token_request.json rename to network_auth/tests/data/token_request.json diff --git a/network_auth/tests/test_network_auth.py b/network_auth/tests/test_network_auth.py new file mode 100644 index 00000000..c87098f9 --- /dev/null +++ b/network_auth/tests/test_network_auth.py @@ -0,0 +1,91 @@ +from os.path import abspath + +import responses +from vonage_http_client.http_client import HttpClient +from vonage_network_auth import NetworkAuth +from vonage_network_auth.responses import OidcResponse + +from testutils import build_response, get_mock_jwt_auth + +path = abspath(__file__) + + +network_auth = NetworkAuth(HttpClient(get_mock_jwt_auth())) + + +def test_http_client_property(): + http_client = network_auth.http_client + assert isinstance(http_client, HttpClient) + + +@responses.activate +def test_oidc_request(): + build_response( + path, + 'POST', + 'https://api-eu.vonage.com/oauth2/bc-authorize', + 'oidc_request.json', + ) + + response = network_auth.make_oidc_request( + number='447700900000', + scope='dpv:FraudPreventionAndDetection#check-sim-swap', + ) + + assert response.auth_req_id == 'arid/8b0d35f3-4627-487c-a776-aegtdsf4rsd2' + assert response.expires_in == 300 + assert response.interval == 0 + + +@responses.activate +def test_request_access_token(): + build_response( + path, + 'POST', + 'https://api-eu.vonage.com/oauth2/token', + 'token_request.json', + ) + + oidc_response_dict = { + 'auth_req_id': '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537', + 'expires_in': '120', + 'interval': '2', + } + oidc_response = OidcResponse(**oidc_response_dict) + response = network_auth.request_access_token(oidc_response.auth_req_id) + + assert ( + response.access_token + == 'eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vYW51YmlzLWNlcnRzLWMxLWV1dzEucHJvZC52MS52b25hZ2VuZXR3b3Jrcy5uZXQvandrcyIsImtpZCI6IkNOPVZvbmFnZSAxdmFwaWd3IEludGVybmFsIENBOjoxOTUxODQ2ODA3NDg1NTYwNjYzODY3MTM0NjE2MjU2MTU5MjU2NDkiLCJ0eXAiOiJKV1QiLCJ4NXUiOiJodHRwczovL2FudWJpcy1jZXJ0cy1jMS1ldXcxLnByb2QudjEudm9uYWdlbmV0d29ya3MubmV0L3YxL2NlcnRzLzA4NjliNDMyZTEzZmIyMzcwZTk2ZGI4YmUxMDc4MjJkIn0.eyJwcmluY2lwYWwiOnsiYXBpS2V5IjoiNGI1MmMwMGUiLCJhcHBsaWNhdGlvbklkIjoiMmJlZTViZWQtNmZlZS00ZjM2LTkxNmQtNWUzYjRjZDI1MjQzIiwibWFzdGVyQWNjb3VudElkIjoiNGI1MmMwMGUiLCJjYXBhYmlsaXRpZXMiOlsibmV0d29yay1hcGktZmVhdHVyZXMiXSwiZXh0cmFDb25maWciOnsiY2FtYXJhU3RhdGUiOiJmb0ZyQndnOFNmeGMydnd2S1o5Y3UrMlgrT0s1K2FvOWhJTTVGUGZMQ1dOeUlMTHR3WmY1dFRKbDdUc1p4QnY4QWx3aHM2bFNWcGVvVkhoWngvM3hUenFRWVkwcHpIZE5XL085ZEdRN1RKOE9sU1lDdTFYYXFEcnNFbEF4WEJVcUpGdnZTTkp5a1A5ZDBYWVN4ajZFd0F6UUFsNGluQjE1c3VMRFNsKy82U1FDa29Udnpld0tvcFRZb0F5MVg2dDJVWXdEVWFDNjZuOS9kVWxIemN3V0NGK3QwOGNReGxZVUxKZyt3T0hwV2xvWGx1MGc3REx0SCtHd0pvRGJoYnMyT2hVY3BobGZqajBpeHQ1OTRsSG5sQ1NYNkZrMmhvWEhKUW01S3JtOVBKSmttK0xTRjVsRTd3NUxtWTRvYTFXSGpkY0dwV1VsQlNQY000YnprOGU0bVE9PSJ9fSwiZmVkZXJhdGVkQXNzZXJ0aW9ucyI6e30sImF1ZCI6ImFwaS1ldS52b25hZ2UuY29tIiwiZXhwIjoxNzE3MDkyODY4LCJqdGkiOiJmNDZhYTViOC1hODA2LTRjMzctODQyMS02OGYwMzJjNDlhMWYiLCJpYXQiOjE3MTcwOTE5NzAsImlzcyI6IlZJQU0tSUFQIiwibmJmIjoxNzE3MDkxOTU1fQ.iLUbyDPR1HGLKh29fy6fqK65Q1O7mjWOletAEPJD4eu7gb0E85EL4M9R7ckJq5lIvgedQt3vBheTaON9_u-VYjMqo8ulPoEoGUDHbOzNbs4MmCW0_CRdDPGyxnUhvcbuJhPgnEHxmfHjJBljncUnk-Z7XCgyNajBNXeQQnHkRF_6NMngxJ-qjjhqbYL0VsF_JS7-TXxixNL0KAFl0SeN2DjkfwRBCclP-69CTExDjyOvouAcchqi-6ZYj_tXPCrTADuzUrQrW8C5nHp2-XjWJSFKzyvi48n8V1U6KseV-eYzBzvy7bJf0tRMX7G6gctTYq3DxdC_eXvXlnp1zx16mg' + ) + assert response.token_type == 'bearer' + assert response.expires_in == 29 + + +@responses.activate +def test_whole_oauth2_flow(): + build_response( + path, + 'POST', + 'https://api-eu.vonage.com/oauth2/bc-authorize', + 'oidc_request.json', + ) + build_response( + path, + 'POST', + 'https://api-eu.vonage.com/oauth2/token', + 'token_request.json', + ) + + access_token = network_auth.get_oauth2_user_token( + number='447700900000', scope='dpv:FraudPreventionAndDetection#check-sim-swap' + ) + assert ( + access_token + == 'eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vYW51YmlzLWNlcnRzLWMxLWV1dzEucHJvZC52MS52b25hZ2VuZXR3b3Jrcy5uZXQvandrcyIsImtpZCI6IkNOPVZvbmFnZSAxdmFwaWd3IEludGVybmFsIENBOjoxOTUxODQ2ODA3NDg1NTYwNjYzODY3MTM0NjE2MjU2MTU5MjU2NDkiLCJ0eXAiOiJKV1QiLCJ4NXUiOiJodHRwczovL2FudWJpcy1jZXJ0cy1jMS1ldXcxLnByb2QudjEudm9uYWdlbmV0d29ya3MubmV0L3YxL2NlcnRzLzA4NjliNDMyZTEzZmIyMzcwZTk2ZGI4YmUxMDc4MjJkIn0.eyJwcmluY2lwYWwiOnsiYXBpS2V5IjoiNGI1MmMwMGUiLCJhcHBsaWNhdGlvbklkIjoiMmJlZTViZWQtNmZlZS00ZjM2LTkxNmQtNWUzYjRjZDI1MjQzIiwibWFzdGVyQWNjb3VudElkIjoiNGI1MmMwMGUiLCJjYXBhYmlsaXRpZXMiOlsibmV0d29yay1hcGktZmVhdHVyZXMiXSwiZXh0cmFDb25maWciOnsiY2FtYXJhU3RhdGUiOiJmb0ZyQndnOFNmeGMydnd2S1o5Y3UrMlgrT0s1K2FvOWhJTTVGUGZMQ1dOeUlMTHR3WmY1dFRKbDdUc1p4QnY4QWx3aHM2bFNWcGVvVkhoWngvM3hUenFRWVkwcHpIZE5XL085ZEdRN1RKOE9sU1lDdTFYYXFEcnNFbEF4WEJVcUpGdnZTTkp5a1A5ZDBYWVN4ajZFd0F6UUFsNGluQjE1c3VMRFNsKy82U1FDa29Udnpld0tvcFRZb0F5MVg2dDJVWXdEVWFDNjZuOS9kVWxIemN3V0NGK3QwOGNReGxZVUxKZyt3T0hwV2xvWGx1MGc3REx0SCtHd0pvRGJoYnMyT2hVY3BobGZqajBpeHQ1OTRsSG5sQ1NYNkZrMmhvWEhKUW01S3JtOVBKSmttK0xTRjVsRTd3NUxtWTRvYTFXSGpkY0dwV1VsQlNQY000YnprOGU0bVE9PSJ9fSwiZmVkZXJhdGVkQXNzZXJ0aW9ucyI6e30sImF1ZCI6ImFwaS1ldS52b25hZ2UuY29tIiwiZXhwIjoxNzE3MDkyODY4LCJqdGkiOiJmNDZhYTViOC1hODA2LTRjMzctODQyMS02OGYwMzJjNDlhMWYiLCJpYXQiOjE3MTcwOTE5NzAsImlzcyI6IlZJQU0tSUFQIiwibmJmIjoxNzE3MDkxOTU1fQ.iLUbyDPR1HGLKh29fy6fqK65Q1O7mjWOletAEPJD4eu7gb0E85EL4M9R7ckJq5lIvgedQt3vBheTaON9_u-VYjMqo8ulPoEoGUDHbOzNbs4MmCW0_CRdDPGyxnUhvcbuJhPgnEHxmfHjJBljncUnk-Z7XCgyNajBNXeQQnHkRF_6NMngxJ-qjjhqbYL0VsF_JS7-TXxixNL0KAFl0SeN2DjkfwRBCclP-69CTExDjyOvouAcchqi-6ZYj_tXPCrTADuzUrQrW8C5nHp2-XjWJSFKzyvi48n8V1U6KseV-eYzBzvy7bJf0tRMX7G6gctTYq3DxdC_eXvXlnp1zx16mg' + ) + + +def test_number_plus_prefixes(): + assert network_auth._ensure_plus_prefix('447700900000') == '+447700900000' + assert network_auth._ensure_plus_prefix('+447700900000') == '+447700900000' diff --git a/gnp_sim_swap/BUILD b/network_sim_swap/BUILD similarity index 76% rename from gnp_sim_swap/BUILD rename to network_sim_swap/BUILD index 51bef29c..11bc974e 100644 --- a/gnp_sim_swap/BUILD +++ b/network_sim_swap/BUILD @@ -4,11 +4,11 @@ file(name='readme', source='README.md') files(sources=['tests/data/*']) python_distribution( - name='vonage-gnp-sim-swap', + name='vonage-network-sim-swap', dependencies=[ ':pyproject', ':readme', - 'gnp_sim_swap/src/vonage_gnp_sim_swap', + 'network_sim_swap/src/vonage_network_sim_swap', ], provides=python_artifact(), generate_setup=False, diff --git a/gnp_sim_swap/CHANGES.md b/network_sim_swap/CHANGES.md similarity index 100% rename from gnp_sim_swap/CHANGES.md rename to network_sim_swap/CHANGES.md diff --git a/network_sim_swap/README.md b/network_sim_swap/README.md new file mode 100644 index 00000000..ecf96e5b --- /dev/null +++ b/network_sim_swap/README.md @@ -0,0 +1,38 @@ +# Vonage Sim Swap Network API Client + +This package (`vonage-network-sim-swap`) allows you to check whether a SIM card has been swapped, and the last swap date. + +This package is not intended to be used directly, instead being accessed from an enclosing SDK package. Thus, it doesn't require manual installation or configuration unless you're using this package independently of an SDK. + +For full API documentation, refer to the [Vonage developer documentation](https://developer.vonage.com). + +## Registering to Use the Sim Swap API + +To use this API, you must first create and register your business profile with the Vonage Network Registry. [This documentation page](https://developer.vonage.com/en/getting-started-network/registration) explains how this can be done. You need to obtain approval for each network and region you want to use the APIs in. + +## Installation + +Install from the Python Package Index with pip: + +```bash +pip install vonage-camara-auth +``` + +## Usage + +### Create a `CamaraAuth` Object + +```python +from vonage_camara_auth import CamaraAuth +from vonage_http_client import HttpClient, Auth + +camara_auth = CamaraAuth(HttpClient(Auth(application_id='application-id', private_key='private-key'))) +``` + +### Generate an Authenticated Access Token + +```python +token = camara_auth.get_oauth2_user_token( + number='447700900000', scope='dpv:FraudPreventionAndDetection#check-sim-swap' +) +``` diff --git a/gnp_sim_swap/pyproject.toml b/network_sim_swap/pyproject.toml similarity index 84% rename from gnp_sim_swap/pyproject.toml rename to network_sim_swap/pyproject.toml index cd4115d5..4c7f25db 100644 --- a/gnp_sim_swap/pyproject.toml +++ b/network_sim_swap/pyproject.toml @@ -1,13 +1,13 @@ [project] -name = "vonage-gnp-sim-swap" +name = "vonage-network-sim-swap" version = "1.0.0" -description = "Package for working with the GNP Sim Swap API." +description = "Package for working with the Vonage Sim Swap Network API." readme = "README.md" authors = [{ name = "Vonage", email = "devrel@vonage.com" }] requires-python = ">=3.8" dependencies = [ "vonage-http-client>=1.3.1", - "vonage-camara-auth>=1.0.0", + "vonage-network-auth>=1.0.0", "vonage-utils>=1.1.2", ] classifiers = [ diff --git a/gnp_sim_swap/src/vonage_gnp_sim_swap/BUILD b/network_sim_swap/src/vonage_network_sim_swap/BUILD similarity index 100% rename from gnp_sim_swap/src/vonage_gnp_sim_swap/BUILD rename to network_sim_swap/src/vonage_network_sim_swap/BUILD diff --git a/network_sim_swap/src/vonage_network_sim_swap/__init__.py b/network_sim_swap/src/vonage_network_sim_swap/__init__.py new file mode 100644 index 00000000..41b72410 --- /dev/null +++ b/network_sim_swap/src/vonage_network_sim_swap/__init__.py @@ -0,0 +1,4 @@ +from .responses import LastSwapDate, SwapStatus +from .sim_swap import NetworkSimSwap + +__all__ = ['NetworkSimSwap', 'LastSwapDate', 'SwapStatus'] diff --git a/gnp_sim_swap/src/vonage_gnp_sim_swap/responses.py b/network_sim_swap/src/vonage_network_sim_swap/responses.py similarity index 100% rename from gnp_sim_swap/src/vonage_gnp_sim_swap/responses.py rename to network_sim_swap/src/vonage_network_sim_swap/responses.py diff --git a/gnp_sim_swap/src/vonage_gnp_sim_swap/sim_swap.py b/network_sim_swap/src/vonage_network_sim_swap/sim_swap.py similarity index 84% rename from gnp_sim_swap/src/vonage_gnp_sim_swap/sim_swap.py rename to network_sim_swap/src/vonage_network_sim_swap/sim_swap.py index 4e146d68..2c85dff5 100644 --- a/gnp_sim_swap/src/vonage_gnp_sim_swap/sim_swap.py +++ b/network_sim_swap/src/vonage_network_sim_swap/sim_swap.py @@ -1,20 +1,20 @@ from pydantic import validate_call -from vonage_camara_auth import CamaraAuth from vonage_http_client import HttpClient +from vonage_network_auth import NetworkAuth from vonage_utils.types import PhoneNumber from .responses import LastSwapDate, SwapStatus -class SimSwap: - """Class containing methods for working with the Vonage SIM Swap API.""" +class NetworkSimSwap: + """Class containing methods for working with the Vonage SIM Swap Network API.""" def __init__(self, http_client: HttpClient): self._http_client = http_client self._host = 'api-eu.vonage.com' self._auth_type = 'oauth2' - self._camara_auth = CamaraAuth(self._http_client) + self._network_auth = NetworkAuth(self._http_client) @validate_call def check(self, phone_number: PhoneNumber, max_age: int = None) -> SwapStatus: @@ -25,8 +25,9 @@ def check(self, phone_number: PhoneNumber, max_age: int = None) -> SwapStatus: max_age (int, optional): Period in hours to be checked for SIM swap. Returns: + SwapStatus: Class containing the Swap Status response. """ - token = self._camara_auth.get_oauth2_user_token( + token = self._network_auth.get_oauth2_user_token( number=phone_number, scope='dpv:FraudPreventionAndDetection#check-sim-swap' ) @@ -47,7 +48,7 @@ def get_last_swap_date(self, phone_number: PhoneNumber) -> LastSwapDate: Returns: """ - token = self._camara_auth.get_oauth2_user_token( + token = self._network_auth.get_oauth2_user_token( number=phone_number, scope='dpv:FraudPreventionAndDetection#retrieve-sim-swap-date', ) diff --git a/network_sim_swap/tests/BUILD b/network_sim_swap/tests/BUILD new file mode 100644 index 00000000..b77e3c32 --- /dev/null +++ b/network_sim_swap/tests/BUILD @@ -0,0 +1 @@ +python_tests(dependencies=['network_sim_swap', 'testutils']) diff --git a/gnp_sim_swap/tests/data/check_sim_swap.json b/network_sim_swap/tests/data/check_sim_swap.json similarity index 100% rename from gnp_sim_swap/tests/data/check_sim_swap.json rename to network_sim_swap/tests/data/check_sim_swap.json diff --git a/gnp_sim_swap/tests/data/get_swap_date.json b/network_sim_swap/tests/data/get_swap_date.json similarity index 100% rename from gnp_sim_swap/tests/data/get_swap_date.json rename to network_sim_swap/tests/data/get_swap_date.json diff --git a/gnp_sim_swap/tests/test_sim_swap.py b/network_sim_swap/tests/test_sim_swap.py similarity index 100% rename from gnp_sim_swap/tests/test_sim_swap.py rename to network_sim_swap/tests/test_sim_swap.py diff --git a/pants.toml b/pants.toml index 527156bb..5d4a4979 100644 --- a/pants.toml +++ b/pants.toml @@ -34,10 +34,10 @@ filter = [ 'vonage_gnp/src', 'http_client/src', 'application/src', - 'camara_auth/src', 'gnp_sim_swap/src', 'jwt/src', 'messages/src', + 'network_auth/src', 'number_insight/src', 'number_insight_v2/src', 'sms/src', diff --git a/vonage/README.md b/vonage/README.md index 8552f886..a86bc71f 100644 --- a/vonage/README.md +++ b/vonage/README.md @@ -30,12 +30,14 @@ options = HttpClientOptions(api_host='api.nexmo.com', timeout=30) vonage = Vonage(auth=auth, http_client_options=options) ``` -The Vonage class provides access to various Vonage APIs through its properties. For example, to use methods to call the Number Insight API v2: +The Vonage class provides access to various Vonage APIs through its properties. For example, to use methods to call the SMS API: ```python -from vonage_number_insight_v2 import FraudCheckRequest +from vonage_sms import SmsMessage -vonage.number_insight_v2.fraud_check(FraudCheckRequest(phone='1234567890')) +message = SmsMessage(to='1234567890', from_='Vonage', text='Hello World') +response = client.sms.send(message) +print(response.model_dump_json(exclude_unset=True)) ``` You can also access the underlying `HttpClient` instance through the `http_client` property: diff --git a/vonage/pyproject.toml b/vonage/pyproject.toml index b3ee559f..7f745c35 100644 --- a/vonage/pyproject.toml +++ b/vonage/pyproject.toml @@ -11,7 +11,6 @@ dependencies = [ "vonage-application>=1.0.0", "vonage-messages>=1.1.1", "vonage-number-insight>=1.0.0", - "vonage-number-insight-v2>=0.1.1b0", "vonage-sms>=1.1.1", "vonage-users>=1.1.2", "vonage-verify>=1.1.1", diff --git a/vonage/src/vonage/__init__.py b/vonage/src/vonage/__init__.py index ee39bfea..d3ead5e8 100644 --- a/vonage/src/vonage/__init__.py +++ b/vonage/src/vonage/__init__.py @@ -6,7 +6,6 @@ HttpClientOptions, Messages, NumberInsight, - NumberInsightV2, Sms, Users, Verify, @@ -22,7 +21,6 @@ 'Application', 'Messages', 'NumberInsight', - 'NumberInsightV2', 'Sms', 'Users', 'Verify', diff --git a/vonage/src/vonage/vonage.py b/vonage/src/vonage/vonage.py index f329646d..5896df52 100644 --- a/vonage/src/vonage/vonage.py +++ b/vonage/src/vonage/vonage.py @@ -4,7 +4,6 @@ from vonage_http_client import Auth, HttpClient, HttpClientOptions from vonage_messages import Messages from vonage_number_insight import NumberInsight -from vonage_number_insight_v2 import NumberInsightV2 from vonage_sms import Sms from vonage_users import Users from vonage_verify import Verify @@ -35,7 +34,6 @@ def __init__( self.application = Application(self._http_client) self.messages = Messages(self._http_client) self.number_insight = NumberInsight(self._http_client) - self.number_insight_v2 = NumberInsightV2(self._http_client) self.sms = Sms(self._http_client) self.users = Users(self._http_client) self.verify = Verify(self._http_client) diff --git a/vonage_gnp/CHANGES.md b/vonage_gnp/CHANGES.md deleted file mode 100644 index 9dcf11da..00000000 --- a/vonage_gnp/CHANGES.md +++ /dev/null @@ -1,267 +0,0 @@ -# 3.99.1a10 -- Migrate the Vonage JWT package -- Internal refactoring - -# 3.99.0a10 -- Add support for the [Vonage Application API](https://developer.vonage.com/en/application/overview). - -# 3.99.0a9 -- Internal refactoring - -# 3.99.0a8 -- Add support for the [Vonage Number Insight API](https://developer.vonage.com/en/number-insight/overview). -- Update minimum dependency version - -# 3.99.0a7 -- Add support for the [Vonage Voice API](https://developer.vonage.com/en/voice/voice-api/overview). -- Add `http_client` property to each module that has an HTTP Client, e.g. Voice, Sms, Verify. - -# 3.99.0a6 -- Add support for the [Vonage Messages API](https://developer.vonage.com/en/messages/overview). - -# 3.99.0a5 -- Add support for the [Vonage Verify V2 API](https://developer.vonage.com/en/verify/overview). -- Expose error classes at the top level of the `vonage-http-client` package. - -# 3.99.0a4 -- Add support for the [Vonage Verify API](https://developer.vonage.com/en/api/verify). -- Add `last_request` and `last_response` properties to the HTTP Client. - -# 3.99.0a3 -- Add support for the [Vonage Users API](https://developer.vonage.com/en/api/application.v2#User). - -# 3.99.0a2 -- Internal refactoring - -# 3.99.0a1 -- Add support for the [Vonage SMS API](https://developer.vonage.com/en/messaging/sms/overview). - -# 3.99.0a0 -Created new monorepo structure - this package `vonage` is now a way to depend on the functionality of all Vonage APIs, which has been moved into separate packages. Additionally, there are many breaking changes. - -# 3.11.0 -- Add method to check JWT signatures of Voice API webhooks: `vonage.Voice.verify_signature` - -# 3.10.0 -- Indicating support for Python 3.12 - -# 3.9.1 -- Updating Meetings API url to a `/v1` endpoint - -# 3.9.0 -- Dropped support for Python 3.7 as it's end-of-life and no longer receiving security updates - -# 3.8.0 -- Adding support for the [Users component of the Vonage Application API](https://developer.vonage.com/en/api/application.v2#User) - -# 3.7.1 -- Fixing dependency version to a specific major version - -# 3.7.0 -- Adding support for the [Vonage Meetings API](https://developer.vonage.com/en/meetings/overview) -- Adding partial support for the [Vonage Proactive Connect API](https://developer.vonage.com/en/proactive-connect/overview) - supporting API methods relating to `lists`, `items` and `events` -- Returning a more descriptive (non-internal) error message if invalid values are provided for `application_id` and/or `private_key` when instantiating a Vonage client object - -# 3.6.0 -- Adding support for the [Vonage Subaccounts API](https://developer.vonage.com/en/account/subaccounts/overview) - -# 3.5.2 -- Using the [Vonage JWT Generator](https://github.com/Vonage/vonage-python-jwt) instead of `PyJWT` for generating JWTs. -- Other internal refactoring and enhancements - -# 3.5.1 -- Updating the internal use of the `fraud_check` parameter in the Vonage Verify V2 API - -# 3.5.0 -- Adding support for V2 of the Vonage Verify API - - Multiple authentication channels are supported (sms, voice, email, whatsapp, whatsapp interactive messages and silent authentication) - - Using fallback channels is now possible in case verification methods fail - - You can now customise the verification code that is sent, or even specify your own custom code -- Adding `advancedMachineDetection` functionality to the NCCO builder for the Vonage Voice API - -# 3.4.0 -- Internal refactoring changes -- Using header authentication for the Numbers API - -# 3.3.0 -- Updated Messages API: - - Added new messaging channels for Viber Service Messages (`video`, `file`) - - Added new WhatsApp `sticker` message channel - - Increased `client_ref` max value to 100 characters -- Deprecated `pay` action in the NCCO builder as it is being removed by Vonage - -# 3.2.2 -- Fixing a bug on Windows - -# 3.2.1 -- Fixing an import bug - -# 3.2.0 -- Adding an NCCO Builder to make it easier to work with NCCOs when using the Voice API -- Individual NCCO Actions can be created as Pydantic models, which can be built into an NCCO via the `Ncco.build_ncco` method - -# 3.1.0 -- Supporting Python 3.11 -- Upgrading some old dependencies - -# 3.0.2 -- Bugfix in `messages.py` where authentication method was not being checked for correctly, throwing an error when using header auth. - -# 3.0.1 -- Fixed bug where a JWT was created globally and could expire. Now a new JWT is generated when a request is made. -- Fixed bug where timeout was not passed to session object. - -# 3.0.0 -Breaking changes: -- Removed deprecated methods from `client.py` that are now available in specific modules related to each of the available Vonage APIs. E.g. to call the number insight API, the methods are now called in this way: `client.number_insight.get_basic_number_insight(...)`, or by instantiating the `NumberInsight` class directly: `ni = vonage.NumberInsight(client)`, `ni.get_basic_number_insight(...)` etc. -- Removed automatic client creation when instantiating an `sms`, `voice` or `verify` object. You can now use these APIs from a client instance you create (e.g. `client.sms.send_message()`) or pass in a client to the API class to create it (e.g. `sms = vonage.Sms(client)`), as has been the case since v2.7.0 of the SDK. -- Removed methods to call the Message Search API, which has been retired by Vonage. -- Removed deprecated voice and number insight methods from `voice.py` (`initiate_call, initiate_tts_call and initiate_tts_prompt_call`) and `number_insight.py` (`request_number_insight`). -- Renamed the `Account.delete_secret()` method to `revoke_secret()` to bring it in line with what is described in our documentation. - -Deprecations: -- Deprecated the ApplicationV2 class and created an Application class with the same methods to bring the naming in line with other classes. This can be called from the client object with `client.application.create_application(...)` etc. or directly with `application = vonage.Application(client)`, `application.create_application(...)` etc. -- Deprecated old Pricing API methods `get_sms_pricing` and `get_voice_pricing`. -- Deprecated Redact class as it's a dev preview product that's unsupported in the SDK and will be removed in a later release. - -Enhancements: -- Added `get_all_countries_pricing` method to `Account` object. -- Added a `type` parameter for pricing calls, so `sms` or `voice` pricing can now be chosen. -- Added `max_retries`, `timeout`, `pool_connections` and `pool_maxsize` optional keyword arguments to the `Client` class, which can now be specified on instantiation and used in the API calls made with the client. - -# 2.8.0 -- Added Messages API v1.0 support. Messages API can now be used by calling the `client.messages.send_message()` method. - -# 2.7.0 -- Moved some client methods into their own classes: `account.py, application.py, -message_search.py, number_insight.py, numbers.py, short_codes.py, ussd.py` -- Deprecated the corresponding client methods. These will be removed in a major release that's coming soon. -- Client now instantiates a class object for each API when it is created, e.g. `vonage.Client(key="mykey", secret="mysecret")` -instantiates instances of `Account`, `Sms`, `NumberInsight` etc. These instances can now be called directly from `Client`, e.g. -``` -client = vonage.Client(key="mykey", secret="mysecret") - -print(f"Account balance is: {client.account.get_balance()}") - -print("Sending an SMS") -client.sms.send_message( - "from": "Vonage", - "to": "SOME_PHONE_NUMBER", - "text": "Hello from Vonage's SMS API" -) - -``` - -# 2.6.x - -- Dropped support for Python 3.6 and below -- Now supporting currently supported stable versions of Python, i.e. Python 3.7-3.10 -- Internal refactoring and enhancements -- Adding default `max_retries` option to the `BasicAuthenticationServer` constructor, specifying optional parameters - -# 2.5.5 - -- Support for Independent SMS, Voice and Verify APIs with tests as well as current client methods -- Getters/Setters to extract/rewrite custom attributes -- PSD2 Verification support -- Dropping support for Python 2.7 -- Roadmap to better error handling -- Supporting Python 3.8 - -# 2.4.0 - -- Application V2 API added under `Client.application_v2` -- Existing application methods under `Client` are now deprecated. - -# 2.3.0 - -- Explicit parameter list for the `nexmo.Client` constructor. **This may cause errors in code passing incorrect or spurious arguments to the Client constructor.** -- Secret Management -- Support for Authorization header authentication. - -# 2.2.0 - -- Add support for `redact_transaction`. - -# 2.1.0 - -- Add support for `get_recording` -- Add support for SMS conversion -- Add debug logging for most calls, under the 'nexmo' logger. -- Internal refactoring (affects only private methods.) - -# 2.0.0 - -- Drop support for Python 3.3 (in line with the cryptography library we depend upon) -- Ensure timestamp is added the params list if signing requests -- Avoid value injection in signature auth. -- Add support for different hashes for signature generation (thanks @trancee!) -- Tests ported to pytest - -# 1.5.0 - -- Add ability to provide a file path as private_key param no the nexmo.Client constructor - -- Add send/stop endpoints for audio/speech/dtmf - -- Add new number insight endpoints - -# 1.4.0 - -- Add new Voice API call methods - -- Add Application API methods - -- Add check_signature method for checking callback signatures - -- Deprecate old Verify API methods - -# 1.3.0 - -- Add get_sms_pricing method - -- Add get_voice_pricing method - -- Add get_event_alert_numbers method to get opt-in/opt-out numbers - -- Add resubscribe_event_alert_number method to opt-in a number - -- Add more clearly named methods for Verify API - -- Add app_name and app_version options - -# 1.2.0 - -- Add topup method - -- Add update_settings method - -- Add api_host attribute - -- Add ClientError and ServerError classes - -# 1.1.0 - -- Move repository to https://github.com/nexmo/nexmo-python - -- Add get_basic_number_insight method for Number Insight Basic API - -- Add get_number_insight method for Number Insight Standard API - -- Add User-Agent header to requests - -# 1.0.3 - -- Change license from LGPL-3.0 to MIT - -# 1.0.2 - -- Remove merge helper function - -# 1.0.1 - -- Python 3.x fixes - -# 1.0.0 - -- First version! diff --git a/vonage_gnp/src/gnp/BUILD b/vonage_gnp/src/gnp/BUILD deleted file mode 100644 index 53e6e16a..00000000 --- a/vonage_gnp/src/gnp/BUILD +++ /dev/null @@ -1 +0,0 @@ -python_sources(name='gnp') diff --git a/vonage_gnp/src/gnp/__init__.py b/vonage_gnp/src/gnp/__init__.py deleted file mode 100644 index ea2299e8..00000000 --- a/vonage_gnp/src/gnp/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from vonage_utils import VonageError - -__all__ = [ - 'VonageError', -] diff --git a/vonage_gnp/BUILD b/vonage_network/BUILD similarity index 65% rename from vonage_gnp/BUILD rename to vonage_network/BUILD index fc42ca8d..6f2c0062 100644 --- a/vonage_gnp/BUILD +++ b/vonage_network/BUILD @@ -3,8 +3,8 @@ resource(name='pyproject', source='pyproject.toml') file(name='readme', source='README.md') python_distribution( - name='vonage', - dependencies=[':pyproject', ':readme', 'vonage/src/vonage'], + name='vonage_network', + dependencies=[':pyproject', ':readme', 'vonage_network/src/vonage_network'], provides=python_artifact(), generate_setup=False, repositories=['@pypi'], diff --git a/vonage_network/CHANGES.md b/vonage_network/CHANGES.md new file mode 100644 index 00000000..26cbc56f --- /dev/null +++ b/vonage_network/CHANGES.md @@ -0,0 +1,2 @@ +# 0.1.0b0 +- Initial beta release \ No newline at end of file diff --git a/vonage_gnp/README.md b/vonage_network/README.md similarity index 100% rename from vonage_gnp/README.md rename to vonage_network/README.md diff --git a/vonage_gnp/pyproject.toml b/vonage_network/pyproject.toml similarity index 65% rename from vonage_gnp/pyproject.toml rename to vonage_network/pyproject.toml index b3ee559f..2cce3954 100644 --- a/vonage_gnp/pyproject.toml +++ b/vonage_network/pyproject.toml @@ -1,23 +1,11 @@ [project] -name = "vonage" +name = "vonage-network" dynamic = ["version"] -description = "Python Server SDK for using Vonage APIs" +description = "Python Server SDK for using Vonage Network APIs" readme = "README.md" authors = [{ name = "Vonage", email = "devrel@vonage.com" }] requires-python = ">=3.8" -dependencies = [ - "vonage-utils>=1.1.1", - "vonage-http-client>=1.3.1", - "vonage-application>=1.0.0", - "vonage-messages>=1.1.1", - "vonage-number-insight>=1.0.0", - "vonage-number-insight-v2>=0.1.1b0", - "vonage-sms>=1.1.1", - "vonage-users>=1.1.2", - "vonage-verify>=1.1.1", - "vonage-verify-v2>=1.1.1", - "vonage-voice>=1.0.3", -] +dependencies = ["vonage-utils>=1.1.1", "vonage-http-client>=1.3.1"] classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", diff --git a/vonage_network/src/vonage_network/BUILD b/vonage_network/src/vonage_network/BUILD new file mode 100644 index 00000000..79353bfe --- /dev/null +++ b/vonage_network/src/vonage_network/BUILD @@ -0,0 +1 @@ +python_sources(name='vonage_network') diff --git a/vonage_network/src/vonage_network/__init__.py b/vonage_network/src/vonage_network/__init__.py new file mode 100644 index 00000000..e3f49e54 --- /dev/null +++ b/vonage_network/src/vonage_network/__init__.py @@ -0,0 +1,18 @@ +from vonage_utils import VonageError + +from .vonage_network import ( + Auth, + HttpClient, + HttpClientOptions, + NetworkAuth, + VonageNetwork, +) + +__all__ = [ + 'VonageError', + 'VonageNetwork', + 'NetworkAuth', + 'Auth', + 'HttpClient', + 'HttpClientOptions', +] diff --git a/vonage_gnp/src/gnp/_version.py b/vonage_network/src/vonage_network/_version.py similarity index 100% rename from vonage_gnp/src/gnp/_version.py rename to vonage_network/src/vonage_network/_version.py diff --git a/vonage_gnp/src/gnp/gnp.py b/vonage_network/src/vonage_network/vonage_network.py similarity index 54% rename from vonage_gnp/src/gnp/gnp.py rename to vonage_network/src/vonage_network/vonage_network.py index 38acbb22..5309ceab 100644 --- a/vonage_gnp/src/gnp/gnp.py +++ b/vonage_network/src/vonage_network/vonage_network.py @@ -1,19 +1,22 @@ +from platform import python_version from typing import Optional from vonage_http_client import Auth, HttpClient, HttpClientOptions - -from gnp_sim_swap import SimSwap +from vonage_network_auth import NetworkAuth from ._version import __version__ +# from network_sim_swap import SimSwap + -class VonageGnp: - """Main Server SDK class for using Vonage GNP APIs. +class VonageNetwork: + """Main Server SDK class for using Vonage Network APIs. When creating an instance, it will create the authentication objects and - an HTTP Client needed for using Vonage APIs. - Use an instance of this class to access the Vonage GNP APIs, e.g. to access - methods associated with the Vonage Sim Swap API, call `vonage_gnp.sim_swap.method_name()`. + an HTTP Client needed for using Vonage Network APIs. + + Use an instance of this class to access the Vonage Network APIs, e.g. to access + methods associated with the Vonage Sim Swap API, call `vonage_network.sim_swap.method_name()`. Args: auth (Auth): Class dealing with authentication objects and methods. @@ -24,8 +27,12 @@ def __init__( self, auth: Auth, http_client_options: Optional[HttpClientOptions] = None ): self._http_client = HttpClient(auth, http_client_options, __version__) + self._http_client._user_agent = ( + f'vonage-network-python-sdk/{__version__} python/{python_version()}' + ) + self.network_auth = NetworkAuth(self._http_client) - self.sim_swap = SimSwap() + # self.sim_swap = SimSwap() @property def http_client(self): diff --git a/vonage_gnp/tests/BUILD b/vonage_network/tests/BUILD similarity index 100% rename from vonage_gnp/tests/BUILD rename to vonage_network/tests/BUILD diff --git a/vonage_gnp/tests/test_vonage.py b/vonage_network/tests/test_vonage_network.py similarity index 59% rename from vonage_gnp/tests/test_vonage.py rename to vonage_network/tests/test_vonage_network.py index 707eca0d..7bcf7ce8 100644 --- a/vonage_gnp/tests/test_vonage.py +++ b/vonage_network/tests/test_vonage_network.py @@ -1,10 +1,11 @@ from vonage_http_client.http_client import HttpClient +from vonage_network._version import __version__ -from vonage.vonage import Auth, Vonage, __version__ +from vonage_network import Auth, VonageNetwork def test_create_vonage_class_instance(): - vonage = Vonage(Auth(api_key='asdf', api_secret='qwerasdf')) + vonage = VonageNetwork(Auth(api_key='asdf', api_secret='qwerasdf')) assert vonage.http_client.auth.api_key == 'asdf' assert vonage.http_client.auth.api_secret == 'qwerasdf' @@ -12,4 +13,4 @@ def test_create_vonage_class_instance(): vonage.http_client.auth.create_basic_auth_string() == 'Basic YXNkZjpxd2VyYXNkZg==' ) assert type(vonage.http_client) == HttpClient - assert f'vonage-python-sdk/{__version__}' in vonage.http_client._user_agent + assert f'vonage-network-python-sdk/{__version__}' in vonage.http_client.user_agent