use crate::database::*; use crate::util::result::{Error, Result}; use mongodb::bson::{doc, from_document}; use rocket::http::RawStr; use rocket::request::FromParam; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use validator::Validate; #[derive(Validate, Serialize, Deserialize)] pub struct Ref { #[validate(length(min = 1, max = 26))] pub id: String, } impl Ref { pub fn from_unchecked(id: String) -> Ref { Ref { id } } pub fn from(id: String) -> Result { let r = Ref { id }; r.validate() .map_err(|error| Error::FailedValidation { error })?; Ok(r) } pub async fn fetch(&self, collection: &'static str) -> Result { let doc = get_collection(&collection) .find_one( doc! { "_id": &self.id }, None, ) .await .map_err(|_| Error::DatabaseError { operation: "find_one", with: &collection, })? .ok_or_else(|| Error::UnknownUser)?; Ok(from_document::(doc).map_err(|_| Error::DatabaseError { operation: "from_document", with: &collection, })?) } pub async fn fetch_user(&self) -> Result { self.fetch("users").await } pub async fn fetch_channel(&self) -> Result { self.fetch("channels").await } pub async fn fetch_server(&self) -> Result { self.fetch("servers").await } pub async fn fetch_invite(&self) -> Result { self.fetch("invites").await } pub async fn fetch_message(&self, channel: &Channel) -> Result { let message: Message = self.fetch("messages").await?; if &message.channel != channel.id() { Err(Error::InvalidOperation) } else { Ok(message) } } } impl User { pub fn as_ref(&self) -> Ref { Ref { id: self.id.to_string(), } } } impl<'r> FromParam<'r> for Ref { type Error = &'r RawStr; fn from_param(param: &'r RawStr) -> Result { if let Ok(result) = Ref::from(param.to_string()) { if result.validate().is_ok() { return Ok(result); } } Err(param) } }