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

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

@ -1,7 +1,48 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)] // Master comment type that is stored in database
#[derive(Deserialize, Serialize)]
pub struct Comment { pub struct Comment {
pub author: Option<String>, // None/null is Anonymous pub author: Option<String>, // None/null is Anonymous
pub email: Option<String>,
pub text: 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 rusqlite::{params, Connection, Result};
use crate::comment::Comment; use crate::comment::{Comment, CommentSend};
pub struct Database { pub struct Database {
conn: Connection, conn: Connection,
@ -11,6 +11,7 @@ impl Database {
conn.execute( conn.execute(
"CREATE TABLE comment ( "CREATE TABLE comment (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
email TEXT,
author TEXT, author TEXT,
text TEXT NOT NULL text TEXT NOT NULL
)", )",
@ -21,20 +22,37 @@ impl Database {
pub fn get_comments(&self) -> Result<Vec<Comment>> { pub fn get_comments(&self) -> Result<Vec<Comment>> {
self.conn self.conn
.prepare("SELECT author, text FROM comment")? .prepare("SELECT author, email, text FROM comment")?
.query_map([], |row| { .query_map([], |row| {
Ok(Comment { Ok(Comment {
author: row.get(0)?, author: row.get(0)?,
text: row.get(1)?, email: row.get(1)?,
text: row.get(2)?,
}) })
})? })?
.collect() .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<()> { pub fn create_comment(&self, comment: &Comment) -> Result<()> {
self.conn.execute( self.conn.execute(
"INSERT INTO comment (author, text) VALUES (?1, ?2)", "INSERT INTO comment (author, email, text) VALUES (?1, ?2, ?3)",
params![&comment.author, &comment.text], params![&comment.author, &comment.email, &comment.text],
)?; )?;
Ok(()) Ok(())
} }

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

Loading…
Cancel
Save