use std::any::Any;
use std::fmt;
use cheetah_string::CheetahString;
use rocketmq_error::REDACTED;
use crate::authentication::context::base_authentication_context::BaseAuthenticationContext;
use crate::authentication::AsAny;
use crate::authorization::context::authentication_context::AuthenticationContext;
#[derive(Default)]
pub struct DefaultAuthenticationContext {
pub base: BaseAuthenticationContext,
username: Option<CheetahString>,
content: Option<Vec<u8>>,
signature: Option<CheetahString>,
request_timestamp: Option<CheetahString>,
request_timestamp_millis: Option<i64>,
verified_transport_identity: Option<Vec<u8>>,
}
impl fmt::Debug for DefaultAuthenticationContext {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("DefaultAuthenticationContext")
.field("username", &self.username)
.field("content_len", &self.content.as_ref().map(Vec::len))
.field("signature", &self.signature.as_ref().map(|_| REDACTED))
.field("request_timestamp", &self.request_timestamp)
.field("request_timestamp_millis", &self.request_timestamp_millis)
.field(
"verified_transport_identity_len",
&self.verified_transport_identity.as_ref().map(Vec::len),
)
.finish_non_exhaustive()
}
}
impl DefaultAuthenticationContext {
pub fn new() -> Self {
Self::default()
}
pub fn username(&self) -> Option<&CheetahString> {
self.username.as_ref()
}
pub fn set_username(&mut self, username: CheetahString) {
self.username = Some(username);
}
pub fn content(&self) -> Option<&[u8]> {
self.content.as_deref()
}
pub fn set_content(&mut self, content: Vec<u8>) {
self.content = Some(content);
}
pub fn signature(&self) -> Option<&CheetahString> {
self.signature.as_ref()
}
pub fn set_signature(&mut self, signature: CheetahString) {
self.signature = Some(signature);
}
pub fn request_timestamp(&self) -> Option<&CheetahString> {
self.request_timestamp.as_ref()
}
pub fn set_request_timestamp(&mut self, request_timestamp: CheetahString) {
self.request_timestamp = Some(request_timestamp);
}
pub fn request_timestamp_millis(&self) -> Option<i64> {
self.request_timestamp_millis
}
pub fn set_request_timestamp_millis(&mut self, request_timestamp_millis: i64) {
self.request_timestamp_millis = Some(request_timestamp_millis);
}
pub fn verified_transport_identity(&self) -> Option<&[u8]> {
self.verified_transport_identity.as_deref()
}
pub fn set_verified_transport_identity(&mut self, identity: Vec<u8>) {
self.verified_transport_identity = Some(identity);
}
}
impl AsAny for DefaultAuthenticationContext {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl AuthenticationContext for DefaultAuthenticationContext {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_authentication_context_default_and_new() {
let context = DefaultAuthenticationContext::default();
assert!(context.username().is_none());
assert!(context.content().is_none());
assert!(context.signature().is_none());
assert!(context.request_timestamp().is_none());
assert!(context.request_timestamp_millis().is_none());
assert!(context.verified_transport_identity().is_none());
let context = DefaultAuthenticationContext::new();
assert!(context.username().is_none());
assert!(context.content().is_none());
assert!(context.signature().is_none());
assert!(context.request_timestamp().is_none());
assert!(context.request_timestamp_millis().is_none());
assert!(context.verified_transport_identity().is_none());
}
#[test]
fn test_default_authentication_context_setters_and_getters() {
let mut context = DefaultAuthenticationContext::new();
let username = CheetahString::from("test_user");
let content = vec![1, 2, 3];
let signature = CheetahString::from("test_signature");
let request_timestamp = CheetahString::from("20231227T194619Z");
context.set_username(username.clone());
context.set_content(content.clone());
context.set_signature(signature.clone());
context.set_request_timestamp(request_timestamp.clone());
context.set_request_timestamp_millis(1_703_706_379_000);
context.set_verified_transport_identity(vec![7, 8, 9]);
assert_eq!(context.username(), Some(&username));
assert_eq!(context.content(), Some(content.as_slice()));
assert_eq!(context.signature(), Some(&signature));
assert_eq!(context.request_timestamp(), Some(&request_timestamp));
assert_eq!(context.request_timestamp_millis(), Some(1_703_706_379_000));
assert_eq!(context.verified_transport_identity(), Some([7, 8, 9].as_slice()));
}
#[test]
fn test_default_authentication_context_as_any() {
let context = DefaultAuthenticationContext::new();
let any = context.as_any();
assert!(any.is::<DefaultAuthenticationContext>());
let mut context_mut = DefaultAuthenticationContext::new();
let any_mut = context_mut.as_any_mut();
assert!(any_mut.is::<DefaultAuthenticationContext>());
}
#[test]
fn default_authentication_context_debug_redacts_signature() {
let mut context = DefaultAuthenticationContext::new();
context.set_username(CheetahString::from("alice"));
context.set_content(vec![1, 2, 3, 4]);
context.set_signature(CheetahString::from("signature-secret"));
let debug = format!("{context:?}");
assert!(debug.contains("alice"));
assert!(debug.contains("content_len"));
assert!(debug.contains(REDACTED));
assert!(!debug.contains("signature-secret"));
}
}