crates/gunnar-grpc/src/service/webhook.rs
//! `Webhooks` configures the outbound delivery of event-stream events to external URLs.
//!
//! Every verb is server-scoped admin: an endpoint receives events about every
//! repository its filter covers, signed with the server's key, so who may
//! configure one is the same question as who may configure replication —
//! gunnar-admin, `Access::Server`. The work itself is the server's
//! [`ControlPlane`](crate::seam::ControlPlane) implementation; this layer only
//! authenticates, authorises and forwards, exactly as `service::mirror` does
//! for replication (one implementation).
use gunnar_proto::webhooks_server::Webhooks;
use gunnar_proto::{
AddWebhookRequest, ListWebhooksRequest, RemoveWebhookRequest, WebhookListResponse,
};
use tonic::{Request, Response, Status};
use crate::auth::Access;
use crate::service::WebhooksService;
use gunnar_proto::GrantLevel;
#[tonic::async_trait]
impl Webhooks for WebhooksService {
async fn add_webhook(
&self,
request: Request<AddWebhookRequest>,
) -> Result<Response<WebhookListResponse>, Status> {
let caller = self.ctx.caller(&request)?;
self.ctx.require(
&caller,
Access::Server,
GrantLevel::Admin,
"Webhooks.AddWebhook",
)?;
Ok(Response::new(
self.ctx.control.webhook_add(request.into_inner())?,
))
}
async fn list_webhooks(
&self,
request: Request<ListWebhooksRequest>,
) -> Result<Response<WebhookListResponse>, Status> {
let caller = self.ctx.caller(&request)?;
self.ctx.require(
&caller,
Access::Server,
GrantLevel::Admin,
"Webhooks.ListWebhooks",
)?;
Ok(Response::new(self.ctx.control.webhook_list()?))
}
async fn remove_webhook(
&self,
request: Request<RemoveWebhookRequest>,
) -> Result<Response<WebhookListResponse>, Status> {
let caller = self.ctx.caller(&request)?;
self.ctx.require(
&caller,
Access::Server,
GrantLevel::Admin,
"Webhooks.RemoveWebhook",
)?;
Ok(Response::new(
self.ctx
.control
.webhook_remove(&request.into_inner().name)?,
))
}
}