User profile and admin privileges

This commit is contained in:
Alphonse Paix
2025-10-01 01:17:59 +02:00
parent 3e81c27ab3
commit 402c560354
22 changed files with 467 additions and 43 deletions

82
src/routes/users.rs Normal file
View File

@@ -0,0 +1,82 @@
use crate::{
authentication::Role,
domain::{PostEntry, UserEntry},
routes::{AppError, not_found_html},
startup::AppState,
templates::{HtmlTemplate, UserTemplate},
};
use anyhow::Context;
use axum::{
extract::{Path, State},
response::{IntoResponse, Response},
};
use sqlx::PgPool;
use uuid::Uuid;
#[derive(serde::Deserialize)]
pub struct ProfilePath {
username: String,
}
#[tracing::instrument(name = "Fetching user data", skip(connection_pool))]
pub async fn user_profile(
State(AppState {
connection_pool, ..
}): State<AppState>,
Path(ProfilePath { username }): Path<ProfilePath>,
) -> Result<Response, AppError> {
match fetch_user_data(&connection_pool, &username)
.await
.context("Failed to fetch user data.")?
{
Some(user) => {
let posts = fetch_user_posts(&connection_pool, &user.user_id)
.await
.context("Could not fetch user posts.")?;
let template = HtmlTemplate(UserTemplate { user, posts });
Ok(template.into_response())
}
None => {
tracing::error!(username = %username, "user not found");
Ok(not_found_html().into_response())
}
}
}
#[tracing::instrument(name = "Fetching user profile", skip_all)]
async fn fetch_user_data(
connection_pool: &PgPool,
username: &str,
) -> Result<Option<UserEntry>, sqlx::Error> {
sqlx::query_as!(
UserEntry,
r#"
SELECT user_id, username, full_name, role as "role: Role", member_since, bio
FROM users
WHERE username = $1
"#,
username
)
.fetch_optional(connection_pool)
.await
}
#[tracing::instrument(name = "Fetching user posts", skip_all)]
async fn fetch_user_posts(
connection_pool: &PgPool,
user_id: &Uuid,
) -> Result<Vec<PostEntry>, sqlx::Error> {
sqlx::query_as!(
PostEntry,
r#"
SELECT u.username as author, p.post_id, p.title, p.content, p.published_at
FROM posts p
INNER JOIN users u ON p.author_id = u.user_id
WHERE p.author_id = $1
ORDER BY p.published_at DESC
"#,
user_id
)
.fetch_all(connection_pool)
.await
}