Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cuenca/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
'LimitedWallet',
'LoginToken',
'Otp',
'OperatorLogin',
'PasswordReset',
'Platform',
'Questionnaires',
Expand Down Expand Up @@ -80,6 +81,7 @@
KYCValidation,
LimitedWallet,
LoginToken,
OperatorLogin,
Otp,
PasswordReset,
PhoneVerificationAssociations,
Expand Down
3 changes: 3 additions & 0 deletions cuenca/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
'LimitedWallet',
'LoginToken',
'Otp',
'OperatorLogin',
'PasswordReset',
'Platform',
'PhoneVerificationAssociation',
Expand Down Expand Up @@ -74,6 +75,7 @@
from .kyc_validations import KYCValidation
from .limited_wallets import LimitedWallet
from .login_tokens import LoginToken
from .operator_logins import OperatorLogin
from .otps import Otp
from .password_resets import PasswordReset
from .phone_verification_associations import PhoneVerificationAssociations
Expand Down Expand Up @@ -124,6 +126,7 @@
KYCValidation,
LimitedWallet,
LoginToken,
OperatorLogin,
PasswordReset,
Questionnaires,
Saving,
Expand Down
51 changes: 51 additions & 0 deletions cuenca/resources/operator_logins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from typing import Annotated, ClassVar

from cuenca_validations.types import LogConfig, OperatorRole
from cuenca_validations.types.requests import OperatorLoginRequest
Comment thread
coderabbitai[bot] marked this conversation as resolved.
from pydantic import ConfigDict

from ..http import Session, session as global_session
from .base import Creatable


class OperatorLogin(Creatable):
"""Authenticate a company operator (portal personas morales).

Authed endpoint: ``POST /operator-login``. Response ``id`` is the
Session.id; use it as ``X-Cuenca-SessionId`` on subsequent requests.
"""

_resource: ClassVar = 'operator-login'

id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
Comment thread
rogelioLpz marked this conversation as resolved.
operator_id: str
role: OperatorRole
legal_person_id: str

model_config = ConfigDict(
json_schema_extra={
'example': {
'id': 'SEWqY5cvkISJOxHyEKjAKf8w',
'operator_id': 'OPWqY5cvkISJOxHyEKjAKf8w',
'role': 'authorizer',
'legal_person_id': 'USWqY5cvkISJOxHyEKjAKf8w',
}
}
)

@classmethod
def create(
cls,
email: str,
password: str,
*,
session: Session = global_session,
) -> 'OperatorLogin':
req = OperatorLoginRequest(email=email, password=password)
login = cls._create(
session=session,
email=str(req.email),
password=req.password.get_secret_value(),
)
session.headers['X-Cuenca-SessionId'] = login.id
return login
2 changes: 1 addition & 1 deletion cuenca/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = '2.2.3'
__version__ = '2.2.4'
CLIENT_VERSION = __version__
API_VERSION = '2020-03-19'
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
requests==2.32.3
cuenca-validations==2.1.39
cuenca-validations==2.1.44
pydantic-extra-types==2.10.2
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
python_requires='>=3.9',
install_requires=[
'requests>=2.32.0',
'cuenca-validations>=2.1.34',
'cuenca-validations>=2.1.44',
'pydantic-extra-types>=2.10.0',
],
classifiers=[
Expand Down
47 changes: 47 additions & 0 deletions tests/resources/test_operator_logins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from unittest.mock import MagicMock, patch

import pytest
from cuenca_validations.types import OperatorRole

from cuenca import OperatorLogin
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_operator_login_create(mock_request: MagicMock, session: Session):
mock_request.return_value.ok = True
mock_request.return_value.content = (
b'{"id":"SEWqY5cvkISJOxHyEKjAKf8w",'
b'"operator_id":"OPWqY5cvkISJOxHyEKjAKf8w",'
b'"role":"operator",'
b'"legal_person_id":"USWqY5cvkISJOxHyEKjAKf8w"}'
)

login = OperatorLogin.create(
'Maria+Tag@Aceros.com',
'supersecret',
session=session,
)

assert login.id == 'SEWqY5cvkISJOxHyEKjAKf8w'
assert login.operator_id == 'OPWqY5cvkISJOxHyEKjAKf8w'
assert login.role == OperatorRole.operator
assert login.legal_person_id == 'USWqY5cvkISJOxHyEKjAKf8w'
assert session.headers['X-Cuenca-SessionId'] == login.id
assert 'X-Cuenca-LoginId' not in session.headers

mock_request.assert_called_once()
_, kwargs = mock_request.call_args
assert kwargs['method'] == 'post'
assert kwargs['url'] == 'https://sandbox.cuenca.com/operator-login'
assert kwargs['json'] == {
'email': 'maria@aceros.com',
'password': 'supersecret',
}
Loading