unitycatalog_server/api/
mod.rs1pub use agent_skills::AgentSkillHandler;
2pub use agents::AgentHandler;
3pub use catalogs::CatalogHandler;
4pub use credentials::CredentialHandler;
5pub use entity_tag_assignments::EntityTagAssignmentHandler;
6pub use external_locations::ExternalLocationHandler;
7pub use functions::FunctionHandler;
8pub use model_versions::ModelVersionHandler;
9pub use policies::PolicyHandler;
10pub use registered_models::RegisteredModelHandler;
11pub use schemas::SchemaHandler;
12pub use staging_tables::StagingTableHandler;
13pub use tables::TableHandler;
14pub use tag_policies::TagPolicyHandler;
15pub use temporary_credentials::TemporaryCredentialHandler;
16pub use volumes::VolumeHandler;
17
18use crate::policy::{Permission, Principal};
19use unitycatalog_common::models::ResourceIdent;
20
21pub mod agent_skills;
35pub mod agents;
36pub mod catalogs;
37pub mod credentials;
38pub mod entity_tag_assignments;
39pub mod external_locations;
40pub mod functions;
41pub mod model_versions;
42pub mod policies;
43pub mod registered_models;
44pub mod schemas;
45pub mod staging_tables;
46pub mod tables;
47pub mod tag_policies;
48pub mod temporary_credentials;
49pub mod volumes;
50
51pub(crate) fn page_size(max_results: Option<i32>) -> crate::Result<Option<usize>> {
56 match max_results {
57 Some(v) if v < 0 => Err(crate::Error::invalid_argument(
58 "max_results must not be negative",
59 )),
60 Some(v) if v > 0 => Ok(Some(v as usize)),
61 _ => Ok(None),
62 }
63}
64
65pub(crate) enum UpdateMask<'a> {
71 All,
72 Fields(Vec<&'a str>),
73}
74
75impl<'a> UpdateMask<'a> {
76 pub(crate) fn parse(mask: Option<&'a str>, updatable: &[&str]) -> crate::Result<Self> {
77 let fields: Vec<&str> = mask
78 .unwrap_or_default()
79 .split(',')
80 .map(str::trim)
81 .filter(|f| !f.is_empty())
82 .collect();
83 if fields.is_empty() || fields == ["*"] {
84 return Ok(Self::All);
85 }
86 if let Some(unknown) = fields.iter().find(|f| !updatable.contains(f)) {
87 return Err(crate::Error::invalid_argument(format!(
88 "update_mask names a field that cannot be updated: '{unknown}'"
89 )));
90 }
91 Ok(Self::Fields(fields))
92 }
93
94 pub(crate) fn names(&self, field: &str) -> bool {
96 matches!(self, Self::Fields(fields) if fields.contains(&field))
97 }
98}
99
100#[derive(Debug, Clone)]
101pub struct RequestContext {
102 pub recipient: Principal,
103}
104
105impl RequestContext {
106 pub fn recipient(&self) -> &Principal {
107 &self.recipient
108 }
109}
110
111impl AsRef<Principal> for RequestContext {
112 fn as_ref(&self) -> &Principal {
113 &self.recipient
114 }
115}
116
117#[cfg(feature = "bin")]
121impl unitycatalog_storage_proxy::ForwardedUser for RequestContext {
122 fn forwarded_user(&self) -> Option<&str> {
123 match &self.recipient {
124 Principal::User(name) => Some(name),
125 Principal::Anonymous => None,
126 }
127 }
128}
129
130pub trait SecuredAction: Send + Sync {
131 fn resource(&self) -> ResourceIdent;
133
134 fn permission(&self) -> &'static Permission;
136}
137
138#[cfg(test)]
139mod tests {
140 use super::page_size;
141
142 #[test]
143 fn test_page_size() {
144 assert_eq!(page_size(None).unwrap(), None);
145 assert_eq!(page_size(Some(0)).unwrap(), None);
146 assert_eq!(page_size(Some(25)).unwrap(), Some(25));
147 assert!(page_size(Some(-1)).is_err());
148 }
149}