surrealdb_core/dbs/
session.rs

1use crate::ctx::MutableContext;
2use crate::iam::Auth;
3use crate::iam::{Level, Role};
4use crate::sql::value::Value;
5use chrono::Utc;
6use std::collections::BTreeMap;
7use std::sync::Arc;
8
9/// Specifies the current session information when processing a query.
10#[derive(Clone, Debug, Default, Eq, PartialEq)]
11#[non_exhaustive]
12pub struct Session {
13	/// The current session [`Auth`] information
14	pub au: Arc<Auth>,
15	/// Whether realtime queries are supported
16	pub rt: bool,
17	/// The current connection IP address
18	pub ip: Option<String>,
19	/// The current connection origin
20	pub or: Option<String>,
21	/// The current connection ID
22	pub id: Option<String>,
23	/// The currently selected namespace
24	pub ns: Option<String>,
25	/// The currently selected database
26	pub db: Option<String>,
27	/// The current access method
28	pub ac: Option<String>,
29	/// The current authentication token
30	pub tk: Option<Value>,
31	/// The current record authentication data
32	pub rd: Option<Value>,
33	/// The current expiration time of the session
34	pub exp: Option<i64>,
35	/// The parameters set
36	pub parameters: BTreeMap<String, Value>,
37}
38
39impl Session {
40	/// Set the selected namespace for the session
41	pub fn with_ns(mut self, ns: &str) -> Session {
42		self.ns = Some(ns.to_owned());
43		self
44	}
45
46	/// Set the selected database for the session
47	pub fn with_db(mut self, db: &str) -> Session {
48		self.db = Some(db.to_owned());
49		self
50	}
51
52	/// Set the selected access method for the session
53	pub fn with_ac(mut self, ac: &str) -> Session {
54		self.ac = Some(ac.to_owned());
55		self
56	}
57
58	// Set the realtime functionality of the session
59	pub fn with_rt(mut self, rt: bool) -> Session {
60		self.rt = rt;
61		self
62	}
63
64	/// Retrieves the selected namespace
65	pub(crate) fn ns(&self) -> Option<Arc<str>> {
66		self.ns.as_deref().map(Into::into)
67	}
68
69	/// Retrieves the selected database
70	pub(crate) fn db(&self) -> Option<Arc<str>> {
71		self.db.as_deref().map(Into::into)
72	}
73
74	/// Checks if live queries are allowed
75	pub(crate) fn live(&self) -> bool {
76		self.rt
77	}
78
79	/// Checks if the session has expired
80	pub(crate) fn expired(&self) -> bool {
81		match self.exp {
82			Some(exp) => Utc::now().timestamp() > exp,
83			// It is currently possible to have sessions without expiration.
84			None => false,
85		}
86	}
87
88	pub(crate) fn values(&self) -> Vec<(&'static str, Value)> {
89		let access: Value = self.ac.to_owned().into();
90		let auth: Value = self.rd.to_owned().into();
91		let token: Value = self.tk.to_owned().into();
92		let session: Value = Value::from(map! {
93			"ac".to_string() => self.ac.to_owned().into(),
94			"exp".to_string() => self.exp.to_owned().into(),
95			"db".to_string() => self.db.to_owned().into(),
96			"id".to_string() => self.id.to_owned().into(),
97			"ip".to_string() => self.ip.to_owned().into(),
98			"ns".to_string() => self.ns.to_owned().into(),
99			"or".to_string() => self.or.to_owned().into(),
100			"rd".to_string() => self.rd.to_owned().into(),
101			"tk".to_string() => self.tk.to_owned().into(),
102		});
103
104		vec![("access", access), ("auth", auth), ("token", token), ("session", session)]
105	}
106
107	/// Convert a session into a runtime
108	pub(crate) fn context(&self, ctx: &mut MutableContext) {
109		let vars = self.values().into_iter();
110
111		ctx.add_values(vars);
112	}
113
114	/// Create a system session for a given level and role
115	pub fn for_level(level: Level, role: Role) -> Session {
116		// Create a new session
117		let mut sess = Session::default();
118		// Set the session details
119		match level {
120			Level::Root => {
121				sess.au = Arc::new(Auth::for_root(role));
122			}
123			Level::Namespace(ns) => {
124				sess.au = Arc::new(Auth::for_ns(role, &ns));
125				sess.ns = Some(ns);
126			}
127			Level::Database(ns, db) => {
128				sess.au = Arc::new(Auth::for_db(role, &ns, &db));
129				sess.ns = Some(ns);
130				sess.db = Some(db);
131			}
132			_ => {}
133		}
134		sess
135	}
136
137	/// Create a record user session for a given NS and DB
138	pub fn for_record(ns: &str, db: &str, ac: &str, rid: Value) -> Session {
139		Session {
140			ac: Some(ac.to_owned()),
141			au: Arc::new(Auth::for_record(rid.to_string(), ns, db, ac)),
142			rt: false,
143			ip: None,
144			or: None,
145			id: None,
146			ns: Some(ns.to_owned()),
147			db: Some(db.to_owned()),
148			tk: None,
149			rd: Some(rid),
150			exp: None,
151			parameters: Default::default(),
152		}
153	}
154
155	/// Create a system session for the root level with Owner role
156	pub fn owner() -> Session {
157		Session::for_level(Level::Root, Role::Owner)
158	}
159
160	/// Create a system session for the root level with Editor role
161	pub fn editor() -> Session {
162		Session::for_level(Level::Root, Role::Editor)
163	}
164
165	/// Create a system session for the root level with Viewer role
166	pub fn viewer() -> Session {
167		Session::for_level(Level::Root, Role::Viewer)
168	}
169}