Add proper shutdown, rate limits, config validation, cors config, fix dangling cursors, cache regex, merge created texts
This commit is contained in:
parent
4763bc9d04
commit
e15b0f9903
28 changed files with 1278 additions and 465 deletions
|
|
@ -1,8 +1,17 @@
|
|||
use std::sync::LazyLock;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
static DEDUP_SUFFIX_REGEX: LazyLock<Regex> =
|
||||
LazyLock::new(|| Regex::new(r" \((\d+)\)$").expect("invalid regex"));
|
||||
|
||||
pub fn dedup_paths(path: &str) -> impl Iterator<Item = String> {
|
||||
let mut path_parts = path.split('/').collect::<Vec<_>>();
|
||||
let file_name = path_parts.pop().unwrap().to_owned();
|
||||
let file_name = path_parts
|
||||
.pop()
|
||||
.filter(|s| !s.is_empty())
|
||||
.unwrap_or(path)
|
||||
.to_owned();
|
||||
|
||||
let mut directory = path_parts.join("/");
|
||||
if !directory.is_empty() {
|
||||
|
|
@ -29,14 +38,13 @@ pub fn dedup_paths(path: &str) -> impl Iterator<Item = String> {
|
|||
}
|
||||
};
|
||||
|
||||
let regex = Regex::new(r" \((\d+)\)$").unwrap();
|
||||
let start_number = regex
|
||||
let start_number = DEDUP_SUFFIX_REGEX
|
||||
.captures(&stem)
|
||||
.and_then(|caps| caps.get(1))
|
||||
.and_then(|m| m.as_str().parse::<u32>().ok())
|
||||
.unwrap_or(0);
|
||||
|
||||
let clean_stem = regex.replace(&stem, "").to_string();
|
||||
let clean_stem = DEDUP_SUFFIX_REGEX.replace(&stem, "").to_string();
|
||||
|
||||
(start_number..).map(move |dedup_number| {
|
||||
if dedup_number == 0 {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::app_state::database::models::VaultId;
|
||||
use crate::utils::dedup_paths::dedup_paths;
|
||||
use anyhow::{Result, bail};
|
||||
use log::info;
|
||||
use anyhow::Result;
|
||||
use log::{debug, info};
|
||||
use sqlx::sqlite::SqliteConnection;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
use anyhow::{Result, ensure};
|
||||
|
||||
/// Sanitize the document's path to allow all clients to create the same path in
|
||||
/// their filesystem. If we didn't do this server-side, client's would need to
|
||||
/// deal with mapping invalid names to valid ones and then back.
|
||||
pub fn sanitize_path(path: &str) -> String {
|
||||
pub fn sanitize_path(path: &str) -> Result<String> {
|
||||
let options = sanitize_filename::Options {
|
||||
truncate: true,
|
||||
windows: true, // Windows is the lowest common denominator
|
||||
replacement: "",
|
||||
};
|
||||
|
||||
path.split('/')
|
||||
let result = path
|
||||
.split('/')
|
||||
.map(|part| {
|
||||
let proposal = sanitize_filename::sanitize_with_options(part, options.clone());
|
||||
if !part.is_empty() && proposal.is_empty() {
|
||||
|
|
@ -18,7 +21,10 @@ pub fn sanitize_path(path: &str) -> String {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("/")
|
||||
.join("/");
|
||||
|
||||
ensure!(!result.is_empty(), "Relative path is empty after sanitization");
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -27,8 +33,32 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_sanitize_path() {
|
||||
assert_eq!(sanitize_path("/my/path/what?"), "/my/path/what");
|
||||
assert_eq!(sanitize_path("file (1).md"), "file (1).md");
|
||||
assert_eq!(sanitize_path("/my/path/\\\\:?"), "/my/path/_");
|
||||
assert_eq!(sanitize_path("/my/path/what?").unwrap(), "/my/path/what");
|
||||
assert_eq!(sanitize_path("file (1).md").unwrap(), "file (1).md");
|
||||
assert_eq!(sanitize_path("/my/path/\\\\:?").unwrap(), "/my/path/_");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sanitize_path_empty() {
|
||||
assert!(sanitize_path("").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sanitize_path_idempotent_simple() {
|
||||
let mut result = sanitize_path("notes/my file.md").unwrap();
|
||||
for _ in 0..5 {
|
||||
result = sanitize_path(&result).unwrap();
|
||||
}
|
||||
assert_eq!(result, "notes/my file.md");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sanitize_path_idempotent_special_chars() {
|
||||
let first = sanitize_path("/my/path/what?/file:name<>.md").unwrap();
|
||||
let mut result = first.clone();
|
||||
for _ in 0..5 {
|
||||
result = sanitize_path(&result).unwrap();
|
||||
}
|
||||
assert_eq!(result, first);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue