Coverage for dataexcept/security_exceptions.py: 100%
23 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-09-03 20:46 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-09-03 20:46 +0000
1"""Custom exceptions for security-related operations."""
3from __future__ import annotations
5from .base import DataExceptError
6from .redaction import redact_secret, remove_secret
9class SecurityError(DataExceptError):
10 """Base exception for security errors."""
12 pass
15class EncryptionError(SecurityError):
16 """Raised when data encryption fails."""
18 def __init__(self, algorithm: str, message: str | None = None) -> None:
19 """Initialize EncryptionError.
21 Args:
22 algorithm: Name of the encryption algorithm.
23 message: Optional custom error message.
24 """
25 self.algorithm = algorithm
26 default = f"Encryption failed using {algorithm}"
27 super().__init__(message or default)
30class DecryptionError(SecurityError):
31 """Raised when data decryption fails."""
33 def __init__(self, algorithm: str, message: str | None = None) -> None:
34 """Initialize DecryptionError.
36 Args:
37 algorithm: Name of the decryption algorithm.
38 message: Optional custom error message.
39 """
40 self.algorithm = algorithm
41 default = f"Decryption failed using {algorithm}"
42 super().__init__(message or default)
45class InvalidTokenError(SecurityError):
46 """Raised when an authentication token is invalid or expired."""
48 def __init__(
49 self,
50 token: str | None = None,
51 message: str | None = None,
52 ) -> None:
53 """Initialize InvalidTokenError.
55 Args:
56 token: The problematic token.
57 message: Optional custom error message.
58 """
59 # The raw token is never stored or rendered: this exception is often
60 # logged, and the caller already holds the value it passed in.
61 self.token = redact_secret(token)
62 default = "Invalid authentication token"
63 if token:
64 default += f": {self.token}"
65 # The library was handed the secret, so it can be removed even from a
66 # message the caller wrote themselves.
67 super().__init__(remove_secret(message or default, token))
70__all__ = [
71 "SecurityError",
72 "EncryptionError",
73 "DecryptionError",
74 "InvalidTokenError",
75]