From 346095d20e3d817d150cbea49e87a49fbcaa2304 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Fri, 7 Feb 2025 14:08:20 +0100 Subject: nodeid guard --- common/src/impl.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++- common/src/lib.rs | 6 +++++ 2 files changed, 79 insertions(+), 1 deletion(-) (limited to 'common/src') diff --git a/common/src/impl.rs b/common/src/impl.rs index 3814b1d..db702d3 100644 --- a/common/src/impl.rs +++ b/common/src/impl.rs @@ -4,8 +4,10 @@ Copyright (C) 2025 metamuffin */ use crate::{ - Node, NodeID, ObjectIds, PeopleGroup, SourceTrack, SourceTrackKind, TmdbKind, TraktKind, + Node, NodeID, NodeIDOrSlug, ObjectIds, PeopleGroup, SourceTrack, SourceTrackKind, TmdbKind, + TraktKind, }; +use hex::FromHexError; use std::{fmt::Display, str::FromStr}; impl SourceTrackKind { @@ -170,3 +172,73 @@ impl NodeID { pub const MIN: NodeID = NodeID([0; 32]); pub const MAX: NodeID = NodeID([255; 32]); } + +#[cfg(feature = "rocket")] +impl<'a> rocket::request::FromParam<'a> for NodeID { + type Error = FromHexError; + fn from_param(param: &'a str) -> Result { + if let Some(id) = param.strip_prefix("+") { + let mut k = [0; 32]; + hex::decode_to_slice(id, &mut k)?; + Ok(NodeID(k)) + } else { + Ok(NodeID::from_slug(¶m)) + } + } +} +#[cfg(feature = "rocket")] +impl rocket::http::uri::fmt::FromUriParam for NodeID { + type Target = NodeID; + fn from_uri_param(param: NodeID) -> Self::Target { + param + } +} +#[cfg(feature = "rocket")] +impl<'a> rocket::http::uri::fmt::FromUriParam for NodeID { + type Target = &'a str; + fn from_uri_param(param: &'a String) -> Self::Target { + param.as_str() + } +} +#[cfg(feature = "rocket")] +impl<'a> rocket::http::uri::fmt::FromUriParam for NodeID { + type Target = &'a str; + fn from_uri_param(param: &'a str) -> Self::Target { + param + } +} +#[cfg(feature = "rocket")] +impl rocket::http::uri::fmt::UriDisplay for NodeID { + fn fmt( + &self, + f: &mut rocket::http::uri::fmt::Formatter<'_, rocket::http::uri::fmt::Path>, + ) -> std::fmt::Result { + f.write_value(format!("+{}", hex::encode(self.0)))?; + Ok(()) + } +} +impl Display for NodeID { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("+")?; + f.write_str(&hex::encode(self.0))?; + Ok(()) + } +} +impl Display for NodeIDOrSlug { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + NodeIDOrSlug::ID(x) => x.fmt(f), + NodeIDOrSlug::Slug(x) => x.fmt(f), + } + } +} +impl From for NodeIDOrSlug { + fn from(value: NodeID) -> Self { + Self::ID(value) + } +} +impl From for NodeIDOrSlug { + fn from(value: String) -> Self { + Self::Slug(value) + } +} diff --git a/common/src/lib.rs b/common/src/lib.rs index 74476fe..43adfba 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -3,6 +3,7 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2025 metamuffin */ +#![feature(array_try_map)] pub mod api; pub mod config; pub mod helpers; @@ -26,6 +27,11 @@ use std::{ )] pub struct NodeID(pub [u8; 32]); +pub enum NodeIDOrSlug { + ID(NodeID), + Slug(String), +} + #[derive(Debug, Clone, Deserialize, Serialize, Default, Encode, Decode)] pub struct Node { #[serde(default)] -- cgit v1.2.3-70-g09d2