cuenca-validations 2.0.5.dev2__tar.gz → 2.0.5.dev4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/PKG-INFO +1 -1
  2. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/__init__.py +2 -2
  3. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/general.py +3 -3
  4. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/helpers.py +7 -0
  5. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/requests.py +9 -2
  6. cuenca_validations-2.0.5.dev4/cuenca_validations/version.py +1 -0
  7. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations.egg-info/PKG-INFO +1 -1
  8. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/tests/test_types.py +36 -9
  9. cuenca_validations-2.0.5.dev2/cuenca_validations/version.py +0 -1
  10. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/LICENSE +0 -0
  11. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/README.md +0 -0
  12. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/__init__.py +0 -0
  13. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/card_bins.py +0 -0
  14. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/errors.py +0 -0
  15. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/py.typed +0 -0
  16. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/card.py +0 -0
  17. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/enums.py +0 -0
  18. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/files.py +0 -0
  19. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/identities.py +0 -0
  20. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/morals.py +0 -0
  21. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/types/queries.py +0 -0
  22. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/typing.py +0 -0
  23. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations/validators.py +0 -0
  24. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations.egg-info/SOURCES.txt +0 -0
  25. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations.egg-info/dependency_links.txt +0 -0
  26. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations.egg-info/requires.txt +0 -0
  27. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/cuenca_validations.egg-info/top_level.txt +0 -0
  28. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/setup.cfg +0 -0
  29. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/setup.py +0 -0
  30. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/tests/__init__.py +0 -0
  31. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/tests/test_card.py +0 -0
  32. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/tests/test_errors.py +0 -0
  33. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/tests/test_helpers.py +0 -0
  34. {cuenca_validations-2.0.5.dev2 → cuenca_validations-2.0.5.dev4}/tests/test_statement.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cuenca_validations
3
- Version: 2.0.5.dev2
3
+ Version: 2.0.5.dev4
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -104,7 +104,7 @@ __all__ = [
104
104
  'digits',
105
105
  'get_state_name',
106
106
  'uuid_field',
107
- 'Metadata',
107
+ 'LogConfig',
108
108
  ]
109
109
 
110
110
  from .card import StrictPaymentCardNumber
@@ -153,7 +153,7 @@ from .enums import (
153
153
  from .files import BatchFileMetadata
154
154
  from .general import (
155
155
  JSONEncoder,
156
- Metadata,
156
+ LogConfig,
157
157
  SantizedDict,
158
158
  StrictPositiveInt,
159
159
  digits,
@@ -86,6 +86,6 @@ def get_state_name(state: State):
86
86
 
87
87
 
88
88
  @dataclass
89
- class Metadata:
90
- sensitive: bool
91
- log_chars: int = 0
89
+ class LogConfig:
90
+ masked: bool = False
91
+ unmasked_chars_length: int = 0
@@ -2,9 +2,16 @@ import uuid
2
2
  from base64 import urlsafe_b64encode
3
3
  from typing import Callable
4
4
 
5
+ from .general import LogConfig
6
+
5
7
 
6
8
  def uuid_field(prefix: str = '') -> Callable[[], str]:
7
9
  def base64_uuid_func() -> str:
8
10
  return prefix + urlsafe_b64encode(uuid.uuid4().bytes).decode()[:-2]
9
11
 
10
12
  return base64_uuid_func
13
+
14
+
15
+ def get_log_config(field) -> LogConfig:
16
+ """Helper function to find LogConfig in field metadata"""
17
+ return next(m for m in field.metadata if isinstance(m, LogConfig))
@@ -54,7 +54,12 @@ from .card import (
54
54
  PaymentCardNumber,
55
55
  StrictPaymentCardNumber,
56
56
  )
57
- from .general import SerializableAnyUrl, SerializableHttpUrl, StrictPositiveInt
57
+ from .general import (
58
+ LogConfig,
59
+ SerializableAnyUrl,
60
+ SerializableHttpUrl,
61
+ StrictPositiveInt,
62
+ )
58
63
  from .identities import (
59
64
  Address,
60
65
  Beneficiary,
@@ -490,7 +495,9 @@ class UserUpdateRequest(BaseModel):
490
495
 
491
496
 
492
497
  class UserLoginRequest(BaseRequest):
493
- password: str # Set password field to str for backward compatibility.
498
+ password: Annotated[
499
+ str, LogConfig(masked=True)
500
+ ] # Set password field to str for backward compatibility.
494
501
  user_id: Optional[str] = Field(None, description='Deprecated field')
495
502
  model_config = ConfigDict(
496
503
  json_schema_extra={'example': {'password': 'supersecret'}},
@@ -0,0 +1 @@
1
+ __version__ = '2.0.5.dev4'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cuenca_validations
3
- Version: 2.0.5.dev2
3
+ Version: 2.0.5.dev4
4
4
  Summary: Cuenca common validations
5
5
  Home-page: https://github.com/cuenca-mx/cuenca-validations
6
6
  Author: Cuenca
@@ -6,7 +6,7 @@ from typing import Annotated
6
6
 
7
7
  import pytest
8
8
  from freezegun import freeze_time
9
- from pydantic import BaseModel, SecretStr, ValidationError
9
+ from pydantic import AfterValidator, BaseModel, SecretStr, ValidationError
10
10
 
11
11
  from cuenca_validations.types import (
12
12
  Address,
@@ -25,7 +25,8 @@ from cuenca_validations.types.enums import (
25
25
  SessionType,
26
26
  State,
27
27
  )
28
- from cuenca_validations.types.general import Metadata, StrictPositiveInt
28
+ from cuenca_validations.types.general import LogConfig, StrictPositiveInt
29
+ from cuenca_validations.types.helpers import get_log_config
29
30
  from cuenca_validations.types.requests import (
30
31
  ApiKeyUpdateRequest,
31
32
  BankAccountValidationRequest,
@@ -589,22 +590,48 @@ def test_strict_positive_int_invalid(value, expected_error, expected_message):
589
590
  IntModel(value=value)
590
591
 
591
592
 
593
+ def validate_password(password: str) -> str:
594
+ """
595
+ Example of a custom validator
596
+ Check if the password contains repeated numbers
597
+ """
598
+ import re
599
+
600
+ if re.search(r'(\d).*\1', password):
601
+ raise ValueError("Password cannot contain repeated digits")
602
+ return password
603
+
604
+
592
605
  class MetadataModel(BaseModel):
593
- secret: Annotated[str, Metadata(sensitive=True)]
594
- partial_secret: Annotated[str, Metadata(sensitive=True, log_chars=4)]
606
+ password: Annotated[
607
+ str, AfterValidator(validate_password), LogConfig(masked=True)
608
+ ]
609
+ secret: Annotated[str, LogConfig(masked=True)]
610
+ partial_secret: Annotated[
611
+ str, LogConfig(masked=True, unmasked_chars_length=4)
612
+ ]
595
613
 
596
614
 
597
615
  def test_metadata():
598
- model = MetadataModel(secret="super-secret", partial_secret="1234567890")
616
+ model = MetadataModel(
617
+ password="Mypass123",
618
+ secret="super-secret",
619
+ partial_secret="1234567890",
620
+ )
599
621
 
622
+ password_field = MetadataModel.model_fields["password"]
600
623
  secret_field = MetadataModel.model_fields["secret"]
601
624
  partial_field = MetadataModel.model_fields["partial_secret"]
602
625
 
603
- assert secret_field.metadata[0].sensitive is True
604
- assert secret_field.metadata[0].log_chars == 0
626
+ assert get_log_config(password_field).masked is True
627
+ assert get_log_config(password_field).unmasked_chars_length == 0
628
+
629
+ assert get_log_config(secret_field).masked is True
630
+ assert get_log_config(secret_field).unmasked_chars_length == 0
605
631
 
606
- assert partial_field.metadata[0].sensitive is True
607
- assert partial_field.metadata[0].log_chars == 4
632
+ assert get_log_config(partial_field).masked is True
633
+ assert get_log_config(partial_field).unmasked_chars_length == 4
608
634
 
635
+ assert model.password == "Mypass123"
609
636
  assert model.secret == "super-secret"
610
637
  assert model.partial_secret == "1234567890"
@@ -1 +0,0 @@
1
- __version__ = '2.0.5.dev2'