move user registration into a dedicated function

This commit is contained in:
Bryan Stitt 2023-06-09 18:31:47 -07:00
parent 71d3d63524
commit 4a9c1a0ce6
11 changed files with 164 additions and 164 deletions

12
Cargo.lock generated
View File

@ -4107,9 +4107,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.59"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
@ -4304,9 +4304,9 @@ dependencies = [
[[package]]
name = "rdkafka"
version = "0.31.0"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88383df3a85a38adfa2aa447d3ab6eb9cedcb49613adcf18e7e7ebb3b62e9b03"
checksum = "f8733bc5dc0b192d1a4b28073f9bff1326ad9e4fecd4d9b025d6fc358d1c3e79"
dependencies = [
"futures-channel",
"futures-util",
@ -4322,9 +4322,9 @@ dependencies = [
[[package]]
name = "rdkafka-sys"
version = "4.4.0+1.9.2"
version = "4.5.0+1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ac9d87c3aba1748e3112318459f2ac8bff80bfff7359e338e0463549590249"
checksum = "1bb0676c2112342ac7165decdedbc4e7086c0af384479ccce534546b10687a5d"
dependencies = [
"cmake",
"libc",

View File

@ -76,7 +76,7 @@ pagerduty-rs = { version = "0.1.6", default-features = false, features = ["async
parking_lot = { version = "0.12.1", features = ["arc_lock", "nightly", "serde"] }
prettytable = "0.10.0"
proctitle = "0.1.1"
rdkafka = { version = "0.31.0" }
rdkafka = { version = "0.32.2" }
regex = "1.8.4"
reqwest = { version = "0.11.18", default-features = false, features = ["deflate", "gzip", "json", "tokio-rustls"] }
rmp-serde = "1.1.1"

View File

@ -49,7 +49,6 @@ use redis_rate_limiter::{redis, DeadpoolRuntime, RedisConfig, RedisPool, RedisRa
use serde::Serialize;
use serde_json::json;
use serde_json::value::RawValue;
use std::borrow::Cow;
use std::fmt;
use std::net::IpAddr;
use std::num::NonZeroU64;
@ -1512,15 +1511,13 @@ impl Web3ProxyApp {
JsonRpcResponseEnum::from(serde_json::Value::Bool(false))
}
"eth_subscribe" => JsonRpcErrorData {
message: Cow::Borrowed(
"notifications not supported. eth_subscribe is only available over a websocket",
),
message: "notifications not supported. eth_subscribe is only available over a websocket".into(),
code: -32601,
data: None,
}
.into(),
"eth_unsubscribe" => JsonRpcErrorData {
message: Cow::Borrowed("notifications not supported. eth_unsubscribe is only available over a websocket"),
message: "notifications not supported. eth_unsubscribe is only available over a websocket".into(),
code: -32601,
data: None,
}.into(),
@ -1547,7 +1544,7 @@ impl Web3ProxyApp {
// TODO: what error code?
// TODO: use Web3ProxyError::BadRequest
JsonRpcErrorData {
message: Cow::Borrowed("Invalid request"),
message: "Invalid request".into(),
code: -32600,
data: None
}.into()
@ -1575,7 +1572,7 @@ impl Web3ProxyApp {
// TODO: this needs the correct error code in the response
// TODO: Web3ProxyError::BadRequest instead?
JsonRpcErrorData {
message: Cow::Borrowed("invalid request"),
message: "invalid request".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
}.into()
@ -1583,7 +1580,7 @@ impl Web3ProxyApp {
}
}
"test" => JsonRpcErrorData {
message: Cow::Borrowed("The method test does not exist/is not available."),
message: "The method test does not exist/is not available.".into(),
code: -32601,
data: None,
}.into(),

View File

@ -49,7 +49,7 @@ pub enum Web3ProxyError {
BadRequest(Cow<'static, str>),
#[error(ignore)]
#[from(ignore)]
BadResponse(String),
BadResponse(Cow<'static, str>),
BadRouting,
Contract(ContractError<EthersHttpProvider>),
Database(DbErr),
@ -134,7 +134,7 @@ pub enum Web3ProxyError {
SerdeJson(serde_json::Error),
/// simple way to return an error message to the user and an anyhow to our logs
#[display(fmt = "{}, {}, {:?}", _0, _1, _2)]
StatusCode(StatusCode, String, Option<anyhow::Error>),
StatusCode(StatusCode, Cow<'static, str>, Option<anyhow::Error>),
/// TODO: what should be attached to the timout?
#[display(fmt = "{:?}", _0)]
#[error(ignore)]
@ -153,7 +153,7 @@ pub enum Web3ProxyError {
WebsocketOnly,
#[display(fmt = "{:?}, {}", _0, _1)]
#[error(ignore)]
WithContext(Option<Box<Web3ProxyError>>, String),
WithContext(Option<Box<Web3ProxyError>>, Cow<'static, str>),
}
impl Web3ProxyError {
@ -165,7 +165,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Owned(err.to_string()),
message: err.to_string().into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -177,7 +177,7 @@ impl Web3ProxyError {
(
StatusCode::FORBIDDEN,
JsonRpcErrorData {
message: Cow::Borrowed("FORBIDDEN"),
message: "FORBIDDEN".into(),
code: StatusCode::FORBIDDEN.as_u16().into(),
data: None,
},
@ -189,7 +189,7 @@ impl Web3ProxyError {
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
// TODO: is it safe to expose all of our anyhow strings?
message: Cow::Owned(err.to_string()),
message: err.to_string().into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -204,7 +204,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Owned(format!("bad request: {}", err)),
message: format!("bad request: {}", err).into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -216,7 +216,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Owned(format!("bad response: {}", err)),
message: format!("bad response: {}", err).into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -227,7 +227,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("bad routing"),
message: "bad routing".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -238,7 +238,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("database error!"),
message: "database error!".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -249,7 +249,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Owned(format!("contract error: {}", err)),
message: format!("contract error: {}", err).into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -260,7 +260,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Owned(format!("decimal error: {}", err)),
message: format!("decimal error: {}", err).into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -274,10 +274,11 @@ impl Web3ProxyError {
(
StatusCode::UNAUTHORIZED,
JsonRpcErrorData {
message: Cow::Owned(format!(
message: format!(
"both the primary and eip191 verification failed: {:#?}; {:#?}",
err_1, err_191
)),
)
.into(),
code: StatusCode::UNAUTHORIZED.as_u16().into(),
data: None,
},
@ -288,7 +289,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("ether http client error"),
message: "ether http client error".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -299,7 +300,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("ether provider error"),
message: "ether provider error".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -310,7 +311,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("ether ws client error"),
message: "ether ws client error".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -321,7 +322,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("flume recv error!"),
message: "flume recv error!".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -333,7 +334,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("gas estimate result is not an U256"),
message: "gas estimate result is not an U256".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -344,7 +345,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: format!("{}", err).into(),
message: err.to_string().into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -355,7 +356,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Owned(format!("{}", err)),
message: err.to_string().into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -367,7 +368,7 @@ impl Web3ProxyError {
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
// TODO: is it safe to expose these error strings?
message: Cow::Owned(err.to_string()),
message: err.to_string().into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -379,7 +380,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("influxdb2 error!"),
message: "influxdb2 error!".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -390,10 +391,11 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Owned(format!(
message: format!(
"Invalid blocks bounds requested. min ({}) > max ({})",
min, max
)),
)
.into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -404,7 +406,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Owned(err.to_string()),
message: err.to_string().into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -415,7 +417,7 @@ impl Web3ProxyError {
(
StatusCode::FORBIDDEN,
JsonRpcErrorData {
message: Cow::Owned(format!("IP ({}) is not allowed!", ip)),
message: format!("IP ({}) is not allowed!", ip).into(),
code: StatusCode::FORBIDDEN.as_u16().into(),
data: None,
},
@ -426,7 +428,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Owned(format!("{}", err)),
message: err.to_string().into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -437,7 +439,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("invalid message eip given"),
message: "invalid message eip given".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -448,7 +450,7 @@ impl Web3ProxyError {
(
StatusCode::UNAUTHORIZED,
JsonRpcErrorData {
message: Cow::Borrowed("invalid invite code"),
message: "invalid invite code".into(),
code: StatusCode::UNAUTHORIZED.as_u16().into(),
data: None,
},
@ -460,7 +462,7 @@ impl Web3ProxyError {
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
// TODO: is it safe to expose our io error strings?
message: Cow::Owned(err.to_string()),
message: err.to_string().into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -471,7 +473,7 @@ impl Web3ProxyError {
(
StatusCode::UNAUTHORIZED,
JsonRpcErrorData {
message: Cow::Borrowed("invalid referral code"),
message: "invalid referral code".into(),
code: StatusCode::UNAUTHORIZED.as_u16().into(),
data: None,
},
@ -482,7 +484,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("invalid referer!"),
message: "invalid referer!".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -493,7 +495,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("invalid signature length"),
message: "invalid signature length".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -504,7 +506,7 @@ impl Web3ProxyError {
(
StatusCode::FORBIDDEN,
JsonRpcErrorData {
message: Cow::Borrowed("invalid user agent!"),
message: "invalid user agent!".into(),
code: StatusCode::FORBIDDEN.as_u16().into(),
data: None,
},
@ -515,7 +517,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("UserKey was not a ULID or UUID"),
message: "UserKey was not a ULID or UUID".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -526,7 +528,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("UserTier is not valid!"),
message: "UserTier is not valid!".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -545,7 +547,7 @@ impl Web3ProxyError {
code,
JsonRpcErrorData {
// TODO: different messages of cancelled or not?
message: Cow::Borrowed("Unable to complete request"),
message: "Unable to complete request".into(),
code: code.as_u16().into(),
data: None,
},
@ -560,7 +562,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Owned(format!("msgpack encode error: {}", err)),
message: format!("msgpack encode error: {}", err).into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -571,7 +573,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("Blocks here must have a number or hash"),
message: "Blocks here must have a number or hash".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -582,7 +584,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_GATEWAY,
JsonRpcErrorData {
message: Cow::Borrowed("no blocks known"),
message: "no blocks known".into(),
code: StatusCode::BAD_GATEWAY.as_u16().into(),
data: None,
},
@ -593,7 +595,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_GATEWAY,
JsonRpcErrorData {
message: Cow::Borrowed("no consensus head block"),
message: "no consensus head block".into(),
code: StatusCode::BAD_GATEWAY.as_u16().into(),
data: None,
},
@ -604,7 +606,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_GATEWAY,
JsonRpcErrorData {
message: Cow::Borrowed("unable to retry for request handle"),
message: "unable to retry for request handle".into(),
code: StatusCode::BAD_GATEWAY.as_u16().into(),
data: None,
},
@ -615,7 +617,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_GATEWAY,
JsonRpcErrorData {
message: Cow::Borrowed("no servers synced"),
message: "no servers synced".into(),
code: StatusCode::BAD_GATEWAY.as_u16().into(),
data: None,
},
@ -629,10 +631,11 @@ impl Web3ProxyError {
(
StatusCode::BAD_GATEWAY,
JsonRpcErrorData {
message: Cow::Owned(format!(
message: format!(
"not enough rpcs connected {}/{}",
num_known, min_head_rpcs
)),
)
.into(),
code: StatusCode::BAD_GATEWAY.as_u16().into(),
data: None,
},
@ -643,10 +646,11 @@ impl Web3ProxyError {
(
StatusCode::BAD_GATEWAY,
JsonRpcErrorData {
message: Cow::Owned(format!(
message: format!(
"not enough soft limit available {}/{}",
available, needed
)),
)
.into(),
code: StatusCode::BAD_GATEWAY.as_u16().into(),
data: None,
},
@ -658,7 +662,7 @@ impl Web3ProxyError {
(
StatusCode::NOT_FOUND,
JsonRpcErrorData {
message: Cow::Borrowed("not found!"),
message: "not found!".into(),
code: StatusCode::NOT_FOUND.as_u16().into(),
data: None,
},
@ -669,7 +673,7 @@ impl Web3ProxyError {
(
StatusCode::NOT_IMPLEMENTED,
JsonRpcErrorData {
message: Cow::Borrowed("work in progress"),
message: "work in progress".into(),
code: StatusCode::NOT_IMPLEMENTED.as_u16().into(),
data: None,
},
@ -680,7 +684,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("Origin required"),
message: "Origin required".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -691,7 +695,7 @@ impl Web3ProxyError {
(
StatusCode::FORBIDDEN,
JsonRpcErrorData {
message: Cow::Owned(format!("Origin ({}) is not allowed!", origin)),
message: format!("Origin ({}) is not allowed!", origin).into(),
code: StatusCode::FORBIDDEN.as_u16().into(),
data: None,
},
@ -702,7 +706,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("parse bytes error!"),
message: "parse bytes error!".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -713,7 +717,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("parse message error!"),
message: "parse message error!".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -724,7 +728,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("unable to parse address"),
message: "unable to parse address".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -735,7 +739,7 @@ impl Web3ProxyError {
(
StatusCode::PAYMENT_REQUIRED,
JsonRpcErrorData {
message: Cow::Borrowed("Payment is required and user is not premium"),
message: "Payment is required and user is not premium".into(),
code: StatusCode::PAYMENT_REQUIRED.as_u16().into(),
data: None,
},
@ -767,7 +771,7 @@ impl Web3ProxyError {
(
StatusCode::TOO_MANY_REQUESTS,
JsonRpcErrorData {
message: Cow::Owned(msg),
message: msg.into(),
code: StatusCode::TOO_MANY_REQUESTS.as_u16().into(),
data: None,
},
@ -778,7 +782,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("redis error!"),
message: "redis error!".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -789,7 +793,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("Referer required"),
message: "Referer required".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -800,7 +804,7 @@ impl Web3ProxyError {
(
StatusCode::FORBIDDEN,
JsonRpcErrorData {
message: Cow::Owned(format!("Referer ({:?}) is not allowed", referer)),
message: format!("Referer ({:?}) is not allowed", referer).into(),
code: StatusCode::FORBIDDEN.as_u16().into(),
data: None,
},
@ -812,7 +816,7 @@ impl Web3ProxyError {
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
// TODO: is it safe to expose all of our anyhow strings?
message: Cow::Borrowed("semaphore acquire error"),
message: "semaphore acquire error".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -823,7 +827,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("error stat_sender sending response_stat"),
message: "error stat_sender sending response_stat".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -834,7 +838,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Owned(format!("de/serialization error! {}", err)),
message: format!("de/serialization error! {}", err).into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -852,7 +856,7 @@ impl Web3ProxyError {
(
*status_code,
JsonRpcErrorData {
message: err_msg.to_owned().into(),
message: err_msg.clone(),
code: code.into(),
data: None,
},
@ -904,7 +908,7 @@ impl Web3ProxyError {
Self::UnknownKey => (
StatusCode::UNAUTHORIZED,
JsonRpcErrorData {
message: Cow::Borrowed("unknown api key!"),
message: "unknown api key!".into(),
code: StatusCode::UNAUTHORIZED.as_u16().into(),
data: None,
},
@ -914,7 +918,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("User agent required"),
message: "User agent required".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -925,7 +929,7 @@ impl Web3ProxyError {
(
StatusCode::FORBIDDEN,
JsonRpcErrorData {
message: Cow::Owned(format!("User agent ({}) is not allowed!", ua)),
message: format!("User agent ({}) is not allowed!", ua).into(),
code: StatusCode::FORBIDDEN.as_u16().into(),
data: None,
},
@ -937,7 +941,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("user ids should always be non-zero"),
message: "user ids should always be non-zero".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -948,7 +952,7 @@ impl Web3ProxyError {
(
StatusCode::BAD_REQUEST,
JsonRpcErrorData {
message: Cow::Borrowed("verification error!"),
message: "verification error!".into(),
code: StatusCode::BAD_REQUEST.as_u16().into(),
data: None,
},
@ -959,7 +963,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("watch recv error!"),
message: "watch recv error!".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -970,7 +974,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: Cow::Borrowed("watch send error!"),
message: "watch send error!".into(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -997,7 +1001,7 @@ impl Web3ProxyError {
(
StatusCode::INTERNAL_SERVER_ERROR,
JsonRpcErrorData {
message: msg.to_owned().into(),
message: msg.clone(),
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
data: None,
},
@ -1038,11 +1042,11 @@ impl IntoResponse for Web3ProxyError {
}
pub trait Web3ProxyErrorContext<T> {
fn web3_context<S: Into<String>>(self, msg: S) -> Result<T, Web3ProxyError>;
fn web3_context<S: Into<Cow<'static, str>>>(self, msg: S) -> Result<T, Web3ProxyError>;
}
impl<T> Web3ProxyErrorContext<T> for Option<T> {
fn web3_context<S: Into<String>>(self, msg: S) -> Result<T, Web3ProxyError> {
fn web3_context<S: Into<Cow<'static, str>>>(self, msg: S) -> Result<T, Web3ProxyError> {
self.ok_or(Web3ProxyError::WithContext(None, msg.into()))
}
}
@ -1051,7 +1055,7 @@ impl<T, E> Web3ProxyErrorContext<T> for Result<T, E>
where
E: Into<Web3ProxyError>,
{
fn web3_context<S: Into<String>>(self, msg: S) -> Result<T, Web3ProxyError> {
fn web3_context<S: Into<Cow<'static, str>>>(self, msg: S) -> Result<T, Web3ProxyError> {
self.map_err(|err| Web3ProxyError::WithContext(Some(Box::new(err.into())), msg.into()))
}
}

View File

@ -264,7 +264,7 @@ async fn _websocket_handler_with_key(
) {
(None, None, _) => Err(Web3ProxyError::StatusCode(
StatusCode::BAD_REQUEST,
"this page is for rpcs".to_string(),
"this page is for rpcs".into(),
None,
)),
(Some(redirect_public_url), _, None) => {
@ -277,7 +277,7 @@ async fn _websocket_handler_with_key(
// i don't think this is possible
Err(Web3ProxyError::StatusCode(
StatusCode::UNAUTHORIZED,
"AUTHORIZATION header required".to_string(),
"AUTHORIZATION header required".into(),
None,
))
} else {
@ -295,7 +295,7 @@ async fn _websocket_handler_with_key(
// any other combinations get a simple error
_ => Err(Web3ProxyError::StatusCode(
StatusCode::BAD_REQUEST,
"this page is for rpcs".to_string(),
"this page is for rpcs".into(),
None,
)),
}

View File

@ -18,11 +18,11 @@ use entities::{balance, login, pending_login, referee, referrer, rpc_key, user};
use ethers::{prelude::Address, types::Bytes};
use hashbrown::HashMap;
use http::StatusCode;
use log::{debug, warn, trace};
use log::{debug, trace, warn};
use migration::sea_orm::prelude::{Decimal, Uuid};
use migration::sea_orm::{
self, ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter,
TransactionTrait,
self, ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, IntoActiveModel,
QueryFilter, TransactionTrait,
};
use serde_json::json;
use siwe::{Message, VerificationOpts};
@ -143,6 +143,54 @@ pub async fn user_login_get(
Ok(message.into_response())
}
pub async fn register_new_user(
db_conn: &DatabaseConnection,
address: Address,
) -> anyhow::Result<(user::Model, rpc_key::Model, balance::Model)> {
// all or nothing
let txn = db_conn.begin().await?;
// the only thing we need from them is an address
// everything else is optional
// TODO: different invite codes should allow different levels
// TODO: maybe decrement a count on the invite code?
// TODO: There will be two different transactions. The first one inserts the user, the second one marks the user as being referred
let new_user = user::ActiveModel {
address: sea_orm::Set(address.to_fixed_bytes().into()),
..Default::default()
};
let new_user = new_user.insert(&txn).await?;
// create the user's first api key
let rpc_secret_key = RpcSecretKey::new();
let user_rpc_key = rpc_key::ActiveModel {
user_id: sea_orm::Set(new_user.id),
secret_key: sea_orm::Set(rpc_secret_key.into()),
description: sea_orm::Set(None),
..Default::default()
};
let user_rpc_key = user_rpc_key
.insert(&txn)
.await
.web3_context("Failed saving new user key")?;
// create an empty balance entry
let user_balance = balance::ActiveModel {
user_id: sea_orm::Set(new_user.id),
..Default::default()
};
let user_balance = user_balance.insert(&txn).await?;
// save the user and key and balance to the database
txn.commit().await?;
Ok((new_user, user_rpc_key, user_balance))
}
/// `POST /user/login` - Register or login by posting a signed "siwe" message.
/// It is recommended to save the returned bearer token in a cookie.
/// The bearer token can be used to authenticate other requests, such as getting the user's stats or modifying the user's profile.
@ -264,50 +312,8 @@ pub async fn user_login_post(
}
}
let txn = db_conn.begin().await?;
// First add a user
// the only thing we need from them is an address
// everything else is optional
// TODO: different invite codes should allow different levels
// TODO: maybe decrement a count on the invite code?
// TODO: There will be two different transactions. The first one inserts the user, the second one marks the user as being referred
let caller = user::ActiveModel {
address: sea_orm::Set(our_msg.address.into()),
..Default::default()
};
let caller = caller.insert(&txn).await?;
// create the user's first api key
let rpc_secret_key = RpcSecretKey::new();
let user_rpc_key = rpc_key::ActiveModel {
user_id: sea_orm::Set(caller.id),
secret_key: sea_orm::Set(rpc_secret_key.into()),
description: sea_orm::Set(None),
..Default::default()
};
let user_rpc_key = user_rpc_key
.insert(&txn)
.await
.web3_context("Failed saving new user key")?;
// We should also create the balance entry ...
let user_balance = balance::ActiveModel {
user_id: sea_orm::Set(caller.id),
..Default::default()
};
user_balance.insert(&txn).await?;
let user_rpc_keys = vec![user_rpc_key];
// Also add a part for the invite code, i.e. who invited this guy
// save the user and key to the database
txn.commit().await?;
let (caller, caller_key, _) =
register_new_user(&db_conn, our_msg.address.into()).await?;
let txn = db_conn.begin().await?;
// First, optionally catch a referral code from the parameters if there is any
@ -336,7 +342,7 @@ pub async fn user_login_post(
}
txn.commit().await?;
(caller, user_rpc_keys, StatusCode::CREATED)
(caller, vec![caller_key], StatusCode::CREATED)
}
Some(caller) => {
// Let's say that a user that exists can actually also redeem a key in retrospect...

View File

@ -1,6 +1,7 @@
use crate::app::Web3ProxyApp;
use crate::errors::{Web3ProxyError, Web3ProxyResponse};
use crate::frontend::authorization::login_is_authorized;
use crate::frontend::users::authentication::register_new_user;
use anyhow::Context;
use axum::{
extract::Path,
@ -169,7 +170,7 @@ pub async fn user_balance_post(
PaymentFactory::new(payment_factory_address, app.internal_provider().clone());
debug!(
"Payment Factor Filter is: {:?}",
"Payment Factory Filter: {:?}",
payment_factory_contract.payment_received_filter()
);
@ -251,12 +252,13 @@ pub async fn user_balance_post(
.one(&db_conn)
.await?
{
Some(x) => Ok(x),
Some(x) => x,
None => {
// todo!("make their account");
Err(Web3ProxyError::AccessDenied)
let (user, _, _) = register_new_user(&db_conn, recipient_account).await?;
user
}
}?;
};
// For now we only accept stablecoins
// And we hardcode the peg (later we would have to depeg this, for example

View File

@ -211,7 +211,7 @@ impl From<&'static str> for JsonRpcErrorData {
fn from(value: &'static str) -> Self {
Self {
code: -32000,
message: Cow::Borrowed(value),
message: value.into(),
data: None,
}
}
@ -221,7 +221,7 @@ impl From<String> for JsonRpcErrorData {
fn from(value: String) -> Self {
Self {
code: -32000,
message: Cow::Owned(value),
message: value.into(),
data: None,
}
}
@ -273,7 +273,7 @@ impl JsonRpcForwardedResponse {
result: None,
error: Some(JsonRpcErrorData {
code: code.unwrap_or(-32099),
message: Cow::Owned(message),
message: message.into(),
// TODO: accept data as an argument
data: None,
}),
@ -319,10 +319,7 @@ impl JsonRpcForwardedResponse {
data = err.data.clone();
} else if let Some(err) = err.as_serde_error() {
// this is not an rpc error. keep it as an error
return Err(Web3ProxyError::BadResponse(format!(
"bad response: {}",
err
)));
return Err(Web3ProxyError::BadResponse(err.to_string().into()));
} else {
return Err(anyhow::anyhow!("unexpected ethers error! {:?}", err).into());
}
@ -336,7 +333,7 @@ impl JsonRpcForwardedResponse {
result: None,
error: Some(JsonRpcErrorData {
code,
message: Cow::Owned(message),
message: message.into(),
data,
}),
})

View File

@ -5,7 +5,6 @@ use hashbrown::hash_map::DefaultHashBuilder;
use moka::future::Cache;
use serde_json::value::RawValue;
use std::{
borrow::Cow,
hash::{BuildHasher, Hash, Hasher},
sync::Arc,
};
@ -211,10 +210,7 @@ impl TryFrom<ProviderError> for JsonRpcErrorData {
data = err.data.clone();
} else if let Some(err) = err.as_serde_error() {
// this is not an rpc error. keep it as an error
return Err(Web3ProxyError::BadResponse(format!(
"bad response: {}",
err
)));
return Err(Web3ProxyError::BadResponse(err.to_string().into()));
} else {
return Err(anyhow::anyhow!("unexpected ethers error! {:?}", err).into());
}
@ -224,7 +220,7 @@ impl TryFrom<ProviderError> for JsonRpcErrorData {
Ok(JsonRpcErrorData {
code,
message: Cow::Owned(message),
message: message.into(),
data,
})
}

View File

@ -27,7 +27,6 @@ use serde::ser::{SerializeStruct, Serializer};
use serde::Serialize;
use serde_json::json;
use serde_json::value::RawValue;
use std::borrow::Cow;
use std::cmp::min_by_key;
use std::fmt::{self, Display};
use std::sync::atomic::Ordering;
@ -1079,7 +1078,7 @@ impl Web3Rpcs {
// TODO: what error code?
// cloudflare gives {"jsonrpc":"2.0","error":{"code":-32043,"message":"Requested data cannot be older than 128 blocks."},"id":1}
Err(JsonRpcErrorData {
message: Cow::Borrowed("Requested data is not available"),
message: "Requested data is not available".into(),
code: -32043,
data: None,
}

View File

@ -605,8 +605,7 @@ impl BufferedRpcQueryStats {
// ==================
let sender_latest_balance = match NonZeroU64::try_from(sender_rpc_entity.user_id) {
Err(_) => Err(Web3ProxyError::BadResponse(
"Balance is not positive, although it was previously checked to be as such!"
.to_string(),
"Balance is not positive, although it was previously checked to be as such!".into(),
)),
// We don't do an get_or_insert, because technically we don't have the most up to date balance
// Also let's keep things simple in terms of writing and getting. A single place writes it, multiple places can remove / poll it