Skip to main content

surrealdb_sql/statements/
access.rs

1use common::fmt::{EscapeIdent, EscapeKwFreeIdent, SqlDuration};
2use surrealdb_strand::Strand;
3use surrealdb_types::{SqlFormat, ToSql, write_sql};
4
5use crate::{Base, Cond, RecordIdLit};
6
7#[derive(Clone, Debug, PartialEq, Eq)]
8#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
9pub enum AccessStatement {
10	Grant(AccessStatementGrant),   // Create access grant.
11	Show(AccessStatementShow),     // Show access grants.
12	Revoke(AccessStatementRevoke), // Revoke access grant.
13	Purge(AccessStatementPurge),   // Purge access grants.
14}
15
16#[derive(Clone, Debug, PartialEq, Eq)]
17#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
18pub struct AccessStatementGrant {
19	pub ac: Strand,
20	pub base: Option<Base>,
21	pub subject: Subject,
22}
23
24#[derive(Clone, Debug, Default, PartialEq, Eq)]
25#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
26pub struct AccessStatementShow {
27	pub ac: Strand,
28	pub base: Option<Base>,
29	pub gr: Option<Strand>,
30	pub cond: Option<Cond>,
31}
32
33#[derive(Clone, Debug, Default, PartialEq, Eq)]
34#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
35pub struct AccessStatementRevoke {
36	pub ac: Strand,
37	pub base: Option<Base>,
38	pub gr: Option<Strand>,
39	pub cond: Option<Cond>,
40}
41
42#[derive(Clone, Debug, Default, PartialEq, Eq)]
43#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
44pub struct AccessStatementPurge {
45	pub ac: Strand,
46	pub base: Option<Base>,
47	pub kind: PurgeKind,
48	pub grace: std::time::Duration,
49}
50
51#[derive(Clone, Debug, Default, PartialEq, Eq)]
52#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
53pub enum PurgeKind {
54	#[default]
55	Expired,
56	Revoked,
57	Both,
58}
59
60#[derive(Clone, Debug, PartialEq, Eq)]
61pub enum Subject {
62	Record(RecordIdLit),
63	User(Strand),
64}
65
66impl ToSql for AccessStatement {
67	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
68		match self {
69			Self::Grant(stmt) => {
70				write_sql!(f, fmt, "ACCESS {}", EscapeKwFreeIdent(stmt.ac.as_str()));
71				if let Some(ref v) = stmt.base {
72					write_sql!(f, fmt, " ON {v}");
73				}
74				write_sql!(f, fmt, " GRANT");
75				match &stmt.subject {
76					Subject::User(x) => write_sql!(f, fmt, " FOR USER {}", EscapeIdent(x.as_str())),
77					Subject::Record(x) => write_sql!(f, fmt, " FOR RECORD {}", x),
78				}
79			}
80			Self::Show(stmt) => {
81				write_sql!(f, fmt, "ACCESS {}", EscapeKwFreeIdent(stmt.ac.as_str()));
82				if let Some(ref v) = stmt.base {
83					write_sql!(f, fmt, " ON {v}");
84				}
85				write_sql!(f, fmt, " SHOW");
86				match &stmt.gr {
87					Some(v) => write_sql!(f, fmt, " GRANT {}", EscapeKwFreeIdent(v.as_str())),
88					None => match &stmt.cond {
89						Some(v) => write_sql!(f, fmt, " {v}"),
90						None => write_sql!(f, fmt, " ALL"),
91					},
92				};
93			}
94			Self::Revoke(stmt) => {
95				write_sql!(f, fmt, "ACCESS {}", EscapeKwFreeIdent(stmt.ac.as_str()));
96				if let Some(ref v) = stmt.base {
97					write_sql!(f, fmt, " ON {v}");
98				}
99				write_sql!(f, fmt, " REVOKE");
100				match &stmt.gr {
101					Some(v) => write_sql!(f, fmt, " GRANT {}", EscapeKwFreeIdent(v.as_str())),
102					None => match &stmt.cond {
103						Some(v) => write_sql!(f, fmt, " {v}"),
104						None => write_sql!(f, fmt, " ALL"),
105					},
106				};
107			}
108			Self::Purge(stmt) => {
109				write_sql!(f, fmt, "ACCESS {}", EscapeKwFreeIdent(stmt.ac.as_str()));
110				if let Some(ref v) = stmt.base {
111					write_sql!(f, fmt, " ON {v}");
112				}
113				f.push_str(" PURGE");
114				match stmt.kind {
115					PurgeKind::Expired => f.push_str(" EXPIRED"),
116					PurgeKind::Revoked => f.push_str(" REVOKED"),
117					PurgeKind::Both => f.push_str(" EXPIRED, REVOKED"),
118				}
119				if !stmt.grace.is_zero() {
120					write_sql!(f, fmt, " FOR {}", SqlDuration(stmt.grace));
121				}
122			}
123		}
124	}
125}