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 @@ -42,6 +42,7 @@
'WhatsappTransfer',
'configure',
'get_balance',
'JwtToken',
]

from . import http
Expand All @@ -65,6 +66,7 @@
FileBatch,
Identity,
IdentityEvent,
JwtToken,
KYCValidation,
KYCVerification,
LimitedWallet,
Expand Down
3 changes: 3 additions & 0 deletions cuenca/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
'WalletTransaction',
'Webhook',
'WhatsappTransfer',
'JwtToken',
]

from .accounts import Account
Expand All @@ -59,6 +60,7 @@
from .files import File
from .identities import Identity
from .identity_events import IdentityEvent
from .jwt_tokens import JwtToken
from .kyc_validations import KYCValidation
from .kyc_verifications import KYCVerification
from .limited_wallets import LimitedWallet
Expand Down Expand Up @@ -123,6 +125,7 @@
WhatsappTransfer,
Webhook,
Platform,
JwtToken,
]
for resource_cls in resource_classes:
RESOURCES[resource_cls._resource] = resource_cls # type: ignore
10 changes: 7 additions & 3 deletions cuenca/resources/api_keys.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import datetime as dt
from typing import ClassVar, Optional
from typing import Annotated, ClassVar, Optional

from cuenca_validations.types import ApiKeyQuery, ApiKeyUpdateRequest
from cuenca_validations.types import (
ApiKeyQuery,
ApiKeyUpdateRequest,
LogConfig,
)
from pydantic import ConfigDict

from ..http import Session, session as global_session
Expand All @@ -12,7 +16,7 @@ class ApiKey(Creatable, Queryable, Retrievable, Updateable):
_resource: ClassVar = 'api_keys'
_query_params: ClassVar = ApiKeyQuery

secret: str
secret: Annotated[str, LogConfig(masked=True)]
deactivated_at: Optional[dt.datetime] = None
user_id: Optional[str] = None
model_config = ConfigDict(
Expand Down
5 changes: 3 additions & 2 deletions cuenca/resources/cards.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import datetime as dt
from typing import ClassVar, Optional
from typing import Annotated, ClassVar, Optional

from cuenca_validations.types import (
CardFundingType,
CardIssuer,
CardStatus,
CardType,
)
from cuenca_validations.types.general import LogConfig
from cuenca_validations.types.queries import CardQuery
from cuenca_validations.types.requests import CardRequest, CardUpdateRequest

Expand All @@ -22,7 +23,7 @@ class Card(Retrievable, Queryable, Creatable, Updateable):
_query_params: ClassVar = CardQuery

user_id: Optional[str] = None
number: str
number: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
exp_month: int
exp_year: int
cvv2: str
Expand Down
32 changes: 32 additions & 0 deletions cuenca/resources/jwt_tokens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import datetime as dt
from typing import Annotated, ClassVar

from cuenca_validations.types import LogConfig
from pydantic import ConfigDict

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


class JwtToken(Creatable):
_resource: ClassVar = 'token'

id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
token: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
created_at: dt.datetime
api_key_uri: str

model_config = ConfigDict(
json_schema_extra={
'example': {
'id': 'jwt_XXXX...redacted',
'token': 'jwt_XXXX...redacted',
'created_at': '2025-01-24T22:34:37.659667',
'api_key_uri': '/api_key/AKsczy7tsiRd2IbjL_nYFolQ',
}
}
)

@classmethod
def create(cls, session: Session = global_session) -> 'JwtToken':
return cls._create(session=session)
5 changes: 4 additions & 1 deletion cuenca/resources/login_tokens.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import ClassVar
from typing import Annotated, ClassVar

from cuenca_validations.types import LogConfig
from pydantic import ConfigDict

from ..http import Session, session as global_session
Expand All @@ -9,6 +10,8 @@
class LoginToken(Creatable):
_resource: ClassVar = 'login_tokens'

id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]

model_config = ConfigDict(
json_schema_extra={'example': {'id': 'LTNEUInh69SuKXXmK95sROwQ'}}
)
Expand Down
5 changes: 3 additions & 2 deletions cuenca/resources/otps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import ClassVar
from typing import Annotated, ClassVar

from cuenca_validations.types import LogConfig
from pydantic import ConfigDict

from ..http import Session, session as global_session
Expand All @@ -8,7 +9,7 @@

class Otp(Creatable):
_resource: ClassVar = 'otps'
secret: str
secret: Annotated[str, LogConfig(masked=True)]

model_config = ConfigDict(
json_schema_extra={
Expand Down
6 changes: 3 additions & 3 deletions cuenca/resources/sessions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime as dt
from typing import ClassVar, Optional
from typing import Annotated, ClassVar, Optional

from cuenca_validations.types import SessionRequest, SessionType
from cuenca_validations.types import LogConfig, SessionRequest, SessionType
from cuenca_validations.types.general import SerializableAnyUrl
from pydantic import ConfigDict

Expand All @@ -12,7 +12,7 @@
class Session(Creatable, Retrievable, Queryable):
_resource: ClassVar = 'sessions'

id: str
id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
created_at: dt.datetime
user_id: str
platform_id: str
Expand Down
5 changes: 4 additions & 1 deletion cuenca/resources/user_logins.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime as dt
from typing import ClassVar, Optional
from typing import Annotated, ClassVar, Optional

from cuenca_validations.types import LogConfig
from cuenca_validations.types.requests import UserLoginRequest
from pydantic import ConfigDict

Expand All @@ -11,6 +12,8 @@
class UserLogin(Creatable):
_resource: ClassVar = 'user_logins'

id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]

last_login_at: Optional[dt.datetime] = None
success: bool

Expand Down
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.0.1'
__version__ = '2.1.0'
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.0.4
cuenca-validations==2.1.0
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.0.4',
'cuenca-validations>=2.1.0',
'pydantic-extra-types>=2.10.0',
],
classifiers=[
Expand Down
138 changes: 138 additions & 0 deletions tests/resources/cassettes/test_jwt_tokens.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
interactions:
- request:
body: '{"password": "111111"}'
headers:
Authorization:
- DUMMY
Content-Length:
- '26'
Content-Type:
- application/json
User-Agent:
- cuenca-python/2.0.1
X-Cuenca-Api-Version:
- '2020-03-19'
method: POST
uri: https://sandbox.cuenca.com/user_logins
response:
body:
string: '{"success":true,"id":"ULm7x8e0hfQYyUWwM3ysqgTw","last_login_at":"2025-01-27T22:50:04.745000Z"}'
headers:
Connection:
- keep-alive
Content-Length:
- '94'
Content-Type:
- application/json
Date:
- Mon, 27 Jan 2025 23:08:55 GMT
X-Request-Time:
- 'value: 0.421'
x-amz-apigw-id:
- FEfBLEMtCYcEKuQ=
x-amzn-Remapped-Connection:
- keep-alive
x-amzn-Remapped-Content-Length:
- '94'
x-amzn-Remapped-Date:
- Mon, 27 Jan 2025 23:08:55 GMT
x-amzn-Remapped-Server:
- nginx/1.26.2
x-amzn-RequestId:
- 855b6c10-2e41-4b1f-b0fe-6030bd4e0032
status:
code: 201
message: Created
- request:
body: '{}'
headers:
Authorization:
- DUMMY
Content-Length:
- '2'
Content-Type:
- application/json
User-Agent:
- cuenca-python/2.0.1
X-Cuenca-Api-Version:
- '2020-03-19'
X-Cuenca-LoginId:
- ULm7x8e0hfQYyUWwM3ysqgTw
method: POST
uri: https://sandbox.cuenca.com/login_tokens
response:
body:
string: '{"id":"LTqXrT9Z64S329W0D-uJKwmQ"}'
headers:
Connection:
- keep-alive
Content-Length:
- '33'
Content-Type:
- application/json
Date:
- Mon, 27 Jan 2025 23:08:56 GMT
X-Request-Time:
- 'value: 0.202'
x-amz-apigw-id:
- FEfBSG6ZCYcEPMg=
x-amzn-Remapped-Connection:
- keep-alive
x-amzn-Remapped-Content-Length:
- '33'
x-amzn-Remapped-Date:
- Mon, 27 Jan 2025 23:08:56 GMT
x-amzn-Remapped-Server:
- nginx/1.26.2
x-amzn-RequestId:
- 7876a2df-cbdc-40f5-b2b8-c4dcfcdc2d23
status:
code: 201
message: Created
- request:
body: '{}'
headers:
Authorization:
- DUMMY
Content-Length:
- '2'
Content-Type:
- application/json
User-Agent:
- cuenca-python/2.0.1
X-Cuenca-Api-Version:
- '2020-03-19'
X-Cuenca-LoginToken:
- LTqXrT9Z64S329W0D-uJKwmQ
method: POST
uri: https://sandbox.cuenca.com/token
response:
body:
string: '{"id":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzg2MjQxMzYsImlhdCI6MTczODAxOTMzNiwic3ViIjoiQUsyTDh6Y0x2YlRJR1ZsQXdndm9LX1dnIiwidWlkIjoiYWYxM2JmZDgtZGQwMy0xMWVmLThkN2MtMGE1OGE5ZmVhYzAyIn0.tpCxBTcKGWvuRUsKmo7a7IcofgrhVmxIIEiaDBRbAhY","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzg2MjQxMzYsImlhdCI6MTczODAxOTMzNiwic3ViIjoiQUsyTDh6Y0x2YlRJR1ZsQXdndm9LX1dnIiwidWlkIjoiYWYxM2JmZDgtZGQwMy0xMWVmLThkN2MtMGE1OGE5ZmVhYzAyIn0.tpCxBTcKGWvuRUsKmo7a7IcofgrhVmxIIEiaDBRbAhY","created_at":"2025-01-27T23:08:56.372428","api_key_uri":"/api_key/AK2L8zcLvbTIGVlAwgvoK_Wg"}'
headers:
Connection:
- keep-alive
Content-Length:
- '576'
Content-Type:
- application/json
Date:
- Mon, 27 Jan 2025 23:08:56 GMT
X-Request-Time:
- 'value: 0.104'
x-amz-apigw-id:
- FEfBWHrtiYcEAJA=
x-amzn-Remapped-Connection:
- keep-alive
x-amzn-Remapped-Content-Length:
- '576'
x-amzn-Remapped-Date:
- Mon, 27 Jan 2025 23:08:56 GMT
x-amzn-Remapped-Server:
- nginx/1.26.2
x-amzn-RequestId:
- 79544974-46c4-4003-a548-48731d96f703
status:
code: 201
message: Created
version: 1
10 changes: 10 additions & 0 deletions tests/resources/test_jwt_tokens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import pytest

from cuenca import JwtToken


@pytest.mark.vcr
def test_jwt_tokens():
jwt_token = JwtToken.create()
assert jwt_token
assert isinstance(jwt_token.token, str)
Loading