Skip to main content

uqa_sql/catalog/roles/
session.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Session authorization identities and independently restorable role settings.
8
9use super::{identity::RoleBinding, RoleDefinition};
10use std::sync::Arc;
11
12#[derive(Clone)]
13pub struct SessionAuthorization {
14    authenticated: Arc<RoleBinding>,
15    session: Arc<RoleBinding>,
16    selected: Option<Arc<RoleBinding>>,
17    effective: Arc<RoleBinding>,
18}
19
20impl Default for SessionAuthorization {
21    fn default() -> Self {
22        Self::new(
23            RoleBinding::from_definition(&RoleDefinition::bootstrap())
24                .expect("bootstrap role identity"),
25        )
26    }
27}
28
29impl SessionAuthorization {
30    pub fn new(authenticated: RoleBinding) -> Self {
31        let authenticated = Arc::new(authenticated);
32        Self {
33            session: authenticated.clone(),
34            effective: authenticated.clone(),
35            authenticated,
36            selected: None,
37        }
38    }
39
40    pub fn authenticated(&self) -> &Arc<RoleBinding> {
41        &self.authenticated
42    }
43
44    pub fn session(&self) -> &Arc<RoleBinding> {
45        &self.session
46    }
47
48    pub fn outer(&self) -> &Arc<RoleBinding> {
49        self.selected.as_ref().unwrap_or(&self.session)
50    }
51
52    pub fn current(&self) -> &Arc<RoleBinding> {
53        &self.effective
54    }
55
56    pub fn selected(&self) -> Option<&Arc<RoleBinding>> {
57        self.selected.as_ref()
58    }
59
60    pub fn set_role(&mut self, selected: Option<Arc<RoleBinding>>) {
61        self.effective = selected.as_ref().unwrap_or(&self.session).clone();
62        self.selected = selected;
63    }
64
65    /// Session and role assignment commute during transaction-local restoration.
66    pub fn restore_session(&mut self, session: Arc<RoleBinding>) {
67        if self.selected.is_none() {
68            self.effective = session.clone();
69        }
70        self.session = session;
71    }
72
73    pub fn set_session(&mut self, session: Arc<RoleBinding>) {
74        self.restore_session(session);
75        self.set_role(None);
76    }
77
78    pub fn set_effective(&mut self, role: Arc<RoleBinding>) {
79        self.effective = role;
80    }
81
82    pub fn discard(&mut self) {
83        self.set_session(self.authenticated.clone());
84    }
85
86    pub fn show_role(&self) -> &str {
87        self.selected
88            .as_ref()
89            .map_or("none", |role| role.name.as_str())
90    }
91}
92
93#[cfg(test)]
94mod tests;