Skip to content

Commit 4a0c538

Browse files
gmorales96gabino
andauthored
Feature/add sensitive metadata (#414)
* Add sensitive metadata annotation to resource * Add JwtToken resource for generating JWT tokens * Bump cuenca-validations to version 2.0.5.dev1 * Bump version to 2.0.2.dev1 * Bump version to 2.0.2.dev2 * Update cuenca-validations type annotations from Metadata to LogConfig * Bump version to 2.0.2.dev3 * Release version 2.0.2 * Update JwtToken example with redacted JWT tokens * Remove unmasked characters length from OTP secret logging * Simplify JwtToken test by removing session configuration * Add masked logging configuration for UserLogin ID * Add masked logging configuration for card number * Bump version to 2.0.2.dev3 * Update cuenca-validations to version 2.1.0 * Change unmasked characters length from ApiKey secret logging * Release version 2.1.0 --------- Co-authored-by: gabino <gabino@cuenca.com>
1 parent f338ff4 commit 4a0c538

File tree

14 files changed

+212
-15
lines changed

14 files changed

+212
-15
lines changed

cuenca/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
'WhatsappTransfer',
4343
'configure',
4444
'get_balance',
45+
'JwtToken',
4546
]
4647

4748
from . import http
@@ -65,6 +66,7 @@
6566
FileBatch,
6667
Identity,
6768
IdentityEvent,
69+
JwtToken,
6870
KYCValidation,
6971
KYCVerification,
7072
LimitedWallet,

cuenca/resources/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
'WalletTransaction',
3939
'Webhook',
4040
'WhatsappTransfer',
41+
'JwtToken',
4142
]
4243

4344
from .accounts import Account
@@ -59,6 +60,7 @@
5960
from .files import File
6061
from .identities import Identity
6162
from .identity_events import IdentityEvent
63+
from .jwt_tokens import JwtToken
6264
from .kyc_validations import KYCValidation
6365
from .kyc_verifications import KYCVerification
6466
from .limited_wallets import LimitedWallet
@@ -123,6 +125,7 @@
123125
WhatsappTransfer,
124126
Webhook,
125127
Platform,
128+
JwtToken,
126129
]
127130
for resource_cls in resource_classes:
128131
RESOURCES[resource_cls._resource] = resource_cls # type: ignore

cuenca/resources/api_keys.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import datetime as dt
2-
from typing import ClassVar, Optional
2+
from typing import Annotated, ClassVar, Optional
33

4-
from cuenca_validations.types import ApiKeyQuery, ApiKeyUpdateRequest
4+
from cuenca_validations.types import (
5+
ApiKeyQuery,
6+
ApiKeyUpdateRequest,
7+
LogConfig,
8+
)
59
from pydantic import ConfigDict
610

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

15-
secret: str
19+
secret: Annotated[str, LogConfig(masked=True)]
1620
deactivated_at: Optional[dt.datetime] = None
1721
user_id: Optional[str] = None
1822
model_config = ConfigDict(

cuenca/resources/cards.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import datetime as dt
2-
from typing import ClassVar, Optional
2+
from typing import Annotated, ClassVar, Optional
33

44
from cuenca_validations.types import (
55
CardFundingType,
66
CardIssuer,
77
CardStatus,
88
CardType,
99
)
10+
from cuenca_validations.types.general import LogConfig
1011
from cuenca_validations.types.queries import CardQuery
1112
from cuenca_validations.types.requests import CardRequest, CardUpdateRequest
1213

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

2425
user_id: Optional[str] = None
25-
number: str
26+
number: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
2627
exp_month: int
2728
exp_year: int
2829
cvv2: str

cuenca/resources/jwt_tokens.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import datetime as dt
2+
from typing import Annotated, ClassVar
3+
4+
from cuenca_validations.types import LogConfig
5+
from pydantic import ConfigDict
6+
7+
from ..http import Session, session as global_session
8+
from .base import Creatable
9+
10+
11+
class JwtToken(Creatable):
12+
_resource: ClassVar = 'token'
13+
14+
id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
15+
token: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
16+
created_at: dt.datetime
17+
api_key_uri: str
18+
19+
model_config = ConfigDict(
20+
json_schema_extra={
21+
'example': {
22+
'id': 'jwt_XXXX...redacted',
23+
'token': 'jwt_XXXX...redacted',
24+
'created_at': '2025-01-24T22:34:37.659667',
25+
'api_key_uri': '/api_key/AKsczy7tsiRd2IbjL_nYFolQ',
26+
}
27+
}
28+
)
29+
30+
@classmethod
31+
def create(cls, session: Session = global_session) -> 'JwtToken':
32+
return cls._create(session=session)

cuenca/resources/login_tokens.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
from typing import ClassVar
1+
from typing import Annotated, ClassVar
22

3+
from cuenca_validations.types import LogConfig
34
from pydantic import ConfigDict
45

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

13+
id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
14+
1215
model_config = ConfigDict(
1316
json_schema_extra={'example': {'id': 'LTNEUInh69SuKXXmK95sROwQ'}}
1417
)

cuenca/resources/otps.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
from typing import ClassVar
1+
from typing import Annotated, ClassVar
22

3+
from cuenca_validations.types import LogConfig
34
from pydantic import ConfigDict
45

56
from ..http import Session, session as global_session
@@ -8,7 +9,7 @@
89

910
class Otp(Creatable):
1011
_resource: ClassVar = 'otps'
11-
secret: str
12+
secret: Annotated[str, LogConfig(masked=True)]
1213

1314
model_config = ConfigDict(
1415
json_schema_extra={

cuenca/resources/sessions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import datetime as dt
2-
from typing import ClassVar, Optional
2+
from typing import Annotated, ClassVar, Optional
33

4-
from cuenca_validations.types import SessionRequest, SessionType
4+
from cuenca_validations.types import LogConfig, SessionRequest, SessionType
55
from cuenca_validations.types.general import SerializableAnyUrl
66
from pydantic import ConfigDict
77

@@ -12,7 +12,7 @@
1212
class Session(Creatable, Retrievable, Queryable):
1313
_resource: ClassVar = 'sessions'
1414

15-
id: str
15+
id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
1616
created_at: dt.datetime
1717
user_id: str
1818
platform_id: str

cuenca/resources/user_logins.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime as dt
2-
from typing import ClassVar, Optional
2+
from typing import Annotated, ClassVar, Optional
33

4+
from cuenca_validations.types import LogConfig
45
from cuenca_validations.types.requests import UserLoginRequest
56
from pydantic import ConfigDict
67

@@ -11,6 +12,8 @@
1112
class UserLogin(Creatable):
1213
_resource: ClassVar = 'user_logins'
1314

15+
id: Annotated[str, LogConfig(masked=True, unmasked_chars_length=4)]
16+
1417
last_login_at: Optional[dt.datetime] = None
1518
success: bool
1619

cuenca/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
__version__ = '2.0.1'
1+
__version__ = '2.1.0'
22
CLIENT_VERSION = __version__
33
API_VERSION = '2020-03-19'

0 commit comments

Comments
 (0)