|
|
|
@ -5,20 +5,26 @@ use hard_format::formats::{
|
|
|
|
|
PEMFormattedString,
|
|
|
|
|
PEMFormattedStr,
|
|
|
|
|
MaxLenString,
|
|
|
|
|
self,
|
|
|
|
|
};
|
|
|
|
|
use tripcode::Tripcode;
|
|
|
|
|
|
|
|
|
|
id_type!(PostID; "A unique post ID");
|
|
|
|
|
|
|
|
|
|
/// Max length of `email` or `name` feild
|
|
|
|
|
const ID_MAX_LEN: usize = defaults::POST_ID_MAX_LEN;
|
|
|
|
|
|
|
|
|
|
/// String type that limits its bytes to the ID string max limit.
|
|
|
|
|
pub type IDMaxString = MaxLenString<ID_MAX_LEN>;
|
|
|
|
|
pub type IDMaxString = MaxLenString<{defaults::POST_ID_MAX_LEN}>;
|
|
|
|
|
|
|
|
|
|
/// The timestamp type used in posts
|
|
|
|
|
pub type PostTimestamp = chrono::DateTime<defaults::Timezone>;
|
|
|
|
|
|
|
|
|
|
/// A size limited PEM formatting specifier
|
|
|
|
|
type PostBodyFormat = formats::BothFormat<formats::MaxLenFormat<{defaults::POST_BODY_MAX_SIZE}>, formats::PEMFormat>;
|
|
|
|
|
|
|
|
|
|
/// A size limited PEM string
|
|
|
|
|
pub type PostBodyString = hard_format::FormattedString<PostBodyFormat>;
|
|
|
|
|
/// A size limited PEM string
|
|
|
|
|
pub type PostBodyStr = hard_format::FormattedStr<PostBodyFormat>;
|
|
|
|
|
|
|
|
|
|
/// A single completed post
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
|
|
|
pub struct Post
|
|
|
|
@ -31,7 +37,8 @@ pub struct Post
|
|
|
|
|
email: Option<IDMaxString>,
|
|
|
|
|
|
|
|
|
|
/// The client-side encrypted body string
|
|
|
|
|
body: PEMFormattedString,
|
|
|
|
|
body: PostBodyString,
|
|
|
|
|
|
|
|
|
|
/// Signature of the body (optional).
|
|
|
|
|
signature: Option<PEMFormattedString>,
|
|
|
|
|
|
|
|
|
@ -55,16 +62,16 @@ impl Post
|
|
|
|
|
/// Time since this post was created as a Chrono `Duration`.
|
|
|
|
|
pub fn time_since_creation(&self) -> chrono::Duration
|
|
|
|
|
{
|
|
|
|
|
defaults::Timezone::now() - self.created
|
|
|
|
|
defaults::Timezone::now() - self.created
|
|
|
|
|
}
|
|
|
|
|
/// Has this post expired?
|
|
|
|
|
///
|
|
|
|
|
/// Expired posts should be removed
|
|
|
|
|
pub fn expired(&self) -> bool
|
|
|
|
|
{
|
|
|
|
|
if let Ok(dur) = self.time_since_creation().to_std()
|
|
|
|
|
if let Ok(dur) = &self.time_since_creation().to_std()
|
|
|
|
|
{
|
|
|
|
|
dur >= *self.expires_in.as_ref().unwrap_or(&defaults::POST_EXPIRE)
|
|
|
|
|
dur >= self.expires_in.as_ref().unwrap_or(&defaults::POST_EXPIRE)
|
|
|
|
|
} else {
|
|
|
|
|
// Conversion failed. Expire the post
|
|
|
|
|
true
|
|
|
|
@ -96,10 +103,15 @@ impl Post
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The body of this post
|
|
|
|
|
pub fn body(&self) -> &PEMFormattedStr
|
|
|
|
|
pub fn body(&self) -> &PostBodyStr
|
|
|
|
|
{
|
|
|
|
|
self.body.as_ref()
|
|
|
|
|
}
|
|
|
|
|
/// The PEM formatted signature of this post, if there is one.
|
|
|
|
|
pub fn signature(&self) -> Option<&PEMFormattedStr>
|
|
|
|
|
{
|
|
|
|
|
self.signature.as_ref().map(|x| x.as_ref())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
@ -114,7 +126,7 @@ mod tests
|
|
|
|
|
name: Some("Some name".to_owned().try_into().unwrap()),
|
|
|
|
|
email: None,
|
|
|
|
|
tripcode: Some(super::Tripcode::generate("uhh hello").unwrap()),
|
|
|
|
|
body: unsafe { super::PEMFormattedStr::new_unchecked("test").to_owned() }, //temporary
|
|
|
|
|
body: unsafe { super::PostBodyStr::new_unchecked("test").to_owned() }, //temporary
|
|
|
|
|
signature: None,
|
|
|
|
|
hash: Default::default(),
|
|
|
|
|
|
|
|
|
@ -127,5 +139,5 @@ mod tests
|
|
|
|
|
let post2: super::Post = serde_json::from_slice(&post_json[..]).expect("Deserialise");
|
|
|
|
|
assert_eq!(post, post2);
|
|
|
|
|
println!("Post was: {:?}", post);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|