web3-proxy/web3_proxy/src/admin_queries.rs

122 lines
4.1 KiB
Rust
Raw Normal View History

2023-02-19 23:27:53 +03:00
use crate::app::Web3ProxyApp;
use crate::errors::{Web3ProxyError, Web3ProxyResponse};
use crate::http_params::get_user_id_from_params;
2023-02-19 23:27:53 +03:00
use anyhow::Context;
use axum::response::IntoResponse;
2023-02-19 23:27:53 +03:00
use axum::{
headers::{authorization::Bearer, Authorization},
2023-03-01 22:23:59 +03:00
Json, TypedHeader,
2023-02-19 23:27:53 +03:00
};
2023-02-10 20:48:51 +03:00
use entities::{admin, login, user, user_tier};
2023-02-19 23:27:53 +03:00
use ethers::prelude::Address;
use hashbrown::HashMap;
2023-03-01 22:23:59 +03:00
use log::{debug, info};
use migration::sea_orm::{
self, ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter,
};
2023-02-19 23:27:53 +03:00
2023-02-19 23:34:39 +03:00
// TODO: Add some logic to check if the operating user is an admin
// If he is, return true
// If he is not, return false
// This function is used to give permission to certain users
2023-02-19 23:27:53 +03:00
pub async fn query_admin_modify_usertier<'a>(
app: &'a Web3ProxyApp,
bearer: Option<TypedHeader<Authorization<Bearer>>>,
2023-03-01 22:23:59 +03:00
params: &'a HashMap<String, String>,
) -> Web3ProxyResponse {
2023-02-19 23:27:53 +03:00
// Quickly return if any of the input tokens are bad
let user_address: Vec<u8> = params
.get("user_address")
2023-03-01 22:23:59 +03:00
.ok_or_else(|| {
2023-05-31 09:17:05 +03:00
Web3ProxyError::BadRequest("Unable to find user_address key in request".into())
2023-03-01 22:23:59 +03:00
})?
2023-02-19 23:27:53 +03:00
.parse::<Address>()
2023-03-01 22:23:59 +03:00
.map_err(|_| {
2023-05-31 09:17:05 +03:00
Web3ProxyError::BadRequest("Unable to parse user_address as an Address".into())
2023-03-01 22:23:59 +03:00
})?
.to_fixed_bytes()
.into();
let user_tier_title = params.get("user_tier_title").ok_or_else(|| {
2023-05-31 09:17:05 +03:00
Web3ProxyError::BadRequest("Unable to get the user_tier_title key from the request".into())
2023-03-01 22:23:59 +03:00
})?;
2023-02-19 23:27:53 +03:00
// Prepare output body
let mut response_body = HashMap::new();
// Establish connections
2023-03-01 22:23:59 +03:00
let db_conn = app
.db_conn()
.context("query_admin_modify_user needs a db")?;
2023-02-19 23:27:53 +03:00
let db_replica = app
.db_replica()
.context("query_user_stats needs a db replica")?;
let mut redis_conn = app
.redis_conn()
.await
.context("query_admin_modify_user had a redis connection error")?
.context("query_admin_modify_user needs a redis")?;
// Will modify logic here
2023-02-19 23:27:53 +03:00
// Try to get the user who is calling from redis (if existent) / else from the database
// TODO: Make a single query, where you retrieve the user, and directly from it the secondary user (otherwise we do two jumpy, which is unnecessary)
// get the user id first. if it is 0, we should use a cache on the app
2023-03-01 22:23:59 +03:00
let caller_id =
get_user_id_from_params(&mut redis_conn, &db_conn, &db_replica, bearer, params).await?;
2023-02-19 23:27:53 +03:00
2023-06-17 09:46:20 +03:00
trace!("Caller id is: {:?}", caller_id);
2023-02-19 23:27:53 +03:00
// Check if the caller is an admin (i.e. if he is in an admin table)
2023-03-01 22:23:59 +03:00
let _admin: admin::Model = admin::Entity::find()
.filter(admin::Column::UserId.eq(caller_id))
.one(&db_conn)
2023-02-19 23:27:53 +03:00
.await?
.ok_or(Web3ProxyError::AccessDenied)?;
2023-02-19 23:27:53 +03:00
// If we are here, that means an admin was found, and we can safely proceed
// Fetch the admin, and the user
let user: user::Model = user::Entity::find()
.filter(user::Column::Address.eq(user_address))
.one(&db_conn)
2023-02-19 23:27:53 +03:00
.await?
.ok_or(Web3ProxyError::BadRequest(
2023-05-31 09:17:05 +03:00
"No user with this id found".into(),
2023-03-01 22:23:59 +03:00
))?;
2023-02-19 23:27:53 +03:00
// Return early if the target user_tier_id is the same as the original user_tier_id
response_body.insert(
"user_tier_title",
serde_json::Value::Number(user.user_tier_id.into()),
2023-02-19 23:27:53 +03:00
);
// Now we can modify the user's tier
2023-02-10 20:48:51 +03:00
let new_user_tier: user_tier::Model = user_tier::Entity::find()
2023-02-19 23:27:53 +03:00
.filter(user_tier::Column::Title.eq(user_tier_title.clone()))
.one(&db_conn)
2023-02-19 23:27:53 +03:00
.await?
.ok_or(Web3ProxyError::BadRequest(
2023-05-31 09:17:05 +03:00
"User Tier name was not found".into(),
2023-03-01 22:23:59 +03:00
))?;
2023-02-19 23:27:53 +03:00
if user.user_tier_id == new_user_tier.id {
info!("user already has that tier");
} else {
2023-02-10 20:48:51 +03:00
let mut user = user.clone().into_active_model();
2023-02-19 23:27:53 +03:00
user.user_tier_id = sea_orm::Set(new_user_tier.id);
user.save(&db_conn).await?;
info!("user's tier changed");
}
2023-03-01 22:23:59 +03:00
// Now delete all bearer tokens of this user
2023-02-10 20:48:51 +03:00
login::Entity::delete_many()
.filter(login::Column::UserId.eq(user.id))
.exec(&db_conn)
.await?;
2023-02-19 23:27:53 +03:00
Ok(Json(&response_body).into_response())
}