Skip to main content

surql_parser/upstream/sql/
permission.rs

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