Skip to main content

rocketmq_auth/authentication/context/
base_authentication_context.rs

1// Copyright 2023 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::any::Any;
16use std::collections::HashMap;
17
18use cheetah_string::CheetahString;
19
20use crate::authentication::AsAny;
21use crate::authorization::context::authentication_context::AuthenticationContext;
22
23#[derive(Debug, Default)]
24pub struct BaseAuthenticationContext {
25    channel_id: Option<CheetahString>,
26
27    rpc_code: Option<CheetahString>,
28
29    ext_info: HashMap<CheetahString, Box<dyn Any + Send + Sync>>,
30}
31
32impl BaseAuthenticationContext {
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    pub fn channel_id(&self) -> Option<&CheetahString> {
38        self.channel_id.as_ref()
39    }
40
41    pub fn set_channel_id(&mut self, channel_id: Option<CheetahString>) {
42        self.channel_id = channel_id;
43    }
44
45    pub fn rpc_code(&self) -> Option<&CheetahString> {
46        self.rpc_code.as_ref()
47    }
48
49    pub fn set_rpc_code(&mut self, rpc_code: Option<CheetahString>) {
50        self.rpc_code = rpc_code;
51    }
52}
53
54impl BaseAuthenticationContext {
55    pub fn get_ext_info<T: 'static>(&self, key: &CheetahString) -> Option<&T> {
56        self.ext_info.get(key).and_then(|v| v.downcast_ref::<T>())
57    }
58    pub fn has_ext_info(&self, key: &CheetahString) -> bool {
59        self.ext_info.contains_key(key)
60    }
61    pub fn ext_info(&self) -> &HashMap<CheetahString, Box<dyn Any + Send + Sync>> {
62        &self.ext_info
63    }
64
65    pub fn ext_info_mut(&mut self) -> &mut HashMap<CheetahString, Box<dyn Any + Send + Sync>> {
66        &mut self.ext_info
67    }
68}
69
70impl BaseAuthenticationContext {
71    pub fn set_ext_info<T>(&mut self, key: CheetahString, value: T)
72    where
73        T: Any + Send + Sync,
74    {
75        self.ext_info.insert(key, Box::new(value));
76    }
77}
78
79impl AuthenticationContext for BaseAuthenticationContext {}
80
81impl AsAny for BaseAuthenticationContext {
82    fn as_any_mut(&mut self) -> &mut dyn Any {
83        self
84    }
85
86    fn as_any(&self) -> &dyn Any {
87        self
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use cheetah_string::CheetahString;
94
95    use crate::authentication::context::base_authentication_context::BaseAuthenticationContext;
96    use crate::authentication::AsAny;
97
98    #[test]
99    fn new_base_authentication_context() {
100        let base_authentication_context = BaseAuthenticationContext::new();
101
102        assert!(base_authentication_context.channel_id().is_none());
103        assert!(base_authentication_context.rpc_code().is_none());
104        assert!(base_authentication_context.ext_info().is_empty());
105    }
106
107    #[test]
108    fn set_and_get_channel_and_rpc() {
109        let mut base_authentication_context = BaseAuthenticationContext::new();
110        base_authentication_context.set_channel_id(Some(CheetahString::from("channel-123")));
111        base_authentication_context.set_rpc_code(Some(CheetahString::from("rpc-456")));
112
113        assert_eq!(
114            Some(&CheetahString::from("channel-123")),
115            base_authentication_context.channel_id()
116        );
117        assert_eq!(
118            Some(&CheetahString::from("rpc-456")),
119            base_authentication_context.rpc_code()
120        );
121    }
122
123    #[test]
124    fn set_get_and_has_ext_info() {
125        let mut base_authentication_context = BaseAuthenticationContext::new();
126        base_authentication_context.set_ext_info(CheetahString::from("info-1"), 123);
127
128        assert!(base_authentication_context.has_ext_info(&CheetahString::from("info-1")));
129        assert_eq!(
130            Some(123),
131            base_authentication_context
132                .get_ext_info::<i32>(&CheetahString::from("info-1"))
133                .copied()
134        );
135    }
136
137    #[test]
138    fn ext_info_nonexistent_key_returns_none() {
139        let base_authentication_context = BaseAuthenticationContext::new();
140
141        assert!(!base_authentication_context.has_ext_info(&CheetahString::from("nonexistent")));
142        assert_eq!(
143            None,
144            base_authentication_context.get_ext_info::<i32>(&CheetahString::from("nonexistent"))
145        );
146    }
147
148    #[test]
149    fn ext_info_wrong_type_returns_none() {
150        let mut base_authentication_context = BaseAuthenticationContext::new();
151        base_authentication_context.set_ext_info(CheetahString::from("info-2"), CheetahString::from("xyz"));
152
153        assert_eq!(
154            None,
155            base_authentication_context
156                .get_ext_info::<u32>(&CheetahString::from("info-2"))
157                .copied()
158        );
159    }
160
161    #[test]
162    fn ext_info_mut_can_modify() {
163        let mut base_authentication_context = BaseAuthenticationContext::new();
164        base_authentication_context
165            .ext_info_mut()
166            .insert(CheetahString::from("info-3"), Box::new(64u32));
167
168        assert_eq!(
169            Some(64u32),
170            base_authentication_context
171                .get_ext_info::<u32>(&CheetahString::from("info-3"))
172                .copied()
173        );
174    }
175
176    #[test]
177    fn as_any_downcasts_work() {
178        let mut base_authentication_context = BaseAuthenticationContext::new();
179
180        let any_ref = base_authentication_context.as_any();
181        assert!(any_ref.downcast_ref::<BaseAuthenticationContext>().is_some());
182
183        let any_mut_ref = base_authentication_context.as_any_mut();
184        assert!(any_mut_ref.downcast_mut::<BaseAuthenticationContext>().is_some());
185    }
186}