Fix avatar

This commit is contained in:
Adrian Woźniak 2023-04-04 13:52:42 +02:00
parent 35cf6ebaf9
commit d78139c799
11 changed files with 185 additions and 439 deletions

416
Cargo.lock generated
View File

@ -234,7 +234,7 @@ dependencies = [
"ahash 0.7.6",
"bytes",
"bytestring",
"cfg-if 1.0.0",
"cfg-if",
"cookie",
"derive_more",
"encoding_rs",
@ -321,7 +321,7 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"getrandom",
"once_cell",
"version_check 0.9.4",
@ -400,12 +400,6 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "anymap2"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c"
[[package]]
name = "ascii_utils"
version = "0.9.3"
@ -618,35 +612,6 @@ dependencies = [
"uuid 1.3.0",
]
[[package]]
name = "bitque_client"
version = "0.1.0"
dependencies = [
"bincode",
"bitque-data",
"chrono",
"console_error_panic_hook",
"derive_enum_iter",
"derive_enum_primitive",
"dotenv",
"futures",
"js-sys",
"seed",
"serde",
"serde_json",
"strum",
"tracing",
"tracing-subscriber",
"tracing-subscriber-wasm",
"uuid 1.3.0",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test",
"wasm-sockets",
"web-sys",
"wee_alloc",
]
[[package]]
name = "bitquec"
version = "0.1.0"
@ -729,12 +694,6 @@ dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -867,16 +826,6 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen",
]
[[package]]
name = "convert_case"
version = "0.4.0"
@ -925,7 +874,7 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@ -934,7 +883,7 @@ version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"crossbeam-utils",
]
@ -944,7 +893,7 @@ version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@ -1094,15 +1043,6 @@ dependencies = [
"uuid 1.3.0",
]
[[package]]
name = "dbg"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4677188513e0e9d7adced5997cf9a1e7a3c996c994f90093325c5332c1a8b221"
dependencies = [
"version_check 0.1.5",
]
[[package]]
name = "derive_db_execute"
version = "0.1.0"
@ -1311,12 +1251,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112"
[[package]]
name = "enclose"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1056f553da426e9c025a662efa48b52e62e0a3a7648aa2d15aeaaf7f0d329357"
[[package]]
name = "encoding"
version = "0.2.33"
@ -1387,7 +1321,7 @@ version = "0.8.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@ -1619,179 +1553,9 @@ version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen",
]
[[package]]
name = "gloo"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a4bef6b277b3ab073253d4bca60761240cf8d6998f4bd142211957b69a61b20"
dependencies = [
"gloo-console",
"gloo-dialogs",
"gloo-events",
"gloo-file",
"gloo-history",
"gloo-net",
"gloo-render",
"gloo-storage",
"gloo-timers",
"gloo-utils",
"gloo-worker",
]
[[package]]
name = "gloo-console"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f"
dependencies = [
"gloo-utils",
"js-sys",
"serde",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-dialogs"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-events"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-file"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7"
dependencies = [
"futures-channel",
"gloo-events",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-history"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd451019e0b7a2b8a7a7b23e74916601abf1135c54664e57ff71dcc26dfcdeb7"
dependencies = [
"gloo-events",
"gloo-utils",
"serde",
"serde-wasm-bindgen",
"serde_urlencoded",
"thiserror",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-net"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10"
dependencies = [
"futures-channel",
"futures-core",
"futures-sink",
"gloo-utils",
"js-sys",
"pin-project",
"serde",
"serde_json",
"thiserror",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "gloo-render"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-storage"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480"
dependencies = [
"gloo-utils",
"js-sys",
"serde",
"serde_json",
"thiserror",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-timers"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c"
dependencies = [
"futures-channel",
"futures-core",
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "gloo-utils"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8e8fc851e9c7b9852508bc6e3f690f452f474417e8545ec9857b7f7377036b5"
dependencies = [
"js-sys",
"serde",
"serde_json",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "gloo-worker"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a"
dependencies = [
"anymap2",
"bincode",
"gloo-console",
"gloo-utils",
"js-sys",
"serde",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
@ -2018,7 +1782,7 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@ -2218,7 +1982,7 @@ version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@ -2277,12 +2041,6 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memory_units"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
[[package]]
name = "mime"
version = "0.3.17"
@ -2454,7 +2212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2"
dependencies = [
"bitflags 1.3.2",
"cfg-if 1.0.0",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
@ -2534,7 +2292,7 @@ version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"libc",
"redox_syscall 0.2.16",
"smallvec",
@ -2559,26 +2317,6 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pin-project"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
dependencies = [
"proc-macro2 1.0.54",
"quote 1.0.26",
"syn 1.0.109",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@ -2997,7 +2735,7 @@ version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"ordered-multimap",
]
@ -3011,7 +2749,7 @@ dependencies = [
"aws-creds",
"aws-region",
"base64 0.13.1",
"cfg-if 1.0.0",
"cfg-if",
"hex",
"hmac",
"http",
@ -3133,12 +2871,6 @@ dependencies = [
"parking_lot",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -3174,34 +2906,6 @@ dependencies = [
"libc",
]
[[package]]
name = "seed"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9352d75dd253803ce05722fe3acaafffc461d4faeaf0ebe0d8bf831059482e21"
dependencies = [
"console_error_panic_hook",
"cookie",
"dbg",
"enclose",
"futures",
"getrandom",
"gloo-file",
"gloo-timers",
"gloo-utils",
"indexmap",
"js-sys",
"rand 0.8.5",
"serde",
"serde-wasm-bindgen",
"serde_json",
"uuid 1.3.0",
"version_check 0.9.4",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "semver"
version = "1.0.17"
@ -3217,17 +2921,6 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde-xml-rs"
version = "0.5.1"
@ -3298,7 +2991,7 @@ version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"cpufeatures",
"digest",
]
@ -3315,7 +3008,7 @@ version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"cpufeatures",
"digest",
]
@ -3418,12 +3111,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "static_assertions"
version = "1.1.0"
@ -3538,7 +3225,7 @@ version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"fastrand",
"redox_syscall 0.3.5",
"rustix 0.37.5",
@ -3614,7 +3301,7 @@ version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"once_cell",
]
@ -3782,7 +3469,7 @@ version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"log",
"pin-project-lite",
"tracing-attributes",
@ -3840,17 +3527,6 @@ dependencies = [
"tracing-log",
]
[[package]]
name = "tracing-subscriber-wasm"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79804e80980173c6c8e53d98508eb24a2dbc4ee17a3e8d2ca8e5bad6bf13a898"
dependencies = [
"gloo",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "triple_accel"
version = "0.3.4"
@ -4042,9 +3718,7 @@ version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
dependencies = [
"cfg-if 1.0.0",
"serde",
"serde_json",
"cfg-if",
"wasm-bindgen-macro",
]
@ -4069,7 +3743,7 @@ version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
@ -4104,43 +3778,6 @@ version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db36fc0f9fb209e88fb3642590ae0205bb5a56216dabd963ba15879fe53a30b"
dependencies = [
"console_error_panic_hook",
"js-sys",
"scoped-tls",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0734759ae6b3b1717d661fe4f016efcfb9828f5edb4520c18eaee05af3b43be9"
dependencies = [
"proc-macro2 1.0.54",
"quote 1.0.26",
]
[[package]]
name = "wasm-sockets"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d14bbe65995269301ab677e5d69b3b69195447c01137ef44f72b10eecea55c77"
dependencies = [
"js-sys",
"log",
"thiserror",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-streams"
version = "0.2.3"
@ -4218,19 +3855,6 @@ dependencies = [
"uuid 1.3.0",
]
[[package]]
name = "wee_alloc"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
dependencies = [
"cfg-if 0.1.10",
"libc",
"memory_units",
"spin",
"winapi",
]
[[package]]
name = "wildmatch"
version = "2.1.1"

View File

@ -26,7 +26,7 @@ members = [
"./crates/cloud-storage-actor",
"./crates/filesystem-actor",
# Client
"./crates/web"
# "./crates/web"
]
exclude = [
"crates/bitque-cli",

View File

@ -28,19 +28,21 @@ impl actix::Actor for CloudStorageExecutor {
#[derive(actix::Message)]
#[rtype(result = "Result<String, AmazonError>")]
pub struct S3PutObject {
pub struct PutObject {
pub source: tokio::sync::broadcast::Receiver<bytes::Bytes>,
pub file_name: String,
pub dir: String,
}
impl actix::Handler<S3PutObject> for CloudStorageExecutor {
impl actix::Handler<PutObject> for CloudStorageExecutor {
type Result = Result<String, AmazonError>;
fn handle(&mut self, msg: S3PutObject, _ctx: &mut Self::Context) -> Self::Result {
let S3PutObject {
fn handle(&mut self, msg: PutObject, _ctx: &mut Self::Context) -> Self::Result {
let PutObject {
// source,
mut source,
file_name,
dir,
} = msg;
bitque_config::cloud_storage::config().set_variables();
@ -77,7 +79,7 @@ impl actix::Handler<S3PutObject> for CloudStorageExecutor {
})?
.with_path_style();
let put = bucket
.put_object(file_name.as_str(), &v)
.put_object(format!("{dir}/{file_name}").as_str(), &v)
.await
.map_err(|e| {
warn!("{e}");

View File

@ -157,6 +157,9 @@ mod tests {
use super::*;
use crate::build_pool;
use crate::schema::issues::dsl::issues;
use crate::schema::tokens::dsl::tokens;
use crate::schema::user_settings::dsl::user_settings;
#[test]
fn check_collision() {
@ -169,7 +172,10 @@ mod tests {
let conn = &mut conn;
conn.begin_test_transaction().unwrap();
diesel::delete(user_settings).execute(conn).unwrap();
diesel::delete(user_projects).execute(conn).unwrap();
diesel::delete(tokens).execute(conn).unwrap();
diesel::delete(issues).execute(conn).unwrap();
diesel::delete(users).execute(conn).unwrap();
diesel::delete(projects).execute(conn).unwrap();

View File

@ -54,7 +54,7 @@ impl Handler<Invite> for MailExecutor {
.body(html)
.map_err(|e| {
log::error!("{:?}", e);
MailError::MailformedBody
MailError::MalformedBody
})?;
transport.send(&mail).map(|_| ()).map_err(|e| {

View File

@ -15,7 +15,7 @@ pub enum MailError {
EmailWithoutDomain,
InvalidEmailAddress,
FailedToSendEmail,
MailformedBody,
MalformedBody,
}
pub struct MailExecutor {

View File

@ -56,7 +56,7 @@ impl Handler<Welcome> for MailExecutor {
.body(html)
.map_err(|e| {
log::error!("{:?}", e);
MailError::MailformedBody
MailError::MalformedBody
})?;
transport.send(&mail).map(|_| ()).map_err(|e| {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

View File

@ -15,6 +15,11 @@ pub enum HighlightError {
ResultUnserializable,
}
#[derive(Clone, Debug)]
pub enum AvatarError {
Upload,
}
#[derive(Clone, Debug)]
pub enum ServiceError {
Unauthorized,
@ -24,6 +29,7 @@ pub enum ServiceError {
RegisterCollision,
Error(WsError),
Highlight(HighlightError),
Avatar(AvatarError),
}
impl ServiceError {
@ -84,6 +90,9 @@ impl Into<HttpResponse> for ServiceError {
"Highlight succeed but result can't be send",
))
}
ServiceError::Avatar(AvatarError::Upload) => {
HttpResponse::UnprocessableEntity().finish()
}
}
}
}

View File

@ -1,56 +1,168 @@
use actix::{spawn, Addr};
use actix_multipart::Field;
use actix_web::web::Data;
use actix_web::{Error, HttpResponse};
use actix_web::Error;
use bitque_data::UserId;
use bytes::Bytes;
use futures::future::join_all;
use futures::StreamExt;
use tokio::sync::broadcast::{Receiver, Sender};
use tracing::error;
use crate::{AvatarError, ServiceError};
pub trait UploadField {
fn name(&self) -> &str;
/// Read file from client
async fn read_content(&mut self, sender: Sender<Bytes>);
}
impl UploadField for Field {
fn name(&self) -> &str {
self.content_disposition().get_filename().unwrap()
}
async fn read_content(&mut self, sender: Sender<Bytes>) {
while let Some(chunk) = self.next().await {
let data = chunk.unwrap();
if let Err(err) = sender.send(data) {
error!("{:?}", err);
}
}
}
}
#[cfg(all(feature = "local-storage", feature = "cloud-storage"))]
pub(crate) async fn handle_image(
user_id: UserId,
mut field: Field,
fs: Data<Addr<filesystem_actor::LocalStorageExecutor>>,
mut field: impl UploadField,
local_storage: Data<Addr<filesystem_actor::LocalStorageExecutor>>,
cloud_storage: Data<Addr<cloud_storage_actor::CloudStorageExecutor>>,
) -> Result<String, Error> {
let filename = field.content_disposition().get_filename().unwrap();
let filename = field.name();
let system_file_name = format!("{}-{}", user_id, filename);
let (sender, receiver) = tokio::sync::broadcast::channel(64);
let fs_fut = local_storage_write(system_file_name.clone(), fs, user_id, sender.subscribe());
let aws_fut = cloud_storage_write(system_file_name, cloud_storage, receiver);
let read_fut = read_form_data(&mut field, sender);
read_fut.await;
let results = join_all([spawn(fs_fut), spawn(aws_fut)]).await;
let results_fut = join_all([
spawn(local_storage_write(
system_file_name.clone(),
local_storage,
user_id,
sender.subscribe(),
)),
spawn(cloud_storage_write(
filename.to_string(),
cloud_storage,
format!("user_{user_id}"),
receiver,
)),
]);
let (_, results) = tokio::join!(field.read_content(sender), results_fut);
for res in results {
return if let Ok(Some(link)) = res {
Ok(link)
} else {
Err(HttpResponse::UnprocessableEntity().finish().into())
Err(ServiceError::Avatar(AvatarError::Upload).into())
};
}
Err(HttpResponse::UnprocessableEntity().finish().into())
Err(ServiceError::Avatar(AvatarError::Upload).into())
}
#[cfg(test)]
mod local_and_cloud {
use std::borrow::Cow;
use actix::SyncArbiter;
use actix_web::web::Data;
use bytes::Bytes;
use tokio::spawn;
use tokio::sync::broadcast::Sender;
use crate::handlers::upload_avatar_image::{handle_image, UploadField};
pub struct FieldMock<'s>(Cow<'s, [u8]>);
impl<'s> UploadField for FieldMock<'s> {
fn name(&self) -> &str {
"foo.bar"
}
async fn read_content(&mut self, sender: Sender<Bytes>) {
loop {
if self.0.is_empty() {
break;
}
let len = self.0.len().min(30);
let slice = self.0[0..len].to_vec();
self.0 = self.0[len..].to_vec().into();
sender.send(Bytes::copy_from_slice(&slice)).unwrap();
}
}
}
#[actix::test]
async fn asset_test_mock() {
let v = (0..255).into_iter().collect::<Vec<_>>();
let mut field = FieldMock(v.into());
let (tx, mut rx) = tokio::sync::broadcast::channel::<Bytes>(64);
let read = async {
spawn(async move {
let mut len = 0;
while let Ok(bytes) = rx.recv().await {
len += bytes.len();
}
len
})
.await
};
let write = async move {
spawn(async move {
field.read_content(tx).await;
})
.await
};
let (_, len) = tokio::join!(write, read);
assert_eq!(len.unwrap(), 255);
}
#[actix::test]
async fn large_image() {
let field = FieldMock(Cow::Borrowed(include_bytes!(
"../../assets/LotC_Wallpaper_2560x1440.jpg"
)));
let local_storage = Data::new(SyncArbiter::start(
1,
filesystem_actor::LocalStorageExecutor::default,
));
let cloud_storage = Data::new(SyncArbiter::start(
1,
cloud_storage_actor::CloudStorageExecutor::default,
));
let res = handle_image(0, field, local_storage, cloud_storage).await;
eprintln!("{res:#?}");
res.unwrap();
}
}
#[cfg(all(not(feature = "local-storage"), feature = "cloud-storage"))]
pub(crate) async fn handle_image(
user_id: UserId,
mut field: Field,
mut field: impl UploadField,
cloud_storage: Data<Addr<cloud_storage_actor::CloudStorageExecutor>>,
) -> Result<String, Error> {
let filename = field.content_disposition().get_filename().unwrap();
let filename = field.name();
let system_file_name = format!("{}-{}", user_id, filename);
let (sender, receiver) = tokio::sync::broadcast::channel(64);
let aws_fut = cloud - storage_write(system_file_name, cloud_storage, receiver);
let read_fut = read_form_data(&mut field, sender);
let read_fut = field.read_content(sender);
let aws_join = tokio::task::spawn(aws_fut);
read_fut.await;
@ -67,16 +179,16 @@ pub(crate) async fn handle_image(
#[cfg(all(feature = "local-storage", not(feature = "cloud-storage")))]
pub(crate) async fn handle_image(
user_id: UserId,
mut field: Field,
mut field: impl UploadField,
fs: Data<Addr<filesystem_actor::LocalStorageExecutor>>,
) -> Result<String, Error> {
let filename = field.content_disposition().get_filename().unwrap();
let filename = field.name();
let system_file_name = format!("{}-{}", user_id, filename);
let (sender, _receiver) = tokio::sync::broadcast::channel(64);
let fs_fut = local_storage_write(system_file_name, fs, user_id, sender.subscribe());
let read_fut = read_form_data(&mut field, sender);
let read_fut = field.read_content(sender);
let fs_join = tokio::task::spawn(fs_fut);
read_fut.await;
@ -90,22 +202,13 @@ pub(crate) async fn handle_image(
Ok(new_link.unwrap_or_default())
}
/// Read file from client
async fn read_form_data(field: &mut Field, sender: Sender<bytes::Bytes>) {
while let Some(chunk) = field.next().await {
let data = chunk.unwrap();
if let Err(err) = sender.send(data) {
error!("{:?}", err);
}
}
}
/// Stream bytes directly to AWS S3 Service
/// Stream bytes directly to Cloud Storage Service
#[cfg(feature = "cloud-storage")]
async fn cloud_storage_write(
system_file_name: String,
cloud_storage: Data<Addr<cloud_storage_actor::CloudStorageExecutor>>,
receiver: Receiver<bytes::Bytes>,
dir: String,
receiver: Receiver<Bytes>,
) -> Option<String> {
let s3 = bitque_config::cloud_storage::config();
if !s3.active {
@ -113,9 +216,10 @@ async fn cloud_storage_write(
}
match cloud_storage
.send(cloud_storage_actor::S3PutObject {
.send(cloud_storage_actor::PutObject {
source: receiver,
file_name: system_file_name.to_string(),
dir,
})
.await
{
@ -128,8 +232,8 @@ async fn cloud_storage_write(
async fn local_storage_write(
system_file_name: String,
fs: Data<Addr<filesystem_actor::LocalStorageExecutor>>,
_user_id: bitque_data::UserId,
receiver: Receiver<bytes::Bytes>,
_user_id: UserId,
receiver: Receiver<Bytes>,
) -> Option<String> {
let web_config = bitque_config::web::config();
let fs_config = bitque_config::fs::config();

View File

@ -1,3 +1,4 @@
#![feature(async_fn_in_trait)]
extern crate core;
use actix::Addr;