Allow root authentication over WebSocket connection
This commit is contained in:
parent
89915f9a62
commit
e5a78bed06
5 changed files with 110 additions and 29 deletions
|
@ -7,10 +7,12 @@ use argon2::password_hash::{PasswordHash, PasswordVerifier};
|
|||
use argon2::Argon2;
|
||||
use chrono::{Duration, Utc};
|
||||
use jsonwebtoken::{encode, EncodingKey};
|
||||
use std::sync::Arc;
|
||||
use surrealdb::sql::Object;
|
||||
use surrealdb::Auth;
|
||||
use surrealdb::Session;
|
||||
|
||||
pub async fn signin(vars: Object) -> Result<String, Error> {
|
||||
pub async fn signin(session: &mut Session, vars: Object) -> Result<String, Error> {
|
||||
// Parse the specified variables
|
||||
let ns = vars.get("NS").or_else(|| vars.get("ns"));
|
||||
let db = vars.get("DB").or_else(|| vars.get("db"));
|
||||
|
@ -23,7 +25,7 @@ pub async fn signin(vars: Object) -> Result<String, Error> {
|
|||
let db = db.to_strand().as_string();
|
||||
let sc = sc.to_strand().as_string();
|
||||
// Attempt to signin to specified scope
|
||||
let res = super::signin::sc(ns, db, sc, vars).await?;
|
||||
let res = super::signin::sc(session, ns, db, sc, vars).await?;
|
||||
// Return the result to the client
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -41,7 +43,7 @@ pub async fn signin(vars: Object) -> Result<String, Error> {
|
|||
let user = user.to_strand().as_string();
|
||||
let pass = pass.to_strand().as_string();
|
||||
// Attempt to signin to database
|
||||
let res = super::signin::db(ns, db, user, pass).await?;
|
||||
let res = super::signin::db(session, ns, db, user, pass).await?;
|
||||
// Return the result to the client
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -62,7 +64,27 @@ pub async fn signin(vars: Object) -> Result<String, Error> {
|
|||
let user = user.to_strand().as_string();
|
||||
let pass = pass.to_strand().as_string();
|
||||
// Attempt to signin to namespace
|
||||
let res = super::signin::ns(ns, user, pass).await?;
|
||||
let res = super::signin::ns(session, ns, user, pass).await?;
|
||||
// Return the result to the client
|
||||
Ok(res)
|
||||
}
|
||||
// There is no username or password
|
||||
_ => Err(Error::InvalidAuth),
|
||||
}
|
||||
}
|
||||
(None, None, None) => {
|
||||
// Get the provided user and pass
|
||||
let user = vars.get("user");
|
||||
let pass = vars.get("pass");
|
||||
// Validate the user and pass
|
||||
match (user, pass) {
|
||||
// There is a username and password
|
||||
(Some(user), Some(pass)) => {
|
||||
// Process the provided values
|
||||
let user = user.to_strand().as_string();
|
||||
let pass = pass.to_strand().as_string();
|
||||
// Attempt to signin to namespace
|
||||
let res = super::signin::su(session, user, pass).await?;
|
||||
// Return the result to the client
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -74,7 +96,13 @@ pub async fn signin(vars: Object) -> Result<String, Error> {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<String, Error> {
|
||||
pub async fn sc(
|
||||
session: &mut Session,
|
||||
ns: String,
|
||||
db: String,
|
||||
sc: String,
|
||||
vars: Object,
|
||||
) -> Result<String, Error> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
|
@ -109,12 +137,14 @@ pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<Stri
|
|||
_ => Utc::now() + Duration::hours(1),
|
||||
}
|
||||
.timestamp(),
|
||||
ns: Some(ns),
|
||||
db: Some(db),
|
||||
sc: Some(sc),
|
||||
ns: Some(ns.to_owned()),
|
||||
db: Some(db.to_owned()),
|
||||
sc: Some(sc.to_owned()),
|
||||
id: Some(rid.to_raw()),
|
||||
..Claims::default()
|
||||
};
|
||||
// Set the authentication on the sesssion
|
||||
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
||||
// Create the authentication token
|
||||
match encode(&*HEADER, &val, &key) {
|
||||
// The auth token was created successfully
|
||||
|
@ -139,7 +169,13 @@ pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<Stri
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn db(ns: String, db: String, user: String, pass: String) -> Result<String, Error> {
|
||||
pub async fn db(
|
||||
session: &mut Session,
|
||||
ns: String,
|
||||
db: String,
|
||||
user: String,
|
||||
pass: String,
|
||||
) -> Result<String, Error> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Create a new readonly transaction
|
||||
|
@ -160,11 +196,13 @@ pub async fn db(ns: String, db: String, user: String, pass: String) -> Result<St
|
|||
iat: Utc::now().timestamp(),
|
||||
nbf: Utc::now().timestamp(),
|
||||
exp: (Utc::now() + Duration::hours(1)).timestamp(),
|
||||
ns: Some(ns),
|
||||
db: Some(db),
|
||||
ns: Some(ns.to_owned()),
|
||||
db: Some(db.to_owned()),
|
||||
id: Some(user),
|
||||
..Claims::default()
|
||||
};
|
||||
// Set the authentication on the sesssion
|
||||
session.au = Arc::new(Auth::Db(ns, db));
|
||||
// Create the authentication token
|
||||
match encode(&*HEADER, &val, &key) {
|
||||
// The auth token was created successfully
|
||||
|
@ -182,7 +220,12 @@ pub async fn db(ns: String, db: String, user: String, pass: String) -> Result<St
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn ns(ns: String, user: String, pass: String) -> Result<String, Error> {
|
||||
pub async fn ns(
|
||||
session: &mut Session,
|
||||
ns: String,
|
||||
user: String,
|
||||
pass: String,
|
||||
) -> Result<String, Error> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Create a new readonly transaction
|
||||
|
@ -203,10 +246,12 @@ pub async fn ns(ns: String, user: String, pass: String) -> Result<String, Error>
|
|||
iat: Utc::now().timestamp(),
|
||||
nbf: Utc::now().timestamp(),
|
||||
exp: (Utc::now() + Duration::hours(1)).timestamp(),
|
||||
ns: Some(ns),
|
||||
ns: Some(ns.to_owned()),
|
||||
id: Some(user),
|
||||
..Claims::default()
|
||||
};
|
||||
// Set the authentication on the sesssion
|
||||
session.au = Arc::new(Auth::Ns(ns));
|
||||
// Create the authentication token
|
||||
match encode(&*HEADER, &val, &key) {
|
||||
// The auth token was created successfully
|
||||
|
@ -223,3 +268,17 @@ pub async fn ns(ns: String, user: String, pass: String) -> Result<String, Error>
|
|||
_ => Err(Error::InvalidAuth),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn su(session: &mut Session, user: String, pass: String) -> Result<String, Error> {
|
||||
// Get the config options
|
||||
let opts = CF.get().unwrap();
|
||||
// Attempt to verify the root user
|
||||
if let Some(root) = &opts.pass {
|
||||
if user == opts.user && &pass == root {
|
||||
session.au = Arc::new(Auth::Kv);
|
||||
return Ok(String::from(""));
|
||||
}
|
||||
}
|
||||
// The specified user login does not exist
|
||||
Err(Error::InvalidAuth)
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@ use crate::err::Error;
|
|||
use crate::iam::token::{Claims, HEADER};
|
||||
use chrono::{Duration, Utc};
|
||||
use jsonwebtoken::{encode, EncodingKey};
|
||||
use std::sync::Arc;
|
||||
use surrealdb::sql::Object;
|
||||
use surrealdb::Auth;
|
||||
use surrealdb::Session;
|
||||
|
||||
pub async fn signup(vars: Object) -> Result<String, Error> {
|
||||
pub async fn signup(session: &mut Session, vars: Object) -> Result<String, Error> {
|
||||
// Parse the specified variables
|
||||
let ns = vars.get("NS").or_else(|| vars.get("ns"));
|
||||
let db = vars.get("DB").or_else(|| vars.get("db"));
|
||||
|
@ -21,7 +23,7 @@ pub async fn signup(vars: Object) -> Result<String, Error> {
|
|||
let db = db.to_strand().as_string();
|
||||
let sc = sc.to_strand().as_string();
|
||||
// Attempt to signin to specified scope
|
||||
let res = super::signup::sc(ns, db, sc, vars).await?;
|
||||
let res = super::signup::sc(session, ns, db, sc, vars).await?;
|
||||
// Return the result to the client
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -29,7 +31,13 @@ pub async fn signup(vars: Object) -> Result<String, Error> {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<String, Error> {
|
||||
pub async fn sc(
|
||||
session: &mut Session,
|
||||
ns: String,
|
||||
db: String,
|
||||
sc: String,
|
||||
vars: Object,
|
||||
) -> Result<String, Error> {
|
||||
// Get a database reference
|
||||
let kvs = DB.get().unwrap();
|
||||
// Get local copy of options
|
||||
|
@ -64,12 +72,14 @@ pub async fn sc(ns: String, db: String, sc: String, vars: Object) -> Result<Stri
|
|||
_ => Utc::now() + Duration::hours(1),
|
||||
}
|
||||
.timestamp(),
|
||||
ns: Some(ns),
|
||||
db: Some(db),
|
||||
sc: Some(sc),
|
||||
ns: Some(ns.to_owned()),
|
||||
db: Some(db.to_owned()),
|
||||
sc: Some(sc.to_owned()),
|
||||
id: Some(rid.to_raw()),
|
||||
..Claims::default()
|
||||
};
|
||||
// Set the authentication on the sesssion
|
||||
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
||||
// Create the authentication token
|
||||
match encode(&*HEADER, &val, &key) {
|
||||
// The auth token was created successfully
|
||||
|
|
|
@ -116,11 +116,11 @@ impl Rpc {
|
|||
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await,
|
||||
},
|
||||
"signup" => match params.take_one() {
|
||||
Value::Object(v) => rpc.read().await.signup(v).await,
|
||||
Value::Object(v) => rpc.write().await.signup(v).await,
|
||||
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await,
|
||||
},
|
||||
"signin" => match params.take_one() {
|
||||
Value::Object(v) => rpc.read().await.signin(v).await,
|
||||
Value::Object(v) => rpc.write().await.signin(v).await,
|
||||
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await,
|
||||
},
|
||||
"invalidate" => match params.len() {
|
||||
|
@ -208,12 +208,18 @@ impl Rpc {
|
|||
Ok(Value::None)
|
||||
}
|
||||
|
||||
async fn signup(&self, vars: Object) -> Result<Value, Error> {
|
||||
crate::iam::signup::signup(vars).await.map(Into::into).map_err(Into::into)
|
||||
async fn signup(&mut self, vars: Object) -> Result<Value, Error> {
|
||||
crate::iam::signup::signup(&mut self.session, vars)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn signin(&self, vars: Object) -> Result<Value, Error> {
|
||||
crate::iam::signin::signin(vars).await.map(Into::into).map_err(Into::into)
|
||||
async fn signin(&mut self, vars: Object) -> Result<Value, Error> {
|
||||
crate::iam::signin::signin(&mut self.session, vars)
|
||||
.await
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn invalidate(&mut self) -> Result<Value, Error> {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use crate::err::Error;
|
||||
use crate::net::session;
|
||||
use bytes::Bytes;
|
||||
use std::str;
|
||||
use surrealdb::sql::Value;
|
||||
use surrealdb::Session;
|
||||
use warp::http::Response;
|
||||
use warp::Filter;
|
||||
|
||||
|
@ -15,6 +17,7 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
|||
// Set post method
|
||||
let post = base
|
||||
.and(warp::post())
|
||||
.and(session::build())
|
||||
.and(warp::body::content_length_limit(MAX))
|
||||
.and(warp::body::bytes())
|
||||
.and_then(handler);
|
||||
|
@ -22,13 +25,13 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
|||
opts.or(post)
|
||||
}
|
||||
|
||||
async fn handler(body: Bytes) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
async fn handler(mut session: Session, body: Bytes) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Convert the HTTP body into text
|
||||
let data = str::from_utf8(&body).unwrap();
|
||||
// Parse the provided data as JSON
|
||||
match surrealdb::sql::json(data) {
|
||||
// The provided value was an object
|
||||
Ok(Value::Object(vars)) => match crate::iam::signin::signin(vars).await {
|
||||
Ok(Value::Object(vars)) => match crate::iam::signin::signin(&mut session, vars).await {
|
||||
// Authentication was successful
|
||||
Ok(v) => Ok(Response::builder().body(v)),
|
||||
// There was an error with authentication
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use crate::err::Error;
|
||||
use crate::net::session;
|
||||
use bytes::Bytes;
|
||||
use std::str;
|
||||
use surrealdb::sql::Value;
|
||||
use surrealdb::Session;
|
||||
use warp::http::Response;
|
||||
use warp::Filter;
|
||||
|
||||
|
@ -15,6 +17,7 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
|||
// Set post method
|
||||
let post = base
|
||||
.and(warp::post())
|
||||
.and(session::build())
|
||||
.and(warp::body::content_length_limit(MAX))
|
||||
.and(warp::body::bytes())
|
||||
.and_then(handler);
|
||||
|
@ -22,13 +25,13 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
|||
opts.or(post)
|
||||
}
|
||||
|
||||
async fn handler(body: Bytes) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
async fn handler(mut session: Session, body: Bytes) -> Result<impl warp::Reply, warp::Rejection> {
|
||||
// Convert the HTTP body into text
|
||||
let data = str::from_utf8(&body).unwrap();
|
||||
// Parse the provided data as JSON
|
||||
match surrealdb::sql::json(data) {
|
||||
// The provided value was an object
|
||||
Ok(Value::Object(vars)) => match crate::iam::signup::signup(vars).await {
|
||||
Ok(Value::Object(vars)) => match crate::iam::signup::signup(&mut session, vars).await {
|
||||
// Authentication was successful
|
||||
Ok(v) => Ok(Response::builder().body(v)),
|
||||
// There was an error with authentication
|
||||
|
|
Loading…
Reference in a new issue