1use serde::{Deserialize, Serialize};
10
11#[expect(
13 clippy::struct_excessive_bools,
14 reason = "models PostgreSQL's independently grantable table-shaped relation privileges"
15)]
16#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
17pub struct TablePrivileges {
18 #[serde(default)]
19 pub select: bool,
20 #[serde(default)]
21 pub insert: bool,
22 #[serde(default)]
23 pub update: bool,
24 #[serde(default)]
25 pub delete: bool,
26 #[serde(default)]
27 pub truncate: bool,
28 #[serde(default)]
29 pub references: bool,
30 #[serde(default)]
31 pub trigger: bool,
32 #[serde(default)]
33 pub maintain: bool,
34}
35
36impl TablePrivileges {
37 pub const ALL: Self = Self {
38 select: true,
39 insert: true,
40 update: true,
41 delete: true,
42 truncate: true,
43 references: true,
44 trigger: true,
45 maintain: true,
46 };
47
48 #[must_use]
49 pub const fn is_empty(self) -> bool {
50 !self.select
51 && !self.insert
52 && !self.update
53 && !self.delete
54 && !self.truncate
55 && !self.references
56 && !self.trigger
57 && !self.maintain
58 }
59
60 #[must_use]
61 pub const fn intersects(self, other: Self) -> bool {
62 self.select && other.select
63 || self.insert && other.insert
64 || self.update && other.update
65 || self.delete && other.delete
66 || self.truncate && other.truncate
67 || self.references && other.references
68 || self.trigger && other.trigger
69 || self.maintain && other.maintain
70 }
71
72 pub fn insert(&mut self, other: Self) {
73 self.select |= other.select;
74 self.insert |= other.insert;
75 self.update |= other.update;
76 self.delete |= other.delete;
77 self.truncate |= other.truncate;
78 self.references |= other.references;
79 self.trigger |= other.trigger;
80 self.maintain |= other.maintain;
81 }
82
83 pub fn remove(&mut self, other: Self) {
84 self.select &= !other.select;
85 self.insert &= !other.insert;
86 self.update &= !other.update;
87 self.delete &= !other.delete;
88 self.truncate &= !other.truncate;
89 self.references &= !other.references;
90 self.trigger &= !other.trigger;
91 self.maintain &= !other.maintain;
92 }
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
97pub struct TableAclEntry {
98 pub role: String,
99 #[serde(default, skip_serializing_if = "Option::is_none")]
100 pub grantor: Option<String>,
101 #[serde(default)]
102 pub privileges: TablePrivileges,
103 #[serde(default)]
104 pub grant_options: TablePrivileges,
105}