[security] Introduce "allow-guests". Deny all caps by default (#2547)
This commit is contained in:
parent
0d43e7a156
commit
bdac1fae72
54 changed files with 961 additions and 593 deletions
|
@ -145,7 +145,7 @@ dependencies = ["build-surrealdb"]
|
|||
script = """
|
||||
#!/bin/bash -ex
|
||||
|
||||
target/debug/surreal start ${_START_SURREALDB_PATH} &>/tmp/surrealdb.log &
|
||||
target/debug/surreal start ${_START_SURREALDB_PATH} --allow-all &>/tmp/surrealdb.log &
|
||||
|
||||
echo $! > /tmp/surreal.pid
|
||||
|
||||
|
|
|
@ -65,11 +65,17 @@ category = "LOCAL USAGE"
|
|||
command = "cargo"
|
||||
args = ["bench", "--package", "surrealdb", "--no-default-features", "--features", "kv-mem,http,scripting"]
|
||||
|
||||
# Run
|
||||
[tasks.run]
|
||||
category = "LOCAL USAGE"
|
||||
command = "cargo"
|
||||
args = ["run", "--no-default-features", "--features", "${DEV_FEATURES}", "--", "${@}"]
|
||||
|
||||
# Serve
|
||||
[tasks.serve]
|
||||
category = "LOCAL USAGE"
|
||||
command = "cargo"
|
||||
args = ["run", "--no-default-features", "--features", "${DEV_FEATURES}", "--", "start", "${@}"]
|
||||
args = ["run", "--no-default-features", "--features", "${DEV_FEATURES}", "--", "start", "--allow-all", "${@}"]
|
||||
|
||||
# SQL
|
||||
[tasks.sql]
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
|
||||
use pprof::criterion::{Output, PProfProfiler};
|
||||
use surrealdb::{dbs::Session, kvs::Datastore};
|
||||
use surrealdb::{
|
||||
dbs::{Capabilities, Session},
|
||||
kvs::Datastore,
|
||||
};
|
||||
|
||||
macro_rules! query {
|
||||
($c: expr, $name: ident, $query: expr) => {
|
||||
|
@ -9,7 +12,8 @@ macro_rules! query {
|
|||
($c: expr, $name: ident, $setup: expr, $query: expr) => {
|
||||
$c.bench_function(stringify!($name), |b| {
|
||||
let (dbs, ses) = futures::executor::block_on(async {
|
||||
let dbs = Datastore::new("memory").await.unwrap();
|
||||
let dbs =
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(Capabilities::all());
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let setup = $setup;
|
||||
if !setup.is_empty() {
|
||||
|
|
|
@ -228,6 +228,7 @@ pub fn connect(address: impl IntoEndpoint) -> Connect<Any, Surreal<Any>> {
|
|||
#[cfg(all(test, feature = "kv-mem"))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::dbs::Capabilities;
|
||||
use crate::opt::auth::Root;
|
||||
use crate::sql::{test::Parse, value::Value};
|
||||
|
||||
|
@ -264,7 +265,9 @@ mod tests {
|
|||
username: "root",
|
||||
password: "root",
|
||||
};
|
||||
let db = connect(("memory", Config::new().user(creds))).await.unwrap();
|
||||
let db = connect(("memory", Config::new().user(creds).capabilities(Capabilities::all())))
|
||||
.await
|
||||
.unwrap();
|
||||
db.use_ns("N").use_db("D").await.unwrap();
|
||||
|
||||
// The client needs to sign in before it can access anything
|
||||
|
|
|
@ -140,7 +140,8 @@ pub(crate) fn router(
|
|||
let kvs = kvs
|
||||
.with_strict_mode(address.config.strict)
|
||||
.with_query_timeout(address.config.query_timeout)
|
||||
.with_transaction_timeout(address.config.transaction_timeout);
|
||||
.with_transaction_timeout(address.config.transaction_timeout)
|
||||
.with_capabilities(address.config.capabilities);
|
||||
|
||||
let kvs = match address.config.notifications {
|
||||
true => kvs.with_notifications(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::iam::Level;
|
||||
use crate::{dbs::Capabilities, iam::Level};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Configuration for server connection, including: strictness, notifications, query_timeout, transaction_timeout
|
||||
|
@ -16,6 +16,7 @@ pub struct Config {
|
|||
pub(crate) username: String,
|
||||
pub(crate) password: String,
|
||||
pub(crate) tick_interval: Option<Duration>,
|
||||
pub(crate) capabilities: Capabilities,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
@ -89,4 +90,10 @@ impl Config {
|
|||
self.tick_interval = interval.into().filter(|x| !x.is_zero());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the capabilities for the database
|
||||
pub fn capabilities(mut self, capabilities: Capabilities) -> Self {
|
||||
self.capabilities = capabilities;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ impl<'a> Context<'a> {
|
|||
/// Check if scripting is allowed
|
||||
#[allow(dead_code)]
|
||||
pub fn check_allowed_scripting(&self) -> Result<(), Error> {
|
||||
if !self.capabilities.is_allowed_scripting() {
|
||||
if !self.capabilities.allows_scripting() {
|
||||
return Err(Error::ScriptingNotAllowed);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -233,7 +233,7 @@ impl<'a> Context<'a> {
|
|||
message: "Invalid function name".to_string(),
|
||||
})?;
|
||||
|
||||
if !self.capabilities.is_allowed_func(&func_target) {
|
||||
if !self.capabilities.allows_function(&func_target) {
|
||||
return Err(Error::FunctionNotAllowed(target.to_string()));
|
||||
}
|
||||
Ok(())
|
||||
|
@ -244,7 +244,7 @@ impl<'a> Context<'a> {
|
|||
pub fn check_allowed_net(&self, target: &Url) -> Result<(), Error> {
|
||||
match target.host() {
|
||||
Some(host)
|
||||
if self.capabilities.is_allowed_net(&NetTarget::Host(
|
||||
if self.capabilities.allows_network_target(&NetTarget::Host(
|
||||
host.to_owned(),
|
||||
target.port_or_known_default(),
|
||||
)) =>
|
||||
|
|
|
@ -12,6 +12,15 @@ pub trait Target {
|
|||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct FuncTarget(pub String, pub Option<String>);
|
||||
|
||||
impl std::fmt::Display for FuncTarget {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match &self.1 {
|
||||
Some(name) => write!(f, "{}:{}", self.0, name),
|
||||
None => write!(f, "{}::*", self.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Target for FuncTarget {
|
||||
fn matches(&self, elem: &Self) -> bool {
|
||||
match self {
|
||||
|
@ -44,6 +53,17 @@ pub enum NetTarget {
|
|||
IPNet(ipnet::IpNet),
|
||||
}
|
||||
|
||||
// impl display
|
||||
impl std::fmt::Display for NetTarget {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Host(host, Some(port)) => write!(f, "{}:{}", host, port),
|
||||
Self::Host(host, None) => write!(f, "{}", host),
|
||||
Self::IPNet(ipnet) => write!(f, "{}", ipnet),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Target for NetTarget {
|
||||
fn matches(&self, elem: &Self) -> bool {
|
||||
match self {
|
||||
|
@ -109,7 +129,7 @@ pub enum Targets<T: Target + Hash + Eq + PartialEq> {
|
|||
All,
|
||||
}
|
||||
|
||||
impl<T: Target + Hash + Eq + PartialEq + std::fmt::Debug> Targets<T> {
|
||||
impl<T: Target + Hash + Eq + PartialEq + std::fmt::Debug + std::fmt::Display> Targets<T> {
|
||||
fn matches(&self, elem: &T) -> bool {
|
||||
match self {
|
||||
Self::None => false,
|
||||
|
@ -119,17 +139,33 @@ impl<T: Target + Hash + Eq + PartialEq + std::fmt::Debug> Targets<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Target + Hash + Eq + PartialEq + std::fmt::Display> std::fmt::Display for Targets<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::None => write!(f, "none"),
|
||||
Self::All => write!(f, "all"),
|
||||
Self::Some(targets) => {
|
||||
let targets =
|
||||
targets.iter().map(|t| t.to_string()).collect::<Vec<String>>().join(", ");
|
||||
write!(f, "{}", targets)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Capabilities are used to limit what a user can do to the system.
|
||||
///
|
||||
/// Capabilities are split into 3 categories:
|
||||
/// Capabilities are split into 4 categories:
|
||||
/// - Scripting: Whether or not the user can execute scripts
|
||||
/// - Guest access: Whether or not a non-authenticated user can execute queries on the system when authentication is enabled.
|
||||
/// - Functions: Whether or not the user can execute certain functions
|
||||
/// - Network: Whether or not the user can access certain network addresses
|
||||
///
|
||||
/// Capabilities are configured globally. By default, capabilities are configured as:
|
||||
/// - Scripting: true
|
||||
/// - Functions: All functions are allowed
|
||||
/// - Network: All network addresses are allowed
|
||||
/// - Scripting: false
|
||||
/// - Guest access: false
|
||||
/// - Functions: No function is allowed nor denied, hence all functions are denied unless explicitly allowed
|
||||
/// - Network: No network address is allowed nor denied, hence all network addresses are denied unless explicitly allowed
|
||||
///
|
||||
/// The capabilities are defined using allow/deny lists for fine-grained control.
|
||||
///
|
||||
|
@ -141,6 +177,7 @@ impl<T: Target + Hash + Eq + PartialEq + std::fmt::Debug> Targets<T> {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Capabilities {
|
||||
scripting: bool,
|
||||
guest_access: bool,
|
||||
|
||||
allow_funcs: Arc<Targets<FuncTarget>>,
|
||||
deny_funcs: Arc<Targets<FuncTarget>>,
|
||||
|
@ -148,11 +185,39 @@ pub struct Capabilities {
|
|||
deny_net: Arc<Targets<NetTarget>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Capabilities {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"scripting={}, guest_access={}, allow_funcs={}, deny_funcs={}, allow_net={}, deny_net={}",
|
||||
self.scripting, self.guest_access, self.allow_funcs, self.deny_funcs, self.allow_net, self.deny_net
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Capabilities {
|
||||
// By default, enable all capabilities
|
||||
fn default() -> Self {
|
||||
Self::none()
|
||||
}
|
||||
}
|
||||
|
||||
impl Capabilities {
|
||||
fn none() -> Self {
|
||||
Self {
|
||||
scripting: false,
|
||||
guest_access: false,
|
||||
|
||||
allow_funcs: Arc::new(Targets::None),
|
||||
deny_funcs: Arc::new(Targets::None),
|
||||
allow_net: Arc::new(Targets::None),
|
||||
deny_net: Arc::new(Targets::None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all() -> Self {
|
||||
Self {
|
||||
scripting: true,
|
||||
guest_access: true,
|
||||
|
||||
allow_funcs: Arc::new(Targets::All),
|
||||
deny_funcs: Arc::new(Targets::None),
|
||||
|
@ -160,43 +225,50 @@ impl Default for Capabilities {
|
|||
deny_net: Arc::new(Targets::None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Capabilities {
|
||||
pub fn with_scripting(mut self, scripting: bool) -> Self {
|
||||
self.scripting = scripting;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_allow_funcs(mut self, allow_funcs: Targets<FuncTarget>) -> Self {
|
||||
pub fn with_guest_access(mut self, guest_access: bool) -> Self {
|
||||
self.guest_access = guest_access;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_functions(mut self, allow_funcs: Targets<FuncTarget>) -> Self {
|
||||
self.allow_funcs = Arc::new(allow_funcs);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_deny_funcs(mut self, deny_funcs: Targets<FuncTarget>) -> Self {
|
||||
pub fn without_functions(mut self, deny_funcs: Targets<FuncTarget>) -> Self {
|
||||
self.deny_funcs = Arc::new(deny_funcs);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_allow_net(mut self, allow_net: Targets<NetTarget>) -> Self {
|
||||
pub fn with_network_targets(mut self, allow_net: Targets<NetTarget>) -> Self {
|
||||
self.allow_net = Arc::new(allow_net);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_deny_net(mut self, deny_net: Targets<NetTarget>) -> Self {
|
||||
pub fn without_network_targets(mut self, deny_net: Targets<NetTarget>) -> Self {
|
||||
self.deny_net = Arc::new(deny_net);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn is_allowed_scripting(&self) -> bool {
|
||||
pub fn allows_scripting(&self) -> bool {
|
||||
self.scripting
|
||||
}
|
||||
|
||||
pub fn is_allowed_func(&self, target: &FuncTarget) -> bool {
|
||||
pub fn allows_guest_access(&self) -> bool {
|
||||
self.guest_access
|
||||
}
|
||||
|
||||
pub fn allows_function(&self, target: &FuncTarget) -> bool {
|
||||
self.allow_funcs.matches(target) && !self.deny_funcs.matches(target)
|
||||
}
|
||||
|
||||
pub fn is_allowed_net(&self, target: &NetTarget) -> bool {
|
||||
pub fn allows_network_target(&self, target: &NetTarget) -> bool {
|
||||
self.allow_net.matches(target) && !self.deny_net.matches(target)
|
||||
}
|
||||
}
|
||||
|
@ -403,77 +475,89 @@ mod tests {
|
|||
// When scripting is allowed
|
||||
{
|
||||
let caps = Capabilities::default().with_scripting(true);
|
||||
assert!(caps.is_allowed_scripting());
|
||||
assert!(caps.allows_scripting());
|
||||
}
|
||||
|
||||
// When scripting is denied
|
||||
{
|
||||
let caps = Capabilities::default().with_scripting(false);
|
||||
assert!(!caps.is_allowed_scripting());
|
||||
assert!(!caps.allows_scripting());
|
||||
}
|
||||
|
||||
// When guest access is allowed
|
||||
{
|
||||
let caps = Capabilities::default().with_guest_access(true);
|
||||
assert!(caps.allows_guest_access());
|
||||
}
|
||||
|
||||
// When guest access is denied
|
||||
{
|
||||
let caps = Capabilities::default().with_guest_access(false);
|
||||
assert!(!caps.allows_guest_access());
|
||||
}
|
||||
|
||||
// When all nets are allowed
|
||||
{
|
||||
let caps = Capabilities::default()
|
||||
.with_allow_net(Targets::<NetTarget>::All)
|
||||
.with_deny_net(Targets::<NetTarget>::None);
|
||||
assert!(caps.is_allowed_net(&NetTarget::from_str("example.com").unwrap()));
|
||||
assert!(caps.is_allowed_net(&NetTarget::from_str("example.com:80").unwrap()));
|
||||
.with_network_targets(Targets::<NetTarget>::All)
|
||||
.without_network_targets(Targets::<NetTarget>::None);
|
||||
assert!(caps.allows_network_target(&NetTarget::from_str("example.com").unwrap()));
|
||||
assert!(caps.allows_network_target(&NetTarget::from_str("example.com:80").unwrap()));
|
||||
}
|
||||
|
||||
// When all nets are allowed and denied at the same time
|
||||
{
|
||||
let caps = Capabilities::default()
|
||||
.with_allow_net(Targets::<NetTarget>::All)
|
||||
.with_deny_net(Targets::<NetTarget>::All);
|
||||
assert!(!caps.is_allowed_net(&NetTarget::from_str("example.com").unwrap()));
|
||||
assert!(!caps.is_allowed_net(&NetTarget::from_str("example.com:80").unwrap()));
|
||||
.with_network_targets(Targets::<NetTarget>::All)
|
||||
.without_network_targets(Targets::<NetTarget>::All);
|
||||
assert!(!caps.allows_network_target(&NetTarget::from_str("example.com").unwrap()));
|
||||
assert!(!caps.allows_network_target(&NetTarget::from_str("example.com:80").unwrap()));
|
||||
}
|
||||
|
||||
// When some nets are allowed and some are denied, deny overrides the allow rules
|
||||
{
|
||||
let caps = Capabilities::default()
|
||||
.with_allow_net(Targets::<NetTarget>::Some(
|
||||
.with_network_targets(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str("example.com").unwrap()].into(),
|
||||
))
|
||||
.with_deny_net(Targets::<NetTarget>::Some(
|
||||
.without_network_targets(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str("example.com:80").unwrap()].into(),
|
||||
));
|
||||
assert!(caps.is_allowed_net(&NetTarget::from_str("example.com").unwrap()));
|
||||
assert!(caps.is_allowed_net(&NetTarget::from_str("example.com:443").unwrap()));
|
||||
assert!(!caps.is_allowed_net(&NetTarget::from_str("example.com:80").unwrap()));
|
||||
assert!(caps.allows_network_target(&NetTarget::from_str("example.com").unwrap()));
|
||||
assert!(caps.allows_network_target(&NetTarget::from_str("example.com:443").unwrap()));
|
||||
assert!(!caps.allows_network_target(&NetTarget::from_str("example.com:80").unwrap()));
|
||||
}
|
||||
|
||||
// When all funcs are allowed
|
||||
{
|
||||
let caps = Capabilities::default()
|
||||
.with_allow_funcs(Targets::<FuncTarget>::All)
|
||||
.with_deny_funcs(Targets::<FuncTarget>::None);
|
||||
assert!(caps.is_allowed_func(&FuncTarget::from_str("http::get").unwrap()));
|
||||
assert!(caps.is_allowed_func(&FuncTarget::from_str("http::post").unwrap()));
|
||||
.with_functions(Targets::<FuncTarget>::All)
|
||||
.without_functions(Targets::<FuncTarget>::None);
|
||||
assert!(caps.allows_function(&FuncTarget::from_str("http::get").unwrap()));
|
||||
assert!(caps.allows_function(&FuncTarget::from_str("http::post").unwrap()));
|
||||
}
|
||||
|
||||
// When all funcs are allowed and denied at the same time
|
||||
{
|
||||
let caps = Capabilities::default()
|
||||
.with_allow_funcs(Targets::<FuncTarget>::All)
|
||||
.with_deny_funcs(Targets::<FuncTarget>::All);
|
||||
assert!(!caps.is_allowed_func(&FuncTarget::from_str("http::get").unwrap()));
|
||||
assert!(!caps.is_allowed_func(&FuncTarget::from_str("http::post").unwrap()));
|
||||
.with_functions(Targets::<FuncTarget>::All)
|
||||
.without_functions(Targets::<FuncTarget>::All);
|
||||
assert!(!caps.allows_function(&FuncTarget::from_str("http::get").unwrap()));
|
||||
assert!(!caps.allows_function(&FuncTarget::from_str("http::post").unwrap()));
|
||||
}
|
||||
|
||||
// When some funcs are allowed and some are denied, deny overrides the allow rules
|
||||
{
|
||||
let caps = Capabilities::default()
|
||||
.with_allow_funcs(Targets::<FuncTarget>::Some(
|
||||
.with_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::*").unwrap()].into(),
|
||||
))
|
||||
.with_deny_funcs(Targets::<FuncTarget>::Some(
|
||||
.without_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::post").unwrap()].into(),
|
||||
));
|
||||
assert!(caps.is_allowed_func(&FuncTarget::from_str("http::get").unwrap()));
|
||||
assert!(caps.is_allowed_func(&FuncTarget::from_str("http::put").unwrap()));
|
||||
assert!(!caps.is_allowed_func(&FuncTarget::from_str("http::post").unwrap()));
|
||||
assert!(caps.allows_function(&FuncTarget::from_str("http::get").unwrap()));
|
||||
assert!(caps.allows_function(&FuncTarget::from_str("http::put").unwrap()));
|
||||
assert!(!caps.allows_function(&FuncTarget::from_str("http::post").unwrap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ pub use self::options::*;
|
|||
pub use self::response::*;
|
||||
pub use self::session::*;
|
||||
|
||||
pub(crate) use self::capabilities::Capabilities;
|
||||
pub(crate) use self::executor::*;
|
||||
pub(crate) use self::iterator::*;
|
||||
pub(crate) use self::statement::*;
|
||||
|
@ -27,6 +26,7 @@ pub(crate) use self::transaction::*;
|
|||
pub(crate) use self::variables::*;
|
||||
|
||||
pub mod capabilities;
|
||||
pub use self::capabilities::Capabilities;
|
||||
pub mod node;
|
||||
|
||||
mod processor;
|
||||
|
|
|
@ -370,6 +370,9 @@ pub async fn asynchronous(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[cfg(all(feature = "scripting", feature = "kv-mem"))]
|
||||
use crate::dbs::Capabilities;
|
||||
|
||||
#[test]
|
||||
fn implementations_are_present() {
|
||||
// Accumulate and display all problems at once to avoid a test -> fix -> test -> fix cycle.
|
||||
|
@ -399,7 +402,10 @@ mod tests {
|
|||
let name = name.replace("::", ".");
|
||||
let sql =
|
||||
format!("RETURN function() {{ return typeof surrealdb.functions.{name}; }}");
|
||||
let dbs = crate::kvs::Datastore::new("memory").await.unwrap();
|
||||
let dbs = crate::kvs::Datastore::new("memory")
|
||||
.await
|
||||
.unwrap()
|
||||
.with_capabilities(Capabilities::all());
|
||||
let ses = crate::dbs::Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await.unwrap();
|
||||
let tmp = res.remove(0).result.unwrap();
|
||||
|
|
|
@ -26,7 +26,7 @@ async fn test_fetch_get() {
|
|||
.await;
|
||||
|
||||
// Execute test
|
||||
let ds = Datastore::new("memory").await.unwrap();
|
||||
let ds = Datastore::new("memory").await.unwrap().with_capabilities(Capabilities::all());
|
||||
let sess = Session::owner();
|
||||
let sql = format!(
|
||||
r#"
|
||||
|
@ -71,7 +71,7 @@ async fn test_fetch_put() {
|
|||
.await;
|
||||
|
||||
// Execute test
|
||||
let ds = Datastore::new("memory").await.unwrap();
|
||||
let ds = Datastore::new("memory").await.unwrap().with_capabilities(Capabilities::all());
|
||||
let sess = Session::owner();
|
||||
let sql = format!(
|
||||
r#"
|
||||
|
@ -121,7 +121,7 @@ async fn test_fetch_error() {
|
|||
.await;
|
||||
|
||||
// Execute test
|
||||
let ds = Datastore::new("memory").await.unwrap();
|
||||
let ds = Datastore::new("memory").await.unwrap().with_capabilities(Capabilities::all());
|
||||
let sess = Session::owner();
|
||||
let sql = format!(
|
||||
r#"
|
||||
|
@ -168,7 +168,7 @@ async fn test_fetch_denied() {
|
|||
|
||||
// Execute test
|
||||
let ds = Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default().with_deny_net(Targets::Some(
|
||||
Capabilities::all().without_network_targets(Targets::Some(
|
||||
[NetTarget::from_str(&server.address().to_string()).unwrap()].into(),
|
||||
)),
|
||||
);
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::dbs::Session;
|
|||
use crate::dbs::Variables;
|
||||
use crate::err::Error;
|
||||
use crate::iam::ResourceKind;
|
||||
use crate::iam::{Action, Auth, Role};
|
||||
use crate::iam::{Action, Auth, Error as IamError, Role};
|
||||
use crate::key::root::hb::Hb;
|
||||
use crate::opt::auth::Root;
|
||||
use crate::sql;
|
||||
|
@ -751,6 +751,17 @@ impl Datastore {
|
|||
sess: &Session,
|
||||
vars: Variables,
|
||||
) -> Result<Vec<Response>, Error> {
|
||||
// Check if anonymous actors can execute queries when auth is enabled
|
||||
// TODO(sgirones): Check this as part of the authoritzation layer
|
||||
if self.auth_enabled && sess.au.is_anon() && !self.capabilities.allows_guest_access() {
|
||||
return Err(IamError::NotAllowed {
|
||||
actor: "anonymous".to_string(),
|
||||
action: "process".to_string(),
|
||||
resource: "query".to_string(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
// Create a new query options
|
||||
let opt = Options::default()
|
||||
.with_id(self.id.0)
|
||||
|
@ -806,6 +817,17 @@ impl Datastore {
|
|||
sess: &Session,
|
||||
vars: Variables,
|
||||
) -> Result<Value, Error> {
|
||||
// Check if anonymous actors can compute values when auth is enabled
|
||||
// TODO(sgirones): Check this as part of the authoritzation layer
|
||||
if self.auth_enabled && !self.capabilities.allows_guest_access() {
|
||||
return Err(IamError::NotAllowed {
|
||||
actor: "anonymous".to_string(),
|
||||
action: "compute".to_string(),
|
||||
resource: "value".to_string(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
// Create a new query options
|
||||
let opt = Options::default()
|
||||
.with_id(self.id.0)
|
||||
|
|
|
@ -10,6 +10,7 @@ mod api_integration {
|
|||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use surrealdb::dbs::capabilities::Capabilities;
|
||||
use surrealdb::error::Api as ApiError;
|
||||
use surrealdb::error::Db as DbError;
|
||||
use surrealdb::opt::auth::Database;
|
||||
|
@ -134,7 +135,10 @@ mod api_integration {
|
|||
username: ROOT_USER,
|
||||
password: ROOT_PASS,
|
||||
};
|
||||
let config = Config::new().user(root).tick_interval(TICK_INTERVAL);
|
||||
let config = Config::new()
|
||||
.user(root)
|
||||
.tick_interval(TICK_INTERVAL)
|
||||
.capabilities(Capabilities::all());
|
||||
let db = Surreal::new::<Mem>(config).await.unwrap();
|
||||
db.signin(root).await.unwrap();
|
||||
db
|
||||
|
@ -224,7 +228,10 @@ mod api_integration {
|
|||
username: ROOT_USER,
|
||||
password: ROOT_PASS,
|
||||
};
|
||||
let config = Config::new().user(root).tick_interval(TICK_INTERVAL);
|
||||
let config = Config::new()
|
||||
.user(root)
|
||||
.tick_interval(TICK_INTERVAL)
|
||||
.capabilities(Capabilities::all());
|
||||
let db = Surreal::new::<File>((path, config)).await.unwrap();
|
||||
db.signin(root).await.unwrap();
|
||||
db
|
||||
|
@ -248,7 +255,10 @@ mod api_integration {
|
|||
username: ROOT_USER,
|
||||
password: ROOT_PASS,
|
||||
};
|
||||
let config = Config::new().user(root).tick_interval(TICK_INTERVAL);
|
||||
let config = Config::new()
|
||||
.user(root)
|
||||
.tick_interval(TICK_INTERVAL)
|
||||
.capabilities(Capabilities::all());
|
||||
let db = Surreal::new::<RocksDb>((path, config)).await.unwrap();
|
||||
db.signin(root).await.unwrap();
|
||||
db
|
||||
|
@ -272,7 +282,10 @@ mod api_integration {
|
|||
username: ROOT_USER,
|
||||
password: ROOT_PASS,
|
||||
};
|
||||
let config = Config::new().user(root).tick_interval(TICK_INTERVAL);
|
||||
let config = Config::new()
|
||||
.user(root)
|
||||
.tick_interval(TICK_INTERVAL)
|
||||
.capabilities(Capabilities::all());
|
||||
let db = Surreal::new::<SpeeDb>((path, config)).await.unwrap();
|
||||
db.signin(root).await.unwrap();
|
||||
db
|
||||
|
@ -295,7 +308,10 @@ mod api_integration {
|
|||
username: ROOT_USER,
|
||||
password: ROOT_PASS,
|
||||
};
|
||||
let config = Config::new().user(root).tick_interval(TICK_INTERVAL);
|
||||
let config = Config::new()
|
||||
.user(root)
|
||||
.tick_interval(TICK_INTERVAL)
|
||||
.capabilities(Capabilities::all());
|
||||
let db = Surreal::new::<TiKv>(("127.0.0.1:2379", config)).await.unwrap();
|
||||
db.signin(root).await.unwrap();
|
||||
db
|
||||
|
@ -318,7 +334,10 @@ mod api_integration {
|
|||
username: ROOT_USER,
|
||||
password: ROOT_PASS,
|
||||
};
|
||||
let config = Config::new().user(root).tick_interval(TICK_INTERVAL);
|
||||
let config = Config::new()
|
||||
.user(root)
|
||||
.tick_interval(TICK_INTERVAL)
|
||||
.capabilities(Capabilities::all());
|
||||
let db = Surreal::new::<FDb>(("/etc/foundationdb/fdb.cluster", config)).await.unwrap();
|
||||
db.signin(root).await.unwrap();
|
||||
db
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -15,7 +16,7 @@ async fn clear_transaction_cache_table() -> Result<(), Error> {
|
|||
COMMIT;
|
||||
SELECT * FROM other;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -71,7 +72,7 @@ async fn clear_transaction_cache_field() -> Result<(), Error> {
|
|||
SELECT * FROM person;
|
||||
COMMIT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
mod parse;
|
||||
use chrono::DateTime;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -33,7 +34,7 @@ async fn table_change_feeds() -> Result<(), Error> {
|
|||
CREATE person:1000 SET name = 'Yusuke';
|
||||
SHOW CHANGES FOR TABLE person SINCE 0;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let start_ts = 0u64;
|
||||
let end_ts = start_ts + 1;
|
||||
|
@ -179,7 +180,7 @@ async fn table_change_feeds() -> Result<(), Error> {
|
|||
|
||||
#[tokio::test]
|
||||
async fn changefeed_with_ts() -> Result<(), Error> {
|
||||
let db = Datastore::new("memory").await?;
|
||||
let db = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
// Enable change feeds
|
||||
let sql = "
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -17,7 +17,7 @@ async fn compare_empty() -> Result<(), Error> {
|
|||
RETURN 0 = 0.0;
|
||||
RETURN 0 = 0.1;
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use std::future::Future;
|
||||
use std::thread::Builder;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[test]
|
||||
|
@ -204,7 +205,7 @@ async fn run_queries(
|
|||
impl Iterator<Item = Result<Value, Error>> + ExactSizeIterator + DoubleEndedIterator + 'static,
|
||||
Error,
|
||||
> {
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
dbs.execute(sql, &ses, None).await.map(|v| v.into_iter().map(|res| res.result))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Part;
|
||||
use surrealdb::sql::Thing;
|
||||
use surrealdb::sql::Value;
|
||||
|
@ -29,7 +30,7 @@ async fn create_with_id() -> Result<(), Error> {
|
|||
CREATE person:other SET id = 'tobie';
|
||||
CREATE person:other CONTENT { id: 'tobie', name: 'Tester' };
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 14);
|
||||
|
@ -177,7 +178,7 @@ async fn create_with_custom_function() -> Result<(), Error> {
|
|||
RETURN fn::record::create({ test: true, name: 'Tobie' });
|
||||
RETURN fn::record::create({ test: true, name: 'Jaime' });
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -214,7 +215,7 @@ async fn create_or_insert_with_permissions() -> Result<(), Error> {
|
|||
DEFINE TABLE demo SCHEMAFULL PERMISSIONS FOR select, create, update WHERE user = $auth.id;
|
||||
DEFINE FIELD user ON TABLE demo VALUE $auth.id;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?.with_auth_enabled(true);
|
||||
let dbs = new_ds().await?.with_auth_enabled(true);
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -272,7 +273,7 @@ async fn create_on_none_values_with_unique_index() -> Result<(), Error> {
|
|||
CREATE foo SET name = 'Jane Doe';
|
||||
";
|
||||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -293,7 +294,7 @@ async fn create_with_unique_index_with_two_flattened_fields() -> Result<(), Erro
|
|||
CREATE user:4 SET account = 'Apple', tags = ['two', 'three'], emails = ['a@example.com', 'b@example.com'];
|
||||
";
|
||||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -326,7 +327,7 @@ async fn create_with_unique_index_with_one_flattened_field() -> Result<(), Error
|
|||
CREATE user:2 SET account = 'Apple', tags = ['two', 'three'], emails = ['a@example.com', 'b@example.com'];
|
||||
";
|
||||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -352,7 +353,7 @@ async fn create_with_unique_index_on_one_field_with_flattened_sub_values() -> Re
|
|||
CREATE user:2 SET account = 'Apple', tags = ['two', 'three'], emails = [ { value:'a@example.com'} , { value:'b@example.com' } ];
|
||||
";
|
||||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -378,7 +379,7 @@ async fn create_with_unique_index_on_two_fields() -> Result<(), Error> {
|
|||
CREATE user:2 SET account = 'Apple', tags = ['two', 'one'], emails = ['b@example.com', 'c@example.com'];
|
||||
";
|
||||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -433,7 +434,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
let sess = Session::for_level(level, role).with_ns(ns).with_db(db);
|
||||
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds.execute(statement, &sess, None).await.unwrap();
|
||||
let res = resp.remove(0).output();
|
||||
|
@ -458,7 +459,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
|
||||
// Test the CREATE statement when the table already exists
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute("CREATE person", &Session::owner().with_ns("NS").with_db("DB"), None)
|
||||
|
@ -528,7 +529,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table doesn't exist
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute("CREATE person", &Session::default().with_ns("NS").with_db("DB"), None)
|
||||
|
@ -546,7 +547,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists but grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -570,7 +571,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -607,7 +608,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table doesn't exist
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute("CREATE person", &Session::default().with_ns("NS").with_db("DB"), None)
|
||||
|
@ -624,7 +625,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table exists but grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -647,7 +648,7 @@ async fn check_permissions_auth_disabled() {
|
|||
}
|
||||
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
// When the table exists and grants full permissions
|
||||
let mut resp = ds
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -12,7 +13,7 @@ async fn datetimes_conversion() -> Result<(), Error> {
|
|||
SELECT * FROM <datetime> "2012-01-01";
|
||||
SELECT * FROM <string> "2012-01-01T08:00:00Z" + "-test";
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
|
||||
mod helpers;
|
||||
use helpers::*;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use parse::Parse;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Idiom;
|
||||
use surrealdb::sql::{Part, Value};
|
||||
|
||||
|
@ -19,7 +18,7 @@ async fn define_statement_namespace() -> Result<(), Error> {
|
|||
DEFINE NAMESPACE test;
|
||||
INFO FOR ROOT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -45,7 +44,7 @@ async fn define_statement_database() -> Result<(), Error> {
|
|||
DEFINE DATABASE test;
|
||||
INFO FOR NS;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -74,7 +73,7 @@ async fn define_statement_function() -> Result<(), Error> {
|
|||
};
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -107,7 +106,7 @@ async fn define_statement_table_drop() -> Result<(), Error> {
|
|||
DEFINE TABLE test DROP;
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -138,7 +137,7 @@ async fn define_statement_table_schemaless() -> Result<(), Error> {
|
|||
DEFINE TABLE test SCHEMALESS;
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -170,7 +169,7 @@ async fn define_statement_table_schemafull() -> Result<(), Error> {
|
|||
DEFINE TABLE test SCHEMAFULL;
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -204,7 +203,7 @@ async fn define_statement_table_schemaful() -> Result<(), Error> {
|
|||
DEFINE TABLE test SCHEMAFUL;
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -240,7 +239,7 @@ async fn define_statement_table_foreigntable() -> Result<(), Error> {
|
|||
INFO FOR DB;
|
||||
INFO FOR TB test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -327,7 +326,7 @@ async fn define_statement_event() -> Result<(), Error> {
|
|||
UPDATE user:test SET email = 'test@surrealdb.com', updated_at = time::now();
|
||||
SELECT count() FROM activity GROUP ALL;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -384,7 +383,7 @@ async fn define_statement_event_when_event() -> Result<(), Error> {
|
|||
UPDATE user:test SET email = 'test@surrealdb.com', updated_at = time::now();
|
||||
SELECT count() FROM activity GROUP ALL;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -441,7 +440,7 @@ async fn define_statement_event_when_logic() -> Result<(), Error> {
|
|||
UPDATE user:test SET email = 'test@surrealdb.com', updated_at = time::now();
|
||||
SELECT count() FROM activity GROUP ALL;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -490,7 +489,7 @@ async fn define_statement_field() -> Result<(), Error> {
|
|||
DEFINE FIELD test ON TABLE user;
|
||||
INFO FOR TABLE user;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -522,7 +521,7 @@ async fn define_statement_field_type() -> Result<(), Error> {
|
|||
DEFINE FIELD test ON TABLE user TYPE string;
|
||||
INFO FOR TABLE user;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -554,7 +553,7 @@ async fn define_statement_field_value() -> Result<(), Error> {
|
|||
DEFINE FIELD test ON TABLE user VALUE $value OR 'GBR';
|
||||
INFO FOR TABLE user;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -586,7 +585,7 @@ async fn define_statement_field_assert() -> Result<(), Error> {
|
|||
DEFINE FIELD test ON TABLE user ASSERT $value != NONE AND $value = /[A-Z]{3}/;
|
||||
INFO FOR TABLE user;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -618,7 +617,7 @@ async fn define_statement_field_type_value_assert() -> Result<(), Error> {
|
|||
DEFINE FIELD test ON TABLE user TYPE string VALUE $value OR 'GBR' ASSERT $value != NONE AND $value = /[A-Z]{3}/;
|
||||
INFO FOR TABLE user;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -654,7 +653,7 @@ async fn define_statement_index_single_simple() -> Result<(), Error> {
|
|||
UPDATE user:1 SET age = 24;
|
||||
UPDATE user:2 SET age = 11;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -702,7 +701,7 @@ async fn define_statement_index_single() -> Result<(), Error> {
|
|||
CREATE user:1 SET email = 'test@surrealdb.com';
|
||||
CREATE user:2 SET email = 'test@surrealdb.com';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -746,7 +745,7 @@ async fn define_statement_index_multiple() -> Result<(), Error> {
|
|||
CREATE user:3 SET account = 'apple', email = 'test@surrealdb.com';
|
||||
CREATE user:4 SET account = 'tesla', email = 'test@surrealdb.com';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -798,7 +797,7 @@ async fn define_statement_index_single_unique() -> Result<(), Error> {
|
|||
DELETE user:1;
|
||||
CREATE user:2 SET email = 'test@surrealdb.com';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -856,7 +855,7 @@ async fn define_statement_index_multiple_unique() -> Result<(), Error> {
|
|||
DELETE user:2;
|
||||
CREATE user:4 SET account = 'tesla', email = 'test@surrealdb.com';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 12);
|
||||
|
@ -931,7 +930,7 @@ async fn define_statement_index_single_unique_existing() -> Result<(), Error> {
|
|||
DEFINE INDEX test ON user COLUMNS email UNIQUE;
|
||||
INFO FOR TABLE user;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
@ -978,7 +977,7 @@ async fn define_statement_index_multiple_unique_existing() -> Result<(), Error>
|
|||
DEFINE INDEX test ON user COLUMNS account, email UNIQUE;
|
||||
INFO FOR TABLE user;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -1023,7 +1022,7 @@ async fn define_statement_index_single_unique_embedded_multiple() -> Result<(),
|
|||
CREATE user:1 SET tags = ['one', 'two'];
|
||||
CREATE user:2 SET tags = ['two', 'three'];
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -1073,7 +1072,7 @@ async fn define_statement_index_multiple_unique_embedded_multiple() -> Result<()
|
|||
CREATE user:3 SET account = 'apple', tags = ['two', 'three'];
|
||||
CREATE user:4 SET account = 'tesla', tags = ['two', 'three'];
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -1133,7 +1132,7 @@ async fn define_statement_analyzer() -> Result<(), Error> {
|
|||
DEFINE ANALYZER autocomplete FILTERS lowercase,edgengram(2,10);
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -1177,7 +1176,7 @@ async fn define_statement_search_index() -> Result<(), Error> {
|
|||
ANALYZE INDEX blog_title ON blog;
|
||||
"#;
|
||||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 8);
|
||||
|
@ -1230,7 +1229,7 @@ async fn define_statement_user_root() -> Result<(), Error> {
|
|||
|
||||
INFO FOR ROOT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner();
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
|
||||
|
@ -1252,7 +1251,7 @@ async fn define_statement_user_root() -> Result<(), Error> {
|
|||
|
||||
#[tokio::test]
|
||||
async fn define_statement_user_ns() -> Result<(), Error> {
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner();
|
||||
|
||||
// Create a NS user and retrieve it.
|
||||
|
@ -1308,7 +1307,7 @@ async fn define_statement_user_ns() -> Result<(), Error> {
|
|||
|
||||
#[tokio::test]
|
||||
async fn define_statement_user_db() -> Result<(), Error> {
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner();
|
||||
|
||||
// Create a NS user and retrieve it.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
|
||||
use channel::{Receiver, TryRecvError};
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::{Action, Notification, Session};
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::{Id, Thing, Value};
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -15,7 +16,7 @@ async fn delete() -> Result<(), Error> {
|
|||
DELETE person:test;
|
||||
SELECT * FROM person;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -79,7 +80,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
let sess = Session::for_level(level, role).with_ns(ns).with_db(db);
|
||||
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute("CREATE person:test", &Session::owner().with_ns("NS").with_db("DB"), None)
|
||||
|
@ -191,7 +192,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists but grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -233,7 +234,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -290,7 +291,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table exists but grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -331,7 +332,7 @@ async fn check_permissions_auth_disabled() {
|
|||
}
|
||||
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
// When the table exists and grants full permissions
|
||||
let mut resp = ds
|
||||
|
@ -375,7 +376,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
#[tokio::test]
|
||||
async fn delete_filtered_live_notification() -> Result<(), Error> {
|
||||
let dbs = Datastore::new("memory").await?.with_notifications();
|
||||
let dbs = new_ds().await?.with_notifications();
|
||||
let ses = Session::owner().with_ns("test").with_db("test").with_rt(true);
|
||||
let res = &mut dbs.execute("CREATE person:test_true SET condition = true", &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -16,7 +17,7 @@ async fn complex_ids() -> Result<(), Error> {
|
|||
CREATE person:`100`;
|
||||
SELECT * FROM person;
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -94,7 +95,7 @@ async fn complex_strings() -> Result<(), Error> {
|
|||
RETURN "String with some \"escaped double quoted\" characters";
|
||||
RETURN "String with some 'single' and \"double\" quoted characters";
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -21,7 +22,7 @@ async fn create_relate_select() -> Result<(), Error> {
|
|||
SELECT *, ->bought AS products FROM user FETCH products;
|
||||
SELECT *, ->(bought AS purchases) FROM user FETCH purchases, purchases.out;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 12);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Thing;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
|
@ -19,7 +20,7 @@ async fn field_definition_value_assert_failure() -> Result<(), Error> {
|
|||
CREATE person:test SET email = 'info@surrealdb.com', other = 'ignore', age = 0;
|
||||
CREATE person:test SET email = 'info@surrealdb.com', other = 'ignore', age = 13;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
@ -102,7 +103,7 @@ async fn field_definition_value_assert_success() -> Result<(), Error> {
|
|||
DEFINE FIELD name ON person TYPE option<string> VALUE $value OR 'No name';
|
||||
CREATE person:test SET email = 'info@surrealdb.com', other = 'ignore', age = 22;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -151,7 +152,7 @@ async fn field_definition_empty_nested_objects() -> Result<(), Error> {
|
|||
};
|
||||
SELECT * FROM person;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -205,7 +206,7 @@ async fn field_definition_empty_nested_arrays() -> Result<(), Error> {
|
|||
};
|
||||
SELECT * FROM person;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -257,7 +258,7 @@ async fn field_definition_empty_nested_flexible() -> Result<(), Error> {
|
|||
};
|
||||
SELECT * FROM person;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -322,7 +323,7 @@ async fn field_definition_default_value() -> Result<(), Error> {
|
|||
UPDATE product:test SET secondary = false;
|
||||
UPDATE product:test SET tertiary = 'something';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 11);
|
||||
|
@ -435,7 +436,7 @@ async fn field_definition_value_reference() -> Result<(), Error> {
|
|||
UPDATE product;
|
||||
SELECT * FROM product;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -536,7 +537,7 @@ async fn field_definition_value_reference_with_future() -> Result<(), Error> {
|
|||
UPDATE product;
|
||||
SELECT * FROM product;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -638,7 +639,7 @@ async fn field_definition_edge_permissions() -> Result<(), Error> {
|
|||
INSERT INTO user (id, name) VALUES (user:one, 'John'), (user:two, 'Lucy');
|
||||
INSERT INTO business (id, owner) VALUES (business:one, user:one), (business:two, user:two);
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?.with_auth_enabled(true);
|
||||
let dbs = new_ds().await?.with_auth_enabled(true);
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -30,7 +31,7 @@ async fn foreach() -> Result<(), Error> {
|
|||
};
|
||||
SELECT * FROM person;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -12,7 +13,7 @@ async fn future_function_simple() -> Result<(), Error> {
|
|||
UPDATE person:test SET birthday = <datetime> '2007-06-22';
|
||||
UPDATE person:test SET birthday = <datetime> '2001-06-22';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -44,7 +45,7 @@ async fn future_function_arguments() -> Result<(), Error> {
|
|||
y = 'b-' + parse::email::user(b)
|
||||
;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -91,7 +92,7 @@ async fn concurrency() -> Result<(), Error> {
|
|||
/// Returns `true` iif `limit` futures are concurrently executed.
|
||||
async fn test_limit(limit: usize) -> Result<bool, Error> {
|
||||
let sql = query(limit, MILLIS);
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = dbs.execute(&sql, &ses, None).await;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -11,7 +12,7 @@ async fn geometry_point() -> Result<(), Error> {
|
|||
UPDATE city:london SET centre = (-0.118092, 51.509865);
|
||||
SELECT * FROM city:london;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -68,7 +69,7 @@ async fn geometry_polygon() -> Result<(), Error> {
|
|||
};
|
||||
SELECT * FROM city:london;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -161,7 +162,7 @@ async fn geometry_multipoint() -> Result<(), Error> {
|
|||
};
|
||||
SELECT * FROM city:london;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -239,7 +240,7 @@ async fn geometry_multipolygon() -> Result<(), Error> {
|
|||
};
|
||||
SELECT * FROM university:oxford;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -344,7 +345,7 @@ async fn geometry_inner_access() -> Result<(), Error> {
|
|||
],
|
||||
};
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -20,7 +21,7 @@ async fn select_limit_fetch() -> Result<(), Error> {
|
|||
SELECT *, time::year(time) AS year FROM temperature;
|
||||
SELECT count(), time::year(time) AS year, country FROM temperature GROUP BY country, year;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 11);
|
||||
|
@ -244,7 +245,7 @@ async fn select_multi_aggregate() -> Result<(), Error> {
|
|||
SELECT group, math::sum(one) AS one, math::sum(two) AS two FROM test GROUP BY group;
|
||||
SELECT group, math::sum(two) AS two, math::sum(one) AS one FROM test GROUP BY group;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
@ -349,7 +350,7 @@ async fn select_multi_aggregate_composed() -> Result<(), Error> {
|
|||
SELECT group, math::sum(math::round(one)) AS one, math::sum(math::round(two)) AS two FROM test GROUP BY group;
|
||||
SELECT group, math::sum(math::ceil(one)) AS one, math::sum(math::ceil(two)) AS two FROM test GROUP BY group;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use surrealdb::dbs::capabilities::Capabilities;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::{Auth, Level, Role};
|
||||
use surrealdb::kvs::Datastore;
|
||||
|
||||
pub async fn new_ds() -> Result<Datastore, Error> {
|
||||
Ok(Datastore::new("memory").await?.with_capabilities(Capabilities::all()))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn iam_run_case(
|
||||
prepare: &str,
|
||||
test: &str,
|
||||
|
@ -86,6 +93,7 @@ pub async fn iam_run_case(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn iam_check_cases(
|
||||
cases: std::slice::Iter<'_, ((Level, Role), (&str, &str), bool)>,
|
||||
scenario: &HashMap<&str, &str>,
|
||||
|
@ -105,14 +113,14 @@ pub async fn iam_check_cases(
|
|||
};
|
||||
// Auth enabled
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(true);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(true);
|
||||
iam_run_case(prepare, test, check, &expected_result, &ds, &sess, *should_succeed)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Auth disabled
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(false);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(false);
|
||||
iam_run_case(prepare, test, check, &expected_result, &ds, &sess, *should_succeed)
|
||||
.await?;
|
||||
}
|
||||
|
@ -128,7 +136,7 @@ pub async fn iam_check_cases(
|
|||
auth_enabled =
|
||||
auth_enabled.then(|| "auth enabled").unwrap_or_else(|| "auth disabled")
|
||||
);
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let expected_result = if auth_enabled {
|
||||
check_results.get(1).unwrap()
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
mod parse;
|
||||
|
||||
mod helpers;
|
||||
use helpers::*;
|
||||
|
||||
|
@ -8,7 +6,6 @@ use std::collections::HashMap;
|
|||
use regex::Regex;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
|
||||
#[tokio::test]
|
||||
async fn info_for_root() {
|
||||
|
@ -17,7 +14,7 @@ async fn info_for_root() {
|
|||
DEFINE USER user ON ROOT PASSWORD 'pass';
|
||||
INFO FOR ROOT
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await.unwrap();
|
||||
let dbs = new_ds().await.unwrap();
|
||||
let ses = Session::owner();
|
||||
|
||||
let mut res = dbs.execute(sql, &ses, None).await.unwrap();
|
||||
|
@ -45,7 +42,7 @@ async fn info_for_ns() {
|
|||
DEFINE TOKEN token ON NS TYPE HS512 VALUE 'secret';
|
||||
INFO FOR NS
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await.unwrap();
|
||||
let dbs = new_ds().await.unwrap();
|
||||
let ses = Session::owner().with_ns("ns");
|
||||
|
||||
let mut res = dbs.execute(sql, &ses, None).await.unwrap();
|
||||
|
@ -79,7 +76,7 @@ async fn info_for_db() {
|
|||
DEFINE ANALYZER analyzer TOKENIZERS BLANK;
|
||||
INFO FOR DB
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await.unwrap();
|
||||
let dbs = new_ds().await.unwrap();
|
||||
let ses = Session::owner().with_ns("ns").with_db("db");
|
||||
|
||||
let mut res = dbs.execute(sql, &ses, None).await.unwrap();
|
||||
|
@ -105,7 +102,7 @@ async fn info_for_scope() {
|
|||
DEFINE TOKEN token ON SCOPE account TYPE HS512 VALUE 'secret';
|
||||
INFO FOR SCOPE account;
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await.unwrap();
|
||||
let dbs = new_ds().await.unwrap();
|
||||
let ses = Session::owner().with_ns("ns").with_db("db");
|
||||
|
||||
let mut res = dbs.execute(sql, &ses, None).await.unwrap();
|
||||
|
@ -133,7 +130,7 @@ async fn info_for_table() {
|
|||
DEFINE INDEX index ON TABLE TB FIELDS field;
|
||||
INFO FOR TABLE TB;
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await.unwrap();
|
||||
let dbs = new_ds().await.unwrap();
|
||||
let ses = Session::owner().with_ns("ns").with_db("db");
|
||||
|
||||
let mut res = dbs.execute(sql, &ses, None).await.unwrap();
|
||||
|
@ -162,7 +159,7 @@ async fn info_for_user() {
|
|||
DEFINE USER user ON NS PASSWORD 'pass';
|
||||
DEFINE USER user ON DB PASSWORD 'pass';
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await.unwrap();
|
||||
let dbs = new_ds().await.unwrap();
|
||||
let ses = Session::owner().with_ns("ns").with_db("db");
|
||||
|
||||
let res = dbs.execute(sql, &ses, None).await.unwrap();
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Part;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
|
@ -16,7 +17,7 @@ async fn insert_statement_object_single() -> Result<(), Error> {
|
|||
something: 'other',
|
||||
};
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -44,7 +45,7 @@ async fn insert_statement_object_multiple() -> Result<(), Error> {
|
|||
},
|
||||
];
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -66,7 +67,7 @@ async fn insert_statement_values_single() -> Result<(), Error> {
|
|||
let sql = "
|
||||
INSERT INTO test (id, test, something) VALUES ('tester', true, 'other');
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -83,7 +84,7 @@ async fn insert_statement_values_multiple() -> Result<(), Error> {
|
|||
let sql = "
|
||||
INSERT INTO test (id, test, something) VALUES (1, true, 'other'), (2, false, 'else');
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -105,7 +106,7 @@ async fn insert_statement_values_retable_id() -> Result<(), Error> {
|
|||
let sql = "
|
||||
INSERT INTO test (id, test, something) VALUES (person:1, true, 'other'), (person:2, false, 'else');
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -128,7 +129,7 @@ async fn insert_statement_on_duplicate_key() -> Result<(), Error> {
|
|||
INSERT INTO test (id, test, something) VALUES ('tester', true, 'other');
|
||||
INSERT INTO test (id, test, something) VALUES ('tester', true, 'other') ON DUPLICATE KEY UPDATE something = 'else';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -149,7 +150,7 @@ async fn insert_statement_output() -> Result<(), Error> {
|
|||
let sql = "
|
||||
INSERT INTO test (id, test, something) VALUES ('tester', true, 'other') RETURN something;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -169,7 +170,7 @@ async fn insert_statement_duplicate_key_update() -> Result<(), Error> {
|
|||
INSERT INTO company (name, founded) VALUES ('SurrealDB', '2021-09-11') ON DUPLICATE KEY UPDATE founded = $input.founded;
|
||||
INSERT INTO company (name, founded) VALUES ('SurrealDB', '2021-09-12') ON DUPLICATE KEY UPDATE founded = $input.founded PARALLEL;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -229,7 +230,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
|
||||
// Test the INSERT statement when the table has to be created
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds.execute(statement, &sess, None).await.unwrap();
|
||||
let res = resp.remove(0).output();
|
||||
|
@ -252,7 +253,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
|
||||
// Test the INSERT statement when the table already exists
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute("CREATE person", &Session::owner().with_ns("NS").with_db("DB"), None)
|
||||
|
@ -321,7 +322,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table doesn't exist
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -343,7 +344,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists but grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -371,7 +372,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -412,7 +413,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table doesn't exist
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -433,7 +434,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table exists but grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -461,7 +462,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -15,7 +16,7 @@ async fn select_limit_fetch() -> Result<(), Error> {
|
|||
CREATE person:jaime SET tags = [tag:js];
|
||||
SELECT * FROM person LIMIT 1 FETCH tags;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -14,7 +15,7 @@ async fn select_where_matches_using_index() -> Result<(), Error> {
|
|||
SELECT id FROM blog WHERE title @1@ 'Hello' EXPLAIN;
|
||||
SELECT id, search::highlight('<em>', '</em>', 1) AS title FROM blog WHERE title @1@ 'Hello';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -62,7 +63,7 @@ async fn select_where_matches_without_using_index_iterator() -> Result<(), Error
|
|||
SELECT id FROM blog WHERE (title @0@ 'hello' AND identifier > 0) OR (title @1@ 'world' AND identifier < 99) EXPLAIN FULL;
|
||||
SELECT id,search::highlight('<em>', '</em>', 1) AS title FROM blog WHERE (title @0@ 'hello' AND identifier > 0) OR (title @1@ 'world' AND identifier < 99);
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
@ -117,7 +118,7 @@ async fn select_where_matches_using_index_and_arrays(parallel: bool) -> Result<(
|
|||
SELECT id, search::highlight('<em>', '</em>', 1) AS content FROM blog WHERE content @1@ 'Hello Bãr' {p};
|
||||
"
|
||||
);
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -186,7 +187,7 @@ async fn select_where_matches_using_index_and_objects(parallel: bool) -> Result<
|
|||
SELECT id, search::highlight('<em>', '</em>', 1) AS content FROM blog WHERE content @1@ 'Hello Bãr' {p};
|
||||
"
|
||||
);
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -250,7 +251,7 @@ async fn select_where_matches_using_index_offsets() -> Result<(), Error> {
|
|||
DEFINE INDEX blog_content ON blog FIELDS content SEARCH ANALYZER simple BM25 HIGHLIGHTS;
|
||||
SELECT id, search::offsets(0) AS title, search::offsets(1) AS content FROM blog WHERE title @0@ 'title' AND content @1@ 'Hello Bãr';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -288,7 +289,7 @@ async fn select_where_matches_using_index_and_score() -> Result<(), Error> {
|
|||
DEFINE INDEX blog_title ON blog FIELDS title SEARCH ANALYZER simple BM25(1.2,0.75) HIGHLIGHTS;
|
||||
SELECT id,search::score(1) AS score FROM blog WHERE title @1@ 'animals';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -326,7 +327,7 @@ async fn select_where_matches_without_using_index_and_score() -> Result<(), Erro
|
|||
WHERE (title @1@ 'dummy1' AND label = 'test')
|
||||
OR (title @2@ 'dummy2' AND label = 'test');
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(&sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -17,7 +18,7 @@ async fn merge_record() -> Result<(), Error> {
|
|||
}
|
||||
};
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -11,7 +12,7 @@ async fn model_count() -> Result<(), Error> {
|
|||
CREATE |test:1000| SET time = time::now();
|
||||
SELECT count() FROM test GROUP ALL;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -36,7 +37,7 @@ async fn model_range() -> Result<(), Error> {
|
|||
CREATE |test:101..1100| SET time = time::now();
|
||||
SELECT count() FROM test GROUP ALL;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -14,7 +15,7 @@ async fn define_global_param() -> Result<(), Error> {
|
|||
LET $test = 56789;
|
||||
SELECT * FROM $test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -57,7 +58,7 @@ async fn define_protected_param() -> Result<(), Error> {
|
|||
SELECT * FROM $test WHERE some = 'thing';
|
||||
LET $auth = { ID: admin:tester };
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
mod parse;
|
||||
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::{Response, Session};
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -118,7 +118,7 @@ async fn select_where_iterate_two_no_index() -> Result<(), Error> {
|
|||
}
|
||||
|
||||
async fn execute_test(sql: &str, expected_result: usize) -> Result<Vec<Response>, Error> {
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let mut res = dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), expected_result);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -13,7 +14,7 @@ async fn query_basic() -> Result<(), Error> {
|
|||
RETURN $test;
|
||||
$test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -45,7 +46,7 @@ async fn query_basic_with_modification() -> Result<(), Error> {
|
|||
RETURN $test + 11369;
|
||||
$test + 11369;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -77,7 +78,7 @@ async fn query_root_function() -> Result<(), Error> {
|
|||
string::lowercase($test);
|
||||
string::slug($test);
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -110,7 +111,7 @@ async fn query_root_record() -> Result<(), Error> {
|
|||
<future> { person:tobie->knows->person.name };
|
||||
person:tobie->knows->person.name;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -12,7 +13,7 @@ async fn relate_with_parameters() -> Result<(), Error> {
|
|||
LET $jaime = person:jaime;
|
||||
RELATE $tobie->knows->$jaime SET id = knows:test, brother = true;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -50,7 +51,7 @@ async fn relate_and_overwrite() -> Result<(), Error> {
|
|||
UPDATE knows:test CONTENT { test: true };
|
||||
SELECT * FROM knows:test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
|
||||
mod helpers;
|
||||
use helpers::*;
|
||||
|
@ -8,11 +9,9 @@ mod util;
|
|||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use parse::Parse;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -22,7 +21,7 @@ async fn remove_statement_table() -> Result<(), Error> {
|
|||
REMOVE TABLE test;
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -56,7 +55,7 @@ async fn remove_statement_analyzer() -> Result<(), Error> {
|
|||
REMOVE ANALYZER english;
|
||||
INFO FOR DB;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -96,7 +95,7 @@ async fn remove_statement_index() -> Result<(), Error> {
|
|||
REMOVE INDEX ft_title ON book;
|
||||
INFO FOR TABLE book;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -17,7 +18,7 @@ async fn script_function_error() -> Result<(), Error> {
|
|||
throw new Error('error');
|
||||
};
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -46,7 +47,7 @@ async fn script_function_simple() -> Result<(), Error> {
|
|||
return "Line 1\nLine 2";
|
||||
};
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -75,7 +76,7 @@ async fn script_function_context() -> Result<(), Error> {
|
|||
}
|
||||
;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -109,7 +110,7 @@ async fn script_function_arguments() -> Result<(), Error> {
|
|||
return `${arguments[0]} is ${arguments[1].join(', ')}`;
|
||||
};
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -152,7 +153,7 @@ async fn script_function_types() -> Result<(), Error> {
|
|||
}
|
||||
;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -182,7 +183,7 @@ async fn script_function_module_os() -> Result<(), Error> {
|
|||
return platform();
|
||||
};
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -200,7 +201,7 @@ async fn script_query_from_script_select() -> Result<(), Error> {
|
|||
CREATE test SET name = "b", number = 1;
|
||||
CREATE test SET name = "c", number = 2;
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
|
||||
// direct query
|
||||
|
@ -254,7 +255,7 @@ async fn script_query_from_script() -> Result<(), Error> {
|
|||
return await surrealdb.query(`CREATE article:test SET name = "The daily news", issue_number = 3`)
|
||||
}
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -293,7 +294,7 @@ async fn script_value_function_params() -> Result<(), Error> {
|
|||
return await surrealdb.value(`$test.name`)
|
||||
}
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -318,7 +319,7 @@ async fn script_value_function_inline_values() -> Result<(), Error> {
|
|||
}
|
||||
}
|
||||
"#;
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -14,7 +15,7 @@ async fn select_field_value() -> Result<(), Error> {
|
|||
SELECT VALUE name FROM person;
|
||||
SELECT name FROM person;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -74,7 +75,7 @@ async fn select_field_and_omit() -> Result<(), Error> {
|
|||
SELECT * OMIT password, opts.security FROM person;
|
||||
SELECT * FROM person;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 4);
|
||||
|
@ -161,7 +162,7 @@ async fn select_expression_value() -> Result<(), Error> {
|
|||
SELECT VALUE !boolean FROM thing;
|
||||
SELECT VALUE !boolean FROM thing EXPLAIN FULL;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -260,7 +261,7 @@ async fn select_dynamic_array_keys_and_object_keys() -> Result<(), Error> {
|
|||
-- Selecting an object or array index value using the value of another document field as a key
|
||||
SELECT languages[primarylang] AS content FROM documentation;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 8);
|
||||
|
@ -359,7 +360,7 @@ async fn select_writeable_subqueries() -> Result<(), Error> {
|
|||
LET $id = (SELECT VALUE id FROM (UPDATE tester:test))[0];
|
||||
RETURN $id;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
@ -403,7 +404,7 @@ async fn select_where_field_is_bool() -> Result<(), Error> {
|
|||
SELECT * FROM test WHERE active = true;
|
||||
";
|
||||
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
@ -495,7 +496,7 @@ async fn select_where_field_is_thing_and_with_index() -> Result<(), Error> {
|
|||
SELECT * FROM post WHERE author = person:tobie EXPLAIN;
|
||||
SELECT * FROM post WHERE author = person:tobie EXPLAIN FULL;
|
||||
SELECT * FROM post WHERE author = person:tobie;";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -572,7 +573,7 @@ async fn select_where_and_with_index() -> Result<(), Error> {
|
|||
DEFINE INDEX person_name ON TABLE person COLUMNS name;
|
||||
SELECT name FROM person WHERE name = 'Tobie' AND genre = 'm' EXPLAIN;
|
||||
SELECT name FROM person WHERE name = 'Tobie' AND genre = 'm';";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -619,7 +620,7 @@ async fn select_where_and_with_unique_index() -> Result<(), Error> {
|
|||
DEFINE INDEX person_name ON TABLE person COLUMNS name UNIQUE;
|
||||
SELECT name FROM person WHERE name = 'Jaime' AND genre = 'm' EXPLAIN;
|
||||
SELECT name FROM person WHERE name = 'Jaime' AND genre = 'm';";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -667,7 +668,7 @@ async fn select_where_and_with_fulltext_index() -> Result<(), Error> {
|
|||
DEFINE INDEX ft_name ON TABLE person COLUMNS name SEARCH ANALYZER simple BM25(1.2,0.75);
|
||||
SELECT name FROM person WHERE name @@ 'Jaime' AND genre = 'm' EXPLAIN;
|
||||
SELECT name FROM person WHERE name @@ 'Jaime' AND genre = 'm';";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
@ -715,7 +716,7 @@ async fn select_where_explain() -> Result<(), Error> {
|
|||
CREATE software:surreal SET name = 'SurrealDB';
|
||||
SELECT * FROM person,software EXPLAIN;
|
||||
SELECT * FROM person,software EXPLAIN FULL;";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -807,7 +808,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
let sess = Session::for_level(level, role).with_ns(ns).with_db(db);
|
||||
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
// Prepare datastore
|
||||
let mut resp = ds
|
||||
|
@ -869,7 +870,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -897,7 +898,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -939,7 +940,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -967,7 +968,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -15,7 +16,7 @@ async fn strict_mode_no_namespace() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let dbs = new_ds().await?.with_strict_mode(true);
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -73,7 +74,7 @@ async fn strict_mode_no_database() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let dbs = new_ds().await?.with_strict_mode(true);
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -126,7 +127,7 @@ async fn strict_mode_no_table() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let dbs = new_ds().await?.with_strict_mode(true);
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 5);
|
||||
|
@ -174,7 +175,7 @@ async fn strict_mode_all_ok() -> Result<(), Error> {
|
|||
CREATE test:tester;
|
||||
SELECT * FROM test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?.with_strict_mode(true);
|
||||
let dbs = new_ds().await?.with_strict_mode(true);
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 6);
|
||||
|
@ -213,7 +214,7 @@ async fn loose_mode_all_ok() -> Result<(), Error> {
|
|||
INFO FOR DB;
|
||||
INFO FOR TABLE test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -23,7 +24,7 @@ async fn subquery_select() -> Result<(), Error> {
|
|||
-- Using an outer SELECT, select a specific record in a subquery, returning an array
|
||||
SELECT * FROM (SELECT age >= 18 AS adult FROM person:test) WHERE adult = true;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -135,7 +136,7 @@ async fn subquery_ifelse_set() -> Result<(), Error> {
|
|||
UPDATE person:test SET sport = ['basketball'] RETURN sport;
|
||||
END;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
@ -250,7 +251,7 @@ async fn subquery_ifelse_array() -> Result<(), Error> {
|
|||
UPDATE person:test SET sport = ['basketball'] RETURN sport;
|
||||
END;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -26,7 +27,7 @@ async fn define_foreign_table() -> Result<(), Error> {
|
|||
UPDATE person:two SET age = 39, score = 90;
|
||||
SELECT * FROM person_by_age;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
mod parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
|
||||
#[tokio::test]
|
||||
async fn throw_basic() -> Result<(), Error> {
|
||||
let sql = "
|
||||
THROW 'there was an error';
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -13,7 +14,7 @@ async fn transaction_basic() -> Result<(), Error> {
|
|||
CREATE person:jaime;
|
||||
COMMIT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
|
@ -50,7 +51,7 @@ async fn transaction_with_return() -> Result<(), Error> {
|
|||
RETURN { tobie: person:tobie, jaime: person:jaime };
|
||||
COMMIT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -76,7 +77,7 @@ async fn transaction_with_failure() -> Result<(), Error> {
|
|||
CREATE person:tobie;
|
||||
COMMIT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -112,7 +113,7 @@ async fn transaction_with_failure_and_return() -> Result<(), Error> {
|
|||
RETURN { tobie: person:tobie, jaime: person:jaime };
|
||||
COMMIT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
@ -135,7 +136,7 @@ async fn transaction_with_throw() -> Result<(), Error> {
|
|||
THROW 'there was an error';
|
||||
COMMIT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -171,7 +172,7 @@ async fn transaction_with_throw_and_return() -> Result<(), Error> {
|
|||
RETURN { tobie: person:tobie, jaime: person:jaime };
|
||||
COMMIT;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 1);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -18,7 +19,7 @@ async fn strict_typing_inline() -> Result<(), Error> {
|
|||
UPDATE person:test SET scores = <set<float, 5>> [1,1,2,2,3,3,4,4,5,5];
|
||||
UPDATE person:test SET scores = <array<float, 5>> [1,1,2,2,3,3,4,4,5,5];
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 9);
|
||||
|
@ -134,7 +135,7 @@ async fn strict_typing_defined() -> Result<(), Error> {
|
|||
UPDATE person:test SET age = 18, enabled = true, name = NONE, scored = [1,1,2,2,3,3,4,4,5,5];
|
||||
UPDATE person:test SET age = 18, enabled = true, name = 'Tobie Morgan Hitchcock', scores = [1,1,2,2,3,3,4,4,5,5];
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 8);
|
||||
|
@ -207,7 +208,7 @@ async fn strict_typing_none_null() -> Result<(), Error> {
|
|||
UPDATE person:test SET name = NULL;
|
||||
UPDATE person:test SET name = NONE;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 15);
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::iam::Role;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -30,7 +31,7 @@ async fn update_simple_with_input() -> Result<(), Error> {
|
|||
UPDATE person:test SET name = 'Tobie';
|
||||
SELECT * FROM person:test;
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 7);
|
||||
|
@ -110,7 +111,7 @@ async fn update_complex_with_input() -> Result<(), Error> {
|
|||
;
|
||||
CREATE product:test SET images = [' test.png '];
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -173,7 +174,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
// Test the statement when the table has to be created
|
||||
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds.execute(statement, &sess, None).await.unwrap();
|
||||
let res = resp.remove(0).output();
|
||||
|
@ -196,7 +197,7 @@ async fn common_permissions_checks(auth_enabled: bool) {
|
|||
|
||||
// Test the statement when the table already exists
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
// Prepare datastore
|
||||
let mut resp = ds
|
||||
|
@ -294,7 +295,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table doesn't exist
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(statement, &Session::default().with_ns("NS").with_db("DB"), None)
|
||||
|
@ -312,7 +313,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -360,7 +361,7 @@ async fn check_permissions_auth_enabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -424,7 +425,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table doesn't exist
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(statement, &Session::default().with_ns("NS").with_db("DB"), None)
|
||||
|
@ -441,7 +442,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table grants no permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
@ -489,7 +490,7 @@ async fn check_permissions_auth_disabled() {
|
|||
|
||||
// When the table exists and grants full permissions
|
||||
{
|
||||
let ds = Datastore::new("memory").await.unwrap().with_auth_enabled(auth_enabled);
|
||||
let ds = new_ds().await.unwrap().with_auth_enabled(auth_enabled);
|
||||
|
||||
let mut resp = ds
|
||||
.execute(
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod parse;
|
||||
use parse::Parse;
|
||||
mod helpers;
|
||||
use helpers::new_ds;
|
||||
use surrealdb::dbs::Session;
|
||||
use surrealdb::err::Error;
|
||||
use surrealdb::kvs::Datastore;
|
||||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -12,7 +13,7 @@ async fn use_statement_set_ns() -> Result<(), Error> {
|
|||
USE NS my_ns;
|
||||
SELECT * FROM $session.ns, session::ns(), $session.db, session::db();
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -38,7 +39,7 @@ async fn use_statement_set_db() -> Result<(), Error> {
|
|||
USE DB my_db;
|
||||
SELECT * FROM $session.ns, session::ns(), $session.db, session::db();
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
@ -64,7 +65,7 @@ async fn use_statement_set_both() -> Result<(), Error> {
|
|||
USE NS my_ns DB my_db;
|
||||
SELECT * FROM $session.ns, session::ns(), $session.db, session::db();
|
||||
";
|
||||
let dbs = Datastore::new("memory").await?;
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 3);
|
||||
|
|
294
src/dbs/mod.rs
294
src/dbs/mod.rs
|
@ -44,14 +44,20 @@ struct DbsCapabilities {
|
|||
allow_all: bool,
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
#[arg(help = "Allow execution of scripting functions")]
|
||||
#[arg(help = "Allow execution of embedded scripting functions")]
|
||||
#[arg(env = "SURREAL_CAPS_ALLOW_SCRIPT", long, conflicts_with = "allow_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = true, hide_default_value = true)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
allow_scripting: bool,
|
||||
|
||||
#[arg(help = "Allow guest users to execute queries")]
|
||||
#[arg(env = "SURREAL_CAPS_ALLOW_GUESTS", long, conflicts_with = "allow_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
allow_guests: bool,
|
||||
|
||||
#[arg(
|
||||
help = "Allow execution of functions. Optionally, you can provide a comma-separated list of function names to allow",
|
||||
help = "Allow execution of all functions. Optionally, you can provide a comma-separated list of function names to allow",
|
||||
long_help = r#"Allow execution of functions. Optionally, you can provide a comma-separated list of function names to allow.
|
||||
Function names must be in the form <family>[::<name>]. For example:
|
||||
- 'http' or 'http::*' -> Include all functions in the 'http' family
|
||||
|
@ -60,7 +66,7 @@ Function names must be in the form <family>[::<name>]. For example:
|
|||
)]
|
||||
#[arg(env = "SURREAL_CAPS_ALLOW_FUNC", long, conflicts_with = "allow_all")]
|
||||
// If the arg is provided without value, then assume it's "", which gets parsed into Targets::All
|
||||
#[arg(default_value_os = "", default_missing_value_os = "", num_args = 0..)]
|
||||
#[arg(default_missing_value_os = "", num_args = 0..)]
|
||||
#[arg(value_parser = super::cli::validator::func_targets)]
|
||||
allow_funcs: Option<Targets<FuncTarget>>,
|
||||
|
||||
|
@ -75,7 +81,7 @@ Targets must be in the form of <host>[:<port>], <ipv4|ipv6>[/<mask>]. For exampl
|
|||
)]
|
||||
#[arg(env = "SURREAL_CAPS_ALLOW_NET", long, conflicts_with = "allow_all")]
|
||||
// If the arg is provided without value, then assume it's "", which gets parsed into Targets::All
|
||||
#[arg(default_value_os = "", default_missing_value_os = "", num_args = 0..)]
|
||||
#[arg(default_missing_value_os = "", num_args = 0..)]
|
||||
#[arg(value_parser = super::cli::validator::net_targets)]
|
||||
allow_net: Option<Targets<NetTarget>>,
|
||||
|
||||
|
@ -89,14 +95,20 @@ Targets must be in the form of <host>[:<port>], <ipv4|ipv6>[/<mask>]. For exampl
|
|||
deny_all: bool,
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
#[arg(help = "Deny execution of scripting functions")]
|
||||
#[arg(help = "Deny execution of embedded scripting functions")]
|
||||
#[arg(env = "SURREAL_CAPS_DENY_SCRIPT", long, conflicts_with = "deny_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
deny_scripting: bool,
|
||||
|
||||
#[arg(help = "Deny guest users to execute queries")]
|
||||
#[arg(env = "SURREAL_CAPS_DENY_GUESTS", long, conflicts_with = "deny_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
deny_guests: bool,
|
||||
|
||||
#[arg(
|
||||
help = "Deny execution of functions. Optionally, you can provide a comma-separated list of function names to deny",
|
||||
help = "Deny execution of all functions. Optionally, you can provide a comma-separated list of function names to deny",
|
||||
long_help = r#"Deny execution of functions. Optionally, you can provide a comma-separated list of function names to deny.
|
||||
Function names must be in the form <family>[::<name>]. For example:
|
||||
- 'http' or 'http::*' -> Include all functions in the 'http' family
|
||||
|
@ -121,8 +133,6 @@ Targets must be in the form of <host>[:<port>], <ipv4|ipv6>[/<mask>]. For exampl
|
|||
#[arg(env = "SURREAL_CAPS_DENY_NET", long, conflicts_with = "deny_all")]
|
||||
// If the arg is provided without value, then assume it's "", which gets parsed into Targets::All
|
||||
#[arg(default_missing_value_os = "", num_args = 0..)]
|
||||
// If deny_all is true, disable this arg and assume a default of Targets::All
|
||||
#[arg(conflicts_with = "deny_all", default_value_if("deny_all", "true", ""))]
|
||||
#[arg(value_parser = super::cli::validator::net_targets)]
|
||||
deny_net: Option<Targets<NetTarget>>,
|
||||
}
|
||||
|
@ -138,6 +148,10 @@ impl DbsCapabilities {
|
|||
false
|
||||
}
|
||||
|
||||
fn get_allow_guests(&self) -> bool {
|
||||
(self.allow_all || self.allow_guests) && !(self.deny_all || self.deny_guests)
|
||||
}
|
||||
|
||||
fn get_allow_funcs(&self) -> Targets<FuncTarget> {
|
||||
if self.deny_all || matches!(self.deny_funcs, Some(Targets::All)) {
|
||||
return Targets::None;
|
||||
|
@ -187,10 +201,11 @@ impl From<DbsCapabilities> for Capabilities {
|
|||
fn from(caps: DbsCapabilities) -> Self {
|
||||
Capabilities::default()
|
||||
.with_scripting(caps.get_scripting())
|
||||
.with_allow_funcs(caps.get_allow_funcs())
|
||||
.with_deny_funcs(caps.get_deny_funcs())
|
||||
.with_allow_net(caps.get_allow_net())
|
||||
.with_deny_net(caps.get_deny_net())
|
||||
.with_guest_access(caps.get_allow_guests())
|
||||
.with_functions(caps.get_allow_funcs())
|
||||
.without_functions(caps.get_deny_funcs())
|
||||
.with_network_targets(caps.get_allow_net())
|
||||
.without_network_targets(caps.get_deny_net())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,6 +236,10 @@ pub async fn init(
|
|||
} else {
|
||||
warn!("❌🔒 IMPORTANT: Authentication is disabled. This is not recommended for production use. 🔒❌");
|
||||
}
|
||||
|
||||
let caps = caps.into();
|
||||
debug!("Server capabilities: {caps}");
|
||||
|
||||
// Parse and setup the desired kv datastore
|
||||
let dbs = Datastore::new(&opt.path)
|
||||
.await?
|
||||
|
@ -229,7 +248,7 @@ pub async fn init(
|
|||
.with_query_timeout(query_timeout)
|
||||
.with_transaction_timeout(transaction_timeout)
|
||||
.with_auth_enabled(auth_enabled)
|
||||
.with_capabilities(caps.into());
|
||||
.with_capabilities(caps);
|
||||
|
||||
dbs.bootstrap().await?;
|
||||
|
||||
|
@ -314,12 +333,8 @@ mod tests {
|
|||
let get = Mock::given(method("GET"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_string("SUCCESS"))
|
||||
.expect(1);
|
||||
let head =
|
||||
Mock::given(method("HEAD")).respond_with(ResponseTemplate::new(200)).expect(1);
|
||||
|
||||
s.register(get).await;
|
||||
s.register(head).await;
|
||||
|
||||
s
|
||||
};
|
||||
|
||||
|
@ -337,13 +352,18 @@ mod tests {
|
|||
s
|
||||
};
|
||||
|
||||
// (Capabilities, Query, Succeeds, Response Contains)
|
||||
// (Datastore, Session, Query, Succeeds, Response Contains)
|
||||
let cases = vec![
|
||||
//
|
||||
// Functions and Networking are allowed
|
||||
//
|
||||
(
|
||||
Capabilities::default(),
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default()
|
||||
.with_functions(Targets::<FuncTarget>::All)
|
||||
.with_network_targets(Targets::<NetTarget>::All),
|
||||
),
|
||||
Session::owner(),
|
||||
format!("RETURN http::get('{}')", server1.uri()),
|
||||
true,
|
||||
"SUCCESS".to_string(),
|
||||
|
@ -352,7 +372,11 @@ mod tests {
|
|||
// Scripting is allowed
|
||||
//
|
||||
(
|
||||
Capabilities::default(),
|
||||
Datastore::new("memory")
|
||||
.await
|
||||
.unwrap()
|
||||
.with_capabilities(Capabilities::default().with_scripting(true)),
|
||||
Session::owner(),
|
||||
"RETURN function() { return '1' }".to_string(),
|
||||
true,
|
||||
"1".to_string(),
|
||||
|
@ -361,109 +385,199 @@ mod tests {
|
|||
// Scripting is not allowed
|
||||
//
|
||||
(
|
||||
Capabilities::default().with_scripting(false),
|
||||
Datastore::new("memory")
|
||||
.await
|
||||
.unwrap()
|
||||
.with_capabilities(Capabilities::default().with_scripting(false)),
|
||||
Session::owner(),
|
||||
"RETURN function() { return '1' }".to_string(),
|
||||
false,
|
||||
"Scripting functions are not allowed".to_string(),
|
||||
),
|
||||
//
|
||||
// Anonymous actor when guest access is allowed and auth is enabled, succeeds
|
||||
//
|
||||
(
|
||||
Datastore::new("memory")
|
||||
.await
|
||||
.unwrap()
|
||||
.with_auth_enabled(true)
|
||||
.with_capabilities(Capabilities::default().with_guest_access(true)),
|
||||
Session::default(),
|
||||
"RETURN 1".to_string(),
|
||||
true,
|
||||
"1".to_string(),
|
||||
),
|
||||
//
|
||||
// Anonymous actor when guest access is not allowed and auth is enabled, throws error
|
||||
//
|
||||
(
|
||||
Datastore::new("memory")
|
||||
.await
|
||||
.unwrap()
|
||||
.with_auth_enabled(true)
|
||||
.with_capabilities(Capabilities::default().with_guest_access(false)),
|
||||
Session::default(),
|
||||
"RETURN 1".to_string(),
|
||||
false,
|
||||
"Not enough permissions to perform this action".to_string(),
|
||||
),
|
||||
//
|
||||
// Anonymous actor when guest access is not allowed and auth is disabled, succeeds
|
||||
//
|
||||
(
|
||||
Datastore::new("memory")
|
||||
.await
|
||||
.unwrap()
|
||||
.with_auth_enabled(false)
|
||||
.with_capabilities(Capabilities::default().with_guest_access(false)),
|
||||
Session::default(),
|
||||
"RETURN 1".to_string(),
|
||||
true,
|
||||
"1".to_string(),
|
||||
),
|
||||
//
|
||||
// Authenticated user when guest access is not allowed and auth is enabled, succeeds
|
||||
//
|
||||
(
|
||||
Datastore::new("memory")
|
||||
.await
|
||||
.unwrap()
|
||||
.with_auth_enabled(true)
|
||||
.with_capabilities(Capabilities::default().with_guest_access(false)),
|
||||
Session::viewer(),
|
||||
"RETURN 1".to_string(),
|
||||
true,
|
||||
"1".to_string(),
|
||||
),
|
||||
//
|
||||
// Some functions are not allowed
|
||||
//
|
||||
(
|
||||
Capabilities::default()
|
||||
.with_allow_funcs(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::*").unwrap()].into(),
|
||||
))
|
||||
.with_deny_funcs(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::get").unwrap()].into(),
|
||||
)),
|
||||
format!("RETURN http::get('{}')", server1.uri()),
|
||||
false,
|
||||
"Function 'http::get' is not allowed".to_string(),
|
||||
),
|
||||
(
|
||||
Capabilities::default()
|
||||
.with_allow_funcs(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::*").unwrap()].into(),
|
||||
))
|
||||
.with_deny_funcs(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::get").unwrap()].into(),
|
||||
)),
|
||||
format!("RETURN http::head('{}')", server1.uri()),
|
||||
true,
|
||||
"NONE".to_string(),
|
||||
),
|
||||
(
|
||||
Capabilities::default()
|
||||
.with_allow_funcs(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::*").unwrap()].into(),
|
||||
))
|
||||
.with_deny_funcs(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("http::get").unwrap()].into(),
|
||||
)),
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default()
|
||||
.with_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("string::*").unwrap()].into(),
|
||||
))
|
||||
.without_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("string::len").unwrap()].into(),
|
||||
)),
|
||||
),
|
||||
Session::owner(),
|
||||
"RETURN string::len('a')".to_string(),
|
||||
false,
|
||||
"Function 'string::len' is not allowed".to_string(),
|
||||
),
|
||||
(
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default()
|
||||
.with_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("string::*").unwrap()].into(),
|
||||
))
|
||||
.without_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("string::len").unwrap()].into(),
|
||||
)),
|
||||
),
|
||||
Session::owner(),
|
||||
"RETURN string::lowercase('A')".to_string(),
|
||||
true,
|
||||
"a".to_string(),
|
||||
),
|
||||
(
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default()
|
||||
.with_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("string::*").unwrap()].into(),
|
||||
))
|
||||
.without_functions(Targets::<FuncTarget>::Some(
|
||||
[FuncTarget::from_str("string::len").unwrap()].into(),
|
||||
)),
|
||||
),
|
||||
Session::owner(),
|
||||
"RETURN time::now()".to_string(),
|
||||
false,
|
||||
"Function 'time::now' is not allowed".to_string(),
|
||||
),
|
||||
//
|
||||
// Some net targets are not allowed
|
||||
//
|
||||
(
|
||||
Capabilities::default()
|
||||
.with_allow_net(Targets::<NetTarget>::Some(
|
||||
[
|
||||
NetTarget::from_str(&server1.address().to_string()).unwrap(),
|
||||
NetTarget::from_str(&server2.address().to_string()).unwrap(),
|
||||
]
|
||||
.into(),
|
||||
))
|
||||
.with_deny_net(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str(&server1.address().to_string()).unwrap()].into(),
|
||||
)),
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default()
|
||||
.with_functions(Targets::<FuncTarget>::All)
|
||||
.with_network_targets(Targets::<NetTarget>::Some(
|
||||
[
|
||||
NetTarget::from_str(&server1.address().to_string()).unwrap(),
|
||||
NetTarget::from_str(&server2.address().to_string()).unwrap(),
|
||||
]
|
||||
.into(),
|
||||
))
|
||||
.without_network_targets(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str(&server1.address().to_string()).unwrap()].into(),
|
||||
)),
|
||||
),
|
||||
Session::owner(),
|
||||
format!("RETURN http::get('{}')", server1.uri()),
|
||||
false,
|
||||
format!("Access to network target '{}/' is not allowed", server1.uri()),
|
||||
),
|
||||
(
|
||||
Capabilities::default()
|
||||
.with_allow_net(Targets::<NetTarget>::Some(
|
||||
[
|
||||
NetTarget::from_str(&server1.address().to_string()).unwrap(),
|
||||
NetTarget::from_str(&server2.address().to_string()).unwrap(),
|
||||
]
|
||||
.into(),
|
||||
))
|
||||
.with_deny_net(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str(&server1.address().to_string()).unwrap()].into(),
|
||||
)),
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default()
|
||||
.with_functions(Targets::<FuncTarget>::All)
|
||||
.with_network_targets(Targets::<NetTarget>::Some(
|
||||
[
|
||||
NetTarget::from_str(&server1.address().to_string()).unwrap(),
|
||||
NetTarget::from_str(&server2.address().to_string()).unwrap(),
|
||||
]
|
||||
.into(),
|
||||
))
|
||||
.without_network_targets(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str(&server1.address().to_string()).unwrap()].into(),
|
||||
)),
|
||||
),
|
||||
Session::owner(),
|
||||
"RETURN http::get('http://1.1.1.1')".to_string(),
|
||||
false,
|
||||
"Access to network target 'http://1.1.1.1/' is not allowed".to_string(),
|
||||
),
|
||||
(
|
||||
Capabilities::default()
|
||||
.with_allow_net(Targets::<NetTarget>::Some(
|
||||
[
|
||||
NetTarget::from_str(&server1.address().to_string()).unwrap(),
|
||||
NetTarget::from_str(&server2.address().to_string()).unwrap(),
|
||||
]
|
||||
.into(),
|
||||
))
|
||||
.with_deny_net(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str(&server1.address().to_string()).unwrap()].into(),
|
||||
)),
|
||||
Datastore::new("memory").await.unwrap().with_capabilities(
|
||||
Capabilities::default()
|
||||
.with_functions(Targets::<FuncTarget>::All)
|
||||
.with_network_targets(Targets::<NetTarget>::Some(
|
||||
[
|
||||
NetTarget::from_str(&server1.address().to_string()).unwrap(),
|
||||
NetTarget::from_str(&server2.address().to_string()).unwrap(),
|
||||
]
|
||||
.into(),
|
||||
))
|
||||
.without_network_targets(Targets::<NetTarget>::Some(
|
||||
[NetTarget::from_str(&server1.address().to_string()).unwrap()].into(),
|
||||
)),
|
||||
),
|
||||
Session::owner(),
|
||||
format!("RETURN http::get('{}')", server2.uri()),
|
||||
true,
|
||||
"SUCCESS".to_string(),
|
||||
),
|
||||
];
|
||||
|
||||
for (idx, (caps, query, succeeds, contains)) in cases.into_iter().enumerate() {
|
||||
let ds = Datastore::new("memory").await.unwrap().with_capabilities(caps);
|
||||
|
||||
let sess = Session::owner();
|
||||
for (idx, (ds, sess, query, succeeds, contains)) in cases.into_iter().enumerate() {
|
||||
info!("Test case {idx}: query={query}, succeeds={succeeds}");
|
||||
let res = ds.execute(&query, &sess, None).await;
|
||||
|
||||
if !succeeds && res.is_err() {
|
||||
let res = res.unwrap_err();
|
||||
assert!(
|
||||
res.to_string().contains(&contains),
|
||||
"Unexpected error for test case {}: {:?}",
|
||||
idx,
|
||||
res.to_string()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let res = res.unwrap().remove(0).output();
|
||||
let res = if succeeds {
|
||||
assert!(res.is_ok(), "Unexpected error for test case {}: {:?}", idx, res);
|
||||
|
|
|
@ -38,7 +38,13 @@ mod cli_integration {
|
|||
#[test(tokio::test)]
|
||||
async fn all_commands() {
|
||||
// Commands without credentials when auth is disabled, should succeed
|
||||
let (addr, _server) = common::start_server_without_auth().await.unwrap();
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
auth: false,
|
||||
args: "--allow-all".to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let creds = ""; // Anonymous user
|
||||
|
||||
info!("* Create a record");
|
||||
|
@ -498,31 +504,17 @@ mod cli_integration {
|
|||
|
||||
#[test(tokio::test)]
|
||||
async fn test_capabilities() {
|
||||
info!("* When all capabilities are enabled by default");
|
||||
{
|
||||
let (addr, _server) = common::start_server_without_auth().await.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
|
||||
let query = format!("RETURN http::get('http://{}/version');\n\n", addr);
|
||||
let output = common::run(&cmd).input(&query).output().unwrap();
|
||||
assert!(output.starts_with("['surrealdb"), "unexpected output: {output:?}");
|
||||
|
||||
let query = "RETURN function() { return '1' };";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
assert!(output.starts_with("['1']"), "unexpected output: {output:?}");
|
||||
}
|
||||
|
||||
info!("* When all capabilities are denied");
|
||||
// Deny all, denies all users to execute functions and access any network address
|
||||
info!("* When all capabilities are denied by default");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
args: "--deny-all".to_owned(),
|
||||
args: "".to_owned(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
let cmd = format!("sql --conn ws://{addr} -u root -p root --ns N --db D --multi");
|
||||
|
||||
let query = format!("RETURN http::get('http://{}/version');\n\n", addr);
|
||||
let output = common::run(&cmd).input(&query).output().unwrap();
|
||||
|
@ -539,6 +531,27 @@ mod cli_integration {
|
|||
);
|
||||
}
|
||||
|
||||
// When all capabilities are allowed, anyone (including non-authenticated users) can execute functions and access any network address
|
||||
info!("* When all capabilities are allowed");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
args: "--allow-all".to_owned(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
|
||||
let query = format!("RETURN http::get('http://{}/version');\n\n", addr);
|
||||
let output = common::run(&cmd).input(&query).output().unwrap();
|
||||
assert!(output.starts_with("['surrealdb"), "unexpected output: {output:?}");
|
||||
|
||||
let query = "RETURN function() { return '1' };";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
assert!(output.starts_with("['1']"), "unexpected output: {output:?}");
|
||||
}
|
||||
|
||||
info!("* When scripting is denied");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
|
@ -548,7 +561,7 @@ mod cli_integration {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
let cmd = format!("sql --conn ws://{addr} -u root -p root --ns N --db D --multi");
|
||||
|
||||
let query = "RETURN function() { return '1' };";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
|
@ -567,7 +580,7 @@ mod cli_integration {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
let cmd = format!("sql --conn ws://{addr} -u root -p root --ns N --db D --multi");
|
||||
|
||||
let query = format!("RETURN http::get('http://{}/version');\n\n", addr);
|
||||
let output = common::run(&cmd).input(&query).output().unwrap();
|
||||
|
@ -583,13 +596,14 @@ mod cli_integration {
|
|||
info!("* When net is enabled for an IP and also denied for a specific port that doesn't match");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
args: "--allow-net 127.0.0.1 --deny-net 127.0.0.1:80".to_owned(),
|
||||
args: "--allow-net 127.0.0.1 --deny-net 127.0.0.1:80 --allow-funcs http::get"
|
||||
.to_owned(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
let cmd = format!("sql --conn ws://{addr} -u root -p root --ns N --db D --multi");
|
||||
|
||||
let query = format!("RETURN http::get('http://{}/version');\n\n", addr);
|
||||
let output = common::run(&cmd).input(&query).output().unwrap();
|
||||
|
@ -605,7 +619,7 @@ mod cli_integration {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
let cmd = format!("sql --conn ws://{addr} -u root -p root --ns N --db D --multi");
|
||||
|
||||
let query = "RETURN http::get('https://surrealdb.com');\n\n";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
|
@ -614,5 +628,59 @@ mod cli_integration {
|
|||
"unexpected output: {output:?}"
|
||||
);
|
||||
}
|
||||
|
||||
info!("* When auth is enabled and guest access is allowed");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
auth: true,
|
||||
args: "--allow-guests".to_owned(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
|
||||
let query = "RETURN 1;\n\n";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
assert!(output.contains("[1]"), "unexpected output: {output:?}");
|
||||
}
|
||||
|
||||
info!("* When auth is enabled and guest access is denied");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
auth: true,
|
||||
args: "--deny-guests".to_owned(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
|
||||
let query = "RETURN 1;\n\n";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
assert!(
|
||||
output.contains("Not enough permissions to perform this action"),
|
||||
"unexpected output: {output:?}"
|
||||
);
|
||||
}
|
||||
|
||||
info!("* When auth is disabled, guest access is always allowed");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
auth: false,
|
||||
args: "--deny-guests".to_owned(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} --ns N --db D --multi");
|
||||
|
||||
let query = "RETURN 1;\n\n";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
assert!(output.contains("[1]"), "unexpected output: {output:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ impl Default for StartServerArguments {
|
|||
tls: false,
|
||||
wait_is_ready: true,
|
||||
tick_interval: time::Duration::new(1, 0),
|
||||
args: String::default(),
|
||||
args: "--allow-all".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue