web3-proxy/web3_proxy/src/frontend/users.rs

74 lines
2.5 KiB
Rust
Raw Normal View History

2022-07-14 00:49:57 +03:00
// So the API needs to show for any given user:
// - show balance in USD
// - show deposits history (currency, amounts, transaction id)
// - show number of requests used (so we can calculate average spending over a month, burn rate for a user etc, something like "Your balance will be depleted in xx days)
// - the email address of a user if he opted in to get contacted via email
// - all the monitoring and stats but that will come from someplace else if I understand corectly?
// I wonder how we handle payment
// probably have to do manual withdrawals
2022-08-04 04:10:27 +03:00
use axum::{response::IntoResponse, Extension, Json};
use axum_client_ip::ClientIp;
2022-08-04 02:17:02 +03:00
use entities::user;
2022-08-04 04:10:27 +03:00
use ethers::{prelude::Address, types::Bytes};
use sea_orm::ActiveModelTrait;
use serde::Deserialize;
use std::sync::Arc;
2022-08-04 02:17:02 +03:00
2022-08-10 05:37:34 +03:00
use crate::app::Web3ProxyApp;
use super::rate_limit::handle_rate_limit_error_response;
2022-08-04 02:17:02 +03:00
2022-07-14 00:49:57 +03:00
pub async fn create_user(
// this argument tells axum to parse the request body
// as JSON into a `CreateUser` type
Json(payload): Json<CreateUser>,
2022-08-04 04:10:27 +03:00
Extension(app): Extension<Arc<Web3ProxyApp>>,
ClientIp(ip): ClientIp,
2022-07-14 00:49:57 +03:00
) -> impl IntoResponse {
2022-08-10 05:37:34 +03:00
if let Some(err_response) =
handle_rate_limit_error_response(app.rate_limit_by_ip(&ip).await).await
{
return err_response.into_response();
2022-08-04 04:10:27 +03:00
}
2022-08-10 05:37:34 +03:00
// TODO: check invite_code against the app's config or database
2022-08-04 04:10:27 +03:00
if payload.invite_code != "llam4n0des!" {
todo!("proper error message")
}
// TODO: dont unwrap. proper error
let signature: [u8; 65] = payload.signature.as_ref().try_into().unwrap();
// TODO: calculate the expected message for the current user. include domain and a nonce. let timestamp be automatic
let message: siwe::Message = "abc123".parse().unwrap();
if let Err(e) = message.verify(signature, None, None, None) {
// message cannot be correctly authenticated
todo!("proper error message: {}", e)
}
2022-08-04 02:17:02 +03:00
let user = user::ActiveModel {
address: sea_orm::Set(payload.address.to_fixed_bytes().into()),
2022-08-04 04:10:27 +03:00
email: sea_orm::Set(payload.email),
2022-08-04 02:17:02 +03:00
..Default::default()
2022-07-14 00:49:57 +03:00
};
2022-08-10 08:56:09 +03:00
let db = app.db_conn.as_ref().unwrap();
2022-08-04 02:17:02 +03:00
2022-08-04 04:10:27 +03:00
// TODO: proper error message
let user = user.insert(db).await.unwrap();
2022-08-04 02:17:02 +03:00
2022-08-04 04:10:27 +03:00
todo!("serialize and return the user: {:?}", user)
2022-08-04 02:17:02 +03:00
// (StatusCode::CREATED, Json(user))
2022-07-14 00:49:57 +03:00
}
// the input to our `create_user` handler
#[derive(Deserialize)]
pub struct CreateUser {
2022-08-04 02:17:02 +03:00
address: Address,
// TODO: make sure the email address is valid
2022-07-14 00:49:57 +03:00
email: Option<String>,
signature: Bytes,
2022-08-04 02:17:02 +03:00
invite_code: String,
2022-07-14 00:49:57 +03:00
}