1use crate::sql::fmt::is_pretty;
2use crate::sql::fmt::pretty_indent;
3use crate::sql::fmt::pretty_sequence_item;
4use crate::sql::statements::info::InfoStructure;
5use crate::sql::Value;
6use revision::revisioned;
7use serde::{Deserialize, Serialize};
8use std::fmt::Write;
9use std::fmt::{self, Display, Formatter};
10use std::str;
11
12#[revisioned(revision = 1)]
13#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
14#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
15#[non_exhaustive]
16pub struct Permissions {
17 pub select: Permission,
18 pub create: Permission,
19 pub update: Permission,
20 pub delete: Permission,
21}
22
23impl Permissions {
24 pub fn none() -> Self {
25 Permissions {
26 select: Permission::None,
27 create: Permission::None,
28 update: Permission::None,
29 delete: Permission::None,
30 }
31 }
32
33 pub fn full() -> Self {
34 Permissions {
35 select: Permission::Full,
36 create: Permission::Full,
37 update: Permission::Full,
38 delete: Permission::Full,
39 }
40 }
41
42 pub fn is_none(&self) -> bool {
43 self.select == Permission::None
44 && self.create == Permission::None
45 && self.update == Permission::None
46 && self.delete == Permission::None
47 }
48
49 pub fn is_full(&self) -> bool {
50 self.select == Permission::Full
51 && self.create == Permission::Full
52 && self.update == Permission::Full
53 && self.delete == Permission::Full
54 }
55}
56
57impl Display for Permissions {
58 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
59 write!(f, "PERMISSIONS")?;
60 if self.is_none() {
61 return write!(f, " NONE");
62 }
63 if self.is_full() {
64 return write!(f, " FULL");
65 }
66 let mut lines = Vec::<(Vec<PermissionKind>, &Permission)>::new();
67 for (c, permission) in [
68 PermissionKind::Select,
69 PermissionKind::Create,
70 PermissionKind::Update,
71 PermissionKind::Delete,
72 ]
73 .into_iter()
74 .zip([&self.select, &self.create, &self.update, &self.delete])
75 {
76 if f.alternate() && matches!(c, PermissionKind::Delete) {
81 continue;
82 }
83
84 if let Some((existing, _)) = lines.iter_mut().find(|(_, p)| *p == permission) {
85 existing.push(c);
86 } else {
87 lines.push((vec![c], permission));
88 }
89 }
90 let indent = if is_pretty() {
91 Some(pretty_indent())
92 } else {
93 f.write_char(' ')?;
94 None
95 };
96 for (i, (kinds, permission)) in lines.into_iter().enumerate() {
97 if i > 0 {
98 if is_pretty() {
99 pretty_sequence_item();
100 } else {
101 f.write_str(", ")?;
102 }
103 }
104 write!(f, "FOR ")?;
105 for (i, kind) in kinds.into_iter().enumerate() {
106 if i > 0 {
107 f.write_str(", ")?;
108 }
109 f.write_str(kind.as_str())?;
110 }
111 match permission {
112 Permission::Specific(_) if is_pretty() => {
113 let _indent = pretty_indent();
114 Display::fmt(permission, f)?;
115 }
116 _ => write!(f, " {permission}")?,
117 }
118 }
119 drop(indent);
120 Ok(())
121 }
122}
123
124impl InfoStructure for Permissions {
125 fn structure(self) -> Value {
126 Value::from(map! {
127 "select".to_string() => self.select.structure(),
128 "create".to_string() => self.create.structure(),
129 "update".to_string() => self.update.structure(),
130 "delete".to_string() => self.delete.structure(),
132 })
133 }
134}
135
136#[derive(Clone, Copy, Eq, PartialEq, Debug)]
137pub(crate) enum PermissionKind {
138 Select,
139 Create,
140 Update,
141 Delete,
142}
143
144impl PermissionKind {
145 fn as_str(&self) -> &str {
146 match self {
147 PermissionKind::Select => "select",
148 PermissionKind::Create => "create",
149 PermissionKind::Update => "update",
150 PermissionKind::Delete => "delete",
151 }
152 }
153}
154
155#[revisioned(revision = 1)]
156#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
157#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
158#[non_exhaustive]
159pub enum Permission {
160 None,
161 #[default]
162 Full,
163 Specific(Value),
164}
165
166impl Permission {
167 pub fn is_none(&self) -> bool {
168 matches!(self, Self::None)
169 }
170
171 pub fn is_full(&self) -> bool {
172 matches!(self, Self::Full)
173 }
174
175 pub fn is_specific(&self) -> bool {
176 matches!(self, Self::Specific(_))
177 }
178}
179
180impl Display for Permission {
181 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
182 match self {
183 Self::None => f.write_str("NONE"),
184 Self::Full => f.write_str("FULL"),
185 Self::Specific(ref v) => write!(f, "WHERE {v}"),
186 }
187 }
188}
189
190impl InfoStructure for Permission {
191 fn structure(self) -> Value {
192 match self {
193 Permission::None => Value::Bool(false),
194 Permission::Full => Value::Bool(true),
195 Permission::Specific(v) => v.to_string().into(),
196 }
197 }
198}