surrealdb_core/iam/
auth.rs

1use crate::sql::statements::{DefineAccessStatement, DefineUserStatement};
2use revision::revisioned;
3use serde::{Deserialize, Serialize};
4
5use super::{is_allowed, Action, Actor, Error, Level, Resource, Role};
6
7/// Specifies the current authentication for the datastore execution context.
8#[revisioned(revision = 1)]
9#[derive(Clone, Default, Debug, Eq, PartialEq, PartialOrd, Hash, Serialize, Deserialize)]
10#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
11#[non_exhaustive]
12pub struct Auth {
13	actor: Actor,
14}
15
16impl Auth {
17	pub fn new(actor: Actor) -> Self {
18		Self {
19			actor,
20		}
21	}
22
23	pub fn id(&self) -> &str {
24		self.actor.id()
25	}
26
27	/// Return current authentication level
28	pub fn level(&self) -> &Level {
29		self.actor.level()
30	}
31
32	/// Check if the current auth is anonymous
33	pub fn is_anon(&self) -> bool {
34		matches!(self.level(), Level::No)
35	}
36
37	/// Check if the current level is Root
38	pub fn is_root(&self) -> bool {
39		matches!(self.level(), Level::Root)
40	}
41
42	/// Check if the current level is Namespace
43	pub fn is_ns(&self) -> bool {
44		matches!(self.level(), Level::Namespace(_))
45	}
46
47	/// Check if the current level is Database
48	pub fn is_db(&self) -> bool {
49		matches!(self.level(), Level::Database(_, _))
50	}
51
52	/// Check if the current level is Record
53	pub fn is_record(&self) -> bool {
54		matches!(self.level(), Level::Record(_, _, _))
55	}
56
57	/// Check if the current level is Namespace, and the namespace matches
58	pub fn is_ns_check(&self, ns: &str) -> bool {
59		matches!(self.level(), Level::Namespace(n) if n.eq(ns))
60	}
61
62	/// Check if the current level is Database, and the namespace and database match
63	pub fn is_db_check(&self, ns: &str, db: &str) -> bool {
64		matches!(self.level(), Level::Database(n, d) if n.eq(ns) && d.eq(db))
65	}
66
67	/// System Auth helpers
68	///
69	/// These are not stored in the database and are used for internal operations
70	/// Do not use for authentication
71	pub fn for_root(role: Role) -> Self {
72		Self::new(Actor::new("system_auth".into(), vec![role], Level::Root))
73	}
74
75	pub fn for_ns(role: Role, ns: &str) -> Self {
76		Self::new(Actor::new("system_auth".into(), vec![role], (ns,).into()))
77	}
78
79	pub fn for_db(role: Role, ns: &str, db: &str) -> Self {
80		Self::new(Actor::new("system_auth".into(), vec![role], (ns, db).into()))
81	}
82
83	pub fn for_record(rid: String, ns: &str, db: &str, ac: &str) -> Self {
84		Self::new(Actor::new(rid.to_string(), vec![], (ns, db, ac).into()))
85	}
86
87	//
88	// Permission checks
89	//
90
91	/// Checks if the current auth is allowed to perform an action on a given resource
92	pub fn is_allowed(&self, action: Action, res: &Resource) -> Result<(), Error> {
93		is_allowed(&self.actor, &action, res, None)
94	}
95
96	/// Checks if the current actor has a given role
97	pub fn has_role(&self, role: Role) -> bool {
98		self.actor.has_role(role)
99	}
100
101	/// Checks if the current actor has a Owner role
102	pub fn has_owner_role(&self) -> bool {
103		self.actor.has_owner_role()
104	}
105
106	/// Checks if the current actor has a Editor role
107	pub fn has_editor_role(&self) -> bool {
108		self.actor.has_editor_role()
109	}
110
111	/// Checks if the current actor has a Viewer role
112	pub fn has_viewer_role(&self) -> bool {
113		self.actor.has_viewer_role()
114	}
115}
116
117impl std::convert::TryFrom<(&DefineUserStatement, Level)> for Auth {
118	type Error = Error;
119	fn try_from(val: (&DefineUserStatement, Level)) -> Result<Self, Self::Error> {
120		Ok(Self::new((val.0, val.1).try_into()?))
121	}
122}
123
124impl std::convert::From<(&DefineAccessStatement, Level)> for Auth {
125	fn from(val: (&DefineAccessStatement, Level)) -> Self {
126		Self::new((val.0, val.1).into())
127	}
128}