1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
//! Module for server record policy implementations.
use thiserror::Error;
use warg_protocol::{package::PackageRecord, registry::PackageName, ProtoEnvelope};
mod authorization;
pub use authorization::*;
/// Represents a record policy error.
#[derive(Debug, Error)]
pub enum RecordPolicyError {
/// A special rejection that indicates the record is not
/// authorized to be published.
///
/// Unauthorized records will never be stored.
#[error("unauthorized operation:: {0}")]
Unauthorized(String),
/// The policy rejected the record with the given message.
#[error("record was rejected by policy: {0}")]
Rejection(String),
}
/// The result type returned by record policies.
pub type RecordPolicyResult<T> = Result<T, RecordPolicyError>;
/// A trait implemented by record policies.
pub trait RecordPolicy: Send + Sync {
/// Checks the record against the policy.
fn check(
&self,
name: &PackageName,
record: &ProtoEnvelope<PackageRecord>,
) -> RecordPolicyResult<()>;
}
/// Represents a collection of record policies.
///
/// Record policies are checked in order of their addition
/// to the collection.
#[derive(Default)]
pub struct RecordPolicyCollection {
policies: Vec<Box<dyn RecordPolicy>>,
}
impl RecordPolicyCollection {
/// Creates a new record policy collection.
pub fn new() -> Self {
Self::default()
}
/// Pushes a new record policy into the collection.
pub fn push(&mut self, policy: impl RecordPolicy + 'static) {
self.policies.push(Box::new(policy));
}
}
impl RecordPolicy for RecordPolicyCollection {
fn check(
&self,
name: &PackageName,
record: &ProtoEnvelope<PackageRecord>,
) -> RecordPolicyResult<()> {
for policy in &self.policies {
policy.check(name, record)?;
}
Ok(())
}
}