1use surrealdb_types::{SqlFormat, ToSql, write_sql};
2
3use crate::{CoverStmts, Expr};
4
5#[derive(Clone, Debug, Default, PartialEq, Eq)]
6#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
7pub struct Permissions {
8 pub select: Permission,
9 pub create: Permission,
10 pub update: Permission,
11 pub delete: Permission,
12}
13
14impl Permissions {
15 pub fn none() -> Self {
16 Permissions {
17 select: Permission::None,
18 create: Permission::None,
19 update: Permission::None,
20 delete: Permission::None,
21 }
22 }
23
24 pub fn full() -> Self {
25 Permissions {
26 select: Permission::Full,
27 create: Permission::Full,
28 update: Permission::Full,
29 delete: Permission::Full,
30 }
31 }
32
33 pub fn is_none(&self) -> bool {
34 matches!(self.select, Permission::None)
35 && matches!(self.create, Permission::None)
36 && matches!(self.update, Permission::None)
37 && matches!(self.delete, Permission::None)
38 }
39
40 pub fn is_full(&self) -> bool {
41 matches!(self.select, Permission::Full)
42 && matches!(self.create, Permission::Full)
43 && matches!(self.update, Permission::Full)
44 && matches!(self.delete, Permission::Full)
45 }
46}
47
48#[derive(Clone, Copy, Eq, PartialEq, Debug)]
49pub enum PermissionKind {
50 Select,
51 Create,
52 Update,
53 Delete,
54}
55
56impl PermissionKind {
57 fn as_str(&self) -> &str {
58 match self {
59 PermissionKind::Select => "select",
60 PermissionKind::Create => "create",
61 PermissionKind::Update => "update",
62 PermissionKind::Delete => "delete",
63 }
64 }
65}
66
67pub struct FieldPermissions<'a>(pub &'a Permissions);
75
76impl surrealdb_types::ToSql for FieldPermissions<'_> {
77 fn fmt_sql(&self, f: &mut String, fmt: surrealdb_types::SqlFormat) {
78 self.0.fmt_sql_actions(f, fmt, false)
79 }
80}
81
82impl surrealdb_types::ToSql for Permissions {
83 fn fmt_sql(&self, f: &mut String, fmt: surrealdb_types::SqlFormat) {
84 self.fmt_sql_actions(f, fmt, true)
85 }
86}
87
88impl Permissions {
89 fn fmt_sql_actions(&self, f: &mut String, fmt: surrealdb_types::SqlFormat, delete: bool) {
92 f.push_str("PERMISSIONS");
93 if self.is_none() {
94 f.push_str(" NONE");
95 return;
96 }
97 if self.is_full() {
98 f.push_str(" FULL");
99 return;
100 }
101 let mut lines = Vec::<(Vec<PermissionKind>, &Permission)>::new();
102 for (c, permission) in [
103 PermissionKind::Select,
104 PermissionKind::Create,
105 PermissionKind::Update,
106 PermissionKind::Delete,
107 ]
108 .into_iter()
109 .zip([&self.select, &self.create, &self.update, &self.delete])
110 {
111 if matches!(c, PermissionKind::Delete) && !delete {
112 continue;
113 }
114
115 if let Some((existing, _)) = lines.iter_mut().find(|(_, p)| *p == permission) {
116 existing.push(c);
117 } else {
118 lines.push((vec![c], permission));
119 }
120 }
121 if fmt.is_pretty() {
122 f.push('\n');
123 let inner_fmt = fmt.increment();
124 inner_fmt.write_indent(f);
125 } else {
126 f.push(' ');
127 }
128 for (i, (kinds, permission)) in lines.into_iter().enumerate() {
129 if i > 0 {
130 if fmt.is_pretty() {
131 f.push(',');
132 f.push('\n');
133 let inner_fmt = fmt.increment();
134 inner_fmt.write_indent(f);
135 } else {
136 f.push_str(", ");
137 }
138 }
139 f.push_str("FOR ");
140 for (i, kind) in kinds.into_iter().enumerate() {
141 if i > 0 {
142 f.push_str(", ");
143 }
144 f.push_str(kind.as_str());
145 }
146 match permission {
147 Permission::Specific(v) if fmt.is_pretty() => {
148 f.push_str(" WHERE ");
149 CoverStmts(v).fmt_sql(f, fmt);
150 }
151 Permission::None => f.push_str(" NONE"),
152 Permission::Full => f.push_str(" FULL"),
153 Permission::Specific(v) => {
154 f.push_str(" WHERE ");
155 CoverStmts(v).fmt_sql(f, fmt);
156 }
157 }
158 }
159 }
160}
161
162#[derive(Clone, Debug, Default, PartialEq, Eq)]
163#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
164pub enum Permission {
165 None,
166 #[default]
167 Full,
168 Specific(Expr),
169}
170
171impl ToSql for Permission {
172 fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
173 match self {
174 Self::None => f.push_str("NONE"),
175 Self::Full => f.push_str("FULL"),
176 Self::Specific(v) => write_sql!(f, sql_fmt, "WHERE {}", CoverStmts(v)),
177 }
178 }
179}