dry redis connections and use bearer tokens
This commit is contained in:
parent
94bc6fef8c
commit
2989b7e91c
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -278,9 +278,9 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.53"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
|
||||
checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -386,6 +386,18 @@ dependencies = [
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-auth"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9770f9a9147b2324066609acb5495538cb25f973129663fba2658ba7ed69407"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"base64 0.13.0",
|
||||
"http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-client-ip"
|
||||
version = "0.2.0"
|
||||
@ -4344,9 +4356,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.83"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
dependencies = [
|
||||
"itoa 1.0.2",
|
||||
"ryu",
|
||||
@ -5521,6 +5533,7 @@ dependencies = [
|
||||
"arc-swap",
|
||||
"argh",
|
||||
"axum",
|
||||
"axum-auth",
|
||||
"axum-client-ip",
|
||||
"axum-macros",
|
||||
"counter",
|
||||
|
@ -20,6 +20,7 @@ anyhow = { version = "1.0.62", features = ["backtrace"] }
|
||||
arc-swap = "1.5.1"
|
||||
argh = "0.1.8"
|
||||
axum = { version = "0.5.15", features = ["headers", "serde_json", "tokio-tungstenite", "ws"] }
|
||||
axum-auth = "0.3.0"
|
||||
axum-client-ip = "0.2.0"
|
||||
axum-macros = "0.2.3"
|
||||
counter = "0.5.6"
|
||||
@ -49,7 +50,7 @@ rustc-hash = "1.1.0"
|
||||
siwe = "0.4.1"
|
||||
sea-orm = { version = "0.9.2", features = ["macros"] }
|
||||
serde = { version = "1.0.144", features = [] }
|
||||
serde_json = { version = "1.0.83", default-features = false, features = ["alloc", "raw_value"] }
|
||||
serde_json = { version = "1.0.85", default-features = false, features = ["alloc", "raw_value"] }
|
||||
# TODO: make sure this time version matches siwe. PR to put this in their prelude
|
||||
time = "0.3.13"
|
||||
tokio = { version = "1.20.1", features = ["full", "tracing"] }
|
||||
|
@ -15,6 +15,7 @@ use futures::stream::StreamExt;
|
||||
use futures::Future;
|
||||
use migration::{Migrator, MigratorTrait};
|
||||
use parking_lot::RwLock;
|
||||
use redis_rate_limit::bb8::PooledConnection;
|
||||
use redis_rate_limit::{
|
||||
bb8::{self, ErrorSink},
|
||||
RedisConnectionManager, RedisErrorSink, RedisPool, RedisRateLimit,
|
||||
@ -158,6 +159,17 @@ impl fmt::Debug for Web3ProxyApp {
|
||||
}
|
||||
|
||||
impl Web3ProxyApp {
|
||||
pub async fn redis_conn(&self) -> anyhow::Result<PooledConnection<RedisConnectionManager>> {
|
||||
match self.redis_pool.as_ref() {
|
||||
None => Err(anyhow::anyhow!("no redis server configured")),
|
||||
Some(redis_pool) => {
|
||||
let redis_conn = redis_pool.get().await?;
|
||||
|
||||
Ok(redis_conn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: should we just take the rpc config as the only arg instead?
|
||||
pub async fn spawn(
|
||||
app_stats: AppStats,
|
||||
|
@ -15,6 +15,7 @@ use axum::{
|
||||
response::IntoResponse,
|
||||
Extension, Json,
|
||||
};
|
||||
use axum_auth::AuthBearer;
|
||||
use axum_client_ip::ClientIp;
|
||||
use axum_macros::debug_handler;
|
||||
use entities::{user, user_keys};
|
||||
@ -48,7 +49,8 @@ pub async fn get_login(
|
||||
// create a message and save it in redis
|
||||
|
||||
// TODO: how many seconds? get from config?
|
||||
let expire_seconds: usize = 300;
|
||||
// TODO: while developing, we put a giant number here
|
||||
let expire_seconds: usize = 28800;
|
||||
|
||||
let nonce = Ulid::new();
|
||||
|
||||
@ -78,21 +80,14 @@ pub async fn get_login(
|
||||
let session_key = format!("pending:{}", nonce);
|
||||
|
||||
// TODO: if no redis server, store in local cache?
|
||||
let mut redis_conn = app
|
||||
.redis_pool
|
||||
.as_ref()
|
||||
.expect("login requires a redis server")
|
||||
.get()
|
||||
.await?;
|
||||
|
||||
// the address isn't enough. we need to save the actual message so we can read the nonce
|
||||
// TODO: what message format is the most efficient to store in redis? probably eip191_string
|
||||
redis_conn
|
||||
.set_ex(session_key, message.to_string(), expire_seconds)
|
||||
// we add 1 to expire_seconds just to be sure redis has the key for the full expiration_time
|
||||
app.redis_conn()
|
||||
.await?
|
||||
.set_ex(session_key, message.to_string(), expire_seconds + 1)
|
||||
.await?;
|
||||
|
||||
drop(redis_conn);
|
||||
|
||||
// there are multiple ways to sign messages and not all wallets support them
|
||||
let message_eip = params
|
||||
.remove("message_eip")
|
||||
@ -152,16 +147,8 @@ pub async fn post_login(
|
||||
let their_sig: [u8; 65] = payload.sig.as_ref().try_into().unwrap();
|
||||
|
||||
// fetch the message we gave them from our redis
|
||||
let redis_pool = app
|
||||
.redis_pool
|
||||
.as_ref()
|
||||
.expect("login requires a redis server");
|
||||
|
||||
let mut redis_conn = redis_pool.get().await.unwrap();
|
||||
|
||||
// TODO: use getdel
|
||||
// TODO: do not unwrap. make this function return a FrontendResult
|
||||
let our_msg: String = redis_conn.get(&their_msg.nonce).await.unwrap();
|
||||
let our_msg: String = app.redis_conn().await?.get(&their_msg.nonce).await?;
|
||||
|
||||
let our_msg: siwe::Message = our_msg.parse().unwrap();
|
||||
|
||||
@ -203,6 +190,7 @@ pub async fn post_login(
|
||||
// TODO: set a cookie?
|
||||
|
||||
// TODO: do not expose user ids
|
||||
// TODO: return an api key and a bearer token
|
||||
(StatusCode::CREATED, Json(user)).into_response()
|
||||
*/
|
||||
} else {
|
||||
@ -224,10 +212,12 @@ pub struct PostUser {
|
||||
pub async fn post_user(
|
||||
Json(payload): Json<PostUser>,
|
||||
Extension(app): Extension<Arc<Web3ProxyApp>>,
|
||||
ClientIp(ip): ClientIp,
|
||||
AuthBearer(auth_token): AuthBearer,
|
||||
) -> FrontendResult {
|
||||
todo!("finish post_user");
|
||||
|
||||
// TODO: check the auth_token is valid for the user in PostUser
|
||||
|
||||
// let user = user::ActiveModel {
|
||||
// address: sea_orm::Set(payload.address.to_fixed_bytes().into()),
|
||||
// email: sea_orm::Set(payload.email),
|
||||
|
Loading…
Reference in New Issue
Block a user