From 86f50e0356e4b661be43c2aeba97a67d83910095 Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Wed, 20 Dec 2023 09:03:04 +0000 Subject: feat: add semver checking to client requests (#1456) * feat: add semver checking to client requests This enforces that the client and the server run the same major version in order to sync successfully. We're using the `Atuin-Version` http header to transfer this information If the user is not on the same MAJOR, then they will see an error like this > Atuin version mismatch! In order to successfully sync, the client and the server must run the same *major* version > Client: 17.1.0 > Server: 18.1.0 > Error: could not sync records due to version mismatch This change means two things 1. We will now only increment major versions if there is a breaking change for sync 2. We can now add breaking changes to sync, for any version >17.1.0. Clients will fail in a meaningful way. * lint, fmt, etc * only check for client newer than server * Add version header to client too --- atuin-server/src/router.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'atuin-server') diff --git a/atuin-server/src/router.rs b/atuin-server/src/router.rs index 90e726d3..581886de 100644 --- a/atuin-server/src/router.rs +++ b/atuin-server/src/router.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use atuin_common::api::ErrorResponse; +use atuin_common::api::{ErrorResponse, ATUIN_CARGO_VERSION, ATUIN_HEADER_VERSION}; use axum::{ extract::FromRequestParts, http::Request, @@ -91,6 +91,16 @@ async fn clacks_overhead(request: Request, next: Next) -> Response { response } +/// Ensure that we only try and sync with clients on the same major version +async fn semver(request: Request, next: Next) -> Response { + let mut response = next.run(request).await; + response + .headers_mut() + .insert(ATUIN_HEADER_VERSION, ATUIN_CARGO_VERSION.parse().unwrap()); + + response +} + #[derive(Clone)] pub struct AppState { pub database: DB, @@ -126,6 +136,7 @@ pub fn router(database: DB, settings: Settings) -> R ServiceBuilder::new() .layer(axum::middleware::from_fn(clacks_overhead)) .layer(TraceLayer::new_for_http()) - .layer(axum::middleware::from_fn(metrics::track_metrics)), + .layer(axum::middleware::from_fn(metrics::track_metrics)) + .layer(axum::middleware::from_fn(semver)), ) } -- cgit v1.3.1