finish basic ProtectedAction
This commit is contained in:
parent
618bfeb861
commit
1d24955d6f
@ -121,7 +121,7 @@ pub struct AppConfig {
|
||||
/// the stats page url for a logged in user. if set, must contain "{user_id}"
|
||||
pub redirect_user_url: Option<String>,
|
||||
|
||||
/// https://sentry.io
|
||||
/// Optionally send errors to <https://sentry.io>
|
||||
pub sentry_url: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -263,8 +263,6 @@ pub async fn login_is_authorized(
|
||||
app: &Web3ProxyApp,
|
||||
ip: IpAddr,
|
||||
) -> Result<AuthorizedRequest, FrontendErrorResponse> {
|
||||
// TODO: i think we could write an `impl From` for this
|
||||
// TODO: move this to an AuthorizedUser extrator
|
||||
let (ip, _semaphore) = match app.rate_limit_login(ip).await? {
|
||||
RateLimitResult::AllowedIp(x, semaphore) => (x, semaphore),
|
||||
RateLimitResult::RateLimitedIp(x, retry_at) => {
|
||||
@ -277,34 +275,6 @@ pub async fn login_is_authorized(
|
||||
Ok(AuthorizedRequest::Ip(ip, None))
|
||||
}
|
||||
|
||||
// TODO: where should we use this?
|
||||
pub async fn bearer_is_authorized(
|
||||
app: &Web3ProxyApp,
|
||||
bearer: Bearer,
|
||||
) -> Result<(AuthorizedRequest, Option<OwnedSemaphorePermit>), FrontendErrorResponse> {
|
||||
let mut redis_conn = app.redis_conn().await.context("Getting redis connection")?;
|
||||
|
||||
// TODO: verify that bearer.token() is a Ulid?
|
||||
let bearer_cache_key = format!("bearer:{}", bearer.token());
|
||||
|
||||
// turn bearer into a user key id
|
||||
let user_id: u64 = redis_conn
|
||||
.get(bearer_cache_key)
|
||||
.await
|
||||
.context("unknown bearer token")?;
|
||||
|
||||
let db_conn = app.db_conn().context("Getting database connection")?;
|
||||
|
||||
// turn user key id into a user key
|
||||
let user_data = user::Entity::find_by_id(user_id)
|
||||
.one(&db_conn)
|
||||
.await
|
||||
.context("fetching user by id")?
|
||||
.context("unknown user id")?;
|
||||
|
||||
todo!("rewrite this. key_is_authorized is wrong. we should check user ids instead")
|
||||
}
|
||||
|
||||
pub async fn ip_is_authorized(
|
||||
app: &Web3ProxyApp,
|
||||
ip: IpAddr,
|
||||
@ -408,7 +378,7 @@ impl Web3ProxyApp {
|
||||
|
||||
pub async fn rate_limit_login(&self, ip: IpAddr) -> anyhow::Result<RateLimitResult> {
|
||||
// TODO: dry this up with rate_limit_by_key
|
||||
// TODO: do we ant semafores here?
|
||||
// TODO: do we want a semaphore here?
|
||||
if let Some(rate_limiter) = &self.login_rate_limiter {
|
||||
match rate_limiter.throttle_label(&ip.to_string(), None, 1).await {
|
||||
Ok(RedisRateLimitResult::Allowed(_)) => Ok(RateLimitResult::AllowedIp(ip, None)),
|
||||
|
@ -3,7 +3,6 @@
|
||||
use super::authorization::{login_is_authorized, UserKey};
|
||||
use super::errors::FrontendResult;
|
||||
use crate::app::Web3ProxyApp;
|
||||
use crate::frontend::authorization::bearer_is_authorized;
|
||||
use crate::user_queries::{get_aggregate_rpc_stats_from_params, get_detailed_stats};
|
||||
use anyhow::Context;
|
||||
use axum::{
|
||||
@ -358,7 +357,6 @@ pub struct PostUser {
|
||||
primary_address: Address,
|
||||
// TODO: make sure the email address is valid. probably have a "verified" column in the database
|
||||
email: Option<String>,
|
||||
// TODO: make them sign this JSON? cookie in session id is hard because its on a different domain
|
||||
}
|
||||
|
||||
/// `POST /user/profile` -- modify the account connected to the bearer token in the `Authentication` header.
|
||||
@ -409,8 +407,6 @@ pub async fn user_balance_get(
|
||||
Extension(app): Extension<Arc<Web3ProxyApp>>,
|
||||
TypedHeader(Authorization(bearer)): TypedHeader<Authorization<Bearer>>,
|
||||
) -> FrontendResult {
|
||||
let (authorized_request, _semaphore) = bearer_is_authorized(&app, bearer).await?;
|
||||
|
||||
todo!("user_balance_get");
|
||||
}
|
||||
|
||||
@ -515,12 +511,7 @@ enum ProtectedAction {
|
||||
|
||||
impl ProtectedAction {
|
||||
/// Verify that the given bearer token and address are allowed to take the specified action.
|
||||
async fn verify(
|
||||
self,
|
||||
app: &Web3ProxyApp,
|
||||
// TODO: i don't think we want Bearer here. we want user_key and a helper for bearer -> user_key
|
||||
bearer: Bearer,
|
||||
) -> anyhow::Result<user::Model> {
|
||||
async fn verify(self, app: &Web3ProxyApp, bearer: Bearer) -> anyhow::Result<user::Model> {
|
||||
// get the attached address from redis for the given auth_token.
|
||||
let mut redis_conn = app.redis_conn().await?;
|
||||
|
||||
@ -528,13 +519,32 @@ impl ProtectedAction {
|
||||
let bearer_cache_key = format!("bearer:{}", bearer.token());
|
||||
|
||||
// TODO: move this to a helper function
|
||||
let user_id: Option<u64> = redis_conn
|
||||
.get(bearer_cache_key)
|
||||
let user_id: u64 = redis_conn
|
||||
.get::<_, Option<u64>>(bearer_cache_key)
|
||||
.await
|
||||
.context("fetching bearer cache key from redis")?;
|
||||
.context("fetching bearer cache key from redis")?
|
||||
.context("unknown bearer token")?;
|
||||
|
||||
// TODO: if auth_address == primary_address, allow
|
||||
// TODO: if auth_address != primary_address, only allow if they are a secondary user with the correct role
|
||||
todo!("verify token for the given user");
|
||||
let db_conn = app.db_conn().context("Getting database connection")?;
|
||||
|
||||
// turn user key id into a user key
|
||||
let user_data = user::Entity::find_by_id(user_id)
|
||||
.one(&db_conn)
|
||||
.await
|
||||
.context("fetching user from db by id")?
|
||||
.context("unknown user id")?;
|
||||
|
||||
match self {
|
||||
Self::PostUser(primary_address) => {
|
||||
let user_address = Address::from_slice(&user_data.address);
|
||||
|
||||
if user_address != primary_address {
|
||||
// TODO: check secondary users
|
||||
return Err(anyhow::anyhow!("user address mismatch"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(user_data)
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ impl Web3Connection {
|
||||
}
|
||||
|
||||
/// reconnect to the provider. errors are retried forever with exponential backoff with jitter.
|
||||
/// We use the "Decorrelated" jitter from https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
|
||||
/// We use the "Decorrelated" jitter from <https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/>
|
||||
/// TODO: maybe it would be better to use "Full Jitter". The "Full Jitter" approach uses less work, but slightly more time.
|
||||
pub async fn retrying_reconnect(
|
||||
self: &Arc<Self>,
|
||||
|
Loading…
Reference in New Issue
Block a user