feat(otter): add link to users page in navbar for admins

main
Jef Roosens 2025-08-29 15:03:05 +02:00
parent 332c05491a
commit 09d782b6a5
Signed by: Jef Roosens
GPG Key ID: 02D4C0997E74717B
6 changed files with 31 additions and 5 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Ability for an account to be an admin
* CLI command to toggle admin status of users
* Admin user management page
## [0.3.0](https://git.rustybever.be/Chewing_Bever/otter/src/tag/0.3.0)

View File

@ -73,10 +73,12 @@ async fn get_index(
headers: HeaderMap,
jar: CookieJar,
) -> AppResult<TemplateResponse<Page<View>>> {
let authenticated = auth::extract_session(ctx.clone(), &jar).await?.is_some();
let user = auth::extract_session(ctx.clone(), &jar)
.await?
.map(|session| session.user);
Ok(View::Index
.page(&headers)
.authenticated(authenticated)
.user(user.as_ref())
.response(&ctx.tera))
}

View File

@ -30,6 +30,8 @@ pub async fn get_sessions(
Query(page): Query<super::Pagination>,
) -> AppResult<TemplateResponse<Page<View>>> {
let next_page = page.next_page();
let admin = session.user.admin;
let sessions = tokio::task::spawn_blocking(move || {
ctx.store
.user(&session.user)
@ -44,7 +46,7 @@ pub async fn get_sessions(
Ok(View::Sessions(sessions, session.id, next_page_query)
.page(&headers)
.headers(&headers)
.authenticated(true)
.authenticated(true, admin)
.response(&ctx.tera))
}

View File

@ -68,7 +68,7 @@ async fn get_users(
Ok(View::Users(users, user_id, next_page_query)
.page(&headers)
.headers(&headers)
.authenticated(true)
.authenticated(true, true)
.response(&ctx.tera))
}

View File

@ -11,6 +11,7 @@ pub struct Page<T> {
template: T,
wrap_with_base: bool,
authenticated: bool,
admin: bool,
}
impl<T: Template> Template for Page<T> {
@ -25,6 +26,7 @@ impl<T: Template> Template for Page<T> {
let mut ctx = tera::Context::new();
ctx.insert("inner", &inner);
ctx.insert("authenticated", &self.authenticated);
ctx.insert("admin", &self.admin);
tera.render(super::BASE_TEMPLATE, &ctx)
} else {
@ -39,6 +41,7 @@ impl<T> Page<T> {
template,
wrap_with_base: false,
authenticated: false,
admin: false,
}
}
@ -54,8 +57,23 @@ impl<T> Page<T> {
self
}
pub fn authenticated(mut self, authenticated: bool) -> Self {
/// Set the view's authentication level
pub fn authenticated(mut self, authenticated: bool, admin: bool) -> Self {
self.authenticated = authenticated;
self.admin = admin;
self
}
/// Utility function to derive authentication level from a given user
pub fn user(mut self, user: Option<&gpodder::User>) -> Self {
if let Some(user) = user {
self.authenticated = true;
self.admin = user.admin;
} else {
self.authenticated = false;
self.admin = false;
}
self
}

View File

@ -23,6 +23,9 @@ a:hover {
<ul>
{% if authenticated %}
<li><a hx-get="/sessions" hx-target="#inner" hx-push-url="true">Sessions</a></li>
{% if admin %}
<li><a hx-get="/users" hx-target="#inner" hx-push-url="true">Users</a></li>
{% endif %}
<li><a hx-post="/logout" hx-target="#inner">Logout</a></li>
{% else %}
<li><a hx-get="/login" hx-target="#inner" hx-push-url="true">Login</a></li>