source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+[[package]]
+name = "chacha20"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+ "rand_core 0.10.1",
+]
+
[[package]]
name = "chrono"
version = "0.4.44"
"libc",
]
+[[package]]
+name = "cpufeatures"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "crc"
version = "3.4.0"
"cfg-if",
"libc",
"r-efi 6.0.0",
+ "rand_core 0.10.1",
"wasip2",
"wasip3",
]
"dav-rs",
"entity",
"migration",
+ "rand 0.10.2",
"sea-orm",
"tokio",
"ui-rs",
"num-integer",
"num-iter",
"num-traits",
- "rand",
+ "rand 0.8.6",
"smallvec",
"zeroize",
]
dependencies = [
"libc",
"rand_chacha",
- "rand_core",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
+dependencies = [
+ "chacha20",
+ "getrandom 0.4.2",
+ "rand_core 0.10.1",
]
[[package]]
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
- "rand_core",
+ "rand_core 0.6.4",
]
[[package]]
"getrandom 0.2.17",
]
+[[package]]
+name = "rand_core"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
+
[[package]]
name = "redox_syscall"
version = "0.5.18"
"num-traits",
"pkcs1",
"pkcs8",
- "rand_core",
+ "rand_core 0.6.4",
"signature",
"spki",
"subtle",
"borsh",
"bytes",
"num-traits",
- "rand",
+ "rand 0.8.6",
"rkyv",
"serde",
"serde_json",
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
- "cpufeatures",
+ "cpufeatures 0.2.17",
"digest",
]
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
- "cpufeatures",
+ "cpufeatures 0.2.17",
"digest",
]
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"digest",
- "rand_core",
+ "rand_core 0.6.4",
]
[[package]]
"memchr",
"once_cell",
"percent-encoding",
- "rand",
+ "rand 0.8.6",
"rsa",
"rust_decimal",
"serde",
"md-5",
"memchr",
"once_cell",
- "rand",
+ "rand 0.8.6",
"rust_decimal",
"serde",
"serde_json",
use tokio::runtime::Runtime;
use std::sync::{Arc};
use std::thread::JoinHandle;
+use rand::distr::Alphanumeric;
+use rand::RngExt;
use tokio::sync::{broadcast, mpsc};
use tokio::sync::broadcast::error::SendError;
use migration::{Expr, JoinType, Migrator, MigratorTrait};
let _ = self.tx.send(cmd);
}
- pub fn save_note<F>(&self, initiator: u64, id: NoteId, note: note::ActiveModel, content: Option<notecontent::ActiveModel>, callback: F)
+ pub fn save_note<F>(&self, initiator: u64, id: NoteId, mut note: note::ActiveModel, content: Option<notecontent::ActiveModel>, callback: F)
where F: FnOnce(SaveNoteResult) + Send + 'static {
+ let Set(collection_id) = note.collection_id else {
+ callback(SaveNoteResult::ValidationError("collection_id not set"));
+ return;
+ };
+ let Set(nn) = ¬e.nodename else {
+ callback(SaveNoteResult::ValidationError("nodename not set"));
+ return;
+ };
+ let nodename = nn.clone();
+ let Set(version) = note.version else {
+ callback(SaveNoteResult::ValidationError("version not set"));
+ return;
+ };
+
let bhandle = self.clone();
let cmd = Box::pin(async move {
- let local_storage_path = if let Set(collection_id) = note.collection_id {
+ let local_storage_path = {
let result = collection::Entity::find_by_id(collection_id)
.join(JoinType::InnerJoin, collection::Relation::Repository.def())
.select_only()
} else {
None
}
- } else {
- return;
};
let result = if let Set(note_id) = note.note_id {
update = update.col_expr(Column::Title, Expr::value(title));
}
- let version = if let Set(version) = note.version {
- version
- } else {
- // not setting version when calling save_note is a mistake and will probably
- // lead to a VersionConflict
- 0
- };
-
let uresult = update
.col_expr(Column::Lastmodified, Expr::value(Utc::now()))
.col_expr(Column::Version, Expr::col(Column::Version).add(1))
}
}
} else {
- let result = note.insert(&bhandle.backend.db).await;
+ let result = note.clone().insert(&bhandle.backend.db).await;
match result {
Ok(note) => Ok(note),
- Err(e) => Err(SaveNoteResult::Error(e)),
+ Err(e) => {
+ // The main reason why insertion might fail is the
+ // collection+name unique constraint.
+ // Generate a random suffix and try it again
+
+ let suffix: String = rand::rng()
+ .sample_iter(Alphanumeric)
+ .take(6)
+ .map(char::from)
+ .collect();
+ let new_nodename = nodename + "-" + suffix.as_str();
+ note.nodename = Set(new_nodename);
+ let result = note.clone().insert(&bhandle.backend.db).await;
+ match result {
+ Ok(note) => Ok(note),
+ Err(e) => Err(SaveNoteResult::Error(e))
+ }
+ }
}
};
pub enum SaveNoteResult {
Ok((entity::note::Model, i32)),
VersionConflict,
- Error(DbErr)
+ Error(DbErr),
+ ValidationError(&'static str)
}
impl SaveNoteResult {