From 2c44f788d95513ef8d2c6e4e296ff26efec9a96f Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 29 Mar 2025 15:37:50 +0100 Subject: [PATCH] feat: store user agent with sessions --- gpodder/src/models.rs | 1 + gpodder/src/repository.rs | 7 ++++++- .../2025-03-29-141707_session_user_agent/down.sql | 2 ++ .../2025-03-29-141707_session_user_agent/up.sql | 2 ++ gpodder_sqlite/src/models/session.rs | 1 + gpodder_sqlite/src/repository/auth.rs | 2 ++ gpodder_sqlite/src/schema.rs | 1 + src/cli/serve.rs | 2 -- src/server/gpodder/advanced/auth.rs | 10 ++++++++-- 9 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/down.sql create mode 100644 gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/up.sql diff --git a/gpodder/src/models.rs b/gpodder/src/models.rs index cde5c50..13ca3a1 100644 --- a/gpodder/src/models.rs +++ b/gpodder/src/models.rs @@ -56,6 +56,7 @@ pub struct EpisodeAction { pub struct Session { pub id: i64, pub last_seen: DateTime, + pub user_agent: Option, pub user: User, } diff --git a/gpodder/src/repository.rs b/gpodder/src/repository.rs index dd9d12a..c96787a 100644 --- a/gpodder/src/repository.rs +++ b/gpodder/src/repository.rs @@ -71,11 +71,16 @@ impl GpodderRepository { } } - pub fn create_session(&self, user: &models::User) -> Result { + pub fn create_session( + &self, + user: &models::User, + user_agent: Option, + ) -> Result { let session = models::Session { id: rand::thread_rng().gen(), last_seen: Utc::now(), user: user.clone(), + user_agent, }; self.store.insert_session(&session)?; diff --git a/gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/down.sql b/gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/down.sql new file mode 100644 index 0000000..e143f7b --- /dev/null +++ b/gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/down.sql @@ -0,0 +1,2 @@ +alter table sessions + drop column user_agent; diff --git a/gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/up.sql b/gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/up.sql new file mode 100644 index 0000000..9c60e01 --- /dev/null +++ b/gpodder_sqlite/migrations/2025-03-29-141707_session_user_agent/up.sql @@ -0,0 +1,2 @@ +alter table sessions + add column user_agent text; diff --git a/gpodder_sqlite/src/models/session.rs b/gpodder_sqlite/src/models/session.rs index 53fe6d9..27dc8bc 100644 --- a/gpodder_sqlite/src/models/session.rs +++ b/gpodder_sqlite/src/models/session.rs @@ -10,6 +10,7 @@ pub struct Session { pub id: i64, pub user_id: i64, pub last_seen: i64, + pub user_agent: Option, } impl Session { diff --git a/gpodder_sqlite/src/repository/auth.rs b/gpodder_sqlite/src/repository/auth.rs index 1b60028..36413e8 100644 --- a/gpodder_sqlite/src/repository/auth.rs +++ b/gpodder_sqlite/src/repository/auth.rs @@ -59,6 +59,7 @@ impl gpodder::AuthStore for SqliteRepository { id: session.id, last_seen: DateTime::from_timestamp(session.last_seen, 0).unwrap(), user: user.into(), + user_agent: session.user_agent.clone(), })), Ok(None) => Ok(None), Err(err) => Err(DbError::from(err).into()), @@ -79,6 +80,7 @@ impl gpodder::AuthStore for SqliteRepository { id: session.id, user_id: session.user.id, last_seen: session.last_seen.timestamp(), + user_agent: session.user_agent.clone(), } .insert_into(sessions::table) .execute(&mut self.pool.get().map_err(DbError::from)?) diff --git a/gpodder_sqlite/src/schema.rs b/gpodder_sqlite/src/schema.rs index 475d929..990293d 100644 --- a/gpodder_sqlite/src/schema.rs +++ b/gpodder_sqlite/src/schema.rs @@ -43,6 +43,7 @@ diesel::table! { id -> BigInt, user_id -> BigInt, last_seen -> BigInt, + user_agent -> Nullable, } } diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 024d5b4..d62849f 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -1,7 +1,5 @@ use std::time::Duration; -use tracing_subscriber::util::SubscriberInitExt; - use crate::server; pub fn serve(config: &crate::config::Config) -> u8 { diff --git a/src/server/gpodder/advanced/auth.rs b/src/server/gpodder/advanced/auth.rs index b4adaeb..8dc2288 100644 --- a/src/server/gpodder/advanced/auth.rs +++ b/src/server/gpodder/advanced/auth.rs @@ -5,10 +5,11 @@ use axum::{ }; use axum_extra::{ extract::{cookie::Cookie, CookieJar}, - headers::{authorization::Basic, Authorization}, + headers::{authorization::Basic, Authorization, UserAgent}, TypedHeader, }; use cookie::time::Duration; +use gpodder::AuthErr; use crate::server::{ error::{AppError, AppResult}, @@ -27,6 +28,7 @@ async fn post_login( Path(username): Path, jar: CookieJar, TypedHeader(auth): TypedHeader>, + user_agent: Option>, ) -> AppResult { // These should be the same according to the spec if username != auth.username() { @@ -62,7 +64,11 @@ async fn post_login( let user = ctx .store .validate_credentials(auth.username(), auth.password())?; - ctx.store.create_session(&user) + + let user_agent = user_agent.map(|header| header.to_string()); + let session = ctx.store.create_session(&user, user_agent)?; + + Ok::<_, AuthErr>(session) }) .await .unwrap()?;