fix some auth
This commit is contained in:
parent
8b35bf5e63
commit
bb9e4f99ef
@ -9,7 +9,7 @@ pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: u64,
|
||||
pub title: String,
|
||||
pub max_requests_per_minute: Option<u64>,
|
||||
pub max_requests_per_period: Option<u64>,
|
||||
pub max_concurrent_requests: Option<u32>,
|
||||
}
|
||||
|
||||
|
@ -64,14 +64,14 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.await?;
|
||||
|
||||
// on user_tier table, rename requests_per_minute to max_requests_per_minute
|
||||
// on user_tier table, rename requests_per_minute to max_requests_per_period
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(Alias::new("user_tier"))
|
||||
.rename_column(
|
||||
Alias::new("requests_per_minute"),
|
||||
Alias::new("max_requests_per_minute"),
|
||||
Alias::new("max_requests_per_period"),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
|
@ -70,7 +70,7 @@ pub struct UserKeyData {
|
||||
/// if None, allow unlimited queries. inherited from the user_tier
|
||||
pub max_requests_per_period: Option<u64>,
|
||||
// if None, allow unlimited concurrent requests. inherited from the user_tier
|
||||
pub max_concurrent_requests: Option<u64>,
|
||||
pub max_concurrent_requests: Option<u32>,
|
||||
/// if None, allow any Origin
|
||||
pub allowed_origins: Option<Vec<Origin>>,
|
||||
/// if None, allow any Referer
|
||||
@ -399,7 +399,7 @@ impl Web3ProxyApp {
|
||||
// TODO: think about this unwrapping
|
||||
top_config
|
||||
.app
|
||||
.public_requests_per_minute
|
||||
.public_requests_per_period
|
||||
.unwrap_or(u64::MAX),
|
||||
60.0,
|
||||
redis_pool.clone(),
|
||||
@ -421,7 +421,7 @@ impl Web3ProxyApp {
|
||||
login_rate_limiter = Some(RedisRateLimiter::new(
|
||||
"web3_proxy",
|
||||
"login",
|
||||
top_config.app.login_rate_limit_per_minute,
|
||||
top_config.app.login_rate_limit_per_period,
|
||||
60.0,
|
||||
redis_pool.clone(),
|
||||
));
|
||||
|
@ -267,10 +267,10 @@ mod tests {
|
||||
let app_config = TopConfig {
|
||||
app: AppConfig {
|
||||
chain_id: 31337,
|
||||
default_user_max_requests_per_minute: Some(6_000_000),
|
||||
default_user_max_requests_per_period: Some(6_000_000),
|
||||
min_sum_soft_limit: 1,
|
||||
min_synced_rpcs: 1,
|
||||
public_requests_per_minute: Some(1_000_000),
|
||||
public_requests_per_period: Some(1_000_000),
|
||||
response_cache_max_bytes: 10_usize.pow(7),
|
||||
redirect_public_url: Some("example.com/".to_string()),
|
||||
redirect_user_url: Some("example.com/{{user_id}}".to_string()),
|
||||
|
@ -25,23 +25,23 @@ impl CheckConfigSubCommand {
|
||||
warn!("app.db_url is not set! Some features disabled")
|
||||
}
|
||||
|
||||
match top_config.app.public_requests_per_minute {
|
||||
match top_config.app.public_requests_per_period {
|
||||
None => {
|
||||
info!("app.public_requests_per_minute is None. Fully open to public requests!")
|
||||
info!("app.public_requests_per_period is None. Fully open to public requests!")
|
||||
}
|
||||
Some(0) => {
|
||||
info!("app.public_requests_per_minute is 0. Public requests are blocked!")
|
||||
info!("app.public_requests_per_period is 0. Public requests are blocked!")
|
||||
}
|
||||
Some(_) => {}
|
||||
}
|
||||
|
||||
match top_config.app.default_user_max_requests_per_minute {
|
||||
match top_config.app.default_user_max_requests_per_period {
|
||||
None => {
|
||||
info!("app.default_user_requests_per_minute is None. Fully open to registered requests!")
|
||||
info!("app.default_user_requests_per_period is None. Fully open to registered requests!")
|
||||
}
|
||||
Some(0) => warn!("app.default_user_requests_per_minute is 0. Registered user's requests are blocked! Are you sure you want that?"),
|
||||
Some(0) => warn!("app.default_user_requests_per_period is 0. Registered user's requests are blocked! Are you sure you want that?"),
|
||||
Some(_) => {
|
||||
// TODO: make sure this isn't < anonymous requests per minute
|
||||
// TODO: make sure this isn't < anonymous requests per period
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,8 +52,8 @@ impl CheckConfigSubCommand {
|
||||
|
||||
// TODO: check min_sum_soft_limit is a reasonable amount
|
||||
// TODO: check min_synced_rpcs is a reasonable amount
|
||||
// TODO: check frontend_rate_limit_per_minute is a reasonable amount. requires redis
|
||||
// TODO: check login_rate_limit_per_minute is a reasonable amount. requires redis
|
||||
// TODO: check frontend_rate_limit_per_period is a reasonable amount. requires redis
|
||||
// TODO: check login_rate_limit_per_period is a reasonable amount. requires redis
|
||||
|
||||
if top_config.app.volatile_redis_url.is_none() {
|
||||
warn!("app.volatile_redis_url is not set! Some features disabled")
|
||||
|
@ -53,7 +53,7 @@ pub struct TopConfig {
|
||||
pub struct AppConfig {
|
||||
/// Request limit for allowed origins for anonymous users.
|
||||
/// These requests get rate limited by IP.
|
||||
pub allowed_origin_requests_per_minute: HashMap<String, u64>,
|
||||
pub allowed_origin_requests_per_period: HashMap<String, u64>,
|
||||
|
||||
/// EVM chain id. 1 for ETH
|
||||
/// TODO: better type for chain_id? max of `u64::MAX / 2 - 36` https://github.com/ethereum/EIPs/issues/2294
|
||||
@ -74,7 +74,7 @@ pub struct AppConfig {
|
||||
/// Default request limit for registered users.
|
||||
/// 0 = block all requests
|
||||
/// None = allow all requests
|
||||
pub default_user_max_requests_per_minute: Option<u64>,
|
||||
pub default_user_max_requests_per_period: Option<u64>,
|
||||
|
||||
/// Restrict user registration.
|
||||
/// None = no code needed
|
||||
@ -87,8 +87,8 @@ pub struct AppConfig {
|
||||
|
||||
/// Rate limit for the login entrypoint.
|
||||
/// This is separate from the rpc limits.
|
||||
#[serde(default = "default_login_rate_limit_per_minute")]
|
||||
pub login_rate_limit_per_minute: u64,
|
||||
#[serde(default = "default_login_rate_limit_per_period")]
|
||||
pub login_rate_limit_per_period: u64,
|
||||
|
||||
/// The soft limit prevents thundering herds as new blocks are seen.
|
||||
#[serde(default = "default_min_sum_soft_limit")]
|
||||
@ -107,8 +107,8 @@ pub struct AppConfig {
|
||||
/// Request limit for anonymous users.
|
||||
/// Some(0) = block all requests
|
||||
/// None = allow all requests
|
||||
#[serde(default = "default_public_requests_per_minute")]
|
||||
pub public_requests_per_minute: Option<u64>,
|
||||
#[serde(default = "default_public_requests_per_period")]
|
||||
pub public_requests_per_period: Option<u64>,
|
||||
|
||||
/// RPC responses are cached locally
|
||||
#[serde(default = "default_response_cache_max_bytes")]
|
||||
@ -150,7 +150,7 @@ fn default_public_max_concurrent_requests() -> Option<usize> {
|
||||
}
|
||||
|
||||
/// 0 blocks anonymous requests by default.
|
||||
fn default_public_requests_per_minute() -> Option<u64> {
|
||||
fn default_public_requests_per_period() -> Option<u64> {
|
||||
Some(0)
|
||||
}
|
||||
|
||||
@ -159,8 +159,8 @@ fn default_bearer_token_max_concurrent_requests() -> u64 {
|
||||
2
|
||||
}
|
||||
|
||||
/// Having a low amount of requests per minute for login is safest.
|
||||
fn default_login_rate_limit_per_minute() -> u64 {
|
||||
/// Having a low amount of requests per period (usually minute) for login is safest.
|
||||
fn default_login_rate_limit_per_period() -> u64 {
|
||||
10
|
||||
}
|
||||
|
||||
|
@ -464,7 +464,7 @@ impl Web3ProxyApp {
|
||||
let max_requests_per_period = origin
|
||||
.map(|origin| {
|
||||
self.config
|
||||
.allowed_origin_requests_per_minute
|
||||
.allowed_origin_requests_per_period
|
||||
.get(&origin.to_string())
|
||||
.cloned()
|
||||
})
|
||||
@ -527,7 +527,16 @@ impl Web3ProxyApp {
|
||||
Some(rpc_key_model) => {
|
||||
// TODO: move these splits into helper functions
|
||||
// TODO: can we have sea orm handle this for us?
|
||||
// let user_tier_model = rpc_key_model.
|
||||
let user_model = user::Entity::find_by_id(rpc_key_model.user_id)
|
||||
.one(&db_conn)
|
||||
.await?
|
||||
.expect("related user");
|
||||
|
||||
let user_tier_model =
|
||||
user_tier::Entity::find_by_id(user_model.user_tier_id)
|
||||
.one(&db_conn)
|
||||
.await?
|
||||
.expect("related user tier");
|
||||
|
||||
let allowed_ips: Option<Vec<IpNet>> =
|
||||
if let Some(allowed_ips) = rpc_key_model.allowed_ips {
|
||||
@ -590,8 +599,8 @@ impl Web3ProxyApp {
|
||||
allowed_referers,
|
||||
allowed_user_agents,
|
||||
log_revert_chance: rpc_key_model.log_revert_chance,
|
||||
max_concurrent_requests: None, // todo! user_tier_model.max_concurrent_requests,
|
||||
max_requests_per_period: None, // todo! user_tier_model.max_requests_per_period,
|
||||
max_concurrent_requests: user_tier_model.max_concurrent_requests,
|
||||
max_requests_per_period: user_tier_model.max_requests_per_period,
|
||||
})
|
||||
}
|
||||
None => Ok(UserKeyData::default()),
|
||||
|
@ -501,13 +501,12 @@ pub struct UserKeyManagement {
|
||||
description: Option<String>,
|
||||
private_txs: Option<bool>,
|
||||
active: Option<bool>,
|
||||
// TODO: enable log_revert_trace: Option<f32>,
|
||||
// TODO: enable log_revert_trace: Option<f64>,
|
||||
allowed_ips: Option<String>,
|
||||
allowed_origins: Option<String>,
|
||||
allowed_referers: Option<String>,
|
||||
allowed_user_agents: Option<String>,
|
||||
// do not allow! `requests_per_minute: Option<u64>,`
|
||||
// do not allow! `max_concurrent_requests: Option<u64>,`
|
||||
// do not allow! `user_tier: Option<u64>,`
|
||||
}
|
||||
|
||||
/// `POST /user/keys` or `PUT /user/keys` -- Use a bearer token to create or update an existing key.
|
||||
|
@ -32,23 +32,32 @@ async fn get_user_id_from_params(
|
||||
let bearer_cache_key = UserBearerToken::try_from(bearer)?.to_string();
|
||||
|
||||
// get the user id that is attached to this bearer token
|
||||
redis_conn
|
||||
let bearer_user_id = redis_conn
|
||||
.get::<_, u64>(bearer_cache_key)
|
||||
.await
|
||||
// TODO: this should be a 403
|
||||
.context("fetching rpc_key_id from redis with bearer_cache_key")
|
||||
.context("fetching rpc_key_id from redis with bearer_cache_key")?;
|
||||
|
||||
let user_id: u64 = user_id.parse().context("Parsing user_id param")?;
|
||||
|
||||
if bearer_user_id != user_id {
|
||||
// TODO: proper HTTP Status code
|
||||
Err(anyhow::anyhow!("permission denied"))
|
||||
} else {
|
||||
Ok(bearer_user_id)
|
||||
}
|
||||
}
|
||||
(_, None) => {
|
||||
// they have a bearer token. we don't care about it on public pages
|
||||
// 0 means all
|
||||
Ok(0)
|
||||
}
|
||||
(None, Some(x)) => {
|
||||
(None, Some(_)) => {
|
||||
// they do not have a bearer token, but requested a specific id. block
|
||||
// TODO: proper error code
|
||||
// TODO: maybe instead of this sharp edged warn, we have a config value?
|
||||
// TODO: check config for if we should deny or allow this
|
||||
x.parse().context("Parsing user_id param")
|
||||
Err(anyhow::anyhow!("permission denied"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user