gunnar-grpc 1.5.0

The tonic service implementations and the event bus behind gunnar's gRPC control plane.
Documentation
//! `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)?,
        ))
    }
}