diff --git a/web3_proxy/src/admin_queries.rs b/web3_proxy/src/admin_queries.rs index a3b956be..e457898f 100644 --- a/web3_proxy/src/admin_queries.rs +++ b/web3_proxy/src/admin_queries.rs @@ -54,7 +54,7 @@ pub async fn query_admin_modify_usertier<'a>( let caller_id = get_user_id_from_params(&mut redis_conn, db_conn, db_replica, bearer, params).await?; - trace!("Caller id is: {:?}", caller_id); + trace!(%caller_id, "query_admin_modify_usertier"); // Check if the caller is an admin (i.e. if he is in an admin table) let _admin: admin::Model = admin::Entity::find() diff --git a/web3_proxy/src/frontend/admin.rs b/web3_proxy/src/frontend/admin.rs index fa60e8b7..aab61bf6 100644 --- a/web3_proxy/src/frontend/admin.rs +++ b/web3_proxy/src/frontend/admin.rs @@ -47,7 +47,7 @@ pub async fn admin_increase_balance( TypedHeader(Authorization(bearer)): TypedHeader>, Query(params): Query>, ) -> Web3ProxyResponse { - let (caller, _) = app.bearer_is_authorized(bearer).await?; + let (caller, _semaphore) = app.bearer_is_authorized(bearer).await?; let caller_id = caller.id; @@ -59,7 +59,10 @@ pub async fn admin_increase_balance( .filter(admin::Column::UserId.eq(caller_id)) .one(&txn) .await? - .ok_or(Web3ProxyError::AccessDenied)?; + .ok_or_else(|| { + warn!(%caller_id, "not an admin"); + Web3ProxyError::AccessDenied + })?; // Get the user from params let user_address: Address = params @@ -72,6 +75,7 @@ pub async fn admin_increase_balance( Web3ProxyError::BadRequest("Unable to parse user_address as an Address".into()) })?; + // Get the note from params let note: String = params .get("note") .ok_or_else(|| Web3ProxyError::BadRequest("Unable to find 'note' key in request".into()))? @@ -311,11 +315,11 @@ pub async fn admin_imitate_login_get( Ok(message.into_response()) } -/// `POST /admin/login` - Admin login by posting a signed "siwe" message +/// `POST /admin/imitate-login` - Admin 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 admin requests #[debug_handler] -pub async fn admin_login_post( +pub async fn admin_imitate_login_post( Extension(app): Extension>, InsecureClientIp(ip): InsecureClientIp, Json(payload): Json, @@ -479,44 +483,3 @@ pub async fn admin_login_post( Ok(response) } - -// TODO: This is basically an exact copy of the user endpoint, I should probabl refactor this code ... -/// `POST /admin/imitate-logout` - Forget the bearer token in the `Authentication` header. -#[debug_handler] -pub async fn admin_logout_post( - Extension(app): Extension>, - TypedHeader(Authorization(bearer)): TypedHeader>, -) -> Web3ProxyResponse { - let user_bearer = UserBearerToken::try_from(bearer)?; - - let db_conn = app.db_conn()?; - - if let Err(err) = login::Entity::delete_many() - .filter(login::Column::BearerToken.eq(user_bearer.uuid())) - .exec(db_conn) - .await - { - debug!("Failed to delete {}: {}", user_bearer.redis_key(), err); - } - - let now = Utc::now(); - - // also delete any expired logins - let delete_result = login::Entity::delete_many() - .filter(login::Column::ExpiresAt.lte(now)) - .exec(db_conn) - .await; - - debug!("Deleted expired logins: {:?}", delete_result); - - // also delete any expired pending logins - let delete_result = login::Entity::delete_many() - .filter(login::Column::ExpiresAt.lte(now)) - .exec(db_conn) - .await; - - debug!("Deleted expired pending logins: {:?}", delete_result); - - // TODO: what should the response be? probably json something - Ok("goodbye".into_response()) -} diff --git a/web3_proxy/src/frontend/mod.rs b/web3_proxy/src/frontend/mod.rs index 33c80f01..dd1061e8 100644 --- a/web3_proxy/src/frontend/mod.rs +++ b/web3_proxy/src/frontend/mod.rs @@ -216,15 +216,17 @@ pub async fn serve( ) .route("/admin/modify_role", post(admin::admin_change_user_roles)) .route( - "/admin/imitate-login/:admin_address/:user_address", + "/admin/imitate_login/:admin_address/:user_address", get(admin::admin_imitate_login_get), ) .route( - "/admin/imitate-login/:admin_address/:user_address/:message_eip", + "/admin/imitate_login/:admin_address/:user_address/:message_eip", get(admin::admin_imitate_login_get), ) - .route("/admin/imitate-login", post(admin::admin_login_post)) - .route("/admin/imitate-logout", post(admin::admin_logout_post)) + .route( + "/admin/imitate_login", + post(admin::admin_imitate_login_post), + ) // // Axum layers // layers are ordered bottom up diff --git a/web3_proxy/src/frontend/users/authentication.rs b/web3_proxy/src/frontend/users/authentication.rs index c76e5416..9f342a86 100644 --- a/web3_proxy/src/frontend/users/authentication.rs +++ b/web3_proxy/src/frontend/users/authentication.rs @@ -63,9 +63,9 @@ pub async fn user_login_get( let nonce = Ulid::new(); - let issued_at = OffsetDateTime::now_utc(); + let now = OffsetDateTime::now_utc(); - let expiration_time = issued_at.add(Duration::new(expire_seconds as i64, 0)); + let expiration_time = now.add(Duration::new(expire_seconds as i64, 0)); // TODO: allow ENS names here? let user_address: Address = params @@ -93,7 +93,7 @@ pub async fn user_login_get( version: siwe::Version::V1, chain_id: app.config.chain_id, expiration_time: Some(expiration_time.into()), - issued_at: issued_at.into(), + issued_at: now.into(), nonce: nonce.to_string(), not_before: None, request_id: None, @@ -102,15 +102,20 @@ pub async fn user_login_get( let db_conn = app.db_conn()?; - // delete ALL expired rows. - let now = Utc::now(); - let _ = pending_login::Entity::delete_many() - .filter(pending_login::Column::ExpiresAt.lte(now)) + // delete any expired logins + let expired_logins = login::Entity::delete_many() + .filter(login::Column::ExpiresAt.lte(now)) .exec(db_conn) - .await?; + .await; + trace!(?expired_logins, "deleted"); + + // delete any expired pending logins + let expired_pending_logins = pending_login::Entity::delete_many() + .filter(login::Column::ExpiresAt.lte(now)) + .exec(db_conn) + .await; + trace!(?expired_pending_logins, "deleted"); - // massage types to fit in the database. sea-orm does not make this very elegant - let uuid = Uuid::from_u128(nonce.into()); // we add 1 to expire_seconds just to be sure the database has the key for the full expiration_time let expires_at = Utc .timestamp_opt(expiration_time.unix_timestamp() + 1, 0) @@ -120,7 +125,7 @@ pub async fn user_login_get( // add a row to the database for this user let user_pending_login = pending_login::ActiveModel { id: sea_orm::NotSet, - nonce: sea_orm::Set(uuid), + nonce: sea_orm::Set(nonce.into()), message: sea_orm::Set(message.to_string()), expires_at: sea_orm::Set(expires_at), imitating_user: sea_orm::Set(None), @@ -388,7 +393,7 @@ pub async fn user_login_post( let user_login = login::ActiveModel { id: sea_orm::NotSet, - bearer_token: sea_orm::Set(user_bearer_token.uuid()), + bearer_token: sea_orm::Set(user_bearer_token.into()), user_id: sea_orm::Set(caller.id), expires_at: sea_orm::Set(expires_at), read_only: sea_orm::Set(false), @@ -424,24 +429,6 @@ pub async fn user_logout_post( warn!("Failed to delete {}: {}", user_bearer.redis_key(), err); } - let now = Utc::now(); - - // also delete any expired logins - let delete_result = login::Entity::delete_many() - .filter(login::Column::ExpiresAt.lte(now)) - .exec(db_conn) - .await; - - trace!("Deleted expired logins: {:?}", delete_result); - - // also delete any expired pending logins - let delete_result = login::Entity::delete_many() - .filter(login::Column::ExpiresAt.lte(now)) - .exec(db_conn) - .await; - - trace!("Deleted expired pending logins: {:?}", delete_result); - // TODO: what should the response be? probably json something Ok("goodbye".into_response()) }