Skip to main content

zlicenser_server/
error.rs

1#[derive(Debug, thiserror::Error)]
2pub enum Error {
3    #[error("record not found")]
4    NotFound,
5    #[error("unique constraint violation: {0}")]
6    Conflict(String),
7    #[error("foreign key constraint violation: {0}")]
8    ForeignKeyViolation(String),
9    #[error("database error: {0}")]
10    Database(String),
11    #[error("migration error: {0}")]
12    Migration(String),
13    #[error("corrupt stored data: {0}")]
14    Corrupt(String),
15
16    #[error("the license offer has expired; begin a new enrollment")]
17    OfferExpired,
18    #[error("no enrollment session found with the given identifier")]
19    SessionNotFound,
20    #[error("invalid state machine transition: {0}")]
21    InvalidTransition(String),
22    #[error("all seat slots for this license are occupied")]
23    SeatLimitReached,
24    #[error("payment intent is not in the RequiresCapture state")]
25    PaymentNotHeld,
26    #[error("TSA timestamping failed after all retries: {0}")]
27    TsaFailed(String),
28    #[error("payment capture failed: {0}")]
29    PaymentCaptureFailed(String),
30    #[error("payment cancellation failed: {0}")]
31    PaymentCancelFailed(String),
32    #[error("revocation is not supported for air-gapped licenses")]
33    RevocationNotSupported,
34    #[error("client version {got} is below the required minimum {required}")]
35    ClientVersionRejected { required: String, got: String },
36    #[error("offer nonce in receipt does not match the session")]
37    OfferNonceMismatch,
38    #[error("consent record is invalid: {0}")]
39    ConsentInvalid(String),
40    #[error("a transfer request is already pending for this license")]
41    TransferAlreadyPending,
42    #[error("the customer's signature on the receipt is invalid")]
43    InvalidReceiptSignature,
44    #[error("product is not accepting new enrollments")]
45    ProductInactive,
46    #[error("no active fingerprint binding found for this hardware on this license")]
47    BindingNotFound,
48    #[error("secret wrapping failed: {0}")]
49    SecretWrappingFailed(String),
50    #[error("no payment provider configured for this product")]
51    NoPaymentProvider,
52}
53
54#[cfg(feature = "storage-sqlite")]
55impl From<sqlx::Error> for Error {
56    fn from(e: sqlx::Error) -> Self {
57        match &e {
58            sqlx::Error::RowNotFound => Error::NotFound,
59            sqlx::Error::Database(db) => {
60                let msg = db.message().to_string();
61                if db.is_unique_violation() {
62                    Error::Conflict(msg)
63                } else if db.is_foreign_key_violation() || msg.contains("FOREIGN KEY") {
64                    Error::ForeignKeyViolation(msg)
65                } else {
66                    Error::Database(msg)
67                }
68            }
69            _ => Error::Database(e.to_string()),
70        }
71    }
72}
73
74#[cfg(all(feature = "storage-postgres", not(feature = "storage-sqlite")))]
75impl From<sqlx::Error> for Error {
76    fn from(e: sqlx::Error) -> Self {
77        match &e {
78            sqlx::Error::RowNotFound => Error::NotFound,
79            sqlx::Error::Database(db) => {
80                let msg = db.message().to_string();
81                if db.is_unique_violation() {
82                    Error::Conflict(msg)
83                } else if db.is_foreign_key_violation() {
84                    Error::ForeignKeyViolation(msg)
85                } else {
86                    Error::Database(msg)
87                }
88            }
89            _ => Error::Database(e.to_string()),
90        }
91    }
92}