Refactor comment serialization/deserialization

main
Elnu 2 years ago
parent f153625d1a
commit 6419b6357c

1
Cargo.lock generated

@ -324,6 +324,7 @@ dependencies = [
"libc",
"num-integer",
"num-traits",
"serde",
"time 0.1.44",
"winapi",
]

@ -13,4 +13,4 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
validator = { version = "0.15.0", features = ["derive"] }
md5 = "0.7.0"
chrono = "0.4.19"
chrono = { version = "0.4.19", features = ["serde"] }

@ -1,54 +1,31 @@
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use chrono::serde::ts_seconds_option;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize, Serializer};
use validator::Validate;
// Master comment type that is stored in database
#[derive(Serialize, Deserialize, Validate)]
pub struct Comment {
pub author: Option<String>, // None/null is Anonymous
pub email: Option<String>,
pub text: String,
pub timestamp: Option<NaiveDateTime>,
}
impl Comment {
pub fn send(&self) -> CommentSend {
CommentSend {
author: self.author.clone(),
gravatar: match self.email.clone() {
Some(email) => Some(format!("{:x}", md5::compute(email.to_lowercase()))),
None => None,
},
text: self.text.clone(),
timestamp: self.timestamp.unwrap().timestamp(),
}
}
}
// Comment type for API responses
#[derive(Serialize)]
pub struct CommentSend {
pub author: Option<String>,
pub gravatar: Option<String>,
pub text: String,
pub timestamp: i64,
}
// Comment type received containing new comment data
#[derive(Deserialize, Validate)]
pub struct CommentReceive {
pub author: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub author: Option<String>, // None is Anonymous
#[serde(rename(serialize = "gravatar"))]
#[serde(serialize_with = "serialize_gravatar")]
#[validate(email)]
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[validate(length(min = 1))]
pub text: String,
#[serde(default)]
#[serde(with = "ts_seconds_option")]
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<DateTime<Utc>>,
}
impl CommentReceive {
pub fn to_master(&self) -> Comment {
Comment {
author: self.author.clone(),
email: self.email.clone(),
text: self.text.clone(),
timestamp: None,
}
fn serialize_gravatar<S>(email: &Option<String>, s: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
match email {
Some(email) => s.serialize_some(&format!("{:x}", md5::compute(email.to_lowercase()))),
None => s.serialize_none(),
}
}

@ -1,5 +1,4 @@
use crate::comment::{Comment, CommentSend};
use chrono::NaiveDateTime;
use crate::Comment;
use rusqlite::{params, Connection, Result};
pub struct Database {
@ -25,20 +24,15 @@ impl Database {
Ok(Self { conn })
}
pub fn get_send_comments(&self) -> Result<Vec<CommentSend>> {
pub fn get_comments(&self) -> Result<Vec<Comment>> {
self.conn
.prepare("SELECT author, email, text, timestamp FROM comment ORDER BY timestamp DESC")?
.query_map([], |row| {
let timestamp: NaiveDateTime = row.get(3)?;
let timestamp = timestamp.timestamp();
Ok(CommentSend {
Ok(Comment {
author: row.get(0)?,
gravatar: match row.get::<usize, Option<String>>(1)? {
Some(email) => Some(format!("{:x}", md5::compute(email.to_lowercase()))),
None => None,
},
email: row.get(1)?,
text: row.get(2)?,
timestamp: timestamp,
timestamp: row.get(3)?,
})
})?
.collect()

@ -19,7 +19,7 @@ async fn get_comments(data: web::Data<AppState>) -> impl Responder {
Ok(db) => db,
Err(_) => return HttpResponse::InternalServerError().into(),
};
HttpResponse::Ok().json(&db.get_send_comments().unwrap())
HttpResponse::Ok().json(&db.get_comments().unwrap())
}
#[post("/")]
@ -30,14 +30,14 @@ async fn post_comment(data: web::Data<AppState>, bytes: web::Bytes) -> impl Resp
Ok(db) => db,
Err(_) => return HttpResponse::InternalServerError(),
};
let comment: CommentReceive = match serde_json::from_str(&text) {
let comment: Comment = match serde_json::from_str(&text) {
Ok(comment) => comment,
Err(_) => return HttpResponse::BadRequest(),
};
if comment.validate().is_err() {
return HttpResponse::BadRequest();
}
db.create_comment(&comment.to_master()).unwrap();
db.create_comment(&comment).unwrap();
HttpResponse::Ok()
}
Err(_) => HttpResponse::BadRequest().into(),

Loading…
Cancel
Save