User profile and admin privileges
This commit is contained in:
82
src/routes/users.rs
Normal file
82
src/routes/users.rs
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user