diff --git a/crates/lox-distributor/src/request_handler.rs b/crates/lox-distributor/src/request_handler.rs index 53dd0a2..b81c5b6 100644 --- a/crates/lox-distributor/src/request_handler.rs +++ b/crates/lox-distributor/src/request_handler.rs @@ -374,6 +374,7 @@ mod tests { // Test Open Invite and get response let invite_response_str = body_to_string(invite_response).await; + println!("Base64 invite {:?}", invite_response_str); let response_data: lox_utils::Invite = serde_json::from_str(&invite_response_str).unwrap(); let token = match lox_utils::validate(&response_data.invite) { Ok(token) => token, diff --git a/crates/lox-utils/src/lib.rs b/crates/lox-utils/src/lib.rs index c413aca..0a137fe 100644 --- a/crates/lox-utils/src/lib.rs +++ b/crates/lox-utils/src/lib.rs @@ -12,13 +12,47 @@ use serde_with::serde_as; use std::array::TryFromSliceError; use std::collections::HashMap; -#[serde_as] +const LOX_INVITE_TOKEN: &str = "loxinvite_"; + #[derive(Serialize, Deserialize)] pub struct Invite { - #[serde_as(as = "[_; OPENINV_LENGTH]")] + #[serde(with = "base64serde")] pub invite: [u8; OPENINV_LENGTH], } +mod base64serde { + use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _}; + use lox_library::OPENINV_LENGTH; + use serde::{Deserialize, Serialize}; + use serde::{Deserializer, Serializer}; + + use crate::LOX_INVITE_TOKEN; + + pub fn serialize(v: &[u8; OPENINV_LENGTH], s: S) -> Result { + let mut base64 = STANDARD_NO_PAD.encode(v); + base64.insert_str(0, LOX_INVITE_TOKEN); + String::serialize(&base64, s) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<[u8; OPENINV_LENGTH], D::Error> { + let mut base64 = String::deserialize(d)?; + let encoded_str = base64.split_off(LOX_INVITE_TOKEN.len()); + if base64 != LOX_INVITE_TOKEN { + return Err(serde::de::Error::custom("Token identifier does not match")) + } + match STANDARD_NO_PAD.decode(encoded_str) { + Ok(output) => { + let out: Result<[u8; OPENINV_LENGTH], D::Error> = match output.try_into() { + Ok(out) => Ok(out), + Err(e) => Err(serde::de::Error::custom(String::from_utf8(e).unwrap())), + }; + out + } + Err(e) => Err(serde::de::Error::custom(e)), + } + } +} + #[derive(Deserialize, Serialize)] pub struct OpenReqState { pub request: proto::open_invite::Request,