Ensure scope SIGNUP
and SIGNIN
works with guest access disabled (#2663)
This commit is contained in:
parent
b83b9d3e3e
commit
9f33d5dc27
3 changed files with 78 additions and 9 deletions
|
@ -116,9 +116,9 @@ pub async fn sc(
|
||||||
// Setup the query params
|
// Setup the query params
|
||||||
let vars = Some(vars.0);
|
let vars = Some(vars.0);
|
||||||
// Setup the system session for finding the signin record
|
// Setup the system session for finding the signin record
|
||||||
let sess = Session::viewer().with_ns(&ns).with_db(&db);
|
let sess = Session::editor().with_ns(&ns).with_db(&db);
|
||||||
// Compute the value with the params
|
// Compute the value with the params
|
||||||
match kvs.compute(val, &sess, vars).await {
|
match kvs.evaluate(val, &sess, vars).await {
|
||||||
// The signin value succeeded
|
// The signin value succeeded
|
||||||
Ok(val) => match val.record() {
|
Ok(val) => match val.record() {
|
||||||
// There is a record returned
|
// There is a record returned
|
||||||
|
|
|
@ -59,7 +59,7 @@ pub async fn sc(
|
||||||
// Setup the system session for creating the signup record
|
// Setup the system session for creating the signup record
|
||||||
let sess = Session::editor().with_ns(&ns).with_db(&db);
|
let sess = Session::editor().with_ns(&ns).with_db(&db);
|
||||||
// Compute the value with the params
|
// Compute the value with the params
|
||||||
match kvs.compute(val, &sess, vars).await {
|
match kvs.evaluate(val, &sess, vars).await {
|
||||||
// The signin value succeeded
|
// The signin value succeeded
|
||||||
Ok(val) => match val.record() {
|
Ok(val) => match val.record() {
|
||||||
// There is a record returned
|
// There is a record returned
|
||||||
|
|
|
@ -787,7 +787,7 @@ impl Datastore {
|
||||||
vars: Variables,
|
vars: Variables,
|
||||||
) -> Result<Vec<Response>, Error> {
|
) -> Result<Vec<Response>, Error> {
|
||||||
// Check if anonymous actors can execute queries when auth is enabled
|
// Check if anonymous actors can execute queries when auth is enabled
|
||||||
// TODO(sgirones): Check this as part of the authoritzation layer
|
// TODO(sgirones): Check this as part of the authorisation layer
|
||||||
if self.auth_enabled && sess.au.is_anon() && !self.capabilities.allows_guest_access() {
|
if self.auth_enabled && sess.au.is_anon() && !self.capabilities.allows_guest_access() {
|
||||||
return Err(IamError::NotAllowed {
|
return Err(IamError::NotAllowed {
|
||||||
actor: "anonymous".to_string(),
|
actor: "anonymous".to_string(),
|
||||||
|
@ -803,8 +803,8 @@ impl Datastore {
|
||||||
.with_db(sess.db())
|
.with_db(sess.db())
|
||||||
.with_live(sess.live())
|
.with_live(sess.live())
|
||||||
.with_auth(sess.au.clone())
|
.with_auth(sess.au.clone())
|
||||||
.with_auth_enabled(self.auth_enabled)
|
.with_strict(self.strict)
|
||||||
.with_strict(self.strict);
|
.with_auth_enabled(self.auth_enabled);
|
||||||
// Create a new query executor
|
// Create a new query executor
|
||||||
let mut exe = Executor::new(self);
|
let mut exe = Executor::new(self);
|
||||||
// Create a default context
|
// Create a default context
|
||||||
|
@ -852,7 +852,7 @@ impl Datastore {
|
||||||
vars: Variables,
|
vars: Variables,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
// Check if anonymous actors can compute values when auth is enabled
|
// Check if anonymous actors can compute values when auth is enabled
|
||||||
// TODO(sgirones): Check this as part of the authoritzation layer
|
// TODO(sgirones): Check this as part of the authorisation layer
|
||||||
if self.auth_enabled && !self.capabilities.allows_guest_access() {
|
if self.auth_enabled && !self.capabilities.allows_guest_access() {
|
||||||
return Err(IamError::NotAllowed {
|
return Err(IamError::NotAllowed {
|
||||||
actor: "anonymous".to_string(),
|
actor: "anonymous".to_string(),
|
||||||
|
@ -868,8 +868,77 @@ impl Datastore {
|
||||||
.with_db(sess.db())
|
.with_db(sess.db())
|
||||||
.with_live(sess.live())
|
.with_live(sess.live())
|
||||||
.with_auth(sess.au.clone())
|
.with_auth(sess.au.clone())
|
||||||
.with_auth_enabled(self.auth_enabled)
|
.with_strict(self.strict)
|
||||||
.with_strict(self.strict);
|
.with_auth_enabled(self.auth_enabled);
|
||||||
|
// Create a default context
|
||||||
|
let mut ctx = Context::default();
|
||||||
|
// Set context capabilities
|
||||||
|
ctx.add_capabilities(self.capabilities.clone());
|
||||||
|
// Set the global query timeout
|
||||||
|
if let Some(timeout) = self.query_timeout {
|
||||||
|
ctx.add_timeout(timeout);
|
||||||
|
}
|
||||||
|
// Setup the notification channel
|
||||||
|
if let Some(channel) = &self.notification_channel {
|
||||||
|
ctx.add_notifications(Some(&channel.0));
|
||||||
|
}
|
||||||
|
// Start an execution context
|
||||||
|
let ctx = sess.context(ctx);
|
||||||
|
// Store the query variables
|
||||||
|
let ctx = vars.attach(ctx)?;
|
||||||
|
// Start a new transaction
|
||||||
|
let txn = self.transaction(val.writeable(), false).await?.enclose();
|
||||||
|
// Compute the value
|
||||||
|
let res = val.compute(&ctx, &opt, &txn, None).await;
|
||||||
|
// Store any data
|
||||||
|
match (res.is_ok(), val.writeable()) {
|
||||||
|
// If the compute was successful, then commit if writeable
|
||||||
|
(true, true) => txn.lock().await.commit().await?,
|
||||||
|
// Cancel if the compute was an error, or if readonly
|
||||||
|
(_, _) => txn.lock().await.cancel().await?,
|
||||||
|
};
|
||||||
|
// Return result
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Evaluates a SQL [`Value`] without checking authenticating config
|
||||||
|
/// This is used in very specific cases, where we do not need to check
|
||||||
|
/// whether authentication is enabled, or guest access is disabled.
|
||||||
|
/// For example, this is used when processing a SCOPE SIGNUP or SCOPE
|
||||||
|
/// SIGNIN clause, which still needs to work without guest access.
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// use surrealdb::kvs::Datastore;
|
||||||
|
/// use surrealdb::err::Error;
|
||||||
|
/// use surrealdb::dbs::Session;
|
||||||
|
/// use surrealdb::sql::Future;
|
||||||
|
/// use surrealdb::sql::Value;
|
||||||
|
///
|
||||||
|
/// #[tokio::main]
|
||||||
|
/// async fn main() -> Result<(), Error> {
|
||||||
|
/// let ds = Datastore::new("memory").await?;
|
||||||
|
/// let ses = Session::owner();
|
||||||
|
/// let val = Value::Future(Box::new(Future::from(Value::Bool(true))));
|
||||||
|
/// let res = ds.evaluate(val, &ses, None).await?;
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[instrument(level = "debug", skip_all)]
|
||||||
|
pub async fn evaluate(
|
||||||
|
&self,
|
||||||
|
val: Value,
|
||||||
|
sess: &Session,
|
||||||
|
vars: Variables,
|
||||||
|
) -> Result<Value, Error> {
|
||||||
|
// Create a new query options
|
||||||
|
let opt = Options::default()
|
||||||
|
.with_id(self.id.0)
|
||||||
|
.with_ns(sess.ns())
|
||||||
|
.with_db(sess.db())
|
||||||
|
.with_live(sess.live())
|
||||||
|
.with_auth(sess.au.clone())
|
||||||
|
.with_strict(self.strict)
|
||||||
|
.with_auth_enabled(self.auth_enabled);
|
||||||
// Create a default context
|
// Create a default context
|
||||||
let mut ctx = Context::default();
|
let mut ctx = Context::default();
|
||||||
// Set context capabilities
|
// Set context capabilities
|
||||||
|
|
Loading…
Reference in a new issue