surrealdb_core/iam/
access.rsuse crate::cnf::INSECURE_FORWARD_ACCESS_ERRORS;
use crate::ctx::MutableContext;
use crate::dbs::Session;
use crate::err::Error;
use crate::kvs::{Datastore, LockType::*, TransactionType::*};
use crate::sql::statements::access;
use crate::sql::{Base, Ident, Thing, Value};
use reblessive;
pub async fn authenticate_record(
kvs: &Datastore,
session: &Session,
authenticate: &Value,
) -> Result<Thing, Error> {
match kvs.evaluate(authenticate, session, None).await {
Ok(val) => match val.record() {
Some(id) => Ok(id),
_ => {
debug!("Authentication attempt as record user rejected by AUTHENTICATE clause");
Err(Error::InvalidAuth)
}
},
Err(e) => {
match e {
Error::Thrown(_) => Err(e),
Error::Tx(_) | Error::TxFailure | Error::TxRetryable => {
debug!("Unexpected error found while executing AUTHENTICATE clause: {e}");
Err(Error::UnexpectedAuth)
}
e => {
debug!("Authentication attempt failed due to an error in the AUTHENTICATE clause: {e}");
if *INSECURE_FORWARD_ACCESS_ERRORS {
Err(e)
} else {
Err(Error::InvalidAuth)
}
}
}
}
}
}
pub async fn authenticate_generic(
kvs: &Datastore,
session: &Session,
authenticate: &Value,
) -> Result<(), Error> {
match kvs.evaluate(authenticate, session, None).await {
Ok(val) => {
match val {
Value::None => Ok(()),
_ => {
debug!("Authentication attempt as system user rejected by AUTHENTICATE clause");
Err(Error::InvalidAuth)
}
}
}
Err(e) => {
match e {
Error::Thrown(_) => Err(e),
Error::Tx(_) | Error::TxFailure | Error::TxRetryable => {
debug!("Unexpected error found while executing an AUTHENTICATE clause: {e}");
Err(Error::UnexpectedAuth)
}
e => {
debug!("Authentication attempt failed due to an error in the AUTHENTICATE clause: {e}");
if *INSECURE_FORWARD_ACCESS_ERRORS {
Err(e)
} else {
Err(Error::InvalidAuth)
}
}
}
}
}
}
pub async fn create_refresh_token_record(
kvs: &Datastore,
ac: Ident,
ns: &str,
db: &str,
rid: Thing,
) -> Result<String, Error> {
let stmt = access::AccessStatementGrant {
ac,
base: Some(Base::Db),
subject: access::Subject::Record(rid),
};
let sess = Session::owner().with_ns(ns).with_db(db);
let opt = kvs.setup_options(&sess);
let mut ctx = MutableContext::background();
let tx = kvs.transaction(Write, Optimistic).await?.enclose();
ctx.set_transaction(tx.clone());
let ctx = ctx.freeze();
let grant = access::create_grant(&stmt, &ctx, &opt).await.map_err(|e| {
warn!("Unexpected error when attempting to create a refresh token: {e}");
Error::UnexpectedAuth
})?;
tx.commit().await?;
match grant.grant {
access::Grant::Bearer(bearer) => Ok(bearer.key.as_string()),
_ => Err(Error::AccessMethodMismatch),
}
}
pub async fn revoke_refresh_token_record(
kvs: &Datastore,
gr: Ident,
ac: Ident,
ns: &str,
db: &str,
) -> Result<(), Error> {
let stmt = access::AccessStatementRevoke {
ac,
base: Some(Base::Db),
gr: Some(gr),
cond: None,
};
let sess = Session::owner().with_ns(ns).with_db(db);
let opt = kvs.setup_options(&sess);
let mut ctx = MutableContext::background();
let tx = kvs.transaction(Write, Optimistic).await?.enclose();
ctx.set_transaction(tx.clone());
let ctx = ctx.freeze();
let mut stack = reblessive::tree::TreeStack::new();
stack
.enter(|stk| async {
access::revoke_grant(&stmt, stk, &ctx, &opt).await.map_err(|e| {
warn!("Unexpected error when attempting to revoke a refresh token: {e}");
Error::UnexpectedAuth
})
})
.finish()
.await?;
tx.commit().await?;
Ok(())
}