surrealdb_core/iam/
access.rs1use crate::cnf::INSECURE_FORWARD_ACCESS_ERRORS;
2use crate::ctx::MutableContext;
3use crate::dbs::Session;
4use crate::err::Error;
5use crate::kvs::{Datastore, LockType::*, TransactionType::*};
6use crate::sql::statements::access;
7use crate::sql::{Base, Ident, Thing, Value};
8use reblessive;
9
10pub async fn authenticate_record(
12 kvs: &Datastore,
13 session: &Session,
14 authenticate: &Value,
15) -> Result<Thing, Error> {
16 match kvs.evaluate(authenticate, session, None).await {
17 Ok(val) => match val.record() {
18 Some(id) => Ok(id),
20 _ => {
22 debug!("Authentication attempt as record user rejected by AUTHENTICATE clause");
23 Err(Error::InvalidAuth)
24 }
25 },
26 Err(e) => {
27 match e {
28 Error::Thrown(_) => Err(e),
30 Error::Tx(_) | Error::TxFailure | Error::TxRetryable => {
33 debug!("Unexpected error found while executing AUTHENTICATE clause: {e}");
34 Err(Error::UnexpectedAuth)
35 }
36 e => {
38 debug!("Authentication attempt failed due to an error in the AUTHENTICATE clause: {e}");
39 if *INSECURE_FORWARD_ACCESS_ERRORS {
40 Err(e)
41 } else {
42 Err(Error::InvalidAuth)
43 }
44 }
45 }
46 }
47 }
48}
49
50pub async fn authenticate_generic(
52 kvs: &Datastore,
53 session: &Session,
54 authenticate: &Value,
55) -> Result<(), Error> {
56 match kvs.evaluate(authenticate, session, None).await {
57 Ok(val) => {
58 match val {
59 Value::None => Ok(()),
61 _ => {
63 debug!("Authentication attempt as system user rejected by AUTHENTICATE clause");
64 Err(Error::InvalidAuth)
65 }
66 }
67 }
68 Err(e) => {
69 match e {
70 Error::Thrown(_) => Err(e),
72 Error::Tx(_) | Error::TxFailure | Error::TxRetryable => {
75 debug!("Unexpected error found while executing an AUTHENTICATE clause: {e}");
76 Err(Error::UnexpectedAuth)
77 }
78 e => {
80 debug!("Authentication attempt failed due to an error in the AUTHENTICATE clause: {e}");
81 if *INSECURE_FORWARD_ACCESS_ERRORS {
82 Err(e)
83 } else {
84 Err(Error::InvalidAuth)
85 }
86 }
87 }
88 }
89 }
90}
91
92pub async fn create_refresh_token_record(
94 kvs: &Datastore,
95 ac: Ident,
96 ns: &str,
97 db: &str,
98 rid: Thing,
99) -> Result<String, Error> {
100 let stmt = access::AccessStatementGrant {
101 ac,
102 base: Some(Base::Db),
103 subject: access::Subject::Record(rid),
104 };
105 let sess = Session::owner().with_ns(ns).with_db(db);
106 let opt = kvs.setup_options(&sess);
107 let mut ctx = MutableContext::background();
109 let tx = kvs.transaction(Write, Optimistic).await?.enclose();
110 ctx.set_transaction(tx.clone());
111 let ctx = ctx.freeze();
112 let grant = access::create_grant(&stmt, &ctx, &opt).await.map_err(|e| {
114 warn!("Unexpected error when attempting to create a refresh token: {e}");
115 Error::UnexpectedAuth
116 })?;
117 tx.commit().await?;
118 match grant.grant {
120 access::Grant::Bearer(bearer) => Ok(bearer.key.as_string()),
121 _ => Err(Error::AccessMethodMismatch),
122 }
123}
124
125pub async fn revoke_refresh_token_record(
127 kvs: &Datastore,
128 gr: Ident,
129 ac: Ident,
130 ns: &str,
131 db: &str,
132) -> Result<(), Error> {
133 let stmt = access::AccessStatementRevoke {
134 ac,
135 base: Some(Base::Db),
136 gr: Some(gr),
137 cond: None,
138 };
139 let sess = Session::owner().with_ns(ns).with_db(db);
140 let opt = kvs.setup_options(&sess);
141 let mut ctx = MutableContext::background();
143 let tx = kvs.transaction(Write, Optimistic).await?.enclose();
144 ctx.set_transaction(tx.clone());
145 let ctx = ctx.freeze();
146 let mut stack = reblessive::tree::TreeStack::new();
148 stack
149 .enter(|stk| async {
150 access::revoke_grant(&stmt, stk, &ctx, &opt).await.map_err(|e| {
151 warn!("Unexpected error when attempting to revoke a refresh token: {e}");
152 Error::UnexpectedAuth
153 })
154 })
155 .finish()
156 .await?;
157 tx.commit().await?;
158 Ok(())
159}