use super::{AuthorizedWorkspaceReadAccess, AuthorizedWorkspaceWriteAccess};
use crate::plugin::{
PluginAuthorizationError, PluginCapabilities, PluginCapabilityRef, PluginIdentity,
WorkspacePath, WorkspacePathRef,
};
use std::fmt::{Debug, Formatter};
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::plugin) struct PluginHostAuthority {
identity: PluginIdentity,
capabilities: PluginCapabilities,
}
impl PluginHostAuthority {
#[must_use]
const fn new(identity: PluginIdentity, capabilities: PluginCapabilities) -> Self {
Self {
identity,
capabilities,
}
}
#[must_use]
pub const fn identity_proof(&self) -> &PluginIdentity {
&self.identity
}
#[must_use]
pub const fn capabilities(&self) -> &PluginCapabilities {
&self.capabilities
}
pub fn authorize(
&self,
capability: PluginCapabilityRef<'_>,
) -> Result<(), PluginAuthorizationError> {
if self.capabilities.allows(capability) {
Ok(())
} else {
Err(PluginAuthorizationError::Denied {
identity: self.identity.clone(),
capability: capability.shape(),
})
}
}
pub(in crate::plugin) fn authorize_workspace_observe(
&self,
path: WorkspacePathRef<'_>,
) -> Result<AuthorizedWorkspaceReadAccess, PluginAuthorizationError> {
self.authorize(PluginCapabilityRef::WorkspaceObserve(path))?;
Ok(AuthorizedWorkspaceReadAccess::new(
self.identity.clone(),
WorkspacePath::from_ref(path),
))
}
pub(in crate::plugin) fn authorize_workspace_artifact_write(
&self,
path: WorkspacePathRef<'_>,
) -> Result<AuthorizedWorkspaceWriteAccess, PluginAuthorizationError> {
self.authorize(PluginCapabilityRef::WorkspaceArtifactWrite(path))?;
Ok(AuthorizedWorkspaceWriteAccess::new(
self.identity.clone(),
WorkspacePath::from_ref(path),
))
}
}
#[derive(Eq, PartialEq)]
pub struct PluginHostContext {
authority: PluginHostAuthority,
}
impl PluginHostContext {
#[must_use]
pub(in crate::plugin) const fn new(
identity: PluginIdentity,
capabilities: PluginCapabilities,
) -> Self {
Self {
authority: PluginHostAuthority::new(identity, capabilities),
}
}
#[cfg(test)]
#[must_use]
pub(crate) fn for_test(identity: impl Into<String>, capabilities: PluginCapabilities) -> Self {
Self::new(
PluginIdentity::try_new(identity).expect("test plugin identity should be valid"),
capabilities,
)
}
#[must_use]
pub fn identity(&self) -> &str {
self.identity_proof().as_str()
}
#[must_use]
pub const fn identity_proof(&self) -> &PluginIdentity {
self.authority.identity_proof()
}
#[must_use]
pub const fn capabilities(&self) -> &PluginCapabilities {
self.authority.capabilities()
}
#[must_use]
pub(in crate::plugin) const fn authority(&self) -> &PluginHostAuthority {
&self.authority
}
pub fn authorize(
&self,
capability: PluginCapabilityRef<'_>,
) -> Result<(), PluginAuthorizationError> {
self.authority.authorize(capability)
}
pub fn authorize_workspace_observe(
&self,
path: WorkspacePathRef<'_>,
) -> Result<AuthorizedWorkspaceReadAccess, PluginAuthorizationError> {
self.authority.authorize_workspace_observe(path)
}
pub fn authorize_workspace_artifact_write(
&self,
path: WorkspacePathRef<'_>,
) -> Result<AuthorizedWorkspaceWriteAccess, PluginAuthorizationError> {
self.authority.authorize_workspace_artifact_write(path)
}
}
impl Debug for PluginHostContext {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PluginHostContext")
.field("identity", &self.identity_proof())
.field("capabilities", self.capabilities())
.finish()
}
}