diff --git a/crates/presentation/src/handlers/html.rs b/crates/presentation/src/handlers/html.rs
index f71192f..2848f28 100644
--- a/crates/presentation/src/handlers/html.rs
+++ b/crates/presentation/src/handlers/html.rs
@@ -497,6 +497,23 @@ pub async fn get_users_list(
}
}
+pub async fn get_user_by_username(
+ State(state): State,
+ Path(username): Path,
+) -> impl IntoResponse {
+ let uname = match domain::value_objects::Username::new(username) {
+ Ok(u) => u,
+ Err(_) => return StatusCode::NOT_FOUND.into_response(),
+ };
+ match state.app_ctx.user_repository.find_by_username(&uname).await {
+ Ok(Some(user)) => {
+ axum::response::Redirect::permanent(&format!("/users/{}", user.id().value()))
+ .into_response()
+ }
+ _ => StatusCode::NOT_FOUND.into_response(),
+ }
+}
+
pub async fn get_user_profile(
OptionalCookieUser(user_id): OptionalCookieUser,
State(state): State,
diff --git a/crates/presentation/src/routes.rs b/crates/presentation/src/routes.rs
index f983ab4..e08197f 100644
--- a/crates/presentation/src/routes.rs
+++ b/crates/presentation/src/routes.rs
@@ -60,6 +60,7 @@ fn html_routes(rate_limit: u64) -> Router {
let base = Router::new()
.route("/", routing::get(handlers::html::get_activity_feed))
.route("/users", routing::get(handlers::html::get_users_list))
+ .route("/u/{username}", routing::get(handlers::html::get_user_by_username))
.route(
"/users/{id}",
routing::get(handlers::html::get_user_profile),