feat: hashids
This commit is contained in:
parent
e258bcc2bd
commit
b5da40fbdc
10 changed files with 2165 additions and 16 deletions
|
@ -68,6 +68,9 @@ pub struct Args {
|
|||
|
||||
#[clap(short, long, env = "MICROBIN_NO_FILE_UPLOAD")]
|
||||
pub no_file_upload: bool,
|
||||
|
||||
#[clap(long, env = "MICROBIN_HASH_IDS")]
|
||||
pub hash_ids: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::dbio::save_to_file;
|
||||
use crate::pasta::PastaFile;
|
||||
use crate::util::animalnumbers::to_animal_names;
|
||||
use crate::util::hashids::to_hashids;
|
||||
use crate::util::misc::is_valid_url;
|
||||
use crate::{AppState, Pasta, ARGS};
|
||||
use actix_multipart::Multipart;
|
||||
|
@ -126,8 +127,11 @@ pub async fn create(
|
|||
}
|
||||
};
|
||||
|
||||
std::fs::create_dir_all(format!("./pasta_data/public/{}", &new_pasta.id_as_animals()))
|
||||
.unwrap();
|
||||
std::fs::create_dir_all(format!(
|
||||
"./pasta_data/public/{}",
|
||||
&new_pasta.id_as_animals()
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let filepath = format!(
|
||||
"./pasta_data/public/{}/{}",
|
||||
|
@ -157,7 +161,12 @@ pub async fn create(
|
|||
|
||||
save_to_file(&pastas);
|
||||
|
||||
let slug = if ARGS.hash_ids {
|
||||
to_hashids(id)
|
||||
} else {
|
||||
to_animal_names(id)
|
||||
};
|
||||
Ok(HttpResponse::Found()
|
||||
.append_header(("Location", format!("{}/pasta/{}", ARGS.public_path, to_animal_names(id))))
|
||||
.append_header(("Location", format!("{}/pasta/{}", ARGS.public_path, slug)))
|
||||
.finish())
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::args::Args;
|
|||
use crate::dbio::save_to_file;
|
||||
use crate::endpoints::errors::ErrorTemplate;
|
||||
use crate::util::animalnumbers::to_u64;
|
||||
use crate::util::hashids::to_u64 as hashid_to_u64;
|
||||
use crate::util::misc::remove_expired;
|
||||
use crate::{AppState, Pasta, ARGS};
|
||||
use actix_multipart::Multipart;
|
||||
|
@ -20,7 +21,11 @@ struct EditTemplate<'a> {
|
|||
pub async fn get_edit(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse {
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
|
||||
let id = to_u64(&*id.into_inner()).unwrap_or(0);
|
||||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&*id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&*id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
||||
|
@ -59,7 +64,11 @@ pub async fn post_edit(
|
|||
.finish());
|
||||
}
|
||||
|
||||
let id = to_u64(&*id.into_inner()).unwrap_or(0);
|
||||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&*id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&*id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
|
||||
|
@ -85,7 +94,10 @@ pub async fn post_edit(
|
|||
save_to_file(&pastas);
|
||||
|
||||
return Ok(HttpResponse::Found()
|
||||
.append_header(("Location", format!("{}/pasta/{}", ARGS.public_path, pastas[i].id_as_animals())))
|
||||
.append_header((
|
||||
"Location",
|
||||
format!("{}/pasta/{}", ARGS.public_path, pastas[i].id_as_animals()),
|
||||
))
|
||||
.finish());
|
||||
} else {
|
||||
break;
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::args::{Args, ARGS};
|
|||
use crate::endpoints::errors::ErrorTemplate;
|
||||
use crate::pasta::Pasta;
|
||||
use crate::util::animalnumbers::to_u64;
|
||||
use crate::util::hashids::to_u64 as hashid_to_u64;
|
||||
use crate::util::misc::remove_expired;
|
||||
use crate::AppState;
|
||||
|
||||
|
@ -19,7 +20,13 @@ struct PastaTemplate<'a> {
|
|||
pub async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse {
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
|
||||
let id = to_u64(&*id.into_inner()).unwrap_or(0);
|
||||
println!("{}", id);
|
||||
|
||||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&*id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&*id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
println!("{}", id);
|
||||
|
||||
|
@ -47,7 +54,11 @@ pub async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
|
|||
pub async fn redirecturl(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse {
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
|
||||
let id = to_u64(&*id.into_inner()).unwrap_or(0);
|
||||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&*id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&*id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
||||
|
@ -74,7 +85,11 @@ pub async fn redirecturl(data: web::Data<AppState>, id: web::Path<String>) -> Ht
|
|||
pub async fn getrawpasta(data: web::Data<AppState>, id: web::Path<String>) -> String {
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
|
||||
let id = to_u64(&*id.into_inner()).unwrap_or(0);
|
||||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&*id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&*id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
remove_expired(&mut pastas);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::args::ARGS;
|
|||
use crate::endpoints::errors::ErrorTemplate;
|
||||
use crate::pasta::PastaFile;
|
||||
use crate::util::animalnumbers::to_u64;
|
||||
use crate::util::hashids::to_u64 as hashid_to_u64;
|
||||
use crate::util::misc::remove_expired;
|
||||
use crate::AppState;
|
||||
use askama::Template;
|
||||
|
@ -19,20 +20,30 @@ pub async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpRes
|
|||
|
||||
let mut pastas = data.pastas.lock().unwrap();
|
||||
|
||||
let id = to_u64(&*id.into_inner()).unwrap_or(0);
|
||||
let id = if ARGS.hash_ids {
|
||||
hashid_to_u64(&*id).unwrap_or(0)
|
||||
} else {
|
||||
to_u64(&*id.into_inner()).unwrap_or(0)
|
||||
};
|
||||
|
||||
for (i, pasta) in pastas.iter().enumerate() {
|
||||
if pasta.id == id {
|
||||
// remove the file itself
|
||||
if let Some(PastaFile { name, .. }) = &pasta.file {
|
||||
if fs::remove_file(format!("./pasta_data/public/{}/{}", pasta.id_as_animals(), name))
|
||||
.is_err()
|
||||
if fs::remove_file(format!(
|
||||
"./pasta_data/public/{}/{}",
|
||||
pasta.id_as_animals(),
|
||||
name
|
||||
))
|
||||
.is_err()
|
||||
{
|
||||
log::error!("Failed to delete file {}!", name)
|
||||
}
|
||||
|
||||
// and remove the containing directory
|
||||
if fs::remove_dir(format!("./pasta_data/public/{}/", pasta.id_as_animals())).is_err() {
|
||||
if fs::remove_dir(format!("./pasta_data/public/{}/", pasta.id_as_animals()))
|
||||
.is_err()
|
||||
{
|
||||
log::error!("Failed to delete directory {}!", name)
|
||||
}
|
||||
}
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -23,6 +23,7 @@ pub mod util {
|
|||
pub mod animalnumbers;
|
||||
pub mod auth;
|
||||
pub mod dbio;
|
||||
pub mod hashids;
|
||||
pub mod misc;
|
||||
pub mod syntaxhighlighter;
|
||||
}
|
||||
|
@ -66,8 +67,14 @@ async fn main() -> std::io::Result<()> {
|
|||
match fs::create_dir_all("./pasta_data/public") {
|
||||
Ok(dir) => dir,
|
||||
Err(error) => {
|
||||
log::error!("Couldn't create data directory ./pasta_data/public/: {:?}", error);
|
||||
panic!("Couldn't create data directory ./pasta_data/public/: {:?}", error);
|
||||
log::error!(
|
||||
"Couldn't create data directory ./pasta_data/public/: {:?}",
|
||||
error
|
||||
);
|
||||
panic!(
|
||||
"Couldn't create data directory ./pasta_data/public/: {:?}",
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::args::ARGS;
|
||||
use crate::util::animalnumbers::to_animal_names;
|
||||
use crate::util::hashids::to_hashids;
|
||||
use crate::util::syntaxhighlighter::html_highlight;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||||
|
@ -44,7 +46,11 @@ pub struct Pasta {
|
|||
|
||||
impl Pasta {
|
||||
pub fn id_as_animals(&self) -> String {
|
||||
to_animal_names(self.id)
|
||||
if ARGS.hash_ids {
|
||||
to_hashids(self.id)
|
||||
} else {
|
||||
to_animal_names(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn created_as_string(&self) -> String {
|
||||
|
|
18
src/util/hashids.rs
Normal file
18
src/util/hashids.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use harsh::Harsh;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref HARSH: Harsh = Harsh::builder().length(6).build().unwrap();
|
||||
}
|
||||
|
||||
pub fn to_hashids(number: u64) -> String {
|
||||
HARSH.encode(&[number])
|
||||
}
|
||||
|
||||
pub fn to_u64(hash_id: &str) -> Result<u64, &str> {
|
||||
let ids = HARSH
|
||||
.decode(hash_id)
|
||||
.map_err(|_e| "Failed to decode hash ID")?;
|
||||
let id = ids.get(0).ok_or("No ID found in hash ID")?;
|
||||
Ok(*id)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue