From a68b68090421af85a2d0d5188f488ee4e66ba4c2 Mon Sep 17 00:00:00 2001 From: Colin Reeder Date: Sat, 18 Jul 2020 20:05:26 -0600 Subject: User profile descriptions (#67) --- src/resp_types.rs | 13 ++++++ src/routes/mod.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 131 insertions(+), 6 deletions(-) diff --git a/src/resp_types.rs b/src/resp_types.rs index 38bbec7..c2d91f3 100644 --- a/src/resp_types.rs +++ b/src/resp_types.rs @@ -94,6 +94,19 @@ pub struct RespMinimalCommunityInfo<'a> { pub host: Cow<'a, str>, } +#[derive(Deserialize, Debug)] +pub struct RespUserInfo<'a> { + #[serde(flatten)] + pub base: RespMinimalAuthorInfo<'a>, + pub description: Cow<'a, str>, +} + +impl<'a> AsRef> for RespUserInfo<'a> { + fn as_ref(&self) -> &RespMinimalAuthorInfo<'a> { + &self.base + } +} + #[derive(Deserialize, Debug)] pub struct RespLoginInfoUser { pub id: i64, diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 736a1ff..4d2daf6 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -5,9 +5,7 @@ use std::sync::Arc; use crate::components::{ Comment, Content, HTPage, MaybeFillInput, MaybeFillTextArea, PostItem, ThingItem, UserLink, }; -use crate::resp_types::{ - RespMinimalAuthorInfo, RespPostCommentInfo, RespPostListPost, RespThingInfo, -}; +use crate::resp_types::{RespPostCommentInfo, RespPostListPost, RespThingInfo, RespUserInfo}; use crate::util::author_is_me; use crate::PageBaseData; @@ -899,7 +897,7 @@ async fn page_user( ) .await?; let user = hyper::body::to_bytes(user.into_body()).await?; - let user: RespMinimalAuthorInfo<'_> = serde_json::from_slice(&user)?; + let user: RespUserInfo<'_> = serde_json::from_slice(&user)?; let things = res_to_error( ctx.http_client @@ -916,11 +914,23 @@ async fn page_user( let things = hyper::body::to_bytes(things.into_body()).await?; let things: Vec = serde_json::from_slice(&things)?; - let title = user.username.as_ref(); + let title = user.as_ref().username.as_ref(); Ok(html_response(render::html! {

{title}

+ { + if let Some(login) = &base_data.login { + if login.user.id == user_id { + Some(render::rsx! { {"Edit"} }) + } else { + None + } + } else { + None + } + } +

{user.description.as_ref()}

{ if things.is_empty() { Some(render::rsx! {

{"Looks like there's nothing here."}

}) @@ -940,6 +950,97 @@ async fn page_user( })) } +async fn page_user_edit( + params: (i64,), + ctx: Arc, + req: hyper::Request, +) -> Result, crate::Error> { + let (user_id,) = params; + + let cookies = get_cookie_map_for_req(&req)?; + + let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, &cookies).await?; + + let is_me = match &base_data.login { + None => false, + Some(login) => login.user.id == user_id, + }; + + if !is_me { + let mut res = html_response(render::html! { + +

{"Edit Profile"}

+
{"You can only edit your own profile."}
+
+ }); + + *res.status_mut() = hyper::StatusCode::FORBIDDEN; + + return Ok(res); + } + + let user = res_to_error( + ctx.http_client + .request( + hyper::Request::get(format!( + "{}/api/unstable/users/{}", + ctx.backend_host, user_id + )) + .body(Default::default())?, + ) + .await?, + ) + .await?; + let user = hyper::body::to_bytes(user.into_body()).await?; + let user: RespUserInfo<'_> = serde_json::from_slice(&user)?; + + Ok(html_response(render::html! { + +

{"Edit Profile"}

+
+
+ +
+ +
+
+ })) +} + +async fn handler_user_edit_submit( + params: (i64,), + ctx: Arc, + req: hyper::Request, +) -> Result, crate::Error> { + let (user_id,) = params; + + let (req_parts, body) = req.into_parts(); + + let cookies = get_cookie_map_for_headers(&req_parts.headers)?; + + let body = hyper::body::to_bytes(body).await?; + let body: serde_json::Value = serde_urlencoded::from_bytes(&body)?; + + res_to_error( + ctx.http_client + .request(with_auth( + hyper::Request::patch(format!("{}/api/unstable/users/me", ctx.backend_host)) + .body(serde_json::to_vec(&body)?.into())?, + &cookies, + )?) + .await?, + ) + .await?; + + Ok(hyper::Response::builder() + .status(hyper::StatusCode::SEE_OTHER) + .header(hyper::header::LOCATION, format!("/users/{}", user_id)) + .body("Successfully created.".into())?) +} + async fn page_home( _: (), ctx: Arc, @@ -1127,7 +1228,18 @@ pub fn route_root() -> crate::RouteNode<()> { .with_child( "users", crate::RouteNode::new().with_child_parse::( - crate::RouteNode::new().with_handler_async("GET", page_user), + crate::RouteNode::new() + .with_handler_async("GET", page_user) + .with_child( + "edit", + crate::RouteNode::new() + .with_handler_async("GET", page_user_edit) + .with_child( + "submit", + crate::RouteNode::new() + .with_handler_async("POST", handler_user_edit_submit), + ), + ), ), ) } -- cgit v1.2.3