From 9187a5cb914b3240cb0b902c75b3b83934d44190 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Mon, 13 Jul 2026 19:47:56 +0200 Subject: [PATCH] add file extension to nodename --- application/backend/src/backend.rs | 16 ++++--- application/backend/src/lib.rs | 3 +- application/backend/src/lockmanager.rs | 1 + application/backend/src/note.rs | 61 ++++++++++++++++++++++++++ application/backend/src/storage.rs | 28 ++++++++++++ 5 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 application/backend/src/note.rs diff --git a/application/backend/src/backend.rs b/application/backend/src/backend.rs index 89d3699..0550be8 100644 --- a/application/backend/src/backend.rs +++ b/application/backend/src/backend.rs @@ -48,6 +48,7 @@ use entity::note::{Column, Entity as Note}; use entity::notecontent::{Entity as NoteContent}; use migration::prelude::Utc; use crate::lockmanager::LockManager; +use crate::note::{create_nodename, randomize_nodename}; use crate::storage::{get_collection_storage_path, get_note_storage_path, write_file}; pub struct Backend { @@ -447,12 +448,18 @@ impl BackendHandle { callback(SaveNoteResult::ValidationError("title not set")); return; }; + let Set(kind) = ¬e.kind else { + callback(SaveNoteResult::ValidationError("note type not set")); + return; + }; let mut nodename = if let Set(nn) = ¬e.nodename { nn.clone() } else { // generate nodename from title - title.clone() + let nodename = create_nodename(title, kind); + note.nodename = Set(nodename.clone()); + nodename }; let bhandle = self.clone(); @@ -512,12 +519,7 @@ impl BackendHandle { // 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(); + let new_nodename = randomize_nodename(nodename.as_str()); note.nodename = Set(new_nodename.clone()); nodename = new_nodename; let result = note.clone().insert(&bhandle.backend.db).await; diff --git a/application/backend/src/lib.rs b/application/backend/src/lib.rs index c781e36..4eed8cd 100644 --- a/application/backend/src/lib.rs +++ b/application/backend/src/lib.rs @@ -1,3 +1,4 @@ pub mod backend; pub mod lockmanager; -pub mod storage; \ No newline at end of file +pub mod storage; +mod note; \ No newline at end of file diff --git a/application/backend/src/lockmanager.rs b/application/backend/src/lockmanager.rs index 7746664..bc7f6a4 100644 --- a/application/backend/src/lockmanager.rs +++ b/application/backend/src/lockmanager.rs @@ -25,6 +25,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + use std::collections::{HashSet}; use std::sync::Arc; diff --git a/application/backend/src/note.rs b/application/backend/src/note.rs new file mode 100644 index 0000000..bd2e32d --- /dev/null +++ b/application/backend/src/note.rs @@ -0,0 +1,61 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +use std::path::Path; +use rand::distr::Alphanumeric; +use rand::RngExt; +use entity::note::NoteType; + +pub fn notetype2ext(t: &NoteType) -> &'static str { + match t { + NoteType::PlainTextNote => { ".txt" } + NoteType::MDTextNote => { ".md" } + } +} + +pub fn create_nodename(title: &str, kind: &NoteType) -> String { + format!("{}{}", title, notetype2ext(kind)) +} + +pub fn randomize_nodename(nodename: &str) -> String { + let suffix: String = rand::rng() + .sample_iter(Alphanumeric) + .take(6) + .map(char::from) + .collect(); + + let path = Path::new(nodename); + let stem = path + .file_stem() + .and_then(|s| s.to_str()) + .unwrap_or(nodename); + + match path.extension().and_then(|e| e.to_str()) { + Some(ext) => format!("{stem}-{suffix}.{ext}"), + None => format!("{stem}_{suffix}"), + } +} diff --git a/application/backend/src/storage.rs b/application/backend/src/storage.rs index df6a187..eb71445 100644 --- a/application/backend/src/storage.rs +++ b/application/backend/src/storage.rs @@ -1,3 +1,31 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + use std::io::ErrorKind; use std::path::Path; use sea_orm::{DatabaseConnection, DbErr, EntityTrait, QuerySelect, RelationTrait}; -- 2.52.0