From 2540182b7c4bd3806d87ef049bbab8f3bff47282 Mon Sep 17 00:00:00 2001 From: Bryan Stitt Date: Mon, 31 Oct 2022 20:51:06 +0000 Subject: [PATCH] put or post for user key management --- web3_proxy/src/frontend/mod.rs | 5 ++-- web3_proxy/src/frontend/users.rs | 48 ++++++++++++++++---------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/web3_proxy/src/frontend/mod.rs b/web3_proxy/src/frontend/mod.rs index a9008941..3a6ecd1e 100644 --- a/web3_proxy/src/frontend/mod.rs +++ b/web3_proxy/src/frontend/mod.rs @@ -12,7 +12,7 @@ use crate::app::Web3ProxyApp; use axum::{ body::Body, handler::Handler, - routing::{get, post}, + routing::{get, post, put}, Extension, Router, }; use http::header::AUTHORIZATION; @@ -75,7 +75,8 @@ pub async fn serve(port: u16, proxy_app: Arc) -> anyhow::Result<() .route("/user/balance", get(users::user_balance_get)) .route("/user/balance/:txid", post(users::user_balance_post)) .route("/user/keys", get(users::rpc_keys_get)) - .route("/user/keys", post(users::rpc_keys_post)) + .route("/user/keys", post(users::rpc_keys_management)) + .route("/user/keys", put(users::rpc_keys_management)) .route("/user/revert_logs", get(users::user_revert_logs_get)) .route( "/user/stats/aggregate", diff --git a/web3_proxy/src/frontend/users.rs b/web3_proxy/src/frontend/users.rs index 4a5c70b5..c2a2fd30 100644 --- a/web3_proxy/src/frontend/users.rs +++ b/web3_proxy/src/frontend/users.rs @@ -38,7 +38,6 @@ use std::sync::Arc; use time::{Duration, OffsetDateTime}; use tracing::{instrument, warn}; use ulid::Ulid; -use uuid::Uuid; /// `GET /user/login/:user_address` or `GET /user/login/:user_address/:message_eip` -- Start the "Sign In with Ethereum" (siwe) login flow. /// @@ -479,12 +478,25 @@ pub async fn rpc_keys_get( Ok(Json(response_json).into_response()) } -/// the JSON input to the `rpc_keys_post` handler. +/// `DELETE /user/keys` -- Use a bearer token to delete an existing key. +#[debug_handler] +#[instrument(level = "trace")] +pub async fn rpc_keys_delete( + Extension(app): Extension>, + TypedHeader(Authorization(bearer)): TypedHeader>, +) -> FrontendResult { + let (user, _semaphore) = app.bearer_is_authorized(bearer).await?; + + // TODO: think about how cascading deletes and billing should work + Err(anyhow::anyhow!("work in progress").into()) +} + +/// the JSON input to the `rpc_keys_management` handler. +/// If `key_id` is set, it updates an existing key. +/// If `key_id` is not set, it creates a new key. #[derive(Debug, Deserialize)] -pub struct UserKeysPost { - // TODO: make sure the email address is valid. probably have a "verified" column in the database - existing_key_id: Option, - existing_key: Option, +pub struct UserKeyManagement { + key_id: Option, description: Option, private_txs: Option, active: Option, @@ -497,22 +509,21 @@ pub struct UserKeysPost { // do not allow! `max_concurrent_requests: Option,` } -/// `POST /user/keys` -- Use a bearer token to create a new key or modify an existing key. -/// -/// TODO: read json from the request body -/// TODO: one key per request? maybe /user/keys/:rpc_key? +/// `POST /user/keys` or `PUT /user/keys` -- Use a bearer token to create or update an existing key. #[debug_handler] #[instrument(level = "trace")] -pub async fn rpc_keys_post( +pub async fn rpc_keys_management( Extension(app): Extension>, TypedHeader(Authorization(bearer)): TypedHeader>, - Json(payload): Json, + Json(payload): Json, ) -> FrontendResult { + // TODO: is there a way we can know if this is a PUT or POST? right now we can modify or create keys with either. though that probably doesn't matter + let (user, _semaphore) = app.bearer_is_authorized(bearer).await?; let db_conn = app.db_conn().context("getting db for user's keys")?; - let mut uk = if let Some(existing_key_id) = payload.existing_key_id { + let mut uk = if let Some(existing_key_id) = payload.key_id { // get the key and make sure it belongs to the user let uk = rpc_keys::Entity::find() .filter(rpc_keys::Column::UserId.eq(user.id)) @@ -522,17 +533,6 @@ pub async fn rpc_keys_post( .context("failed loading user's key")? .context("key does not exist or is not controlled by this bearer token")?; - uk.try_into().unwrap() - } else if let Some(existing_key) = payload.existing_key { - // get the key and make sure it belongs to the user - let uk = rpc_keys::Entity::find() - .filter(rpc_keys::Column::UserId.eq(user.id)) - .filter(rpc_keys::Column::RpcKey.eq(Uuid::from(existing_key))) - .one(&db_conn) - .await - .context("failed loading user's key")? - .context("key does not exist or is not controlled by this bearer token")?; - uk.try_into().unwrap() } else { // make a new key