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 argon2::Argon2;
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use jsonwebtoken::{encode, EncodingKey};
|
use jsonwebtoken::{encode, EncodingKey};
|
||||||
|
use std::sync::Arc;
|
||||||
use surrealdb::sql::Object;
|
use surrealdb::sql::Object;
|
||||||
|
use surrealdb::Auth;
|
||||||
use surrealdb::Session;
|
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
|
// Parse the specified variables
|
||||||
let ns = vars.get("NS").or_else(|| vars.get("ns"));
|
let ns = vars.get("NS").or_else(|| vars.get("ns"));
|
||||||
let db = vars.get("DB").or_else(|| vars.get("db"));
|
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 db = db.to_strand().as_string();
|
||||||
let sc = sc.to_strand().as_string();
|
let sc = sc.to_strand().as_string();
|
||||||
// Attempt to signin to specified scope
|
// 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
|
// Return the result to the client
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +43,7 @@ pub async fn signin(vars: Object) -> Result<String, Error> {
|
||||||
let user = user.to_strand().as_string();
|
let user = user.to_strand().as_string();
|
||||||
let pass = pass.to_strand().as_string();
|
let pass = pass.to_strand().as_string();
|
||||||
// Attempt to signin to database
|
// 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
|
// Return the result to the client
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -62,7 +64,27 @@ pub async fn signin(vars: Object) -> Result<String, Error> {
|
||||||
let user = user.to_strand().as_string();
|
let user = user.to_strand().as_string();
|
||||||
let pass = pass.to_strand().as_string();
|
let pass = pass.to_strand().as_string();
|
||||||
// Attempt to signin to namespace
|
// 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
|
// Return the result to the client
|
||||||
Ok(res)
|
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
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
// Get local copy of options
|
// 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),
|
_ => Utc::now() + Duration::hours(1),
|
||||||
}
|
}
|
||||||
.timestamp(),
|
.timestamp(),
|
||||||
ns: Some(ns),
|
ns: Some(ns.to_owned()),
|
||||||
db: Some(db),
|
db: Some(db.to_owned()),
|
||||||
sc: Some(sc),
|
sc: Some(sc.to_owned()),
|
||||||
id: Some(rid.to_raw()),
|
id: Some(rid.to_raw()),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
|
// Set the authentication on the sesssion
|
||||||
|
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
||||||
// Create the authentication token
|
// Create the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
match encode(&*HEADER, &val, &key) {
|
||||||
// The auth token was created successfully
|
// 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
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
// Create a new readonly transaction
|
// 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(),
|
iat: Utc::now().timestamp(),
|
||||||
nbf: Utc::now().timestamp(),
|
nbf: Utc::now().timestamp(),
|
||||||
exp: (Utc::now() + Duration::hours(1)).timestamp(),
|
exp: (Utc::now() + Duration::hours(1)).timestamp(),
|
||||||
ns: Some(ns),
|
ns: Some(ns.to_owned()),
|
||||||
db: Some(db),
|
db: Some(db.to_owned()),
|
||||||
id: Some(user),
|
id: Some(user),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
|
// Set the authentication on the sesssion
|
||||||
|
session.au = Arc::new(Auth::Db(ns, db));
|
||||||
// Create the authentication token
|
// Create the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
match encode(&*HEADER, &val, &key) {
|
||||||
// The auth token was created successfully
|
// 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
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
// Create a new readonly transaction
|
// 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(),
|
iat: Utc::now().timestamp(),
|
||||||
nbf: Utc::now().timestamp(),
|
nbf: Utc::now().timestamp(),
|
||||||
exp: (Utc::now() + Duration::hours(1)).timestamp(),
|
exp: (Utc::now() + Duration::hours(1)).timestamp(),
|
||||||
ns: Some(ns),
|
ns: Some(ns.to_owned()),
|
||||||
id: Some(user),
|
id: Some(user),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
|
// Set the authentication on the sesssion
|
||||||
|
session.au = Arc::new(Auth::Ns(ns));
|
||||||
// Create the authentication token
|
// Create the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
match encode(&*HEADER, &val, &key) {
|
||||||
// The auth token was created successfully
|
// 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),
|
_ => 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 crate::iam::token::{Claims, HEADER};
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use jsonwebtoken::{encode, EncodingKey};
|
use jsonwebtoken::{encode, EncodingKey};
|
||||||
|
use std::sync::Arc;
|
||||||
use surrealdb::sql::Object;
|
use surrealdb::sql::Object;
|
||||||
|
use surrealdb::Auth;
|
||||||
use surrealdb::Session;
|
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
|
// Parse the specified variables
|
||||||
let ns = vars.get("NS").or_else(|| vars.get("ns"));
|
let ns = vars.get("NS").or_else(|| vars.get("ns"));
|
||||||
let db = vars.get("DB").or_else(|| vars.get("db"));
|
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 db = db.to_strand().as_string();
|
||||||
let sc = sc.to_strand().as_string();
|
let sc = sc.to_strand().as_string();
|
||||||
// Attempt to signin to specified scope
|
// 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
|
// Return the result to the client
|
||||||
Ok(res)
|
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
|
// Get a database reference
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
// Get local copy of options
|
// 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),
|
_ => Utc::now() + Duration::hours(1),
|
||||||
}
|
}
|
||||||
.timestamp(),
|
.timestamp(),
|
||||||
ns: Some(ns),
|
ns: Some(ns.to_owned()),
|
||||||
db: Some(db),
|
db: Some(db.to_owned()),
|
||||||
sc: Some(sc),
|
sc: Some(sc.to_owned()),
|
||||||
id: Some(rid.to_raw()),
|
id: Some(rid.to_raw()),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
|
// Set the authentication on the sesssion
|
||||||
|
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
||||||
// Create the authentication token
|
// Create the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
match encode(&*HEADER, &val, &key) {
|
||||||
// The auth token was created successfully
|
// The auth token was created successfully
|
||||||
|
|
|
@ -116,11 +116,11 @@ impl Rpc {
|
||||||
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await,
|
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await,
|
||||||
},
|
},
|
||||||
"signup" => match params.take_one() {
|
"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,
|
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await,
|
||||||
},
|
},
|
||||||
"signin" => match params.take_one() {
|
"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,
|
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await,
|
||||||
},
|
},
|
||||||
"invalidate" => match params.len() {
|
"invalidate" => match params.len() {
|
||||||
|
@ -208,12 +208,18 @@ impl Rpc {
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn signup(&self, vars: Object) -> Result<Value, Error> {
|
async fn signup(&mut self, vars: Object) -> Result<Value, Error> {
|
||||||
crate::iam::signup::signup(vars).await.map(Into::into).map_err(Into::into)
|
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> {
|
async fn signin(&mut self, vars: Object) -> Result<Value, Error> {
|
||||||
crate::iam::signin::signin(vars).await.map(Into::into).map_err(Into::into)
|
crate::iam::signin::signin(&mut self.session, vars)
|
||||||
|
.await
|
||||||
|
.map(Into::into)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn invalidate(&mut self) -> Result<Value, Error> {
|
async fn invalidate(&mut self) -> Result<Value, Error> {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
use crate::net::session;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use std::str;
|
use std::str;
|
||||||
use surrealdb::sql::Value;
|
use surrealdb::sql::Value;
|
||||||
|
use surrealdb::Session;
|
||||||
use warp::http::Response;
|
use warp::http::Response;
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
|
|
||||||
|
@ -15,6 +17,7 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
||||||
// Set post method
|
// Set post method
|
||||||
let post = base
|
let post = base
|
||||||
.and(warp::post())
|
.and(warp::post())
|
||||||
|
.and(session::build())
|
||||||
.and(warp::body::content_length_limit(MAX))
|
.and(warp::body::content_length_limit(MAX))
|
||||||
.and(warp::body::bytes())
|
.and(warp::body::bytes())
|
||||||
.and_then(handler);
|
.and_then(handler);
|
||||||
|
@ -22,13 +25,13 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
||||||
opts.or(post)
|
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
|
// Convert the HTTP body into text
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
// Parse the provided data as JSON
|
// Parse the provided data as JSON
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
// The provided value was an object
|
// 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
|
// Authentication was successful
|
||||||
Ok(v) => Ok(Response::builder().body(v)),
|
Ok(v) => Ok(Response::builder().body(v)),
|
||||||
// There was an error with authentication
|
// There was an error with authentication
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
use crate::net::session;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use std::str;
|
use std::str;
|
||||||
use surrealdb::sql::Value;
|
use surrealdb::sql::Value;
|
||||||
|
use surrealdb::Session;
|
||||||
use warp::http::Response;
|
use warp::http::Response;
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
|
|
||||||
|
@ -15,6 +17,7 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
||||||
// Set post method
|
// Set post method
|
||||||
let post = base
|
let post = base
|
||||||
.and(warp::post())
|
.and(warp::post())
|
||||||
|
.and(session::build())
|
||||||
.and(warp::body::content_length_limit(MAX))
|
.and(warp::body::content_length_limit(MAX))
|
||||||
.and(warp::body::bytes())
|
.and(warp::body::bytes())
|
||||||
.and_then(handler);
|
.and_then(handler);
|
||||||
|
@ -22,13 +25,13 @@ pub fn config() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
|
||||||
opts.or(post)
|
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
|
// Convert the HTTP body into text
|
||||||
let data = str::from_utf8(&body).unwrap();
|
let data = str::from_utf8(&body).unwrap();
|
||||||
// Parse the provided data as JSON
|
// Parse the provided data as JSON
|
||||||
match surrealdb::sql::json(data) {
|
match surrealdb::sql::json(data) {
|
||||||
// The provided value was an object
|
// 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
|
// Authentication was successful
|
||||||
Ok(v) => Ok(Response::builder().body(v)),
|
Ok(v) => Ok(Response::builder().body(v)),
|
||||||
// There was an error with authentication
|
// There was an error with authentication
|
||||||
|
|
Loading…
Reference in a new issue