surrealdb_sql/statements/
info.rsuse crate::ctx::Context;
use crate::dbs::{Options, Transaction};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::iam::Action;
use crate::iam::ResourceKind;
use crate::{Base, Ident, Object, Value};
use derive::Store;
use revision::revisioned;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
#[revisioned(revision = 1)]
pub enum InfoStatement {
Root,
Ns,
Db,
Sc(Ident),
Tb(Ident),
User(Ident, Option<Base>),
}
impl InfoStatement {
pub(crate) async fn compute(
&self,
_ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
_doc: Option<&CursorDoc<'_>>,
) -> Result<Value, Error> {
match self {
InfoStatement::Root => {
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Root)?;
let mut run = txn.lock().await;
let mut res = Object::default();
let mut tmp = Object::default();
for v in run.all_ns().await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("namespaces".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_root_users().await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("users".to_owned(), tmp.into());
Value::from(res).ok()
}
InfoStatement::Ns => {
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Ns)?;
let mut run = txn.lock().await;
let mut res = Object::default();
let mut tmp = Object::default();
for v in run.all_db(opt.ns()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("databases".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_ns_users(opt.ns()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("users".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_ns_tokens(opt.ns()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("tokens".to_owned(), tmp.into());
Value::from(res).ok()
}
InfoStatement::Db => {
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
let mut run = txn.lock().await;
let mut res = Object::default();
let mut tmp = Object::default();
for v in run.all_db_users(opt.ns(), opt.db()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("users".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_db_tokens(opt.ns(), opt.db()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("tokens".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_db_functions(opt.ns(), opt.db()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("functions".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_db_models(opt.ns(), opt.db()).await?.iter() {
tmp.insert(format!("{}<{}>", v.name, v.version), v.to_string().into());
}
res.insert("models".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_db_params(opt.ns(), opt.db()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("params".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_sc(opt.ns(), opt.db()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("scopes".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_tb(opt.ns(), opt.db()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("tables".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_db_analyzers(opt.ns(), opt.db()).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("analyzers".to_owned(), tmp.into());
Value::from(res).ok()
}
InfoStatement::Sc(sc) => {
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
let mut run = txn.lock().await;
let mut res = Object::default();
let mut tmp = Object::default();
for v in run.all_sc_tokens(opt.ns(), opt.db(), sc).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("tokens".to_owned(), tmp.into());
Value::from(res).ok()
}
InfoStatement::Tb(tb) => {
opt.is_allowed(Action::View, ResourceKind::Any, &Base::Db)?;
let mut run = txn.lock().await;
let mut res = Object::default();
let mut tmp = Object::default();
for v in run.all_tb_events(opt.ns(), opt.db(), tb).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("events".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_tb_fields(opt.ns(), opt.db(), tb).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("fields".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_tb_views(opt.ns(), opt.db(), tb).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("tables".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_tb_indexes(opt.ns(), opt.db(), tb).await?.iter() {
tmp.insert(v.name.to_string(), v.to_string().into());
}
res.insert("indexes".to_owned(), tmp.into());
let mut tmp = Object::default();
for v in run.all_tb_lives(opt.ns(), opt.db(), tb).await?.iter() {
tmp.insert(v.id.to_raw(), v.to_string().into());
}
res.insert("lives".to_owned(), tmp.into());
Value::from(res).ok()
}
InfoStatement::User(user, base) => {
let base = base.clone().unwrap_or(opt.selected_base()?);
opt.is_allowed(Action::View, ResourceKind::Actor, &base)?;
let mut run = txn.lock().await;
let res = match base {
Base::Root => run.get_root_user(user).await?,
Base::Ns => run.get_ns_user(opt.ns(), user).await?,
Base::Db => run.get_db_user(opt.ns(), opt.db(), user).await?,
_ => return Err(Error::InvalidLevel(base.to_string())),
};
Value::from(res.to_string()).ok()
}
}
}
}
impl fmt::Display for InfoStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Root => f.write_str("INFO FOR ROOT"),
Self::Ns => f.write_str("INFO FOR NAMESPACE"),
Self::Db => f.write_str("INFO FOR DATABASE"),
Self::Sc(ref s) => write!(f, "INFO FOR SCOPE {s}"),
Self::Tb(ref t) => write!(f, "INFO FOR TABLE {t}"),
Self::User(ref u, ref b) => match b {
Some(ref b) => write!(f, "INFO FOR USER {u} ON {b}"),
None => write!(f, "INFO FOR USER {u}"),
},
}
}
}