Skip to main content

securitydept_session_context/config/
validator.rs

1use securitydept_utils::redirect::RedirectTargetConfig;
2
3use super::SessionContextConfigSource;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct SessionContextConfigValidationError {
7    pub field_path: String,
8    pub code: String,
9    pub message: String,
10}
11
12impl SessionContextConfigValidationError {
13    pub fn new(
14        field_path: impl Into<String>,
15        code: impl Into<String>,
16        message: impl Into<String>,
17    ) -> Self {
18        Self {
19            field_path: field_path.into(),
20            code: code.into(),
21            message: message.into(),
22        }
23    }
24}
25
26impl std::fmt::Display for SessionContextConfigValidationError {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        write!(
29            f,
30            "session_context config validation failed for {} ({}): {}",
31            self.field_path, self.code, self.message
32        )
33    }
34}
35
36impl std::error::Error for SessionContextConfigValidationError {}
37
38pub trait SessionContextConfigValidator {
39    fn validate_session_context_config<S>(
40        &self,
41        config: &S,
42    ) -> Result<(), SessionContextConfigValidationError>
43    where
44        S: SessionContextConfigSource + ?Sized;
45}
46
47#[derive(Debug, Clone, Copy, Default)]
48pub struct NoopSessionContextConfigValidator;
49
50impl SessionContextConfigValidator for NoopSessionContextConfigValidator {
51    fn validate_session_context_config<S>(
52        &self,
53        _config: &S,
54    ) -> Result<(), SessionContextConfigValidationError>
55    where
56        S: SessionContextConfigSource + ?Sized,
57    {
58        Ok(())
59    }
60}
61
62impl<V> SessionContextConfigValidator for &V
63where
64    V: SessionContextConfigValidator + ?Sized,
65{
66    fn validate_session_context_config<S>(
67        &self,
68        config: &S,
69    ) -> Result<(), SessionContextConfigValidationError>
70    where
71        S: SessionContextConfigSource + ?Sized,
72    {
73        (*self).validate_session_context_config(config)
74    }
75}
76
77impl<V> SessionContextConfigValidator for [V]
78where
79    V: SessionContextConfigValidator,
80{
81    fn validate_session_context_config<S>(
82        &self,
83        config: &S,
84    ) -> Result<(), SessionContextConfigValidationError>
85    where
86        S: SessionContextConfigSource + ?Sized,
87    {
88        for validator in self {
89            validator.validate_session_context_config(config)?;
90        }
91
92        Ok(())
93    }
94}
95
96impl<V, const N: usize> SessionContextConfigValidator for [V; N]
97where
98    V: SessionContextConfigValidator,
99{
100    fn validate_session_context_config<S>(
101        &self,
102        config: &S,
103    ) -> Result<(), SessionContextConfigValidationError>
104    where
105        S: SessionContextConfigSource + ?Sized,
106    {
107        self.as_slice().validate_session_context_config(config)
108    }
109}
110
111impl<V> SessionContextConfigValidator for Vec<V>
112where
113    V: SessionContextConfigValidator,
114{
115    fn validate_session_context_config<S>(
116        &self,
117        config: &S,
118    ) -> Result<(), SessionContextConfigValidationError>
119    where
120        S: SessionContextConfigSource + ?Sized,
121    {
122        self.as_slice().validate_session_context_config(config)
123    }
124}
125
126impl<A, B> SessionContextConfigValidator for (A, B)
127where
128    A: SessionContextConfigValidator,
129    B: SessionContextConfigValidator,
130{
131    fn validate_session_context_config<S>(
132        &self,
133        config: &S,
134    ) -> Result<(), SessionContextConfigValidationError>
135    where
136        S: SessionContextConfigSource + ?Sized,
137    {
138        self.0.validate_session_context_config(config)?;
139        self.1.validate_session_context_config(config)
140    }
141}
142
143impl<A, B, C> SessionContextConfigValidator for (A, B, C)
144where
145    A: SessionContextConfigValidator,
146    B: SessionContextConfigValidator,
147    C: SessionContextConfigValidator,
148{
149    fn validate_session_context_config<S>(
150        &self,
151        config: &S,
152    ) -> Result<(), SessionContextConfigValidationError>
153    where
154        S: SessionContextConfigSource + ?Sized,
155    {
156        self.0.validate_session_context_config(config)?;
157        self.1.validate_session_context_config(config)?;
158        self.2.validate_session_context_config(config)
159    }
160}
161
162#[derive(Debug, Clone, PartialEq, Eq)]
163pub struct SessionContextFixedPostAuthRedirectValidator {
164    post_auth_redirect: RedirectTargetConfig,
165}
166
167impl SessionContextFixedPostAuthRedirectValidator {
168    pub fn new(post_auth_redirect: RedirectTargetConfig) -> Self {
169        Self { post_auth_redirect }
170    }
171}
172
173impl SessionContextConfigValidator for SessionContextFixedPostAuthRedirectValidator {
174    fn validate_session_context_config<S>(
175        &self,
176        config: &S,
177    ) -> Result<(), SessionContextConfigValidationError>
178    where
179        S: SessionContextConfigSource + ?Sized,
180    {
181        if config.post_auth_redirect_config() != &self.post_auth_redirect {
182            return Err(SessionContextConfigValidationError::new(
183                "post_auth_redirect",
184                "fixed_post_auth_redirect_conflict",
185                "session post_auth_redirect is fixed by the host and cannot be overridden",
186            ));
187        }
188
189        Ok(())
190    }
191}