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

48 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-09 20:43 +0000

1from django.core.exceptions import ValidationError 

2from django.db import models 

3 

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

5from benefits.secrets import get_secret_by_name 

6 

7 

8class SwitchioConfig(models.Model): 

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

10 

11 id = models.AutoField(primary_key=True) 

12 environment = models.TextField( 

13 choices=Environment, 

14 help_text="A label to indicate which environment this configuration is for.", 

15 ) 

16 api_key = models.TextField(help_text="The API key used to access the Switchio API.", default="", blank=True) 

17 api_secret_name = SecretNameField( 

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

19 default="", 

20 blank=True, 

21 ) 

22 client_certificate = models.ForeignKey( 

23 PemData, 

24 related_name="+", 

25 on_delete=models.PROTECT, 

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

27 null=True, 

28 blank=True, 

29 default=None, 

30 ) 

31 ca_certificate = models.ForeignKey( 

32 PemData, 

33 related_name="+", 

34 on_delete=models.PROTECT, 

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

36 null=True, 

37 blank=True, 

38 default=None, 

39 ) 

40 private_key = models.ForeignKey( 

41 PemData, 

42 related_name="+", 

43 on_delete=models.PROTECT, 

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

45 null=True, 

46 blank=True, 

47 default=None, 

48 ) 

49 

50 @property 

51 def api_base_url(self): 

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

53 return get_secret_by_name("switchio-qa-api-base-url") 

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

55 return get_secret_by_name("switchio-prod-api-base-url") 

56 else: 

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

58 

59 @property 

60 def api_secret(self): 

61 secret_field = self._meta.get_field("api_secret_name") 

62 return secret_field.secret_value(self) 

63 

64 @property 

65 def client_certificate_data(self): 

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

67 return self.client_certificate.data 

68 

69 @property 

70 def ca_certificate_data(self): 

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

72 return self.ca_certificate.data 

73 

74 @property 

75 def private_key_data(self): 

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

77 return self.private_key.data 

78 

79 def clean(self, agency=None): 

80 field_errors = {} 

81 

82 if agency is not None: 

83 used_by_active_agency = agency.active 

84 elif self.pk is not None: 

85 used_by_active_agency = any((agency.active for agency in self.transitagency_set.all())) 

86 else: 

87 used_by_active_agency = False 

88 

89 if used_by_active_agency: 

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

91 needed = dict( 

92 api_key=self.api_key, 

93 api_secret_name=self.api_secret_name, 

94 client_certificate=self.client_certificate, 

95 ca_certificate=self.ca_certificate, 

96 private_key=self.private_key, 

97 ) 

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

99 

100 if field_errors: 

101 raise ValidationError(field_errors) 

102 

103 def __str__(self): 

104 environment_label = Environment(self.environment).label if self.environment else "unknown" 

105 return f"{environment_label}"