From 0617663b249f9ca488e5de652108b17d67fbaf45 Mon Sep 17 00:00:00 2001 From: Vika Date: Sat, 29 Jul 2023 21:59:56 +0300 Subject: Moved the entire Kittybox tree into the root --- util/src/lib.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 util/src/lib.rs (limited to 'util/src/lib.rs') diff --git a/util/src/lib.rs b/util/src/lib.rs new file mode 100644 index 0000000..c49bdf5 --- /dev/null +++ b/util/src/lib.rs @@ -0,0 +1,123 @@ +#![warn(missing_docs)] +//! Small things that couldn't fit elsewhere in Kittybox, yet may be +//! useful on their own or in multiple Kittybox crates. +//! +//! Some things are gated behind features, namely: +//! - `fs` - enables use of filesystem-related utilities +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Serialize, Deserialize)] +pub struct IndiewebEndpoints { + pub authorization_endpoint: String, + pub token_endpoint: String, + pub webmention: Option, + pub microsub: Option, +} + +/// Data structure representing a Micropub channel in the ?q=channels output. +#[derive(Serialize, Deserialize, PartialEq, Debug)] +#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] +pub struct MicropubChannel { + /// The channel's UID. It is usually also a publically accessible permalink URL. + pub uid: String, + /// The channel's user-friendly name used to recognize it in lists. + pub name: String, +} + +#[derive(Debug, Default)] +/// Common types of webmentions. +pub enum MentionType { + /// Corresponds to a `u-in-reply-to` link. + Reply, + /// Corresponds to a `u-like-of` link. + Like, + /// Corresponds to a `u-repost-of` link. + Repost, + /// Corresponds to a `u-bookmark-of` link. + Bookmark, + /// A plain link without MF2 annotations. + #[default] + Mention +} + +/// Common errors from the IndieWeb protocols that can be reused between modules. +pub mod error; +pub use error::{ErrorType, MicropubError}; + +/// Common data-types useful in creating smart authentication systems. +pub mod auth { + #[derive(PartialEq, Eq, Hash, Clone, Copy)] + pub enum EnrolledCredential { + /// An indicator that a password is enrolled. Passwords can be + /// used to recover from a lost token. + Password, + /// An indicator that one or more WebAuthn credentials were + /// enrolled. + WebAuthn + } +} + +/// A collection of traits for implementing a robust job queue. +pub mod queue; + +#[cfg(feature = "fs")] +/// Commonly-used operations with the file system in Kittybox's +/// underlying storage mechanisms. +pub mod fs { + use std::io::{self, Result}; + use std::path::{Path, PathBuf}; + use rand::{Rng, distributions::Alphanumeric}; + use tokio::fs; + + /// Create a temporary file named `temp.[a-zA-Z0-9]{length}` in + /// the given location and immediately open it. Returns the + /// filename and the corresponding file handle. It is the caller's + /// responsibility to clean up the temporary file when it is no + /// longer needed. + /// + /// Uses [`OpenOptions::create_new`][fs::OpenOptions::create_new] + /// to detect filename collisions, in which case it will + /// automatically retry until the operation succeeds. + /// + /// # Errors + /// + /// Returns the underlying [`io::Error`] if the operation fails + /// due to reasons other than filename collision. + pub async fn mktemp(dir: T, basename: B, length: usize) -> Result<(PathBuf, fs::File)> + where + T: AsRef, + B: Into> + { + let dir = dir.as_ref(); + let basename = basename.into().unwrap_or(""); + fs::create_dir_all(dir).await?; + + loop { + let filename = dir.join(format!( + "{}{}{}", + basename, + if basename.is_empty() { "" } else { "." }, + { + let string = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(length) + .collect::>(); + String::from_utf8(string).unwrap() + } + )); + + match fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(&filename) + .await + { + Ok(file) => return Ok((filename, file)), + Err(err) => match err.kind() { + io::ErrorKind::AlreadyExists => continue, + _ => return Err(err) + } + } + } + } +} -- cgit 1.4.1