edc-connector-client 0.1.0

A Rust client for EDC
Documentation
mod odrl;

use serde::{Deserialize, Serialize};
use serde_with::{formats::PreferMany, serde_as, OneOrMany};

use crate::{BuilderError, ConversionError};

use super::properties::{FromValue, Properties, PropertyValue, ToValue};

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PolicyDefinition {
    #[serde(rename = "@id")]
    id: String,
    policy: Policy,
    #[serde(default)]
    private_properties: Properties,
}

impl PolicyDefinition {
    pub fn builder() -> PolicyDefinitionBuilder {
        PolicyDefinitionBuilder::default()
    }

    pub fn policy(&self) -> &Policy {
        &self.policy
    }

    pub fn private_property<T>(&self, property: &str) -> Result<Option<T>, ConversionError>
    where
        T: FromValue,
    {
        self.private_properties.get(property)
    }

    pub fn id(&self) -> &str {
        &self.id
    }
}

#[derive(Default)]
pub struct PolicyDefinitionBuilder {
    id: Option<String>,
    policy: Option<Policy>,
    private_properties: Properties,
}

impl PolicyDefinitionBuilder {
    pub fn id(mut self, id: &str) -> Self {
        self.id = Some(id.to_string());
        self
    }

    pub fn policy(mut self, policy: Policy) -> Self {
        self.policy = Some(policy);
        self
    }

    pub fn private_property<T>(mut self, property: &str, value: T) -> Self
    where
        T: ToValue,
    {
        self.private_properties.set(property, value);
        self
    }

    pub fn build(self) -> Result<PolicyDefinition, BuilderError> {
        Ok(PolicyDefinition {
            id: self
                .id
                .ok_or_else(|| BuilderError::missing_property("id"))?,
            policy: self
                .policy
                .ok_or_else(|| BuilderError::missing_property("policy"))?,

            private_properties: self.private_properties,
        })
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NewPolicyDefinition {
    #[serde(rename = "@id")]
    id: Option<String>,
    policy: Policy,
    #[serde(default)]
    private_properties: Properties,
}

impl NewPolicyDefinition {
    pub fn builder() -> NewPolicyDefinitionBuilder {
        NewPolicyDefinitionBuilder(NewPolicyDefinition::default())
    }
}

#[derive(Default)]
pub struct NewPolicyDefinitionBuilder(NewPolicyDefinition);

impl NewPolicyDefinitionBuilder {
    pub fn id(mut self, id: &str) -> Self {
        self.0.id = Some(id.to_string());
        self
    }

    pub fn policy(mut self, policy: Policy) -> Self {
        self.0.policy = policy;
        self
    }

    pub fn private_property<T>(mut self, property: &str, value: T) -> Self
    where
        T: ToValue,
    {
        self.0.private_properties.set(property, value);
        self
    }

    pub fn build(self) -> NewPolicyDefinition {
        self.0
    }
}

impl Default for PolicyDefinition {
    fn default() -> Self {
        Self {
            id: Default::default(),
            policy: Policy::builder().build(),
            private_properties: Default::default(),
        }
    }
}

impl Default for NewPolicyDefinition {
    fn default() -> Self {
        Self {
            id: Default::default(),
            policy: Policy::builder().build(),
            private_properties: Default::default(),
        }
    }
}

#[serde_as]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct Policy {
    #[serde(rename = "@id")]
    #[serde(skip_serializing_if = "Option::is_none")]
    id: Option<String>,
    #[serde(rename = "@type")]
    kind: PolicyKind,
    assignee: Option<String>,
    assigner: Option<String>,
    target: Option<String>,
    #[serde_as(deserialize_as = "OneOrMany<_, PreferMany>")]
    #[serde(rename = "permission", alias = "odrl:permission", default)]
    permissions: Vec<Permission>,
}

impl Policy {
    pub fn builder() -> PolicyBuilder {
        PolicyBuilder(Policy {
            id: None,
            kind: PolicyKind::Set,
            assignee: None,
            assigner: None,
            target: None,
            permissions: vec![],
        })
    }

    pub fn kind(&self) -> &PolicyKind {
        &self.kind
    }

    pub fn id(&self) -> Option<&String> {
        self.id.as_ref()
    }

    pub fn assignee(&self) -> Option<&String> {
        self.assignee.as_ref()
    }

    pub fn assigner(&self) -> Option<&String> {
        self.assigner.as_ref()
    }

    pub fn target(&self) -> Option<&String> {
        self.target.as_ref()
    }

    pub fn permissions(&self) -> &[Permission] {
        &self.permissions
    }
}

pub struct PolicyBuilder(Policy);

impl PolicyBuilder {
    pub fn id(mut self, id: &str) -> Self {
        self.0.id = Some(id.to_string());
        self
    }

    pub fn assigner(mut self, assigner: &str) -> Self {
        self.0.assigner = Some(assigner.to_string());
        self
    }

    pub fn target(mut self, target: &str) -> Self {
        self.0.target = Some(target.to_string());
        self
    }

    pub fn kind(mut self, kind: PolicyKind) -> Self {
        self.0.kind = kind;
        self
    }

    pub fn permissions(mut self, permissions: Vec<Permission>) -> Self {
        self.0.permissions = permissions;
        self
    }

    pub fn permission(mut self, permission: Permission) -> Self {
        self.0.permissions.push(permission);
        self
    }

    pub fn build(self) -> Policy {
        self.0
    }
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub enum PolicyKind {
    #[serde(alias = "odrl:Set")]
    Set,
    #[serde(alias = "odrl:Offer")]
    Offer,
    #[serde(alias = "odrl:Agreement")]
    Agreement,
}

#[serde_as]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct Permission {
    #[serde_as(deserialize_as = "OneOrMany<_, PreferMany>")]
    #[serde(rename = "constraint", alias = "odrl:constraint", default)]
    constraints: Vec<Constraint>,
    #[serde(alias = "odrl:action")]
    #[serde(deserialize_with = "crate::types::policy::odrl::action_deserializer")]
    action: Action,
}

impl Permission {
    pub fn builder() -> PermissionBuilder {
        PermissionBuilder(Permission {
            action: Action::new("use".to_string()),
            constraints: vec![],
        })
    }

    pub fn action(&self) -> &Action {
        &self.action
    }

    pub fn constraints(&self) -> &[Constraint] {
        &self.constraints
    }
}

pub struct PermissionBuilder(Permission);

impl PermissionBuilder {
    pub fn constraints(mut self, constraints: Vec<Constraint>) -> Self {
        self.0.constraints = constraints;
        self
    }

    pub fn constraint(mut self, constraint: Constraint) -> Self {
        self.0.constraints.push(constraint);
        self
    }

    pub fn build(self) -> Permission {
        self.0
    }
}

#[derive(Debug, Serialize, PartialEq, Clone)]
pub struct Action(String);

impl Action {
    pub fn id(&self) -> &String {
        &self.0
    }
}

impl Action {
    pub fn new(kind: String) -> Self {
        Action(kind)
    }
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(untagged)]
pub enum Constraint {
    Atomic(AtomicConstraint),
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct AtomicConstraint {
    #[serde(rename = "leftOperand", alias = "odrl:leftOperand")]
    left_operand: String,
    #[serde(alias = "odrl:operator")]
    operator: Operator,
    #[serde(rename = "rightOperand", alias = "odrl:rightOperand")]
    right_operand: PropertyValue,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(untagged)]
pub enum Operator {
    Simple(String),
    Id {
        #[serde(rename = "@id")]
        id: String,
    },
}

impl Operator {
    pub fn simple(op: &str) -> Operator {
        Operator::Simple(op.to_string())
    }

    pub fn id(op: &str) -> Operator {
        Operator::Id { id: op.to_string() }
    }
}

impl AtomicConstraint {
    pub fn new<T: ToValue>(left_operand: &str, operator: &str, right_operand: T) -> Self {
        AtomicConstraint::new_with_operator(
            left_operand,
            Operator::Simple(operator.to_string()),
            right_operand,
        )
    }

    pub fn new_with_operator<T: ToValue>(
        left_operand: &str,
        operator: Operator,
        right_operand: T,
    ) -> Self {
        Self {
            left_operand: left_operand.to_string(),
            operator,
            right_operand: PropertyValue(right_operand.into_value()),
        }
    }
}