+ Adding proper file upload support

! Requirements for variable message fetching not yet met
! /message/get?id=<id> needs a way of passing back file contents
! The file upload is sketchy at best and not necessarily guaranteed to sync the
database with the file system
This commit is contained in:
shockrah 2021-03-23 17:16:05 -07:00
parent 92dc4d888f
commit d02084a22c
3 changed files with 111 additions and 43 deletions

52
json-api/Cargo.lock generated
View File

@ -354,6 +354,7 @@ version = "0.1.0"
dependencies = [
"mysql_async",
"serde",
"tokio 1.4.0",
]
[[package]]
@ -584,7 +585,7 @@ dependencies = [
"http",
"indexmap",
"slab",
"tokio",
"tokio 0.2.25",
"tokio-util 0.3.1",
"tracing",
"tracing-futures",
@ -656,7 +657,7 @@ dependencies = [
"itoa",
"pin-project 1.0.5",
"socket2",
"tokio",
"tokio 0.2.25",
"tower-service",
"tracing",
"want",
@ -724,7 +725,7 @@ dependencies = [
"rand 0.7.3",
"serde",
"serde_json",
"tokio",
"tokio 0.2.25",
"tokio-test",
]
@ -783,9 +784,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.90"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
[[package]]
name = "libz-sys"
@ -871,7 +872,7 @@ checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
dependencies = [
"log",
"mio",
"miow 0.3.6",
"miow 0.3.7",
"winapi 0.3.9",
]
@ -900,11 +901,10 @@ dependencies = [
[[package]]
name = "miow"
version = "0.3.6"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"socket2",
"winapi 0.3.9",
]
@ -928,7 +928,7 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
"tokio",
"tokio 0.2.25",
"tokio-tls",
"tokio-util 0.2.0",
"twox-hash",
@ -1449,18 +1449,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.124"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.124"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
dependencies = [
"proc-macro2",
"quote",
@ -1541,9 +1541,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "standback"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "decebb311175fdaf1bf8a14583716e93163c566db2ead1c1d608c3e1e4313cb8"
checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
dependencies = [
"version_check",
]
@ -1770,6 +1770,18 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "tokio"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722"
dependencies = [
"autocfg",
"bytes 1.0.1",
"memchr",
"pin-project-lite 0.2.6",
]
[[package]]
name = "tokio-macros"
version = "0.2.6"
@ -1789,7 +1801,7 @@ checksum = "ed0049c119b6d505c4447f5c64873636c7af6c75ab0d45fd9f618d82acb8016d"
dependencies = [
"bytes 0.5.6",
"futures-core",
"tokio",
"tokio 0.2.25",
]
[[package]]
@ -1799,7 +1811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
dependencies = [
"native-tls",
"tokio",
"tokio 0.2.25",
]
[[package]]
@ -1813,7 +1825,7 @@ dependencies = [
"futures-sink",
"log",
"pin-project-lite 0.1.12",
"tokio",
"tokio 0.2.25",
]
[[package]]
@ -1827,7 +1839,7 @@ dependencies = [
"futures-sink",
"log",
"pin-project-lite 0.1.12",
"tokio",
"tokio 0.2.25",
]
[[package]]

View File

@ -10,4 +10,4 @@ edition = "2018"
mysql_async = "0.23.1"
serde = { version = "1.0.117", features = [ "derive" ] }
tokio = { version = "1", features = ["fs", "io-util"] }

View File

@ -1,8 +1,14 @@
use std::time::{SystemTime, UNIX_EPOCH};
use mysql_async::{params, Pool};
use tokio::fs;
use tokio::io::AsyncWriteExt;
use mysql_async::params;
use mysql_async::{Pool, Conn};
use mysql_async::prelude::Queryable;
use mysql_async::error::Error as SqlError;
use mysql_async::QueryResult;
use mysql_async::BinaryProtocol;
use crate::{Response, sql_err};
@ -13,27 +19,7 @@ const MAX_MESSAGES: u64 = 1000;
impl Message {
pub async fn send(p: &Pool, content: &str, content_type: &str, cid: UBigInt, uid: UBigInt) -> Result<Response<Self>, SqlError> {
//! @returns on_sucess -> empty
//! @returns on_failure Err(SqlErr)
let conn = p.get_conn().await?;
let q = "INSERT INTO messages
(time, content, content_type, author_id, channel_id)
VALUES (:time, :content, :ctype, :author, :channel)";
let now: i64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time `NOW` failed")
.as_millis() as i64;
let res = conn.prep_exec(q, params!{
"time" => now,
"content" => content,
"ctype" => content_type,
"author" => uid,
"channel" => cid
}).await;
fn send_verify_error(res: Result<QueryResult<Conn, BinaryProtocol>, SqlError> ) -> Result<Response<Self>, SqlError> {
if let Err(e) = res {
return match e {
SqlError::Server(err) => {
@ -52,6 +38,76 @@ impl Message {
else {
return Ok(Response::Empty);
}
}
pub async fn send(p: &Pool, content: &str, content_type: &str, cid: UBigInt, uid: UBigInt) -> Result<Response<Self>, SqlError> {
//! @returns on_sucess -> empty
//! @returns on_failure Err(SqlErr)
let conn = p.get_conn().await?;
let q = "INSERT INTO messages
(time, content, content_type, author_id, channel_id)
VALUES (:time, :content, :ctype, :author, :channel)";
let now: i64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time `NOW` failed")
.as_millis() as i64;
match content_type {
"text/plain" => {
if content.len() > 4_000 {
Ok(Response::RestrictedInput("Large text not allowed".into()))
} else {
let res = conn.prep_exec(q, params!{
"time" => now,
"content" => content,
"ctype" => content_type,
"author" => uid,
"channel" => cid
}).await;
Self::send_verify_error(res)
}
},
_ => {
if content.len() > 10_000_000 {
Ok(Response::RestrictedInput("Large data not allowed".into()))
} else {
let extension = match content_type {
"image/png" => "png",
"image/jpeg" | "image/jpg" => "jpg",
"application/webm" => "webm",
"application/mp4" => "mp4",
"application/mp3" => "mp3",
_ => panic!("Bad file type sent to db layer {}", content_type)
};
let content_ref = format!("{cid}-{time}.{ext}", cid=cid, time=now, ext=extension);
let res = conn.prep_exec(q, params!{
"time" => now,
"content" => &content_ref, // store a ref to a file instead of the actual payload
"ctype" => content_type,
"author" => uid,
"channel" => cid
}).await;
if let Ok(ret) = Self::send_verify_error(res) {
// now save the data to disk
match fs::File::create(content_ref).await {
Ok(mut file) => {
file.write_all(content.as_bytes()).await.expect("Failed to write, but the ref is saved");
Ok(ret)
},
Err(_) => {
Ok(Response::Other("Saved ref but couldn't save file data".into()))
},
}
} else {
Ok(Response::Success)
}
}
}
}
}