it compiles

This commit is contained in:
Bryan Stitt 2022-08-16 21:43:39 +00:00
parent a61af53117
commit 0ccda2f40b
4 changed files with 59 additions and 18 deletions

View File

@ -7,7 +7,7 @@ use std::ops::Add;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
pub use crate::errors::{RedisError, RedisErrorSink};
pub use bb8_redis::{bb8, RedisConnectionManager};
pub use bb8_redis::{bb8, redis, RedisConnectionManager};
pub type RedisPool = bb8::Pool<RedisConnectionManager>;

View File

@ -4,14 +4,20 @@ use axum::{
response::{IntoResponse, Response},
Json,
};
use derive_more::From;
use serde_json::value::RawValue;
use std::error::Error;
pub struct ErrorResponse {
pub inner: Box<dyn Error>,
// TODO: take "IntoResult" instead?
pub type FrontendResult = Result<Response, FrontendErrorResponse>;
#[derive(From)]
pub enum FrontendErrorResponse {
Anyhow(anyhow::Error),
BoxError(Box<dyn Error>),
}
impl IntoResponse for ErrorResponse {
impl IntoResponse for FrontendErrorResponse {
fn into_response(self) -> Response {
todo!("into_response based on the error type")
}

View File

@ -68,13 +68,7 @@ pub async fn serve(port: u16, proxy_app: Arc<Web3ProxyApp>) -> anyhow::Result<()
.route("/u/:user_key", get(ws_proxy::user_websocket_handler))
.route("/health", get(http::health))
.route("/status", get(http::status))
// .route(
// "/login",
// HandleError::new(
// move |app| async { users::get_login(app).await },
// handle_anyhow_error,
// ),
// )
.route("/login", get(users::get_login))
.route("/users", post(users::create_user))
.route(
"/foo",

View File

@ -7,32 +7,73 @@
// I wonder how we handle payment
// probably have to do manual withdrawals
use super::{errors::anyhow_error_into_response, rate_limit::RateLimitResult};
use super::{
errors::{anyhow_error_into_response, FrontendResult},
rate_limit::RateLimitResult,
};
use crate::app::Web3ProxyApp;
use axum::{
response::{ErrorResponse, IntoResponse, Response},
extract::Path,
response::{IntoResponse, Response},
Extension, Json,
};
use axum_client_ip::ClientIp;
use axum_macros::debug_handler;
use entities::user;
use ethers::{prelude::Address, types::Bytes};
use redis_rate_limit::redis::{pipe, AsyncCommands};
use reqwest::StatusCode;
use sea_orm::ActiveModelTrait;
use serde::Deserialize;
use std::sync::Arc;
use uuid::Uuid;
// TODO: how do we customize axum's error response? I think we probably want an enum that implements IntoResponse instead
#[debug_handler]
pub async fn get_login(
Extension(app): Extension<Arc<Web3ProxyApp>>,
) -> Result<Response, ErrorResponse> {
// let redis: RedisPool = app...;
let redis_pool = app.redis_pool.as_ref().unwrap();
ClientIp(ip): ClientIp,
// TODO: what does axum's error handling look like?
Path(user_address): Path<Address>,
) -> FrontendResult {
// TODO: refactor this to use the try operator
let _ip = match app.rate_limit_by_ip(ip).await {
Ok(x) => match x.try_into_response().await {
Ok(RateLimitResult::AllowedIp(x)) => x,
Err(err_response) => return Ok(err_response),
_ => unimplemented!(),
},
Err(err) => return Ok(anyhow_error_into_response(None, None, err)),
};
let redis_conn = redis_pool.get().await.unwrap();
// at first i thought about checking that user_address is in our db
// but theres no need to separate the create_user and login flows
// its a better UX to just click "login with ethereum" and have the account created if it doesn't exist
// we can prompt for an email and and payment after they log in
todo!("how should this work? probably keep stuff in redis ")
let session_id = uuid::Uuid::new_v4();
// TODO: if no redis, store in local cache?
let redis_pool = app
.redis_pool
.as_ref()
.expect("login requires a redis server");
let mut redis_conn = redis_pool.get().await.unwrap();
// TODO: how many seconds? get from config?
let session_expiration_seconds = 300;
let reply: String = redis_conn
.set_ex(
session_id.to_string(),
user_address.to_string(),
session_expiration_seconds,
)
.await
.unwrap();
todo!("how should this work? probably keep stuff in redis")
}
#[debug_handler]