use itertools::Itertools;
use unitycatalog_common::models::ObjectLabel;
use unitycatalog_common::models::recipients::v1::*;
use unitycatalog_common::models::{ResourceIdent, ResourceName, ResourceRef};
use super::{RequestContext, SecuredAction};
use crate::Result;
pub use crate::codegen::recipients::RecipientHandler;
use crate::policy::{Permission, Policy, process_resources};
use crate::store::ResourceStore;
#[async_trait::async_trait]
impl<T: ResourceStore + Policy<RequestContext>> RecipientHandler<RequestContext> for T {
#[tracing::instrument(skip(self, context), fields(resource_name))]
async fn create_recipient(
&self,
request: CreateRecipientRequest,
context: RequestContext,
) -> Result<Recipient> {
tracing::Span::current().record("resource_name", &request.name);
self.check_required(&request, &context).await?;
let resource = Recipient {
name: request.name,
authentication_type: request.authentication_type,
comment: request.comment,
properties: request.properties,
..Default::default()
};
let info = self.create(resource.into()).await?.0.try_into()?;
Ok(info)
}
#[tracing::instrument(skip(self, context), fields(resource_name))]
async fn delete_recipient(
&self,
request: DeleteRecipientRequest,
context: RequestContext,
) -> Result<()> {
tracing::Span::current().record("resource_name", &request.name);
self.check_required(&request, &context).await?;
Ok(self.delete(&request.resource()).await?)
}
#[tracing::instrument(skip(self, context), fields(resource_name))]
async fn get_recipient(
&self,
request: GetRecipientRequest,
context: RequestContext,
) -> Result<Recipient> {
tracing::Span::current().record("resource_name", &request.name);
self.check_required(&request, &context).await?;
Ok(self.get(&request.resource()).await?.0.try_into()?)
}
#[tracing::instrument(skip(self, context))]
async fn list_recipients(
&self,
request: ListRecipientsRequest,
context: RequestContext,
) -> Result<ListRecipientsResponse> {
self.check_required(&request, &context).await?;
let (mut resources, next_page_token) = self
.list(
&ObjectLabel::Recipient,
None,
request.max_results.map(|v| v as usize),
request.page_token,
)
.await?;
process_resources(self, &context, &Permission::Read, &mut resources).await?;
Ok(ListRecipientsResponse {
recipients: resources.into_iter().map(|r| r.try_into()).try_collect()?,
next_page_token,
..Default::default()
})
}
#[tracing::instrument(skip(self, context), fields(resource_name))]
async fn update_recipient(
&self,
request: UpdateRecipientRequest,
context: RequestContext,
) -> Result<Recipient> {
tracing::Span::current().record("resource_name", &request.name);
self.check_required(&request, &context).await?;
let ident = request.resource();
let current: Recipient = self.get(&ident).await?.0.try_into()?;
let updated = Recipient {
name: request.new_name.unwrap_or(request.name),
owner: request.owner.or(current.owner),
comment: request.comment.or(current.comment),
properties: if request.properties.is_empty() {
current.properties
} else {
request.properties
},
..current
};
Ok(self.update(&ident, updated.into()).await?.0.try_into()?)
}
}
impl SecuredAction for CreateRecipientRequest {
fn resource(&self) -> ResourceIdent {
ResourceIdent::recipient(ResourceName::new([self.name.as_str()]))
}
fn permission(&self) -> &'static Permission {
&Permission::Create
}
}
impl SecuredAction for ListRecipientsRequest {
fn resource(&self) -> ResourceIdent {
ResourceIdent::recipient(ResourceRef::Undefined)
}
fn permission(&self) -> &'static Permission {
&Permission::Read
}
}
impl SecuredAction for GetRecipientRequest {
fn resource(&self) -> ResourceIdent {
ResourceIdent::recipient(ResourceName::new([self.name.as_str()]))
}
fn permission(&self) -> &'static Permission {
&Permission::Read
}
}
impl SecuredAction for UpdateRecipientRequest {
fn resource(&self) -> ResourceIdent {
ResourceIdent::recipient(ResourceName::new([self.name.as_str()]))
}
fn permission(&self) -> &'static Permission {
&Permission::Manage
}
}
impl SecuredAction for DeleteRecipientRequest {
fn resource(&self) -> ResourceIdent {
ResourceIdent::recipient(ResourceName::new([self.name.as_str()]))
}
fn permission(&self) -> &'static Permission {
&Permission::Manage
}
}