diff --git a/gpodder/src/lib.rs b/gpodder/src/lib.rs index 0f31248..c106184 100644 --- a/gpodder/src/lib.rs +++ b/gpodder/src/lib.rs @@ -5,5 +5,6 @@ mod store; pub use models::*; pub use repository::GpodderRepository; pub use store::{ - AuthErr, AuthStore, DeviceRepository, EpisodeActionRepository, Store, SubscriptionRepository, + AuthErr, GpodderAuthStore, GpodderDeviceStore, GpodderEpisodeActionStore, GpodderStore, + GpodderSubscriptionStore, }; diff --git a/gpodder/src/repository.rs b/gpodder/src/repository.rs index 5b4f8e2..5c086e6 100644 --- a/gpodder/src/repository.rs +++ b/gpodder/src/repository.rs @@ -6,18 +6,18 @@ use rand::{Rng, rngs::OsRng}; use crate::{ models, - store::{AuthErr, Store}, + store::{AuthErr, GpodderStore}, }; const MAX_SESSION_AGE: i64 = 60 * 60 * 24 * 7; #[derive(Clone)] pub struct GpodderRepository { - store: Arc, + store: Arc, } impl GpodderRepository { - pub fn new(store: impl Store + Send + Sync + 'static) -> Self { + pub fn new(store: impl GpodderStore + Send + Sync + 'static) -> Self { Self { store: Arc::new(store), } diff --git a/gpodder/src/store.rs b/gpodder/src/store.rs index d5fc371..4b60b24 100644 --- a/gpodder/src/store.rs +++ b/gpodder/src/store.rs @@ -24,17 +24,18 @@ impl Display for AuthErr { impl std::error::Error for AuthErr {} -pub trait Store: - AuthStore + DeviceRepository + SubscriptionRepository + EpisodeActionRepository +/// API abstraction providing methods for serving the Gpodder API +pub trait GpodderStore: + GpodderAuthStore + GpodderDeviceStore + GpodderSubscriptionStore + GpodderEpisodeActionStore { } -impl Store for T where - T: AuthStore + DeviceRepository + SubscriptionRepository + EpisodeActionRepository +impl GpodderStore for T where + T: GpodderAuthStore + GpodderDeviceStore + GpodderSubscriptionStore + GpodderEpisodeActionStore { } -pub trait AuthStore { +pub trait GpodderAuthStore { /// Retrieve the session with the given session ID fn get_session(&self, session_id: i64) -> Result, AuthErr>; @@ -63,7 +64,7 @@ pub trait AuthStore { fn remove_old_sessions(&self, min_last_seen: DateTime) -> Result; } -pub trait DeviceRepository { +pub trait GpodderDeviceStore { /// Return all devices associated with the user fn devices_for_user(&self, user: &User) -> Result, AuthErr>; @@ -108,7 +109,7 @@ pub trait DeviceRepository { ) -> Result<(Vec, Vec>), AuthErr>; } -pub trait SubscriptionRepository { +pub trait GpodderSubscriptionStore { /// Return the subscriptions for the given device fn subscriptions_for_device( &self, @@ -149,7 +150,7 @@ pub trait SubscriptionRepository { ) -> Result<(Vec, Vec), AuthErr>; } -pub trait EpisodeActionRepository { +pub trait GpodderEpisodeActionStore { /// Insert the given episode actions into the datastore. fn add_episode_actions( &self, diff --git a/gpodder_sqlite/src/repository/auth.rs b/gpodder_sqlite/src/repository/auth.rs index dbe648d..e32ff85 100644 --- a/gpodder_sqlite/src/repository/auth.rs +++ b/gpodder_sqlite/src/repository/auth.rs @@ -22,7 +22,7 @@ impl From for gpodder::User { } } -impl gpodder::AuthStore for SqliteRepository { +impl gpodder::GpodderAuthStore for SqliteRepository { fn get_user(&self, username: &str) -> Result, AuthErr> { Ok(users::table .select(User::as_select()) diff --git a/gpodder_sqlite/src/repository/device.rs b/gpodder_sqlite/src/repository/device.rs index bd461b9..98ffc12 100644 --- a/gpodder_sqlite/src/repository/device.rs +++ b/gpodder_sqlite/src/repository/device.rs @@ -38,7 +38,7 @@ impl From for DeviceType { } } -impl gpodder::DeviceRepository for SqliteRepository { +impl gpodder::GpodderDeviceStore for SqliteRepository { fn devices_for_user( &self, user: &gpodder::User, diff --git a/gpodder_sqlite/src/repository/episode_action.rs b/gpodder_sqlite/src/repository/episode_action.rs index 8581bd4..4664e05 100644 --- a/gpodder_sqlite/src/repository/episode_action.rs +++ b/gpodder_sqlite/src/repository/episode_action.rs @@ -71,7 +71,7 @@ fn to_gpodder_action( } } -impl gpodder::EpisodeActionRepository for SqliteRepository { +impl gpodder::GpodderEpisodeActionStore for SqliteRepository { fn add_episode_actions( &self, user: &gpodder::User, diff --git a/gpodder_sqlite/src/repository/subscription.rs b/gpodder_sqlite/src/repository/subscription.rs index 03cc666..975d372 100644 --- a/gpodder_sqlite/src/repository/subscription.rs +++ b/gpodder_sqlite/src/repository/subscription.rs @@ -172,7 +172,7 @@ pub fn update_subscriptions_for_single_device( Ok(()) } -impl gpodder::SubscriptionRepository for SqliteRepository { +impl gpodder::GpodderSubscriptionStore for SqliteRepository { fn subscriptions_for_user( &self, user: &gpodder::User, diff --git a/otter/src/server/web/mod.rs b/otter/src/server/web/mod.rs index 2099ab4..b8ec379 100644 --- a/otter/src/server/web/mod.rs +++ b/otter/src/server/web/mod.rs @@ -22,6 +22,11 @@ const SESSION_ID_COOKIE: &str = "sessionid"; pub fn router(ctx: Context) -> Router { Router::new() + .route("/sessions", get(get_sessions)) + .route_layer(axum::middleware::from_fn_with_state( + ctx.clone(), + auth_web_middleware, + )) .route("/", get(get_index)) // .layer(middleware::from_fn_with_state( // ctx.clone(), @@ -161,3 +166,14 @@ pub async fn auth_web_middleware( Err(err) => err.into_response(), } } + +pub async fn get_sessions( + State(ctx): State, + headers: HeaderMap, +) -> TemplateResponse> { + View::Sessions(Vec::new()) + .page(&headers) + .headers(&headers) + .authenticated(true) + .response(&ctx.tera) +} diff --git a/otter/src/web/mod.rs b/otter/src/web/mod.rs index f2a03ee..0035779 100644 --- a/otter/src/web/mod.rs +++ b/otter/src/web/mod.rs @@ -79,6 +79,10 @@ pub fn initialize_tera() -> tera::Result { View::Login.template(), include_str!("templates/views/login.html"), ), + ( + View::Sessions(Vec::new()).template(), + include_str!("templates/views/sessions.html"), + ), ])?; Ok(tera) diff --git a/otter/src/web/templates/base.html b/otter/src/web/templates/base.html index bf13d16..c60df08 100644 --- a/otter/src/web/templates/base.html +++ b/otter/src/web/templates/base.html @@ -21,12 +21,12 @@ a:hover {
    -
  • - {% if authenticated %} - Logout - {% else %} - Login - {% endif %} + {% if authenticated %} +
  • Sessions
  • +
  • Logout
  • + {% else %} +
  • Login
  • + {% endif %}
diff --git a/otter/src/web/templates/views/sessions.html b/otter/src/web/templates/views/sessions.html new file mode 100644 index 0000000..679a565 --- /dev/null +++ b/otter/src/web/templates/views/sessions.html @@ -0,0 +1,18 @@ +

Sessions

+ + + + + + + + + + + + + + + + +
User AgentLast seenAction
FirefoxyesterdayRemove
diff --git a/otter/src/web/view.rs b/otter/src/web/view.rs index 236d8a5..4f15834 100644 --- a/otter/src/web/view.rs +++ b/otter/src/web/view.rs @@ -3,6 +3,7 @@ use super::Template; pub enum View { Index, Login, + Sessions(Vec), } impl Template for View { @@ -10,10 +11,19 @@ impl Template for View { match self { Self::Index => "views/index.html", Self::Login => "views/login.html", + Self::Sessions(_) => "views/sessions.html", } } fn render(&self, tera: &tera::Tera) -> tera::Result { - tera.render(self.template(), &tera::Context::new()) + let mut ctx = tera::Context::new(); + + // match self { + // Self::Sessions(sessions) => { + // ctx.insert("sessions", sessions); + // } + // }; + + tera.render(self.template(), &ctx) } }