diff --git a/CHANGELOG.md b/CHANGELOG.md index d61481f..1cf7e52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,10 @@ 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 dac3229..44e35a5 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: 1, + per_page: 25, } } } @@ -198,7 +198,7 @@ pub async fn auth_web_middleware( match extract_session(ctx, &jar).await { Ok(Some(session)) => { - req.extensions_mut().insert(session.user); + req.extensions_mut().insert(session); next.run(req).await } diff --git a/otter/src/server/web/sessions.rs b/otter/src/server/web/sessions.rs index 013e0e7..d05e3a7 100644 --- a/otter/src/server/web/sessions.rs +++ b/otter/src/server/web/sessions.rs @@ -26,19 +26,20 @@ pub fn router(ctx: Context) -> Router { pub async fn get_sessions( State(ctx): State, headers: HeaderMap, - Extension(user): Extension, + Extension(session): Extension, Query(page): Query, ) -> AppResult>> { let next_page = page.next_page(); - let sessions = - tokio::task::spawn_blocking(move || ctx.store.paginated_sessions(&user, page.into())) - .await - .unwrap()?; + let sessions = tokio::task::spawn_blocking(move || { + ctx.store.paginated_sessions(&session.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, next_page_query) + Ok(View::Sessions(sessions, session.id, next_page_query) .page(&headers) .headers(&headers) .authenticated(true) @@ -47,14 +48,14 @@ pub async fn get_sessions( pub async fn delete_session( State(ctx): State, - Extension(user): Extension, + Extension(session): Extension, Path(id): Path, ) -> AppResult<()> { tokio::task::spawn_blocking(move || { - let session = ctx.store.get_session(id)?; + 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 != user.id { + if session.user.id != other_session.user.id { return Err(AppError::Unauthorized); } diff --git a/otter/src/web/mod.rs b/otter/src/web/mod.rs index f99ff53..93a7119 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(), None).template(), + View::Sessions(Vec::new(), 0, 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 dbf7660..bdd1a2e 100644 --- a/otter/src/web/templates/views/sessions.html +++ b/otter/src/web/templates/views/sessions.html @@ -14,9 +14,13 @@ {{ session.user_agent }} {{ session.last_seen }} + {%- if session.id != current_session_id -%} Remove + {%- else -%} + Current session + {%- endif -%} {% endfor %} diff --git a/otter/src/web/view.rs b/otter/src/web/view.rs index ca58f62..b7e45ec 100644 --- a/otter/src/web/view.rs +++ b/otter/src/web/view.rs @@ -6,7 +6,7 @@ use super::{Query, Template}; pub enum View { Index, Login, - Sessions(Vec, Option), + Sessions(Vec, i64, Option), } #[derive(Serialize)] @@ -30,11 +30,12 @@ impl Template for View { let template = self.template(); match self { - Self::Sessions(sessions, query) => { + Self::Sessions(sessions, current_session_id, 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());