Hide surrealdb-core capabilities struct and implement builder. (#4173)
Co-authored-by: Gerard Guillemas Martos <gguillemas@users.noreply.github.com>
This commit is contained in:
parent
3321c64df7
commit
26de6072aa
8 changed files with 397 additions and 22 deletions
|
@ -304,8 +304,8 @@ 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::opt::capabilities::Capabilities;
|
||||
use crate::sql;
|
||||
use crate::sql::Value;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::sql::Value;
|
|||
use serde::Serialize;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use surrealdb_core::dbs::capabilities::{ParseFuncTargetError, ParseNetTargetError};
|
||||
use thiserror::Error;
|
||||
|
||||
/// An error originating from a remote SurrealDB database
|
||||
|
@ -206,6 +207,24 @@ pub enum Error {
|
|||
/// Tried to insert on an edge or edges
|
||||
#[error("Insert queries on edges not supported: {0}")]
|
||||
InsertOnEdges(Edges),
|
||||
|
||||
#[error("{0}")]
|
||||
InvalidNetTarget(#[from] ParseNetTargetError),
|
||||
|
||||
#[error("{0}")]
|
||||
InvalidFuncTarget(#[from] ParseFuncTargetError),
|
||||
}
|
||||
|
||||
impl From<ParseNetTargetError> for crate::Error {
|
||||
fn from(e: ParseNetTargetError) -> Self {
|
||||
Self::Api(Error::from(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseFuncTargetError> for crate::Error {
|
||||
fn from(e: ParseFuncTargetError) -> Self {
|
||||
Self::Api(Error::from(e))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "protocol-http")]
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
//! The capabilities that can be enabled for a database instance
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use surrealdb_core::dbs::capabilities::{
|
||||
Capabilities as CoreCapabilities, FuncTarget, NetTarget, ParseFuncTargetError,
|
||||
ParseNetTargetError, Targets,
|
||||
};
|
||||
|
||||
/// Capabilities are used to limit what a user can do to the system.
|
||||
///
|
||||
/// Capabilities are split into 4 categories:
|
||||
|
@ -16,6 +23,31 @@
|
|||
///
|
||||
/// The capabilities are defined using allow/deny lists for fine-grained control.
|
||||
///
|
||||
/// # Filtering functions and net-targets.
|
||||
///
|
||||
/// The filtering of net targets and functions is done with an allow/deny list.
|
||||
/// These list can either match everything, nothing or a given list.
|
||||
///
|
||||
/// By default every function and net-target is disallowed. For a function or net target to be
|
||||
/// allowed it must match the allow-list and not match the deny-list. This means that if for
|
||||
/// example a function is both in the allow-list and in the deny-list it will be disallowed.
|
||||
///
|
||||
/// With the combination of both these lists you can filter subgroups. For example:
|
||||
/// ```
|
||||
/// # use surrealdb::opt::capabilities::Capabilities;
|
||||
/// # fn cap() -> surrealdb::Result<Capabilities>{
|
||||
/// # let cap =
|
||||
/// Capabilities::none()
|
||||
/// .with_allow_function("http::*")?
|
||||
/// .with_deny_function("http::post")?
|
||||
///
|
||||
/// # ;
|
||||
/// # Ok(cap)
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Will allow all and only all `http::*` functions except the function `http::post`.
|
||||
///
|
||||
/// Examples:
|
||||
/// - Allow all functions: `--allow-funcs`
|
||||
/// - Allow all functions except `http.*`: `--allow-funcs --deny-funcs 'http.*'`
|
||||
|
@ -38,31 +70,357 @@
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Create a new instance, and allow certain functions
|
||||
#[cfg_attr(feature = "kv-rocksdb", doc = "```no_run")]
|
||||
#[cfg_attr(not(feature = "kv-rocksdb"), doc = "```ignore")]
|
||||
/// # use std::str::FromStr;
|
||||
/// # use surrealdb::engine::local::File;
|
||||
/// # use surrealdb::opt::capabilities::Capabilities;
|
||||
/// # use surrealdb::opt::capabilities::FuncTarget;
|
||||
/// # use surrealdb::opt::capabilities::Targets;
|
||||
/// # use surrealdb::opt::Config;
|
||||
/// # use surrealdb::Surreal;
|
||||
/// # #[tokio::main]
|
||||
/// # async fn main() -> surrealdb::Result<()> {
|
||||
/// let capabilities = Capabilities::default()
|
||||
/// .with_functions(Targets::<FuncTarget>::All)
|
||||
/// .without_functions(Targets::<FuncTarget>::Some(
|
||||
/// [FuncTarget::from_str("http::*").unwrap()].into(),
|
||||
/// ));
|
||||
/// .with_deny_function("http::*")?;
|
||||
/// let config = Config::default().capabilities(capabilities);
|
||||
/// let db = Surreal::new::<File>(("temp.db", config)).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub use crate::dbs::Capabilities;
|
||||
///
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Capabilities {
|
||||
cap: CoreCapabilities,
|
||||
allow_funcs: Targets<FuncTarget>,
|
||||
deny_funcs: Targets<FuncTarget>,
|
||||
allow_net: Targets<NetTarget>,
|
||||
deny_net: Targets<NetTarget>,
|
||||
}
|
||||
|
||||
pub use crate::dbs::capabilities::FuncTarget;
|
||||
pub use crate::dbs::capabilities::NetTarget;
|
||||
pub use crate::dbs::capabilities::Targets;
|
||||
impl Default for Capabilities {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Capabilities {
|
||||
/// Create a builder with default capabilities enabled.
|
||||
///
|
||||
/// Default capabilities enables live query notifications and all (non-scripting) functions.
|
||||
pub fn new() -> Self {
|
||||
Capabilities {
|
||||
cap: CoreCapabilities::default(),
|
||||
allow_funcs: Targets::All,
|
||||
deny_funcs: Targets::None,
|
||||
allow_net: Targets::None,
|
||||
deny_net: Targets::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a builder with all capabilities enabled.
|
||||
pub fn all() -> Self {
|
||||
Capabilities {
|
||||
cap: CoreCapabilities::all(),
|
||||
allow_funcs: Targets::All,
|
||||
deny_funcs: Targets::None,
|
||||
allow_net: Targets::All,
|
||||
deny_net: Targets::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a builder with all capabilities disabled.
|
||||
pub fn none() -> Self {
|
||||
Capabilities {
|
||||
cap: CoreCapabilities::default(),
|
||||
allow_funcs: Targets::None,
|
||||
deny_funcs: Targets::None,
|
||||
allow_net: Targets::None,
|
||||
deny_net: Targets::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set whether to enable the embedded javascript scripting runtime.
|
||||
pub fn with_scripting(self, enabled: bool) -> Self {
|
||||
Self {
|
||||
cap: self.cap.with_scripting(enabled),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Set whether to allow non-authenticated users to execute queries when authentication is
|
||||
/// enabled.
|
||||
pub fn with_guest_access(self, enabled: bool) -> Self {
|
||||
Self {
|
||||
cap: self.cap.with_guest_access(enabled),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Set wether to enable live query notifications.
|
||||
pub fn with_live_query_notifications(self, enabled: bool) -> Self {
|
||||
Self {
|
||||
cap: self.cap.with_live_query_notifications(enabled),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the allow list to allow all functions
|
||||
pub fn allow_all_functions(&mut self) -> &mut Self {
|
||||
self.allow_funcs = Targets::All;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the allow list to allow all functions
|
||||
pub fn with_allow_all_functions(mut self) -> Self {
|
||||
self.allow_all_functions();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny all functions
|
||||
pub fn deny_all_functions(&mut self) -> &mut Self {
|
||||
self.deny_funcs = Targets::All;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny all functions
|
||||
pub fn with_deny_all_function(mut self) -> Self {
|
||||
self.deny_all_functions();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the allow list to allow no function
|
||||
pub fn allow_none_functions(&mut self) -> &mut Self {
|
||||
self.allow_funcs = Targets::None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the allow list to allow no function
|
||||
pub fn with_allow_none_functions(mut self) -> Self {
|
||||
self.allow_none_functions();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny no function
|
||||
pub fn deny_none_functions(&mut self) -> &mut Self {
|
||||
self.deny_funcs = Targets::None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny no function
|
||||
pub fn with_deny_none_function(mut self) -> Self {
|
||||
self.deny_none_functions();
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a function to the allow lists
|
||||
///
|
||||
/// Adding a function to the allow list overwrites previously set allow-all or allow-none
|
||||
/// filters.
|
||||
pub fn allow_function<S: AsRef<str>>(
|
||||
&mut self,
|
||||
func: S,
|
||||
) -> Result<&mut Self, ParseFuncTargetError> {
|
||||
self.allow_function_str(func.as_ref())
|
||||
}
|
||||
|
||||
/// Add a function to the allow lists
|
||||
///
|
||||
/// Adding a function to the allow list overwrites previously set allow-all or allow-none
|
||||
/// filters.
|
||||
pub fn with_allow_function<S: AsRef<str>>(
|
||||
mut self,
|
||||
func: S,
|
||||
) -> Result<Self, ParseFuncTargetError> {
|
||||
self.allow_function(func)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn allow_function_str(&mut self, s: &str) -> Result<&mut Self, ParseFuncTargetError> {
|
||||
let target: FuncTarget = s.parse()?;
|
||||
match self.allow_funcs {
|
||||
Targets::None | Targets::All => {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(target);
|
||||
self.allow_funcs = Targets::Some(set);
|
||||
}
|
||||
Targets::Some(ref mut x) => {
|
||||
x.insert(target);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Add a function to the deny lists
|
||||
///
|
||||
/// Adding a function to the deny list overwrites previously set deny-all or deny-none
|
||||
/// filters.
|
||||
pub fn deny_function<S: AsRef<str>>(
|
||||
&mut self,
|
||||
func: S,
|
||||
) -> Result<&mut Self, ParseFuncTargetError> {
|
||||
self.deny_function_str(func.as_ref())
|
||||
}
|
||||
|
||||
/// Add a function to the deny lists
|
||||
///
|
||||
/// Adding a function to the deny list overwrites previously set deny-all or deny-none
|
||||
/// filters.
|
||||
pub fn with_deny_function<S: AsRef<str>>(
|
||||
mut self,
|
||||
func: S,
|
||||
) -> Result<Self, ParseFuncTargetError> {
|
||||
self.deny_function(func)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn deny_function_str(&mut self, s: &str) -> Result<&mut Self, ParseFuncTargetError> {
|
||||
let target: FuncTarget = s.parse()?;
|
||||
match self.deny_funcs {
|
||||
Targets::None | Targets::All => {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(target);
|
||||
self.deny_funcs = Targets::Some(set);
|
||||
}
|
||||
Targets::Some(ref mut x) => {
|
||||
x.insert(target);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Set the allow list to allow all net targets
|
||||
pub fn allow_all_net_targets(&mut self) -> &mut Self {
|
||||
self.allow_net = Targets::All;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the allow list to allow all net targets
|
||||
pub fn with_allow_all_net_targets(mut self) -> Self {
|
||||
self.allow_all_net_targets();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny all net targets
|
||||
pub fn deny_all_net_targets(&mut self) -> &mut Self {
|
||||
self.deny_net = Targets::All;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny all net targets
|
||||
pub fn with_deny_all_net_target(mut self) -> Self {
|
||||
self.deny_all_net_targets();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the allow list to allow no net targets
|
||||
pub fn allow_none_net_targets(&mut self) -> &mut Self {
|
||||
self.allow_net = Targets::None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the allow list to allow no net targets
|
||||
pub fn with_allow_none_net_targets(mut self) -> Self {
|
||||
self.allow_none_net_targets();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny no net targets
|
||||
pub fn deny_none_net_targets(&mut self) -> &mut Self {
|
||||
self.deny_net = Targets::None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the deny list to deny no net targets
|
||||
pub fn with_deny_none_net_target(mut self) -> Self {
|
||||
self.deny_none_net_targets();
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a net target to the allow lists
|
||||
///
|
||||
/// Adding a net target to the allow list overwrites previously set allow-all or allow-none
|
||||
/// filters.
|
||||
pub fn allow_net_target<S: AsRef<str>>(
|
||||
&mut self,
|
||||
func: S,
|
||||
) -> Result<&mut Self, ParseNetTargetError> {
|
||||
self.allow_net_target_str(func.as_ref())
|
||||
}
|
||||
|
||||
/// Add a net target to the allow lists
|
||||
///
|
||||
/// Adding a net target to the allow list overwrites previously set allow-all or allow-none
|
||||
/// filters.
|
||||
pub fn with_allow_net_target<S: AsRef<str>>(
|
||||
mut self,
|
||||
func: S,
|
||||
) -> Result<Self, ParseNetTargetError> {
|
||||
self.allow_net_target(func)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn allow_net_target_str(&mut self, s: &str) -> Result<&mut Self, ParseNetTargetError> {
|
||||
let target = s.parse()?;
|
||||
match self.allow_net {
|
||||
Targets::None | Targets::All => {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(target);
|
||||
self.allow_net = Targets::Some(set);
|
||||
}
|
||||
Targets::Some(ref mut x) => {
|
||||
x.insert(target);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Add a net target to the deny lists
|
||||
///
|
||||
/// Adding a net target to the deny list overwrites previously set deny-all or deny-none
|
||||
/// filters.
|
||||
pub fn deny_net_target<S: AsRef<str>>(
|
||||
&mut self,
|
||||
func: S,
|
||||
) -> Result<&mut Self, ParseNetTargetError> {
|
||||
self.deny_net_target_str(func.as_ref())
|
||||
}
|
||||
|
||||
/// Add a net target to the deny lists
|
||||
///
|
||||
/// Adding a net target to the deny list overwrites previously set deny-all or deny-none
|
||||
/// filters.
|
||||
pub fn with_deny_net_target<S: AsRef<str>>(
|
||||
mut self,
|
||||
func: S,
|
||||
) -> Result<Self, ParseNetTargetError> {
|
||||
self.deny_net_target(func)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn deny_net_target_str(&mut self, s: &str) -> Result<&mut Self, ParseNetTargetError> {
|
||||
let target = s.parse()?;
|
||||
match self.deny_net {
|
||||
Targets::None | Targets::All => {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(target);
|
||||
self.deny_net = Targets::Some(set);
|
||||
}
|
||||
Targets::Some(ref mut x) => {
|
||||
x.insert(target);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub(crate) fn build(self) -> CoreCapabilities {
|
||||
self.cap
|
||||
.with_functions(self.allow_funcs)
|
||||
.without_functions(self.deny_funcs)
|
||||
.with_network_targets(self.allow_net)
|
||||
.without_network_targets(self.deny_net)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{dbs::Capabilities, iam::Level};
|
||||
use crate::opt::capabilities::Capabilities;
|
||||
#[cfg(any(
|
||||
feature = "kv-mem",
|
||||
feature = "kv-surrealkv",
|
||||
|
@ -8,6 +8,7 @@ use crate::{dbs::Capabilities, iam::Level};
|
|||
))]
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use surrealdb_core::{dbs::Capabilities as CoreCapabilities, iam::Level};
|
||||
|
||||
/// Configuration for server connection, including: strictness, notifications, query_timeout, transaction_timeout
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
@ -24,7 +25,7 @@ pub struct Config {
|
|||
pub(crate) username: String,
|
||||
pub(crate) password: String,
|
||||
pub(crate) tick_interval: Option<Duration>,
|
||||
pub(crate) capabilities: Capabilities,
|
||||
pub(crate) capabilities: CoreCapabilities,
|
||||
#[cfg(any(
|
||||
feature = "kv-mem",
|
||||
feature = "kv-surrealkv",
|
||||
|
@ -117,7 +118,7 @@ impl Config {
|
|||
|
||||
/// Set the capabilities for the database
|
||||
pub fn capabilities(mut self, capabilities: Capabilities) -> Self {
|
||||
self.capabilities = capabilities;
|
||||
self.capabilities = capabilities.build();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ 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;
|
||||
|
@ -20,6 +19,7 @@ mod api_integration {
|
|||
use surrealdb::opt::auth::Namespace;
|
||||
use surrealdb::opt::auth::Record as RecordAccess;
|
||||
use surrealdb::opt::auth::Root;
|
||||
use surrealdb::opt::capabilities::Capabilities;
|
||||
use surrealdb::opt::Config;
|
||||
use surrealdb::opt::PatchOp;
|
||||
use surrealdb::opt::Resource;
|
||||
|
|
|
@ -4,9 +4,8 @@ use crate::cli::abstraction::{
|
|||
};
|
||||
use crate::err::Error;
|
||||
use clap::Args;
|
||||
use surrealdb::dbs::Capabilities;
|
||||
use surrealdb::engine::any::{connect, IntoEndpoint};
|
||||
use surrealdb::opt::Config;
|
||||
use surrealdb::opt::{capabilities::Capabilities, Config};
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct ImportCommandArguments {
|
||||
|
|
|
@ -4,9 +4,8 @@ use crate::cli::abstraction::{
|
|||
};
|
||||
use crate::err::Error;
|
||||
use clap::Args;
|
||||
use surrealdb::dbs::Capabilities;
|
||||
use surrealdb::engine::any::{connect, IntoEndpoint};
|
||||
use surrealdb::opt::Config;
|
||||
use surrealdb::opt::{capabilities::Capabilities, Config};
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct ImportCommandArguments {
|
||||
|
|
|
@ -11,10 +11,9 @@ use rustyline::validate::{ValidationContext, ValidationResult, Validator};
|
|||
use rustyline::{Completer, Editor, Helper, Highlighter, Hinter};
|
||||
use serde::Serialize;
|
||||
use serde_json::ser::PrettyFormatter;
|
||||
use surrealdb::dbs::Capabilities;
|
||||
use surrealdb::engine::any::{connect, IntoEndpoint};
|
||||
use surrealdb::method::{Stats, WithStats};
|
||||
use surrealdb::opt::Config;
|
||||
use surrealdb::opt::{capabilities::Capabilities, Config};
|
||||
use surrealdb::sql::{self, Statement, Value};
|
||||
use surrealdb::{Notification, Response};
|
||||
|
||||
|
|
Loading…
Reference in a new issue