feat: log IP address for pending comments
This commit is contained in:
parent
17e61b8a67
commit
e710e6678f
6 changed files with 71 additions and 49 deletions
|
|
@ -11,7 +11,7 @@ pub type Time = u64;
|
|||
pub struct Dbs {
|
||||
pub comment: Tree<CommentId, Comment>,
|
||||
pub comment_approved: Tree<(TopicHash, Time, CommentId), ()>,
|
||||
pub comment_pending: Tree<(TopicHash, Time, CommentId), ()>,
|
||||
pub comment_pending: Tree<(TopicHash, Time, CommentId), Option<IpAddr>>,
|
||||
/// client_addr -> (last_mutation, mutation_count)
|
||||
pub client_mutation: Tree<IpAddr, (Time, u32)>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ use crate::{config::Config, db::*, queries::*};
|
|||
use log::error;
|
||||
use std::{net::IpAddr, str::FromStr};
|
||||
|
||||
pub fn new_pending_comment(comment: &Comment, dbs: &Dbs) -> Result<CommentId, sled::Error> {
|
||||
pub fn new_pending_comment(
|
||||
comment: &Comment,
|
||||
addr: Option<IpAddr>,
|
||||
dbs: &Dbs,
|
||||
) -> Result<CommentId, sled::Error> {
|
||||
let comment_id = CommentId::new();
|
||||
dbs.comment.insert(&comment_id, comment)?;
|
||||
dbs.comment_pending.insert(
|
||||
|
|
@ -12,7 +16,7 @@ pub fn new_pending_comment(comment: &Comment, dbs: &Dbs) -> Result<CommentId, sl
|
|||
comment.post_time,
|
||||
comment_id.clone(),
|
||||
),
|
||||
&(),
|
||||
&addr,
|
||||
)?;
|
||||
Ok(comment_id)
|
||||
}
|
||||
|
|
@ -47,16 +51,16 @@ pub fn remove_comment(comment_id: CommentId, dbs: &Dbs) -> Result<Option<Comment
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn iter_comments_by_topic<'a>(
|
||||
pub fn iter_comments_by_topic<'a, V: typed_sled::KV>(
|
||||
topic_hash: TopicHash,
|
||||
tree: &'a Tree<(TopicHash, Time, CommentId), ()>,
|
||||
tree: &'a Tree<(TopicHash, Time, CommentId), V>,
|
||||
dbs: &'a Dbs,
|
||||
) -> impl Iterator<Item = (CommentId, Comment)> + 'a {
|
||||
) -> impl Iterator<Item = (CommentId, Comment, V)> + 'a {
|
||||
tree.range(
|
||||
(topic_hash.clone(), 0, CommentId::zero())..=(topic_hash, Time::MAX, CommentId::max()),
|
||||
)
|
||||
.filter_map(|entry| {
|
||||
let ((_topic_hash, _time, comment_id), ()) = entry
|
||||
let ((_topic_hash, _time, comment_id), val) = entry
|
||||
.map_err(|e| error!("Reading comment_by_topic_and_time: {:?}", e))
|
||||
.ok()?;
|
||||
let comment = dbs
|
||||
|
|
@ -68,7 +72,7 @@ pub fn iter_comments_by_topic<'a>(
|
|||
error!("Comment not found");
|
||||
None
|
||||
})?;
|
||||
Some((comment_id, comment))
|
||||
Some((comment_id, comment, val))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -77,12 +81,13 @@ pub fn iter_approved_comments_by_topic(
|
|||
dbs: &Dbs,
|
||||
) -> impl Iterator<Item = (CommentId, Comment)> + '_ {
|
||||
iter_comments_by_topic(topic_hash, &dbs.comment_approved, dbs)
|
||||
.map(|(comment_id, comment, ())| (comment_id, comment))
|
||||
}
|
||||
|
||||
pub fn iter_pending_comments_by_topic(
|
||||
topic_hash: TopicHash,
|
||||
dbs: &Dbs,
|
||||
) -> impl Iterator<Item = (CommentId, Comment)> + '_ {
|
||||
) -> impl Iterator<Item = (CommentId, Comment, Option<IpAddr>)> + '_ {
|
||||
iter_comments_by_topic(topic_hash, &dbs.comment_pending, dbs)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ async fn serve_comments<'a>(
|
|||
context.insert(
|
||||
"comments_pending",
|
||||
&helpers::iter_pending_comments_by_topic(topic_hash.clone(), &dbs)
|
||||
.map(|(comment_id, comment)| CommentWithId {
|
||||
.map(|(comment_id, comment, addr)| CommentWithId {
|
||||
addr: addr.map(|addr| addr.to_string()),
|
||||
author: comment.author,
|
||||
editable: admin,
|
||||
id: comment_id.to_base64(),
|
||||
|
|
@ -142,6 +143,7 @@ async fn serve_comments<'a>(
|
|||
"comments",
|
||||
&helpers::iter_approved_comments_by_topic(topic_hash, &dbs)
|
||||
.map(|(comment_id, comment)| CommentWithId {
|
||||
addr: None,
|
||||
author: comment.author,
|
||||
editable: admin,
|
||||
id: comment_id.to_base64(),
|
||||
|
|
@ -186,7 +188,7 @@ async fn serve_admin<'a>(
|
|||
&dbs.comment_pending
|
||||
.iter()
|
||||
.filter_map(|entry| {
|
||||
let ((_topic_hash, _time, comment_id), ()) = entry
|
||||
let ((_topic_hash, _time, comment_id), addr) = entry
|
||||
.map_err(|e| error!("Reading comment_pending: {:?}", e))
|
||||
.ok()?;
|
||||
let comment = dbs
|
||||
|
|
@ -199,6 +201,7 @@ async fn serve_admin<'a>(
|
|||
None
|
||||
})?;
|
||||
Some(CommentWithId {
|
||||
addr: addr.map(|addr| addr.to_string()),
|
||||
author: comment.author,
|
||||
editable: true,
|
||||
id: comment_id.to_base64(),
|
||||
|
|
@ -257,27 +260,22 @@ async fn handle_post_comments(
|
|||
|
||||
let client_langs = get_client_langs(&req);
|
||||
|
||||
let client_addr = if !admin && config.antispam_enable {
|
||||
match helpers::get_client_addr(config, &req) {
|
||||
Some(Ok(addr)) => {
|
||||
if config.antispam_whitelist.contains(&addr) {
|
||||
None
|
||||
} else {
|
||||
Some(addr)
|
||||
}
|
||||
}
|
||||
Some(Err(e)) => {
|
||||
warn!("Unable to parse client addr: {}", e);
|
||||
None
|
||||
}
|
||||
None => {
|
||||
warn!("No client addr");
|
||||
None
|
||||
}
|
||||
let client_addr = match helpers::get_client_addr(config, &req) {
|
||||
Some(Ok(addr)) => Some(addr),
|
||||
Some(Err(e)) => {
|
||||
warn!("Unable to parse client addr: {}", e);
|
||||
None
|
||||
}
|
||||
None => {
|
||||
warn!("No client addr");
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let antispam_enabled = !admin
|
||||
&& config.antispam_enable
|
||||
&& client_addr
|
||||
.as_ref()
|
||||
.map_or(false, |addr| !config.antispam_whitelist.contains(addr));
|
||||
|
||||
let mut errors = Vec::new();
|
||||
let mut context = Context::new();
|
||||
|
|
@ -291,28 +289,32 @@ async fn handle_post_comments(
|
|||
helpers::check_comment(config, &query.comment, &mut errors);
|
||||
|
||||
if let Some(client_addr) = &client_addr {
|
||||
if let Some(antispam_timeout) =
|
||||
helpers::antispam_check_client_mutation(client_addr, &dbs, config).unwrap()
|
||||
{
|
||||
errors.push(
|
||||
locales
|
||||
.tr(
|
||||
&client_langs,
|
||||
"error-antispam",
|
||||
Some(&FluentArgs::from_iter([(
|
||||
"antispam_timeout",
|
||||
antispam_timeout,
|
||||
)])),
|
||||
)
|
||||
.unwrap()
|
||||
.into_owned(),
|
||||
);
|
||||
if antispam_enabled {
|
||||
if let Some(antispam_timeout) =
|
||||
helpers::antispam_check_client_mutation(client_addr, &dbs, config).unwrap()
|
||||
{
|
||||
errors.push(
|
||||
locales
|
||||
.tr(
|
||||
&client_langs,
|
||||
"error-antispam",
|
||||
Some(&FluentArgs::from_iter([(
|
||||
"antispam_timeout",
|
||||
antispam_timeout,
|
||||
)])),
|
||||
)
|
||||
.unwrap()
|
||||
.into_owned(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errors.is_empty() {
|
||||
if let Some(client_addr) = &client_addr {
|
||||
helpers::antispam_update_client_mutation(client_addr, &dbs).unwrap();
|
||||
if antispam_enabled {
|
||||
helpers::antispam_update_client_mutation(client_addr, &dbs).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
let topic_hash = TopicHash::from_topic(topic);
|
||||
|
|
@ -338,7 +340,7 @@ async fn handle_post_comments(
|
|||
post_time: time,
|
||||
text: query.comment.text,
|
||||
};
|
||||
helpers::new_pending_comment(&comment, &dbs)
|
||||
helpers::new_pending_comment(&comment, client_addr, &dbs)
|
||||
.map_err(|e| error!("Adding pending comment: {:?}", e))
|
||||
.ok();
|
||||
notify_send
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ impl Templates {
|
|||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct CommentWithId {
|
||||
pub addr: Option<String>,
|
||||
pub author: String,
|
||||
pub editable: bool,
|
||||
pub id: String,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue