|
|
@ -5,7 +5,6 @@ use std::{ |
|
|
|
path::PathBuf, |
|
|
|
path::PathBuf, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
#[cfg(target_family = "unix")] |
|
|
|
|
|
|
|
use std::os::unix::fs::DirBuilderExt; |
|
|
|
use std::os::unix::fs::DirBuilderExt; |
|
|
|
|
|
|
|
|
|
|
|
use argon2::{ |
|
|
|
use argon2::{ |
|
|
@ -79,7 +78,7 @@ struct TextMeta { |
|
|
|
|
|
|
|
|
|
|
|
impl TextMeta { |
|
|
|
impl TextMeta { |
|
|
|
pub fn parse(from: &str) -> Result<Self, Error> { |
|
|
|
pub fn parse(from: &str) -> Result<Self, Error> { |
|
|
|
let map = meta_str_to_map(from)?; |
|
|
|
let mut map = meta_str_to_map(from)?; |
|
|
|
Ok(Self { |
|
|
|
Ok(Self { |
|
|
|
language: map.remove("language"), |
|
|
|
language: map.remove("language"), |
|
|
|
}) |
|
|
|
}) |
|
|
@ -88,8 +87,9 @@ impl TextMeta { |
|
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for TextMeta { |
|
|
|
impl std::fmt::Display for TextMeta { |
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
|
|
let buf = "".to_string(); |
|
|
|
let mut buf = "".to_string(); |
|
|
|
self.language |
|
|
|
self.language |
|
|
|
|
|
|
|
.as_ref() |
|
|
|
.map(|lang| buf += format!("{}\n", lang).as_str()); |
|
|
|
.map(|lang| buf += format!("{}\n", lang).as_str()); |
|
|
|
write!(f, "{}---\n", buf) |
|
|
|
write!(f, "{}---\n", buf) |
|
|
|
} |
|
|
|
} |
|
|
@ -101,7 +101,7 @@ struct FileMeta { |
|
|
|
|
|
|
|
|
|
|
|
impl FileMeta { |
|
|
|
impl FileMeta { |
|
|
|
pub fn parse(from: &str) -> Result<Self, Error> { |
|
|
|
pub fn parse(from: &str) -> Result<Self, Error> { |
|
|
|
let map = meta_str_to_map(from)?; |
|
|
|
let mut map = meta_str_to_map(from)?; |
|
|
|
|
|
|
|
|
|
|
|
let file_name = map.remove("file_name").ok_or(Error::Metadata)?; |
|
|
|
let file_name = map.remove("file_name").ok_or(Error::Metadata)?; |
|
|
|
Ok(Self { file_name }) |
|
|
|
Ok(Self { file_name }) |
|
|
@ -210,7 +210,10 @@ impl DataStorage { |
|
|
|
new_text: Option<String>, |
|
|
|
new_text: Option<String>, |
|
|
|
new_meta: Option<TextMeta>, |
|
|
|
new_meta: Option<TextMeta>, |
|
|
|
) -> Result<(), Error> { |
|
|
|
) -> Result<(), Error> { |
|
|
|
let mut paste = self.text.get(&id).ok_or(Error::ShitMissing(id))?; |
|
|
|
let mut paste = self |
|
|
|
|
|
|
|
.text |
|
|
|
|
|
|
|
.get_mut(&id) |
|
|
|
|
|
|
|
.ok_or(Error::ShitMissing(id.clone()))?; |
|
|
|
new_text.map(|nt| paste.text = nt); |
|
|
|
new_text.map(|nt| paste.text = nt); |
|
|
|
new_meta.map(|nm| paste.meta = nm); |
|
|
|
new_meta.map(|nm| paste.meta = nm); |
|
|
|
|
|
|
|
|
|
|
@ -221,10 +224,10 @@ impl DataStorage { |
|
|
|
let old_text = self |
|
|
|
let old_text = self |
|
|
|
.text |
|
|
|
.text |
|
|
|
.remove(&id) |
|
|
|
.remove(&id) |
|
|
|
.ok_or(Error::ShitMissing(id)) |
|
|
|
.ok_or(Error::ShitMissing(id.clone())) |
|
|
|
.map(|(_, paste)| paste.text)?; |
|
|
|
.map(|(_, paste)| paste.text)?; |
|
|
|
|
|
|
|
|
|
|
|
remove_file(self.base_dir.join(*TEXT_DIR).join(id))?; |
|
|
|
remove_file(self.base_dir.join(TEXT_DIR.as_str()).join(id))?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(old_text) |
|
|
|
Ok(old_text) |
|
|
|
} |
|
|
|
} |
|
|
@ -234,17 +237,21 @@ impl DataStorage { |
|
|
|
return Err(Error::IDCollision); |
|
|
|
return Err(Error::IDCollision); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
self.files.insert(id, file_meta); |
|
|
|
self.files.insert(id.clone(), file_meta); |
|
|
|
|
|
|
|
|
|
|
|
self.write_file_meta(id); |
|
|
|
self.write_file_meta(id); |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn delete_file(&mut self, id: String) -> Result<(), Error> { |
|
|
|
pub fn delete_file(&mut self, id: String) -> Result<(), Error> { |
|
|
|
let file_meta = self.files.remove(&id).ok_or(Error::ShitMissing(id))?.1; |
|
|
|
let file_meta = self |
|
|
|
|
|
|
|
.files |
|
|
|
|
|
|
|
.remove(&id) |
|
|
|
|
|
|
|
.ok_or(Error::ShitMissing(id.clone()))? |
|
|
|
|
|
|
|
.1; |
|
|
|
|
|
|
|
|
|
|
|
remove_file(self.base_dir.join(*FILE_DIR).join(id))?; |
|
|
|
remove_file(self.base_dir.join(FILE_DIR.as_str()).join(id.clone()))?; |
|
|
|
remove_file(self.base_dir.join(*FILE_DIR).join(id + ".meta"))?; |
|
|
|
remove_file(self.base_dir.join(FILE_DIR.as_str()).join(id + ".meta"))?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
@ -261,7 +268,7 @@ impl DataStorage { |
|
|
|
|
|
|
|
|
|
|
|
pub fn edit_redirect(&mut self, id: String, new_target: String) -> Result<(), Error> { |
|
|
|
pub fn edit_redirect(&mut self, id: String, new_target: String) -> Result<(), Error> { |
|
|
|
if !self.redirects.contains_key(&id) { |
|
|
|
if !self.redirects.contains_key(&id) { |
|
|
|
return Err(Error::ShitMissing(id)); |
|
|
|
return Err(Error::ShitMissing(id.clone())); |
|
|
|
} |
|
|
|
} |
|
|
|
self.redirects.insert(id, new_target); |
|
|
|
self.redirects.insert(id, new_target); |
|
|
|
|
|
|
|
|
|
|
@ -270,7 +277,9 @@ impl DataStorage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn delete_redirect(&mut self, id: String) -> Result<(), Error> { |
|
|
|
pub fn delete_redirect(&mut self, id: String) -> Result<(), Error> { |
|
|
|
self.redirects.remove(&id).ok_or(Error::ShitMissing(id))?; |
|
|
|
self.redirects |
|
|
|
|
|
|
|
.remove(&id) |
|
|
|
|
|
|
|
.ok_or(Error::ShitMissing(id.clone()))?; |
|
|
|
|
|
|
|
|
|
|
|
self.write_redirects()?; |
|
|
|
self.write_redirects()?; |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
@ -286,8 +295,10 @@ impl DataStorage { |
|
|
|
return Err(Error::Exists); |
|
|
|
return Err(Error::Exists); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
self.users |
|
|
|
self.users.insert( |
|
|
|
.insert(username, UserData::new(username, password, is_admin)?); |
|
|
|
username.clone(), |
|
|
|
|
|
|
|
UserData::new(username, password, is_admin)?, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
self.write_users()?; |
|
|
|
self.write_users()?; |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
@ -299,7 +310,7 @@ impl DataStorage { |
|
|
|
old_password: String, |
|
|
|
old_password: String, |
|
|
|
new_password: String, |
|
|
|
new_password: String, |
|
|
|
) -> Result<(), Error> { |
|
|
|
) -> Result<(), Error> { |
|
|
|
let mut user = *self |
|
|
|
let mut user = self |
|
|
|
.users |
|
|
|
.users |
|
|
|
.get_mut(&username) |
|
|
|
.get_mut(&username) |
|
|
|
.ok_or(Error::ShitMissing(username))?; |
|
|
|
.ok_or(Error::ShitMissing(username))?; |
|
|
@ -318,14 +329,12 @@ impl DataStorage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn ensure_folder_structure(&self) -> Result<(), Error> { |
|
|
|
fn ensure_folder_structure(&self) -> Result<(), Error> { |
|
|
|
let dir_builder = DirBuilder::new().recursive(true); |
|
|
|
let mut dir_builder = DirBuilder::new(); |
|
|
|
if cfg!(target_family = "unix") { |
|
|
|
dir_builder.recursive(true).mode(0o775); |
|
|
|
dir_builder = dir_builder.mode(0o775); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dir_builder.create(self.base_dir)?; |
|
|
|
dir_builder.create(self.base_dir.as_path())?; |
|
|
|
dir_builder.create(self.base_dir.join(*FILE_DIR))?; |
|
|
|
dir_builder.create(self.base_dir.join(FILE_DIR.as_str()))?; |
|
|
|
dir_builder.create(self.base_dir.join(*TEXT_DIR))?; |
|
|
|
dir_builder.create(self.base_dir.join(TEXT_DIR.as_str()))?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
@ -334,11 +343,13 @@ impl DataStorage { |
|
|
|
let f = File::options() |
|
|
|
let f = File::options() |
|
|
|
.create(true) |
|
|
|
.create(true) |
|
|
|
.read(true) |
|
|
|
.read(true) |
|
|
|
.open(self.base_dir.join(*REDIRECTS_FILE))?; |
|
|
|
.open(self.base_dir.join(REDIRECTS_FILE.as_str()))?; |
|
|
|
|
|
|
|
|
|
|
|
for line in io::BufReader::new(f).lines() { |
|
|
|
for line in io::BufReader::new(f).lines() { |
|
|
|
line?; |
|
|
|
let (id, url) = line? |
|
|
|
let (id, url) = line?.split_once(": ").ok_or(Error::Metadata)?; |
|
|
|
.split_once(": ") |
|
|
|
|
|
|
|
.map(|(id, url)| (id.to_string(), url.to_string())) |
|
|
|
|
|
|
|
.ok_or(Error::Metadata)?; |
|
|
|
self.redirects |
|
|
|
self.redirects |
|
|
|
.insert(id.trim().to_string(), url.trim().to_string()); |
|
|
|
.insert(id.trim().to_string(), url.trim().to_string()); |
|
|
|
} |
|
|
|
} |
|
|
@ -347,13 +358,14 @@ impl DataStorage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn load_text(&mut self) -> Result<(), Error> { |
|
|
|
fn load_text(&mut self) -> Result<(), Error> { |
|
|
|
for thing in std::fs::read_dir(self.base_dir.join(*TEXT_DIR)).expect("fs error") { |
|
|
|
for thing in std::fs::read_dir(self.base_dir.join(TEXT_DIR.as_str())).expect("fs error") { |
|
|
|
let dir_entry = thing?; // i'm so good at naming things
|
|
|
|
let dir_entry = thing?; // i'm so good at naming things
|
|
|
|
let id = dir_entry.file_name().into_string().or(Err(Error::FS))?; |
|
|
|
let id = dir_entry.file_name().into_string().or(Err(Error::FS))?; |
|
|
|
let (raw_metadata, text) = read_to_string(dir_entry.path())? |
|
|
|
let (raw_metadata, text) = read_to_string(dir_entry.path())? |
|
|
|
.split_once("---") |
|
|
|
.split_once("---") |
|
|
|
|
|
|
|
.map(|(meta, text)| (meta.to_string(), text.to_string())) |
|
|
|
.expect("invalid text format"); |
|
|
|
.expect("invalid text format"); |
|
|
|
let meta = TextMeta::parse(raw_metadata)?; |
|
|
|
let meta = TextMeta::parse(raw_metadata.as_str())?; |
|
|
|
self.text.insert( |
|
|
|
self.text.insert( |
|
|
|
id, |
|
|
|
id, |
|
|
|
TextPaste { |
|
|
|
TextPaste { |
|
|
@ -366,7 +378,7 @@ impl DataStorage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn load_files(&mut self) -> Result<(), Error> { |
|
|
|
fn load_files(&mut self) -> Result<(), Error> { |
|
|
|
for thing in std::fs::read_dir(self.base_dir.join(*FILE_DIR)).expect("fs error") { |
|
|
|
for thing in std::fs::read_dir(self.base_dir.join(FILE_DIR.as_str())).expect("fs error") { |
|
|
|
let dir_entry = thing?; // i'm so good at naming things
|
|
|
|
let dir_entry = thing?; // i'm so good at naming things
|
|
|
|
let filename = dir_entry |
|
|
|
let filename = dir_entry |
|
|
|
.file_name() |
|
|
|
.file_name() |
|
|
@ -384,70 +396,70 @@ impl DataStorage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn assert_all_files_present(&self) -> Result<(), Error> { |
|
|
|
fn assert_all_files_present(&self) -> Result<(), Error> { |
|
|
|
let files_folder = self.base_dir.join(*FILE_DIR); |
|
|
|
let files_folder = self.base_dir.join(FILE_DIR.as_str()); |
|
|
|
for (id, _) in self.files.into_iter() { |
|
|
|
for meow in self.files.iter() { |
|
|
|
files_folder |
|
|
|
files_folder |
|
|
|
.join(id) |
|
|
|
.join(meow.key()) |
|
|
|
.try_exists() |
|
|
|
.try_exists() |
|
|
|
.or(Err(Error::ShitMissing(id)))?; |
|
|
|
.or(Err(Error::ShitMissing(meow.key().to_string())))?; |
|
|
|
} |
|
|
|
} |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn load_users(&mut self) -> Result<(), Error> { |
|
|
|
fn load_users(&mut self) -> Result<(), Error> { |
|
|
|
let is_admin = true; |
|
|
|
let mut is_admin = true; |
|
|
|
for line in read_to_string(self.base_dir.join(*USERS_FILE))?.lines() { |
|
|
|
for line in read_to_string(self.base_dir.join(USERS_FILE.as_str()))?.lines() { |
|
|
|
if line.starts_with("---") { |
|
|
|
if line.starts_with("---") { |
|
|
|
is_admin = false; |
|
|
|
is_admin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
let user = UserData::parse(line, is_admin)?; |
|
|
|
let user = UserData::parse(line, is_admin)?; |
|
|
|
self.users.insert(user.username, user); |
|
|
|
self.users.insert(user.username.clone(), user); |
|
|
|
} |
|
|
|
} |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn write_redirects(&self) -> Result<(), Error> { |
|
|
|
fn write_redirects(&self) -> Result<(), Error> { |
|
|
|
let fuckery: String = self |
|
|
|
let mut fuckery: String = self |
|
|
|
.redirects |
|
|
|
.redirects |
|
|
|
.into_iter() |
|
|
|
.iter() |
|
|
|
.map(|(id, target)| format!("{}: {}\n", id, target)) |
|
|
|
.map(|meow| format!("{}: {}\n", meow.key(), meow.value())) |
|
|
|
.collect(); |
|
|
|
.collect(); |
|
|
|
std::fs::write(self.base_dir.join(*REDIRECTS_FILE), fuckery)?; |
|
|
|
std::fs::write(self.base_dir.join(REDIRECTS_FILE.as_str()), fuckery)?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn write_users(&self) -> Result<(), Error> { |
|
|
|
fn write_users(&self) -> Result<(), Error> { |
|
|
|
let fuckery = String::from("---"); |
|
|
|
let mut fuckery = String::from("---"); |
|
|
|
self.users.into_iter().map(|(_, user)| { |
|
|
|
self.users.iter().map(|item| { |
|
|
|
if user.is_admin { |
|
|
|
if item.value().is_admin { |
|
|
|
fuckery = format!("{}\n{}", user.to_string(), fuckery) |
|
|
|
fuckery = format!("{}\n{}", item.value().to_string(), fuckery) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
fuckery += format!("\n{}", user.to_string()).as_str() |
|
|
|
fuckery += format!("\n{}", item.value().to_string()).as_str() |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
std::fs::write(self.base_dir.join(*USERS_FILE), fuckery)?; |
|
|
|
std::fs::write(self.base_dir.join(USERS_FILE.as_str()), fuckery)?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn write_text(&self, id: String) -> Result<(), Error> { |
|
|
|
fn write_text(&self, id: String) -> Result<(), Error> { |
|
|
|
let text_paste = self.text.get(&id).ok_or(Error::ShitMissing(id))?; |
|
|
|
let text_paste = self.text.get(&id).ok_or(Error::ShitMissing(id.clone()))?; |
|
|
|
let fuckery = text_paste.meta.to_string(); |
|
|
|
let mut fuckery = text_paste.meta.to_string(); |
|
|
|
fuckery += text_paste.text.as_str(); |
|
|
|
fuckery += text_paste.text.as_str(); |
|
|
|
|
|
|
|
|
|
|
|
std::fs::write(self.base_dir.join(*TEXT_DIR).join(id), fuckery)?; |
|
|
|
std::fs::write(self.base_dir.join(TEXT_DIR.as_str()).join(id), fuckery)?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn write_file_meta(&self, id: String) -> Result<(), Error> { |
|
|
|
fn write_file_meta(&self, id: String) -> Result<(), Error> { |
|
|
|
let file_meta = *self.files.get(&id).ok_or(Error::ShitMissing(id))?; |
|
|
|
let file_meta = self.files.get(&id).ok_or(Error::ShitMissing(id.clone()))?; |
|
|
|
|
|
|
|
|
|
|
|
std::fs::write( |
|
|
|
std::fs::write( |
|
|
|
self.base_dir.join(*FILE_DIR).join(id), |
|
|
|
self.base_dir.join(FILE_DIR.as_str()).join(id), |
|
|
|
file_meta.to_string(), |
|
|
|
file_meta.to_string(), |
|
|
|
)?; |
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|