webcomment/src/server/api.rs

93 lines
2.2 KiB
Rust

#![allow(clippy::too_many_arguments)]
use crate::{config::*, db::*, helpers, notify::Notification};
use crossbeam_channel::Sender;
use log::{error, warn};
use serde::{Deserialize, Serialize};
enum ApiError {
InvalidAdminPassword,
}
pub async fn init_routes(app: &mut tide::Server<()>, config: &'static Config, dbs: Dbs) {
// TODO pagination
app.at(&format!("{}api/comments_by_topic", config.root_url))
.post({
let dbs = dbs.clone();
move |req: tide::Request<()>| query_comments_by_topic(req, config, dbs.clone())
});
}
#[derive(Serialize)]
struct CommentWithId {
pub addr: Option<String>,
pub author: String,
pub editable: bool,
pub id: String,
pub last_edit_time: Option<Time>,
pub status: Option<OriginalComment>,
pub post_time: Time,
pub text: String,
}
#[derive(Clone, Debug, Serialize)]
pub struct OriginalComment {
pub author: String,
pub editable: bool,
pub last_edit_time: Option<Time>,
pub post_time: Time,
pub text: String,
}
#[derive(Deserialize)]
struct CommentsByTopicQuery {
mutation_token: Option<String>,
topic: String,
}
#[derive(Serialize)]
struct CommentsByTopicResp {
comments: Vec<CommentWithId>,
}
async fn query_comments_by_topic(
mut req: tide::Request<()>,
config: &Config,
dbs: Dbs,
) -> tide::Result<tide::Response> {
let Ok(CommentsByTopicQuery {
mutation_token,
topic,
}) = req.body_json().await else {
return Err(tide::Error::from_str(400, "Invalid request"));
};
let topic_hash = TopicHash::from_topic(&topic);
Ok(tide::Response::builder(200)
.content_type(tide::http::mime::JSON)
.header("Access-Control-Allow-Origin", &config.cors_allow_origin)
.body(
tide::Body::from_json(&CommentsByTopicResp {
comments: helpers::iter_approved_comments_by_topic(topic_hash, &dbs)
.map(|(comment_id, comment, _comment_status)| CommentWithId {
addr: None,
author: comment.author,
editable: false,
id: comment_id.to_base64(),
last_edit_time: comment.last_edit_time,
post_time: comment.post_time,
status: None,
text: comment.text,
})
.collect::<Vec<CommentWithId>>(),
})
.map_err(|e| {
error!("Serializing CommentsByTopicResp to json: {e:?}");
tide::Error::from_str(500, "Internal server error")
})?,
)
.build())
}