diff --git a/cuenca/__init__.py b/cuenca/__init__.py index 568f4eb3..62ef7f34 100644 --- a/cuenca/__init__.py +++ b/cuenca/__init__.py @@ -25,6 +25,7 @@ 'LimitedWallet', 'LoginToken', 'Otp', + 'EmailOtp', 'OperatorLogin', 'PasswordReset', 'Platform', @@ -71,6 +72,7 @@ Commission, CurpValidation, Deposit, + EmailOtp, Endpoint, ExistPhones, File, diff --git a/cuenca/resources/__init__.py b/cuenca/resources/__init__.py index bbde7b5a..9b9011a2 100644 --- a/cuenca/resources/__init__.py +++ b/cuenca/resources/__init__.py @@ -25,6 +25,7 @@ 'LimitedWallet', 'LoginToken', 'Otp', + 'EmailOtp', 'OperatorLogin', 'PasswordReset', 'Platform', @@ -65,6 +66,7 @@ from .commissions import Commission from .curp_validations import CurpValidation from .deposits import Deposit +from .email_otps import EmailOtp from .endpoints import Endpoint from .exist_phones import ExistPhones from .file_batches import FileBatch diff --git a/cuenca/resources/email_otps.py b/cuenca/resources/email_otps.py new file mode 100644 index 00000000..7f9c5f9d --- /dev/null +++ b/cuenca/resources/email_otps.py @@ -0,0 +1,28 @@ +import datetime as dt +from typing import ClassVar, Optional + +from pydantic import ConfigDict + +from ..http import Session, session as global_session +from .base import Creatable + + +class EmailOtp(Creatable): + _resource: ClassVar = 'email_otps' + owner_id: Optional[str] = None + expires_at: Optional[dt.datetime] = None + + model_config = ConfigDict( + json_schema_extra={ + 'example': { + 'id': 'EOxxxxxxxxxxxxxxxxxxxxxx', + 'owner_id': 'SSxxxxxxxxxxxxxxxxxxxxxx', + 'expires_at': '2026-09-09T18:00:00', + } + } + ) + + @classmethod + def create(cls, session: Session = global_session) -> 'EmailOtp': + """Request a one-shot email OTP for the current Session.""" + return cls._create(session=session) diff --git a/cuenca/version.py b/cuenca/version.py index f189b057..ad5488e0 100644 --- a/cuenca/version.py +++ b/cuenca/version.py @@ -1,3 +1,3 @@ -__version__ = '2.2.4' +__version__ = '2.2.5.dev0' CLIENT_VERSION = __version__ API_VERSION = '2020-03-19' diff --git a/tests/resources/test_email_otps.py b/tests/resources/test_email_otps.py new file mode 100644 index 00000000..4834b0f4 --- /dev/null +++ b/tests/resources/test_email_otps.py @@ -0,0 +1,36 @@ +import datetime as dt +from unittest.mock import MagicMock, patch + +import pytest + +from cuenca import EmailOtp +from cuenca.http.client import Session + + +@pytest.fixture +def session() -> Session: + s = Session() + s.configure('api_key', 'api_secret', sandbox=True) + return s + + +@patch('cuenca.http.client.requests.Session.request') +def test_email_otp_create(mock_request: MagicMock, session: Session): + mock_request.return_value.ok = True + mock_request.return_value.content = ( + b'{"id":"EOxxxxxxxxxxxxxxxxxxxxxx",' + b'"owner_id":"SSxxxxxxxxxxxxxxxxxxxxxx",' + b'"expires_at":"2026-09-09T18:00:00"}' + ) + + email_otp = EmailOtp.create(session=session) + + assert email_otp.id == 'EOxxxxxxxxxxxxxxxxxxxxxx' + assert email_otp.owner_id == 'SSxxxxxxxxxxxxxxxxxxxxxx' + assert email_otp.expires_at == dt.datetime(2026, 9, 9, 18, 0, 0) + + mock_request.assert_called_once() + _, kwargs = mock_request.call_args + assert kwargs['method'] == 'post' + assert kwargs['url'] == 'https://sandbox.cuenca.com/email_otps' + assert kwargs['json'] == {}