summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Reeder <colin@vpzom.click>2020-06-23 22:03:02 -0600
committerColin Reeder <colin@vpzom.click>2020-06-23 22:03:02 -0600
commit37b2482458a5995c370fd7e59c93cd8b21fe9c1c (patch)
tree45e104b60ed45e831b25e3d6b05c543136ecae30
parent80332be481ca1598960789c02789a83bc61546c2 (diff)
post & reply deletion
-rw-r--r--res/main.css4
-rw-r--r--src/routes/mod.rs207
2 files changed, 207 insertions, 4 deletions
diff --git a/res/main.css b/res/main.css
index 543f186..b53079a 100644
--- a/res/main.css
+++ b/res/main.css
@@ -18,3 +18,7 @@ body {
.mainHeader > .right {
float: right;
}
+
+.actionList > * {
+ margin-right: .5em;
+}
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index 16b9326..f808bf1 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -53,6 +53,17 @@ fn with_auth(
Ok(new_req)
}
+fn author_is_me(author: &Option<RespMinimalAuthorInfo<'_>>, login: &Option<RespLoginInfo>) -> bool {
+ if let Some(author) = author {
+ if let Some(login) = login {
+ if author.id == login.user.id {
+ return true;
+ }
+ }
+ }
+ false
+}
+
#[derive(Deserialize, Debug)]
struct RespLoginInfoUser {
id: i64,
@@ -281,15 +292,27 @@ impl<'community> render::Render for CommunityLink<'community> {
}
#[render::component]
-fn Comment<'comment>(comment: &'comment RespPostCommentInfo<'comment>) {
+fn Comment<'comment, 'base_data>(
+ comment: &'comment RespPostCommentInfo<'comment>,
+ base_data: &'base_data PageBaseData,
+) {
render::rsx! {
<li>
<small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small>
<br />
{comment.content_text.as_ref()}
<br />
- <div>
+ <div class={"actionList"}>
<a href={format!("/comments/{}", comment.id)}>{"reply"}</a>
+ {
+ if author_is_me(&comment.author, &base_data.login) {
+ Some(render::rsx! {
+ <a href={format!("/comments/{}/delete", comment.id)}>{"delete"}</a>
+ })
+ } else {
+ None
+ }
+ }
</div>
{
@@ -300,7 +323,7 @@ fn Comment<'comment>(comment: &'comment RespPostCommentInfo<'comment>) {
{
replies.iter().map(|reply| {
render::rsx! {
- <Comment comment={reply} />
+ <Comment comment={reply} base_data />
}
})
.collect::<Vec<_>>()
@@ -368,6 +391,81 @@ async fn page_comment(
}))
}
+async fn page_comment_delete(
+ params: (i64,),
+ ctx: Arc<crate::RouteContext>,
+ req: hyper::Request<hyper::Body>,
+) -> Result<hyper::Response<hyper::Body>, crate::Error> {
+ let (comment_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 api_res = res_to_error(
+ ctx.http_client
+ .request(with_auth(
+ hyper::Request::get(format!(
+ "{}/api/unstable/comments/{}",
+ ctx.backend_host, comment_id
+ ))
+ .body(Default::default())?,
+ &cookies,
+ )?)
+ .await?,
+ )
+ .await?;
+ let api_res = hyper::body::to_bytes(api_res.into_body()).await?;
+ let comment: RespPostCommentInfo<'_> = serde_json::from_slice(&api_res)?;
+
+ Ok(html_response(render::html! {
+ <HTPage base_data={&base_data}>
+ <p>
+ <small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small>
+ <br />
+ {comment.content_text.as_ref()}
+ </p>
+ <div id={"delete"}>
+ <h2>{"Delete this comment?"}</h2>
+ <form method={"POST"} action={format!("/comments/{}/delete/confirm", comment.id)}>
+ <a href={format!("/comments/{}/", comment.id)}>{"No, cancel"}</a>
+ {" "}
+ <button r#type={"submit"}>{"Yes, delete"}</button>
+ </form>
+ </div>
+ </HTPage>
+ }))
+}
+
+async fn handler_comment_delete_confirm(
+ params: (i64,),
+ ctx: Arc<crate::RouteContext>,
+ req: hyper::Request<hyper::Body>,
+) -> Result<hyper::Response<hyper::Body>, crate::Error> {
+ let (comment_id,) = params;
+
+ let cookies = get_cookie_map_for_req(&req)?;
+
+ res_to_error(
+ ctx.http_client
+ .request(with_auth(
+ hyper::Request::delete(format!(
+ "{}/api/unstable/comments/{}",
+ ctx.backend_host, comment_id,
+ ))
+ .body("".into())?,
+ &cookies,
+ )?)
+ .await?,
+ )
+ .await?;
+
+ Ok(hyper::Response::builder()
+ .status(hyper::StatusCode::SEE_OTHER)
+ .header(hyper::header::LOCATION, "/")
+ .body("Successfully deleted.".into())?)
+}
+
async fn handler_comment_submit_reply(
params: (i64,),
ctx: Arc<crate::RouteContext>,
@@ -626,6 +724,17 @@ async fn page_post(
}
}
}
+ {
+ if author_is_me(&post.as_ref().author, &base_data.login) {
+ Some(render::rsx! {
+ <p>
+ <a href={format!("/posts/{}/delete", post_id)}>{"delete"}</a>
+ </p>
+ })
+ } else {
+ None
+ }
+ }
<div>
<h2>{"Comments"}</h2>
{
@@ -646,7 +755,7 @@ async fn page_post(
{
post.comments.iter().map(|comment| {
render::rsx! {
- <Comment comment={comment} />
+ <Comment comment={comment} base_data={&base_data} />
}
}).collect::<Vec<_>>()
}
@@ -656,6 +765,76 @@ async fn page_post(
}))
}
+async fn page_post_delete(
+ params: (i64,),
+ ctx: Arc<crate::RouteContext>,
+ req: hyper::Request<hyper::Body>,
+) -> Result<hyper::Response<hyper::Body>, crate::Error> {
+ let (post_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 api_res = res_to_error(
+ ctx.http_client
+ .request(with_auth(
+ hyper::Request::get(format!(
+ "{}/api/unstable/posts/{}",
+ ctx.backend_host, post_id
+ ))
+ .body(Default::default())?,
+ &cookies,
+ )?)
+ .await?,
+ )
+ .await?;
+ let api_res = hyper::body::to_bytes(api_res.into_body()).await?;
+
+ let post: RespPostInfo = serde_json::from_slice(&api_res)?;
+
+ Ok(html_response(render::html! {
+ <HTPage base_data={&base_data}>
+ <h1>{post.as_ref().title.as_ref()}</h1>
+ <h2>{"Delete this post?"}</h2>
+ <form method={"POST"} action={format!("/posts/{}/delete/confirm", post.as_ref().id)}>
+ <a href={format!("/posts/{}/", post.as_ref().id)}>{"No, cancel"}</a>
+ {" "}
+ <button r#type={"submit"}>{"Yes, delete"}</button>
+ </form>
+ </HTPage>
+ }))
+}
+
+async fn handler_post_delete_confirm(
+ params: (i64,),
+ ctx: Arc<crate::RouteContext>,
+ req: hyper::Request<hyper::Body>,
+) -> Result<hyper::Response<hyper::Body>, crate::Error> {
+ let (post_id,) = params;
+
+ let cookies = get_cookie_map_for_req(&req)?;
+
+ res_to_error(
+ ctx.http_client
+ .request(with_auth(
+ hyper::Request::delete(format!(
+ "{}/api/unstable/posts/{}",
+ ctx.backend_host, post_id,
+ ))
+ .body("".into())?,
+ &cookies,
+ )?)
+ .await?,
+ )
+ .await?;
+
+ Ok(hyper::Response::builder()
+ .status(hyper::StatusCode::SEE_OTHER)
+ .header(hyper::header::LOCATION, "/")
+ .body("Successfully deleted.".into())?)
+}
+
async fn handler_post_submit_reply(
params: (i64,),
ctx: Arc<crate::RouteContext>,
@@ -804,6 +983,16 @@ pub fn route_root() -> crate::RouteNode<()> {
crate::RouteNode::new()
.with_handler_async("GET", page_comment)
.with_child(
+ "delete",
+ crate::RouteNode::new()
+ .with_handler_async("GET", page_comment_delete)
+ .with_child(
+ "confirm",
+ crate::RouteNode::new()
+ .with_handler_async("POST", handler_comment_delete_confirm),
+ ),
+ )
+ .with_child(
"submit_reply",
crate::RouteNode::new()
.with_handler_async("POST", handler_comment_submit_reply),
@@ -836,6 +1025,16 @@ pub fn route_root() -> crate::RouteNode<()> {
crate::RouteNode::new()
.with_handler_async("GET", page_post)
.with_child(
+ "delete",
+ crate::RouteNode::new()
+ .with_handler_async("GET", page_post_delete)
+ .with_child(
+ "confirm",
+ crate::RouteNode::new()
+ .with_handler_async("POST", handler_post_delete_confirm),
+ ),
+ )
+ .with_child(
"submit_reply",
crate::RouteNode::new()
.with_handler_async("POST", handler_post_submit_reply),