uqa_sql/catalog/security/
sequence_binding.rs1use super::{role_bindings, SequenceSecurity};
10use crate::catalog::roles::{identity::RoleBinding, RoleDefinition, RoleIdentity, RoleReference};
11use std::collections::BTreeMap;
12use uqa_core::{
13 catalog_acl::AclGrantee,
14 catalog_role::BoundAclEntry,
15 catalog_sequence::{SequenceAclEntry, SequencePrivileges},
16};
17
18pub type BoundSequenceAclEntry = BoundAclEntry<SequencePrivileges>;
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct BoundSequenceSecurity {
22 pub role_owner: RoleIdentity,
23 pub acl: Option<Vec<BoundSequenceAclEntry>>,
24}
25
26#[cfg(test)]
27mod tests;
28
29impl BoundSequenceSecurity {
30 pub fn from_row(row: uqa_core::catalog_sequence::BoundSequenceSecurity) -> Self {
31 Self {
32 role_owner: row.role_owner,
33 acl: row.acl,
34 }
35 }
36
37 pub fn row(&self) -> uqa_core::catalog_sequence::BoundSequenceSecurity {
38 uqa_core::catalog_sequence::BoundSequenceSecurity {
39 role_owner: self.role_owner,
40 acl: self.acl.clone(),
41 }
42 }
43
44 pub fn owner(role_owner: RoleIdentity) -> Self {
45 Self {
46 role_owner,
47 acl: None,
48 }
49 }
50
51 pub fn owner_reference(
52 &self,
53 roles: &BTreeMap<String, RoleDefinition>,
54 ) -> Result<RoleReference, crate::SQLError> {
55 let name = role_bindings::role_name(roles, self.role_owner, "sequence")
56 .map_err(crate::SQLError::Internal)?;
57 Ok(RoleReference::Bound(std::sync::Arc::new(
58 RoleBinding::from_definition(&roles[name])?,
59 )))
60 }
61
62 pub fn bind(
63 security: &SequenceSecurity,
64 roles: &BTreeMap<String, RoleDefinition>,
65 ) -> Result<Self, String> {
66 let bind = |name: &str| role_bindings::bind_role(roles, name, "sequence");
67 let entries = |entries: &[SequenceAclEntry]| {
68 entries
69 .iter()
70 .map(|entry| {
71 Ok(BoundSequenceAclEntry {
72 role: entry.role.role_name().map(bind).transpose()?,
73 grantor: bind(entry.grantor.as_deref().unwrap_or(&security.role_owner))?,
74 privileges: entry.privileges,
75 grant_options: entry.grant_options,
76 })
77 })
78 .collect::<Result<Vec<_>, String>>()
79 };
80 Ok(Self {
81 role_owner: bind(&security.role_owner)?,
82 acl: security.acl.as_deref().map(entries).transpose()?,
83 })
84 }
85
86 pub fn resolve(
88 &self,
89 roles: &BTreeMap<String, RoleDefinition>,
90 ) -> Result<SequenceSecurity, String> {
91 let name =
92 |identity| role_bindings::role_name(roles, identity, "sequence").map(str::to_owned);
93 let entries = |entries: &[BoundSequenceAclEntry]| {
94 entries
95 .iter()
96 .map(|entry| {
97 Ok(SequenceAclEntry {
98 role: entry
99 .role
100 .map(&name)
101 .transpose()?
102 .map_or(AclGrantee::Public, AclGrantee::Role),
103 grantor: Some(name(entry.grantor)?),
104 privileges: entry.privileges,
105 grant_options: entry.grant_options,
106 })
107 })
108 .collect::<Result<Vec<_>, String>>()
109 };
110 Ok(SequenceSecurity {
111 role_owner: name(self.role_owner)?,
112 acl: self.acl.as_deref().map(entries).transpose()?,
113 })
114 }
115
116 pub fn validate(&self, roles: &BTreeMap<String, RoleDefinition>) -> Result<(), String> {
117 super::sequence::validate_sequence_security_invariants(&self.resolve(roles)?, roles)
118 }
119
120 pub fn depends_on(&self, role: RoleIdentity) -> bool {
121 self.role_owner == role
122 || self
123 .acl
124 .iter()
125 .flatten()
126 .any(|entry| entry.role == Some(role) || entry.grantor == role)
127 }
128}