Add Gravatar email hashes

main
Elnu 2 years ago
parent bbebe8b119
commit 82e70178d5

29
Cargo.lock generated

@ -589,6 +589,12 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.126"
@ -648,6 +654,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "md5"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]]
name = "memchr"
version = "2.5.0"
@ -971,9 +983,11 @@ name = "soudan"
version = "0.1.0"
dependencies = [
"actix-web",
"md5",
"rusqlite",
"serde",
"serde_json",
"validator",
]
[[package]]
@ -1112,6 +1126,21 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "validator"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f07b0a1390e01c0fc35ebb26b28ced33c9a3808f7f9fbe94d3cc01e233bfeed5"
dependencies = [
"idna",
"lazy_static",
"regex",
"serde",
"serde_derive",
"serde_json",
"url",
]
[[package]]
name = "vcpkg"
version = "0.2.15"

@ -10,3 +10,5 @@ actix-web = "4"
rusqlite = "0.27.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
validator = "0.15.0"
md5 = "0.7.0"

@ -1,7 +1,48 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
// Master comment type that is stored in database
#[derive(Deserialize, Serialize)]
pub struct Comment {
pub author: Option<String>, // None/null is Anonymous
pub email: Option<String>,
pub text: String
}
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(),
}
}
}
// Comment type for API responses
#[derive(Serialize)]
pub struct CommentSend {
pub author: Option<String>,
pub gravatar: Option<String>,
pub text: String
}
// Comment type received containing new comment data
#[derive(Deserialize)]
pub struct CommentReceive {
pub author: Option<String>,
pub email: Option<String>,
pub text: String,
}
impl CommentReceive {
pub fn to_master(&self) -> Comment {
Comment {
author: self.author.clone(),
email: self.email.clone(),
text: self.text.clone(),
}
}
}

@ -1,5 +1,5 @@
use rusqlite::{params, Connection, Result};
use crate::comment::Comment;
use crate::comment::{Comment, CommentSend};
pub struct Database {
conn: Connection,
@ -11,6 +11,7 @@ impl Database {
conn.execute(
"CREATE TABLE comment (
id INTEGER PRIMARY KEY,
email TEXT,
author TEXT,
text TEXT NOT NULL
)",
@ -21,20 +22,37 @@ impl Database {
pub fn get_comments(&self) -> Result<Vec<Comment>> {
self.conn
.prepare("SELECT author, text FROM comment")?
.prepare("SELECT author, email, text FROM comment")?
.query_map([], |row| {
Ok(Comment {
author: row.get(0)?,
text: row.get(1)?,
email: row.get(1)?,
text: row.get(2)?,
})
})?
.collect()
}
pub fn get_send_comments(&self) -> Result<Vec<CommentSend>> {
self.conn
.prepare("SELECT author, email, text FROM comment")?
.query_map([], |row| {
Ok(CommentSend {
author: row.get(0)?,
gravatar: match row.get::<usize, Option<String>>(1)? {
Some(email) => Some(format!("{:x}", md5::compute(email.to_lowercase()))),
None => None,
},
text: row.get(2)?,
})
})?
.collect()
}
pub fn create_comment(&self, comment: &Comment) -> Result<()> {
self.conn.execute(
"INSERT INTO comment (author, text) VALUES (?1, ?2)",
params![&comment.author, &comment.text],
"INSERT INTO comment (author, email, text) VALUES (?1, ?2, ?3)",
params![&comment.author, &comment.email, &comment.text],
)?;
Ok(())
}

@ -1,5 +1,5 @@
mod comment;
pub use comment::Comment;
pub use comment::*;
mod database;
pub use database::Database;
@ -14,22 +14,22 @@ struct AppState {
#[get("/")]
async fn get_comments(data: web::Data<AppState>) -> impl Responder {
let db = &data.db.lock().unwrap();
HttpResponse::Ok().json(&db.get_comments().unwrap())
HttpResponse::Ok().json(&db.get_send_comments().unwrap())
}
#[post("/")]
async fn post_comments(data: web::Data<AppState>, bytes: web::Bytes) -> impl Responder {
async fn post_comment(data: web::Data<AppState>, bytes: web::Bytes) -> impl Responder {
match String::from_utf8(bytes.to_vec()) {
Ok(text) => {
let db = match data.db.lock() {
Ok(db) => db,
Err(_) => return HttpResponse::InternalServerError(),
};
let comment: Comment = match serde_json::from_str(&text) {
let comment: CommentReceive = match serde_json::from_str(&text) {
Ok(comment) => comment,
Err(_) => return HttpResponse::BadRequest(),
};
db.create_comment(&comment).unwrap();
db.create_comment(&comment.to_master()).unwrap();
HttpResponse::Ok()
},
Err(_) => HttpResponse::BadRequest().into()
@ -43,7 +43,7 @@ async fn main() -> Result<(), std::io::Error> {
HttpServer::new(move || {
App::new()
.service(get_comments)
.service(post_comments)
.service(post_comment)
.app_data(state.clone())
})
.bind(("127.0.0.1", 8080))?

Loading…
Cancel
Save