unitycatalog_server/api/
providers.rs1use itertools::Itertools;
2
3use unitycatalog_common::models::ObjectLabel;
4use unitycatalog_common::models::providers::v1::*;
5use unitycatalog_common::models::{ResourceIdent, ResourceName, ResourceRef};
6
7use super::{RequestContext, SecuredAction};
8use crate::Result;
9pub use crate::codegen::providers::ProviderHandler;
10use crate::policy::{Permission, Policy, process_resources};
11use crate::store::ResourceStore;
12
13#[async_trait::async_trait]
14impl<T: ResourceStore + Policy<RequestContext>> ProviderHandler<RequestContext> for T {
15 #[tracing::instrument(skip(self, context), fields(resource_name))]
16 async fn create_provider(
17 &self,
18 request: CreateProviderRequest,
19 context: RequestContext,
20 ) -> Result<Provider> {
21 tracing::Span::current().record("resource_name", &request.name);
22 self.check_required(&request, &context).await?;
23 let resource = Provider {
24 name: request.name,
25 authentication_type: request.authentication_type,
26 owner: request.owner,
27 comment: request.comment,
28 recipient_profile_str: request.recipient_profile_str,
29 properties: request.properties,
30 ..Default::default()
31 };
32 let info = self.create(resource.into()).await?.0.try_into()?;
33 Ok(info)
34 }
35
36 #[tracing::instrument(skip(self, context), fields(resource_name))]
37 async fn delete_provider(
38 &self,
39 request: DeleteProviderRequest,
40 context: RequestContext,
41 ) -> Result<()> {
42 tracing::Span::current().record("resource_name", &request.name);
43 self.check_required(&request, &context).await?;
44 Ok(self.delete(&request.resource()).await?)
45 }
46
47 #[tracing::instrument(skip(self, context), fields(resource_name))]
48 async fn get_provider(
49 &self,
50 request: GetProviderRequest,
51 context: RequestContext,
52 ) -> Result<Provider> {
53 tracing::Span::current().record("resource_name", &request.name);
54 self.check_required(&request, &context).await?;
55 Ok(self.get(&request.resource()).await?.0.try_into()?)
56 }
57
58 #[tracing::instrument(skip(self, context))]
59 async fn list_providers(
60 &self,
61 request: ListProvidersRequest,
62 context: RequestContext,
63 ) -> Result<ListProvidersResponse> {
64 self.check_required(&request, &context).await?;
65 let (mut resources, next_page_token) = self
66 .list(
67 &ObjectLabel::Provider,
68 None,
69 request.max_results.map(|v| v as usize),
70 request.page_token,
71 )
72 .await?;
73 process_resources(self, &context, &Permission::Read, &mut resources).await?;
74 Ok(ListProvidersResponse {
75 providers: resources.into_iter().map(|r| r.try_into()).try_collect()?,
76 next_page_token,
77 ..Default::default()
78 })
79 }
80
81 #[tracing::instrument(skip(self, context), fields(resource_name))]
82 async fn update_provider(
83 &self,
84 request: UpdateProviderRequest,
85 context: RequestContext,
86 ) -> Result<Provider> {
87 tracing::Span::current().record("resource_name", &request.name);
88 self.check_required(&request, &context).await?;
89 let ident = request.resource();
90 let current: Provider = self.get(&ident).await?.0.try_into()?;
91
92 let updated = Provider {
93 name: request.new_name.unwrap_or(request.name),
94 owner: request.owner.or(current.owner),
95 comment: request.comment.or(current.comment),
96 recipient_profile_str: request
97 .recipient_profile_str
98 .or(current.recipient_profile_str),
99 properties: if request.properties.is_empty() {
100 current.properties
101 } else {
102 request.properties
103 },
104 ..current
106 };
107
108 Ok(self.update(&ident, updated.into()).await?.0.try_into()?)
109 }
110}
111
112impl SecuredAction for CreateProviderRequest {
113 fn resource(&self) -> ResourceIdent {
114 ResourceIdent::provider(ResourceName::new([self.name.as_str()]))
115 }
116
117 fn permission(&self) -> &'static Permission {
118 &Permission::Create
119 }
120}
121
122impl SecuredAction for ListProvidersRequest {
123 fn resource(&self) -> ResourceIdent {
124 ResourceIdent::provider(ResourceRef::Undefined)
125 }
126
127 fn permission(&self) -> &'static Permission {
128 &Permission::Read
129 }
130}
131
132impl SecuredAction for GetProviderRequest {
133 fn resource(&self) -> ResourceIdent {
134 ResourceIdent::provider(ResourceName::new([self.name.as_str()]))
135 }
136
137 fn permission(&self) -> &'static Permission {
138 &Permission::Read
139 }
140}
141
142impl SecuredAction for UpdateProviderRequest {
143 fn resource(&self) -> ResourceIdent {
144 ResourceIdent::provider(ResourceName::new([self.name.as_str()]))
145 }
146
147 fn permission(&self) -> &'static Permission {
148 &Permission::Manage
149 }
150}
151
152impl SecuredAction for DeleteProviderRequest {
153 fn resource(&self) -> ResourceIdent {
154 ResourceIdent::provider(ResourceName::new([self.name.as_str()]))
155 }
156
157 fn permission(&self) -> &'static Permission {
158 &Permission::Manage
159 }
160}