Coverage for benefits/enrollment_switchio/models.py: 100%

49 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-08 16:26 +0000

1from django.core.exceptions import ValidationError 

2from django.db import models 

3 

4from benefits.core.models import PemData, SecretNameField, Environment, EnrollmentGroup, TransitProcessorConfig 

5from benefits.secrets import get_secret_by_name 

6 

7 

8class SwitchioConfig(TransitProcessorConfig): 

9 """Configuration for connecting to Switchio, an entity that applies transit agency fare rules to rider transactions.""" 

10 

11 tokenization_api_key = models.TextField( 

12 help_text="The API key used to access the Switchio API for tokenization.", default="", blank=True 

13 ) 

14 tokenization_api_secret_name = SecretNameField( 

15 help_text="The name of the secret containing the api_secret value used to access the Switchio API for tokenization.", # noqa: E501 

16 default="", 

17 blank=True, 

18 ) 

19 enrollment_api_authorization_header = models.TextField( 

20 help_text="The value to use for the 'Authorization' header when accessing the Switchio API for enrollment.", 

21 default="", 

22 blank=True, 

23 ) 

24 pto_id = models.PositiveIntegerField( 

25 help_text="The Public Transport Operator ID to use with the Switchio API for enrollment.", 

26 default=0, 

27 blank=True, 

28 ) 

29 client_certificate = models.ForeignKey( 

30 PemData, 

31 related_name="+", 

32 on_delete=models.PROTECT, 

33 help_text="The client certificate for accessing the Switchio API.", 

34 null=True, 

35 blank=True, 

36 default=None, 

37 ) 

38 ca_certificate = models.ForeignKey( 

39 PemData, 

40 related_name="+", 

41 on_delete=models.PROTECT, 

42 help_text="The CA certificate chain for accessing the Switchio API.", 

43 null=True, 

44 blank=True, 

45 default=None, 

46 ) 

47 private_key = models.ForeignKey( 

48 PemData, 

49 related_name="+", 

50 on_delete=models.PROTECT, 

51 help_text="The private key for accessing the Switchio API.", 

52 null=True, 

53 blank=True, 

54 default=None, 

55 ) 

56 

57 @property 

58 def tokenization_api_base_url(self): 

59 if self.environment == Environment.QA.value: 

60 return get_secret_by_name("switchio-qa-tokenization-api-base-url") 

61 elif self.environment == Environment.PROD.value: 

62 return get_secret_by_name("switchio-prod-tokenization-api-base-url") 

63 else: 

64 raise ValueError(f"Unexpected value for environment: {self.environment}") 

65 

66 @property 

67 def enrollment_api_base_url(self): 

68 if self.environment == Environment.QA.value: 

69 return get_secret_by_name("switchio-qa-enrollment-api-base-url") 

70 elif self.environment == Environment.PROD.value: 

71 return get_secret_by_name("switchio-prod-enrollment-api-base-url") 

72 else: 

73 raise ValueError(f"Unexpected value for environment: {self.environment}") 

74 

75 @property 

76 def tokenization_api_secret(self): 

77 secret_field = self._meta.get_field("tokenization_api_secret_name") 

78 return secret_field.secret_value(self) 

79 

80 @property 

81 def client_certificate_data(self): 

82 """This SwitchioConfig's client certificate as a string.""" 

83 return self.client_certificate.data 

84 

85 @property 

86 def ca_certificate_data(self): 

87 """This SwitchioConfig's CA certificate as a string.""" 

88 return self.ca_certificate.data 

89 

90 @property 

91 def private_key_data(self): 

92 """This SwitchioConfig's private key as a string.""" 

93 return self.private_key.data 

94 

95 def clean(self): 

96 field_errors = {} 

97 

98 if self.transit_agency and self.transit_agency.active: 

99 message = "This field is required when this configuration is referenced by an active transit agency." 

100 needed = dict( 

101 tokenization_api_key=self.tokenization_api_key, 

102 tokenization_api_secret_name=self.tokenization_api_secret_name, 

103 enrollment_api_authorization_header=self.enrollment_api_authorization_header, 

104 pto_id=self.pto_id, 

105 client_certificate=self.client_certificate, 

106 ca_certificate=self.ca_certificate, 

107 private_key=self.private_key, 

108 ) 

109 field_errors.update({k: ValidationError(message) for k, v in needed.items() if not v}) 

110 

111 if field_errors: 

112 raise ValidationError(field_errors) 

113 

114 

115class SwitchioGroup(EnrollmentGroup): 

116 group_id = models.TextField(default=None, blank=True, help_text="The ID of the Switchio group for user enrollment.")