1use std::fmt;
4
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct OdrlDocument {
10 pub policies: Vec<OdrlPolicy>,
12}
13
14impl OdrlDocument {
15 pub fn from_yaml(yaml: &str) -> Result<Self, serde_yaml::Error> {
17 serde_yaml::from_str(yaml)
18 }
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct OdrlPolicy {
26 pub uid: String,
28 #[serde(rename = "type")]
30 pub policy_type: String,
31 pub rules: Vec<OdrlRule>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct OdrlRule {
38 #[serde(rename = "type")]
40 pub rule_type: OdrlRuleType,
41 #[serde(default)]
43 pub assigner: Option<String>,
44 pub assignee: String,
46 pub action: RuleAction,
48 pub target: String,
50 #[serde(default)]
52 pub constraints: Vec<OdrlConstraint>,
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
57#[serde(rename_all = "lowercase")]
58pub enum OdrlRuleType {
59 Permission,
61 Prohibition,
63 Duty,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
71#[serde(rename_all = "lowercase")]
72pub enum RuleAction {
73 Read,
75 Write,
77 Delete,
79 Execute,
81 Delegate,
83 #[serde(rename = "read_internal")]
85 ReadInternal,
86 #[serde(rename = "read_sensitive")]
88 ReadSensitive,
89 #[serde(rename = "write_sensitive")]
91 WriteSensitive,
92 #[serde(rename = "ai:infer")]
94 AiInfer,
95 #[serde(rename = "ai:train")]
97 AiTrain,
98 #[serde(rename = "exfiltrate")]
100 Exfiltrate,
101 Use,
103}
104
105impl RuleAction {
106 pub fn as_permission_name(&self) -> &str {
108 match self {
109 RuleAction::Read => "read",
110 RuleAction::Write => "write",
111 RuleAction::Delete => "delete",
112 RuleAction::Execute => "execute",
113 RuleAction::Delegate => "delegate",
114 RuleAction::ReadInternal => "read_internal",
115 RuleAction::ReadSensitive => "read_sensitive",
116 RuleAction::WriteSensitive => "write_sensitive",
117 RuleAction::AiInfer => "ai:infer",
118 RuleAction::AiTrain => "ai:train",
119 RuleAction::Exfiltrate => "ai:exfiltrate",
120 RuleAction::Use => "*",
121 }
122 }
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct OdrlConstraint {
128 #[serde(rename = "leftOperand")]
130 pub left_operand: ConstraintOperand,
131 pub operator: ConstraintOperator,
133 #[serde(rename = "rightOperand")]
135 pub right_operand: String,
136}
137
138#[derive(Debug, Clone, PartialEq, Eq)]
140pub enum ConstraintOperand {
141 Purpose,
143 DateTime,
145 Count,
147 Custom(String),
149}
150
151impl ConstraintOperand {
152 pub fn parse(name: impl Into<String>) -> Self {
154 let name = name.into();
155 match name.as_str() {
156 "purpose" => Self::Purpose,
157 "dateTime" | "date" => Self::DateTime,
158 "count" => Self::Count,
159 _ => Self::Custom(name),
160 }
161 }
162
163 pub fn as_str(&self) -> &str {
165 match self {
166 Self::Purpose => "purpose",
167 Self::DateTime => "dateTime",
168 Self::Count => "count",
169 Self::Custom(name) => name,
170 }
171 }
172}
173
174impl fmt::Display for ConstraintOperand {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 f.write_str(self.as_str())
177 }
178}
179
180impl Serialize for ConstraintOperand {
181 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
182 where
183 S: Serializer,
184 {
185 serializer.serialize_str(self.as_str())
186 }
187}
188
189impl<'de> Deserialize<'de> for ConstraintOperand {
190 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
191 where
192 D: Deserializer<'de>,
193 {
194 String::deserialize(deserializer).map(Self::parse)
195 }
196}
197
198#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
200#[serde(rename_all = "camelCase")]
201pub enum ConstraintOperator {
202 Eq,
204 Neq,
206 Lt,
208 Lteq,
210 Gt,
212 Gteq,
214 #[serde(rename = "isPartOf")]
216 IsPartOf,
217}