v_authorization_impl/
common.rs

1use v_authorization::common::Trace;
2use std::time::SystemTime;
3use crate::stat_manager::{Stat, StatMode};
4
5// Trait for types that have authorization and tracing capabilities
6pub(crate) trait AuthorizationHelper {
7    fn get_stat_mut(&mut self) -> &mut Option<Stat>;
8    fn get_authorize_counter(&self) -> u64;
9    fn get_max_authorize_counter(&self) -> u64;
10    fn set_authorize_counter(&mut self, value: u64);
11    
12    // Implementation-specific method to perform actual authorization using database
13    fn authorize_use_db(
14        &mut self,
15        uri: &str,
16        user_uri: &str,
17        request_access: u8,
18        is_check_for_reload: bool,
19        trace: &mut Trace,
20    ) -> Result<u8, std::io::Error>;
21    
22    // Default implementation that handles counter logic and retry
23    fn authorize_and_trace_impl(
24        &mut self,
25        uri: &str,
26        user_uri: &str,
27        request_access: u8,
28        is_check_for_reload: bool,
29        trace: &mut Trace,
30    ) -> Result<u8, std::io::Error> {
31        let counter = self.get_authorize_counter() + 1;
32        self.set_authorize_counter(counter);
33        
34        if counter >= self.get_max_authorize_counter() {
35            self.set_authorize_counter(0);
36        }
37
38        match self.authorize_use_db(uri, user_uri, request_access, is_check_for_reload, trace) {
39            Ok(r) => {
40                return Ok(r);
41            },
42            Err(_e) => {
43                // Retry authorization on db error
44                info!("retrying authorization after error");
45            },
46        }
47        // retry authorization if db err
48        self.authorize_use_db(uri, user_uri, request_access, is_check_for_reload, trace)
49    }
50}
51
52// Generic implementation of authorize method that can be used by both LMDB and MDBX contexts
53pub(crate) fn authorize_with_stat<T: AuthorizationHelper>(
54    ctx: &mut T,
55    uri: &str,
56    user_uri: &str,
57    request_access: u8,
58    is_check_for_reload: bool,
59) -> Result<u8, std::io::Error> {
60    let mut t = Trace {
61        acl: &mut String::new(),
62        is_acl: false,
63        group: &mut String::new(),
64        is_group: false,
65        info: &mut String::new(),
66        is_info: false,
67        str_num: 0,
68    };
69
70    let start_time = SystemTime::now();
71
72    let r = ctx.authorize_and_trace_impl(uri, user_uri, request_access, is_check_for_reload, &mut t);
73
74    if let Some(stat) = ctx.get_stat_mut() {
75        if stat.mode == StatMode::Full || stat.mode == StatMode::Minimal {
76            let elapsed = start_time.elapsed().unwrap_or_default();
77            stat.point.set_duration(elapsed);
78            if let Err(e) = stat.point.flush() {
79                warn!("fail flush stat, err={:?}", e);
80            }
81        }
82    }
83
84    r
85}
86
87// Macro to implement AuthorizationContext trait for types that implement AuthorizationHelper
88#[macro_export]
89macro_rules! impl_authorization_context {
90    ($type:ty) => {
91        impl v_authorization::common::AuthorizationContext for $type {
92            fn authorize(
93                &mut self,
94                uri: &str,
95                user_uri: &str,
96                request_access: u8,
97                is_check_for_reload: bool,
98            ) -> Result<u8, std::io::Error> {
99                $crate::common::authorize_with_stat(self, uri, user_uri, request_access, is_check_for_reload)
100            }
101
102            fn authorize_and_trace(
103                &mut self,
104                uri: &str,
105                user_uri: &str,
106                request_access: u8,
107                is_check_for_reload: bool,
108                trace: &mut v_authorization::common::Trace,
109            ) -> Result<u8, std::io::Error> {
110                self.authorize_and_trace_impl(uri, user_uri, request_access, is_check_for_reload, trace)
111            }
112        }
113    };
114}
115