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, 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 pub fn matches_action(&self, action: &str) -> bool {
126 self == &RuleAction::Use || self.as_permission_name() == action
127 }
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct OdrlConstraint {
133 #[serde(rename = "leftOperand")]
135 pub left_operand: ConstraintOperand,
136 pub operator: ConstraintOperator,
138 #[serde(rename = "rightOperand")]
140 pub right_operand: String,
141}
142
143#[derive(Debug, Clone, PartialEq, Eq)]
145pub enum ConstraintOperand {
146 Purpose,
148 DateTime,
150 Count,
152 Custom(String),
154}
155
156impl ConstraintOperand {
157 pub fn parse(name: impl Into<String>) -> Self {
159 let name = name.into();
160 match name.as_str() {
161 "purpose" => Self::Purpose,
162 "dateTime" | "date" => Self::DateTime,
163 "count" => Self::Count,
164 _ => Self::Custom(name),
165 }
166 }
167
168 pub fn as_str(&self) -> &str {
170 match self {
171 Self::Purpose => "purpose",
172 Self::DateTime => "dateTime",
173 Self::Count => "count",
174 Self::Custom(name) => name,
175 }
176 }
177}
178
179impl fmt::Display for ConstraintOperand {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 f.write_str(self.as_str())
182 }
183}
184
185impl Serialize for ConstraintOperand {
186 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
187 where
188 S: Serializer,
189 {
190 serializer.serialize_str(self.as_str())
191 }
192}
193
194impl<'de> Deserialize<'de> for ConstraintOperand {
195 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
196 where
197 D: Deserializer<'de>,
198 {
199 String::deserialize(deserializer).map(Self::parse)
200 }
201}
202
203#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
205#[serde(rename_all = "camelCase")]
206pub enum ConstraintOperator {
207 Eq,
209 Neq,
211 Lt,
213 Lteq,
215 Gt,
217 Gteq,
219 #[serde(rename = "isPartOf")]
221 IsPartOf,
222}