Add ftl_id to RelayAPIException
Instead of deriving the FTL ID from the default_code, add it explictly to the RelayAPIException or derived class. This makes it easier to cross-reference misc.ftl with the exceptions, and verify that a translation is in use.
This commit is contained in:
Родитель
eb5b4e6a8b
Коммит
7002dc6f4a
|
@ -36,10 +36,11 @@ class RelayAPIException(APIException):
|
|||
Base class for exceptions that may be returned through the API.
|
||||
|
||||
Derived classes should set `default_code` to a unique string identifying the
|
||||
exception. There should be a matching Fluent string with an `api-error-`
|
||||
prefix. For example, the Fluent string "api-error-free-tier-limit" matches
|
||||
the exception class with the default_code "free-tier-limit". These Fluent
|
||||
strings are in misc.ftl.
|
||||
exception. The `ftl_id` should be a matching Fluent string with an `api-error-`
|
||||
prefix. For example, the `ftl_id` "api-error-free-tier-limit" matches
|
||||
the exception class with the `default_code` "free-tier-limit". These Fluent
|
||||
strings are in misc.ftl. While the `ftl_id` _could_ be constructed from the
|
||||
`default_code`, it is included as a cross-referencing aid.
|
||||
|
||||
Derived classes can set `default_detail` to a human-readable string, or they
|
||||
can set `default_detail_template` to dynamically create the string from extra
|
||||
|
@ -53,6 +54,7 @@ class RelayAPIException(APIException):
|
|||
default_code: str
|
||||
default_detail: str
|
||||
status_code: int
|
||||
ftl_id: str
|
||||
|
||||
def __init__(
|
||||
self, detail: _APIExceptionInput = None, code: str | None = None
|
||||
|
@ -69,8 +71,20 @@ class RelayAPIException(APIException):
|
|||
self.default_detail = self.default_detail_template.format(**context)
|
||||
if not isinstance(self.default_detail, str):
|
||||
raise TypeError("self.default_detail must be type str")
|
||||
if not isinstance(self.ftl_id, str):
|
||||
raise TypeError("self.ftl_id must be type str")
|
||||
super().__init__(detail, code)
|
||||
|
||||
# Validated the Fluent error ID ftl_id
|
||||
error_code = self.get_codes()
|
||||
if not isinstance(error_code, str):
|
||||
raise TypeError("error_code must be type str")
|
||||
ftl_id_sub = "api-error-"
|
||||
ftl_id_error = error_code.replace("_", "-")
|
||||
expected_ftl_id = ftl_id_sub + ftl_id_error
|
||||
if expected_ftl_id != self.ftl_id:
|
||||
raise ValueError(f'ftl_id is "{self.ftl_id}", expected "{expected_ftl_id}"')
|
||||
|
||||
def error_context(self) -> ErrorContextType:
|
||||
"""Return context variables for client-side translation."""
|
||||
return {}
|
||||
|
@ -78,21 +92,11 @@ class RelayAPIException(APIException):
|
|||
def error_data(self) -> ErrorData:
|
||||
"""Return extra data for API error responses."""
|
||||
|
||||
# For RelayAPIException classes, this is the default_code and is a string
|
||||
error_code = self.get_codes()
|
||||
if not isinstance(error_code, str):
|
||||
raise TypeError("error_code must be type str")
|
||||
|
||||
# Build the Fluent error ID
|
||||
ftl_id_sub = "api-error-"
|
||||
ftl_id_error = error_code.replace("_", "-")
|
||||
ftl_id = ftl_id_sub + ftl_id_error
|
||||
|
||||
# Replace the default message with the translated Fluent string
|
||||
error_context = self.error_context()
|
||||
translated_detail = ftl_bundle.format(ftl_id, error_context)
|
||||
translated_detail = ftl_bundle.format(self.ftl_id, error_context)
|
||||
|
||||
error_data = ErrorData(detail=translated_detail, error_code=error_code)
|
||||
error_data = ErrorData(detail=translated_detail, error_code=self.get_codes())
|
||||
if error_context:
|
||||
error_data["error_context"] = error_context
|
||||
return error_data
|
||||
|
|
|
@ -12,12 +12,14 @@ class CannotMakeAddressException(RelayAPIException):
|
|||
class AccountIsPausedException(CannotMakeAddressException):
|
||||
default_code = "account_is_paused"
|
||||
default_detail = "Your account is on pause."
|
||||
ftl_id = "api-error-account-is-paused"
|
||||
status_code = 403
|
||||
|
||||
|
||||
class AccountIsInactiveException(CannotMakeAddressException):
|
||||
default_code = "account_is_inactive"
|
||||
default_detail = "Your account is not active."
|
||||
ftl_id = "api-error-account-is-inactive"
|
||||
status_code = 403
|
||||
|
||||
|
||||
|
@ -28,6 +30,7 @@ class RelayAddrFreeTierLimitException(CannotMakeAddressException):
|
|||
" You can reuse an existing mask, but using a unique mask for each account is"
|
||||
" the most secure option."
|
||||
)
|
||||
ftl_id = "api-error-free-tier-limit"
|
||||
status_code = 403
|
||||
|
||||
def __init__(self, free_tier_limit: int | None = None):
|
||||
|
@ -44,12 +47,14 @@ class DomainAddrFreeTierException(CannotMakeAddressException):
|
|||
"Your free account does not include custom subdomains for masks."
|
||||
" To create custom masks, upgrade to Relay Premium."
|
||||
)
|
||||
ftl_id = "api-error-free-tier-no-subdomain-masks"
|
||||
status_code = 403
|
||||
|
||||
|
||||
class DomainAddrNeedSubdomainException(CannotMakeAddressException):
|
||||
default_code = "need_subdomain"
|
||||
default_detail = "Please select a subdomain before creating a custom email address."
|
||||
ftl_id = "api-error-need-subdomain"
|
||||
status_code = 400
|
||||
|
||||
|
||||
|
@ -58,6 +63,7 @@ class DomainAddrUpdateException(CannotMakeAddressException):
|
|||
|
||||
default_code = "address_not_editable"
|
||||
default_detail = "You cannot edit an existing domain address field."
|
||||
ftl_id = "api-error-address-not-editable"
|
||||
status_code = 400
|
||||
|
||||
|
||||
|
@ -67,6 +73,7 @@ class DomainAddrUnavailableException(CannotMakeAddressException):
|
|||
"“{unavailable_address}” could not be created."
|
||||
" Please try again with a different mask name."
|
||||
)
|
||||
ftl_id = "api-error-address-unavailable"
|
||||
status_code = 400
|
||||
|
||||
def __init__(self, unavailable_address: str):
|
||||
|
@ -83,6 +90,7 @@ class DomainAddrDuplicateException(CannotMakeAddressException):
|
|||
"“{duplicate_address}” already exists."
|
||||
" Please try again with a different mask name."
|
||||
)
|
||||
ftl_id = "api-error-duplicate-address"
|
||||
status_code = 409
|
||||
|
||||
def __init__(self, duplicate_address: str):
|
||||
|
|
Загрузка…
Ссылка в новой задаче