Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
### Added
- `ErrorResponse::with_retry_after_duration` helper for specifying retry advice via `Duration`.
- Conversion from `telegram_webapp_sdk::utils::validate_init_data::ValidationError` into `AppError` (feature `telegram-webapp-sdk`).

### Changed
- `AppError::log` now includes the stable `code` field alongside `kind`.
Expand Down
125 changes: 125 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ config = ["dep:config"] # config::ConfigError -> AppError
multipart = ["axum"]
tokio = ["dep:tokio"]
reqwest = ["dep:reqwest"]
telegram-webapp-sdk = ["dep:telegram-webapp-sdk"]
turnkey = []

openapi = ["dep:utoipa"]
Expand Down Expand Up @@ -54,6 +55,7 @@ config = { version = "0.15", optional = true }
utoipa = { version = "5.3", optional = true }
tokio = { version = "1", optional = true, features = ["time"] }
reqwest = { version = "0.12", optional = true, default-features = false }
telegram-webapp-sdk = { git = "https://github.com/RAprogramm/telegram-webapp-sdk", rev = "0c5a1d557e1cefe2b37a190c9359be05fe48d41a", optional = true }

[dev-dependencies]
serde_json = "1"
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ utoipa = "5"
<details>
<summary><b>Feature flags</b></summary>

- `axum` — IntoResponse
- `actix` — ResponseError/Responder
- `openapi` — utoipa schema
- `serde_json` — JSON details
- `sqlx`, `redis`, `reqwest`, `validator`, `config`, `tokio`, `multipart`
- `axum` — IntoResponse
- `actix` — ResponseError/Responder
- `openapi` — utoipa schema
- `serde_json` — JSON details
- `sqlx`, `redis`, `reqwest`, `validator`, `config`, `tokio`, `multipart`, `telegram-webapp-sdk`
- `turnkey` — domain taxonomy and conversions for Turnkey errors

</details>
Expand All @@ -190,6 +190,7 @@ utoipa = "5"
- `validator::ValidationErrors` → Validation
- `config::ConfigError` → Config
- `tokio::time::error::Elapsed` → Timeout
- `telegram_webapp_sdk::utils::validate_init_data::ValidationError` → TelegramAuth

</details>

Expand Down
4 changes: 4 additions & 0 deletions src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ mod tokio;
#[cfg_attr(docsrs, doc(cfg(feature = "validator")))]
mod validator;

#[cfg(feature = "telegram-webapp-sdk")]
#[cfg_attr(docsrs, doc(cfg(feature = "telegram-webapp-sdk")))]
mod telegram_webapp_sdk;

/// Map `std::io::Error` to an internal application error.
///
/// Rationale: I/O failures are infrastructure-level and should not leak
Expand Down
60 changes: 60 additions & 0 deletions src/convert/telegram_webapp_sdk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//! Conversion from
//! [`telegram_webapp_sdk::utils::validate_init_data::ValidationError`] into
//! [`AppError`].
//!
//! Enabled with the `telegram-webapp-sdk` feature flag.
//!
//! ## Mapping
//!
//! All [`ValidationError`] variants are mapped to `AppErrorKind::TelegramAuth`
//! and the original error text is preserved in the message.
//!
//! ## Rationale
//!
//! Failing to validate Telegram `initData` indicates an authentication problem
//! with the incoming request. Mapping to `TelegramAuth` keeps this distinction
//! explicit and allows callers to handle it separately from generic bad
//! requests.
//!
//! ## Example
//!
//! ```rust,ignore
//! use masterror::{AppError, AppErrorKind};
//! use telegram_webapp_sdk::utils::validate_init_data::ValidationError;
//!
//! fn convert(err: ValidationError) -> AppError {
//! err.into()
//! }
//!
//! let e = convert(ValidationError::SignatureMismatch);
//! assert!(matches!(e.kind, AppErrorKind::TelegramAuth));
//! ```

#[cfg(feature = "telegram-webapp-sdk")]
use telegram_webapp_sdk::utils::validate_init_data::ValidationError;

#[cfg(feature = "telegram-webapp-sdk")]
use crate::AppError;

/// Map [`ValidationError`] into an [`AppError`] with kind `TelegramAuth`.
#[cfg(feature = "telegram-webapp-sdk")]
#[cfg_attr(docsrs, doc(cfg(feature = "telegram-webapp-sdk")))]
impl From<ValidationError> for AppError {
fn from(err: ValidationError) -> Self {
AppError::telegram_auth(err.to_string())
}
}

#[cfg(all(test, feature = "telegram-webapp-sdk"))]
mod tests {
use telegram_webapp_sdk::utils::validate_init_data::ValidationError;

use super::*;
use crate::AppErrorKind;

#[test]
fn validation_error_maps_to_telegram_auth() {
let err: AppError = ValidationError::SignatureMismatch.into();
assert!(matches!(err.kind, AppErrorKind::TelegramAuth));
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
//! - `config` — `From<config::ConfigError>` mapping
//! - `tokio` — `From<tokio::time::error::Elapsed>` mapping
//! - `reqwest` — `From<reqwest::Error>` mapping
//! - `telegram-webapp-sdk` —
//! `From<telegram_webapp_sdk::utils::validate_init_data::ValidationError>`
//! mapping
//! - `serde_json` — support for structured JSON details in [`ErrorResponse`];
//! also pulled transitively by `axum`
//! - `multipart` — compatibility flag for Axum multipart
Expand Down
Loading