diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cf7e52..d61481f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * Web UI - * Started development based on HTMX and PicoCSS - * Very simple homepage * Login/logout button - * Page for managing logged-in sessions ## [0.1.0](https://git.rustybever.be/Chewing_Bever/otter/src/tag/0.1.0) diff --git a/otter/src/server/web/mod.rs b/otter/src/server/web/mod.rs index 44e35a5..dac3229 100644 --- a/otter/src/server/web/mod.rs +++ b/otter/src/server/web/mod.rs @@ -42,7 +42,7 @@ impl Default for Pagination { fn default() -> Self { Self { page: 0, - per_page: 25, + per_page: 1, } } } @@ -198,7 +198,7 @@ pub async fn auth_web_middleware( match extract_session(ctx, &jar).await { Ok(Some(session)) => { - req.extensions_mut().insert(session); + req.extensions_mut().insert(session.user); next.run(req).await } diff --git a/otter/src/server/web/sessions.rs b/otter/src/server/web/sessions.rs index d05e3a7..611372a 100644 --- a/otter/src/server/web/sessions.rs +++ b/otter/src/server/web/sessions.rs @@ -1,22 +1,18 @@ use axum::{ Extension, Router, - extract::{Path, Query, State}, + extract::{Query, State}, http::HeaderMap, - routing::{delete, get}, + routing::get, }; use crate::{ - server::{ - Context, - error::{AppError, AppResult}, - }, + server::{Context, error::AppResult}, web::{Page, TemplateExt, TemplateResponse, ToQuery, View}, }; pub fn router(ctx: Context) -> Router { Router::new() .route("/sessions", get(get_sessions)) - .route("/sessions/{id}", delete(delete_session)) .route_layer(axum::middleware::from_fn_with_state( ctx.clone(), super::auth_web_middleware, @@ -26,45 +22,21 @@ pub fn router(ctx: Context) -> Router { pub async fn get_sessions( State(ctx): State, headers: HeaderMap, - Extension(session): Extension, + Extension(user): Extension, Query(page): Query, ) -> AppResult>> { let next_page = page.next_page(); - let sessions = tokio::task::spawn_blocking(move || { - ctx.store.paginated_sessions(&session.user, page.into()) - }) - .await - .unwrap()?; + let sessions = + tokio::task::spawn_blocking(move || ctx.store.paginated_sessions(&user, page.into())) + .await + .unwrap()?; let next_page_query = (sessions.len() == next_page.per_page as usize).then_some(next_page.to_query()); - Ok(View::Sessions(sessions, session.id, next_page_query) + Ok(View::Sessions(sessions, next_page_query) .page(&headers) .headers(&headers) .authenticated(true) .response(&ctx.tera)) } - -pub async fn delete_session( - State(ctx): State, - Extension(session): Extension, - Path(id): Path, -) -> AppResult<()> { - tokio::task::spawn_blocking(move || { - let other_session = ctx.store.get_session(id)?; - - // Check to ensure a user can't remove a session that's not theirs - if session.user.id != other_session.user.id { - return Err(AppError::Unauthorized); - } - - ctx.store.remove_session(session.id)?; - - Ok(()) - }) - .await - .unwrap()?; - - Ok(()) -} diff --git a/otter/src/web/mod.rs b/otter/src/web/mod.rs index 93a7119..f99ff53 100644 --- a/otter/src/web/mod.rs +++ b/otter/src/web/mod.rs @@ -82,7 +82,7 @@ pub fn initialize_tera() -> tera::Result { include_str!("templates/views/login.html"), ), ( - View::Sessions(Vec::new(), 0, None).template(), + View::Sessions(Vec::new(), None).template(), include_str!("templates/views/sessions.html"), ), ])?; diff --git a/otter/src/web/templates/views/sessions.html b/otter/src/web/templates/views/sessions.html index bdd1a2e..1a59e34 100644 --- a/otter/src/web/templates/views/sessions.html +++ b/otter/src/web/templates/views/sessions.html @@ -13,15 +13,7 @@ {{ session.user_agent }} {{ session.last_seen }} - - {%- if session.id != current_session_id -%} - Remove - {%- else -%} - Current session - {%- endif -%} - + Remove {% endfor %} {% if next_page_query %} diff --git a/otter/src/web/view.rs b/otter/src/web/view.rs index b7e45ec..5636a16 100644 --- a/otter/src/web/view.rs +++ b/otter/src/web/view.rs @@ -6,12 +6,11 @@ use super::{Query, Template}; pub enum View { Index, Login, - Sessions(Vec, i64, Option), + Sessions(Vec, Option), } #[derive(Serialize)] struct Session { - id: i64, user_agent: Option, last_seen: DateTime, } @@ -30,12 +29,11 @@ impl Template for View { let template = self.template(); match self { - Self::Sessions(sessions, current_session_id, query) => { + Self::Sessions(sessions, query) => { ctx.insert( "sessions", &sessions.into_iter().map(Session::from).collect::>(), ); - ctx.insert("current_session_id", ¤t_session_id); if let Some(query) = query { ctx.insert("next_page_query", &query.encode()); @@ -51,7 +49,6 @@ impl Template for View { impl From for Session { fn from(value: gpodder::Session) -> Self { Self { - id: value.id, user_agent: value.user_agent, last_seen: value.last_seen, }