back to ids
i still think uuids are a better idea, but sea orm has some kinks to work out
This commit is contained in:
parent
20384e7f2f
commit
b90f80f46b
|
@ -2,15 +2,14 @@
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sea_orm::prelude::Uuid;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
#[sea_orm(table_name = "block_list")]
|
#[sea_orm(table_name = "block_list")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key)]
|
||||||
pub uuid: Uuid,
|
pub id: i64,
|
||||||
#[sea_orm(unique)]
|
#[sea_orm(unique)]
|
||||||
pub address: String,
|
pub address: Vec<u8>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,15 @@
|
||||||
|
|
||||||
use super::sea_orm_active_enums::Role;
|
use super::sea_orm_active_enums::Role;
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use sea_orm::prelude::Uuid;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
#[sea_orm(table_name = "secondary_user")]
|
#[sea_orm(table_name = "secondary_user")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key)]
|
||||||
pub uuid: Uuid,
|
pub id: i64,
|
||||||
pub user_id: Uuid,
|
pub user_id: i64,
|
||||||
pub address: String,
|
pub address: Vec<u8>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub role: Role,
|
pub role: Role,
|
||||||
|
@ -22,7 +21,7 @@ pub enum Relation {
|
||||||
#[sea_orm(
|
#[sea_orm(
|
||||||
belongs_to = "super::user::Entity",
|
belongs_to = "super::user::Entity",
|
||||||
from = "Column::UserId",
|
from = "Column::UserId",
|
||||||
to = "super::user::Column::Uuid",
|
to = "super::user::Column::Id",
|
||||||
on_update = "NoAction",
|
on_update = "NoAction",
|
||||||
on_delete = "NoAction"
|
on_delete = "NoAction"
|
||||||
)]
|
)]
|
||||||
|
|
|
@ -2,15 +2,14 @@
|
||||||
|
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sea_orm::prelude::Uuid;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
#[sea_orm(table_name = "user")]
|
#[sea_orm(table_name = "user")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key)]
|
||||||
pub uuid: Uuid,
|
pub id: i64,
|
||||||
#[sea_orm(unique)]
|
#[sea_orm(unique)]
|
||||||
pub address: String,
|
pub address: Vec<u8>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ use serde::{Deserialize, Serialize};
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||||
#[sea_orm(table_name = "user_keys")]
|
#[sea_orm(table_name = "user_keys")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key)]
|
||||||
pub uuid: Uuid,
|
pub id: i64,
|
||||||
pub user_uuid: Uuid,
|
pub user_id: i64,
|
||||||
#[sea_orm(unique)]
|
#[sea_orm(unique)]
|
||||||
pub api_key: Uuid,
|
pub api_key: Uuid,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
@ -21,8 +21,8 @@ pub struct Model {
|
||||||
pub enum Relation {
|
pub enum Relation {
|
||||||
#[sea_orm(
|
#[sea_orm(
|
||||||
belongs_to = "super::user::Entity",
|
belongs_to = "super::user::Entity",
|
||||||
from = "Column::UserUuid",
|
from = "Column::UserId",
|
||||||
to = "super::user::Column::Uuid",
|
to = "super::user::Column::Id",
|
||||||
on_update = "NoAction",
|
on_update = "NoAction",
|
||||||
on_delete = "NoAction"
|
on_delete = "NoAction"
|
||||||
)]
|
)]
|
||||||
|
|
|
@ -12,15 +12,15 @@ impl MigrationTrait for Migration {
|
||||||
Table::create()
|
Table::create()
|
||||||
.table(User::Table)
|
.table(User::Table)
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(User::Uuid)
|
ColumnDef::new(User::Id)
|
||||||
.uuid()
|
.big_integer()
|
||||||
.not_null()
|
.not_null()
|
||||||
.extra("DEFAULT (UUID_TO_BIN(UUID()))".to_string())
|
.primary_key()
|
||||||
.primary_key(),
|
.auto_increment(),
|
||||||
)
|
)
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(User::Address)
|
ColumnDef::new(User::Address)
|
||||||
.string_len(42)
|
.binary_len(20)
|
||||||
.not_null()
|
.not_null()
|
||||||
.unique_key(),
|
.unique_key(),
|
||||||
)
|
)
|
||||||
|
@ -36,16 +36,20 @@ impl MigrationTrait for Migration {
|
||||||
Table::create()
|
Table::create()
|
||||||
.table(SecondaryUser::Table)
|
.table(SecondaryUser::Table)
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(SecondaryUser::Uuid)
|
ColumnDef::new(SecondaryUser::Id)
|
||||||
.uuid()
|
.big_integer()
|
||||||
.not_null()
|
.not_null()
|
||||||
.extra("DEFAULT (UUID_TO_BIN(UUID()))".to_string())
|
.primary_key()
|
||||||
.primary_key(),
|
.auto_increment(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(SecondaryUser::UserId)
|
||||||
|
.big_integer()
|
||||||
|
.not_null(),
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(SecondaryUser::UserId).uuid().not_null())
|
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(SecondaryUser::Address)
|
ColumnDef::new(SecondaryUser::Address)
|
||||||
.string_len(42)
|
.binary_len(20)
|
||||||
.not_null(),
|
.not_null(),
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(SecondaryUser::Description).string())
|
.col(ColumnDef::new(SecondaryUser::Description).string())
|
||||||
|
@ -59,7 +63,7 @@ impl MigrationTrait for Migration {
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
sea_query::ForeignKey::create()
|
sea_query::ForeignKey::create()
|
||||||
.from(SecondaryUser::Table, SecondaryUser::UserId)
|
.from(SecondaryUser::Table, SecondaryUser::UserId)
|
||||||
.to(User::Table, User::Uuid),
|
.to(User::Table, User::Id),
|
||||||
)
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
|
@ -71,15 +75,15 @@ impl MigrationTrait for Migration {
|
||||||
Table::create()
|
Table::create()
|
||||||
.table(BlockList::Table)
|
.table(BlockList::Table)
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(BlockList::Uuid)
|
ColumnDef::new(BlockList::Id)
|
||||||
.uuid()
|
.big_integer()
|
||||||
.not_null()
|
.not_null()
|
||||||
.extra("DEFAULT (UUID_TO_BIN(UUID()))".to_string())
|
.primary_key()
|
||||||
.primary_key(),
|
.auto_increment(),
|
||||||
)
|
)
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(BlockList::Address)
|
ColumnDef::new(BlockList::Address)
|
||||||
.string()
|
.binary_len(20)
|
||||||
.not_null()
|
.not_null()
|
||||||
.unique_key(),
|
.unique_key(),
|
||||||
)
|
)
|
||||||
|
@ -94,13 +98,13 @@ impl MigrationTrait for Migration {
|
||||||
Table::create()
|
Table::create()
|
||||||
.table(UserKeys::Table)
|
.table(UserKeys::Table)
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(UserKeys::Uuid)
|
ColumnDef::new(UserKeys::Id)
|
||||||
.uuid()
|
.big_integer()
|
||||||
.not_null()
|
.not_null()
|
||||||
.extra("DEFAULT (UUID_TO_BIN(UUID()))".to_string())
|
.primary_key()
|
||||||
.primary_key(),
|
.auto_increment(),
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(UserKeys::UserUuid).uuid().not_null())
|
.col(ColumnDef::new(UserKeys::UserId).big_integer().not_null())
|
||||||
.col(
|
.col(
|
||||||
ColumnDef::new(UserKeys::ApiKey)
|
ColumnDef::new(UserKeys::ApiKey)
|
||||||
.uuid()
|
.uuid()
|
||||||
|
@ -123,8 +127,8 @@ impl MigrationTrait for Migration {
|
||||||
.index(sea_query::Index::create().col(UserKeys::Active))
|
.index(sea_query::Index::create().col(UserKeys::Active))
|
||||||
.foreign_key(
|
.foreign_key(
|
||||||
sea_query::ForeignKey::create()
|
sea_query::ForeignKey::create()
|
||||||
.from(UserKeys::Table, UserKeys::UserUuid)
|
.from(UserKeys::Table, UserKeys::UserId)
|
||||||
.to(User::Table, User::Uuid),
|
.to(User::Table, User::Id),
|
||||||
)
|
)
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
|
@ -156,7 +160,7 @@ impl MigrationTrait for Migration {
|
||||||
#[derive(Iden)]
|
#[derive(Iden)]
|
||||||
enum User {
|
enum User {
|
||||||
Table,
|
Table,
|
||||||
Uuid,
|
Id,
|
||||||
Address,
|
Address,
|
||||||
Description,
|
Description,
|
||||||
Email,
|
Email,
|
||||||
|
@ -172,7 +176,7 @@ enum User {
|
||||||
#[derive(Iden)]
|
#[derive(Iden)]
|
||||||
enum SecondaryUser {
|
enum SecondaryUser {
|
||||||
Table,
|
Table,
|
||||||
Uuid,
|
Id,
|
||||||
UserId,
|
UserId,
|
||||||
Address,
|
Address,
|
||||||
Description,
|
Description,
|
||||||
|
@ -184,7 +188,7 @@ enum SecondaryUser {
|
||||||
#[derive(Iden)]
|
#[derive(Iden)]
|
||||||
enum BlockList {
|
enum BlockList {
|
||||||
Table,
|
Table,
|
||||||
Uuid,
|
Id,
|
||||||
Address,
|
Address,
|
||||||
Description,
|
Description,
|
||||||
}
|
}
|
||||||
|
@ -202,8 +206,8 @@ enum BlockList {
|
||||||
#[derive(Iden)]
|
#[derive(Iden)]
|
||||||
enum UserKeys {
|
enum UserKeys {
|
||||||
Table,
|
Table,
|
||||||
Uuid,
|
Id,
|
||||||
UserUuid,
|
UserId,
|
||||||
ApiKey,
|
ApiKey,
|
||||||
Description,
|
Description,
|
||||||
PrivateTxs,
|
PrivateTxs,
|
||||||
|
|
|
@ -48,6 +48,7 @@ sea-orm = { version = "0.9.1", features = ["macros"] }
|
||||||
serde = { version = "1.0.142", features = [] }
|
serde = { version = "1.0.142", features = [] }
|
||||||
serde_json = { version = "1.0.83", default-features = false, features = ["alloc", "raw_value"] }
|
serde_json = { version = "1.0.83", default-features = false, features = ["alloc", "raw_value"] }
|
||||||
tokio = { version = "1.20.1", features = ["full", "tracing"] }
|
tokio = { version = "1.20.1", features = ["full", "tracing"] }
|
||||||
|
# TODO: make sure this uuid version matches what is in sea orm. PR on sea orm to put builder into prelude
|
||||||
uuid = "1.1.2"
|
uuid = "1.1.2"
|
||||||
toml = "0.5.9"
|
toml = "0.5.9"
|
||||||
tracing = "0.1.36"
|
tracing = "0.1.36"
|
||||||
|
|
|
@ -14,6 +14,7 @@ use migration::{Migrator, MigratorTrait};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use redis_cell_client::bb8::ErrorSink;
|
use redis_cell_client::bb8::ErrorSink;
|
||||||
use redis_cell_client::{bb8, RedisCellClient, RedisConnectionManager};
|
use redis_cell_client::{bb8, RedisCellClient, RedisConnectionManager};
|
||||||
|
use sea_orm::DatabaseConnection;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem::size_of_val;
|
use std::mem::size_of_val;
|
||||||
|
@ -236,6 +237,31 @@ fn block_needed(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_migrated_db(
|
||||||
|
db_url: String,
|
||||||
|
min_connections: u32,
|
||||||
|
) -> anyhow::Result<DatabaseConnection> {
|
||||||
|
let mut db_opt = sea_orm::ConnectOptions::new(db_url);
|
||||||
|
|
||||||
|
// TODO: load all these options from the config file
|
||||||
|
// TODO: sqlx logging only in debug. way too verbose for production
|
||||||
|
db_opt
|
||||||
|
.max_connections(100)
|
||||||
|
.min_connections(min_connections)
|
||||||
|
.connect_timeout(Duration::from_secs(8))
|
||||||
|
.idle_timeout(Duration::from_secs(8))
|
||||||
|
.max_lifetime(Duration::from_secs(60))
|
||||||
|
.sqlx_logging(false);
|
||||||
|
// .sqlx_logging_level(log::LevelFilter::Info);
|
||||||
|
|
||||||
|
let db = sea_orm::Database::connect(db_opt).await?;
|
||||||
|
|
||||||
|
// TODO: if error, roll back?
|
||||||
|
Migrator::up(&db, None).await?;
|
||||||
|
|
||||||
|
Ok(db)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: think more about TxState. d
|
// TODO: think more about TxState. d
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum TxState {
|
pub enum TxState {
|
||||||
|
@ -296,24 +322,11 @@ impl Web3ProxyApp {
|
||||||
)> {
|
)> {
|
||||||
// first, we connect to mysql and make sure the latest migrations have run
|
// first, we connect to mysql and make sure the latest migrations have run
|
||||||
let db_conn = if let Some(db_url) = app_config.shared.db_url {
|
let db_conn = if let Some(db_url) = app_config.shared.db_url {
|
||||||
let mut db_opt = sea_orm::ConnectOptions::new(db_url);
|
let min_connections = num_workers.try_into()?;
|
||||||
|
|
||||||
// TODO: load all these options from the config file
|
let db = get_migrated_db(db_url, min_connections).await?;
|
||||||
db_opt
|
|
||||||
.max_connections(100)
|
|
||||||
.min_connections(num_workers.try_into()?)
|
|
||||||
.connect_timeout(Duration::from_secs(8))
|
|
||||||
.idle_timeout(Duration::from_secs(8))
|
|
||||||
.max_lifetime(Duration::from_secs(60))
|
|
||||||
.sqlx_logging(true);
|
|
||||||
// .sqlx_logging_level(log::LevelFilter::Info);
|
|
||||||
|
|
||||||
let db_conn = sea_orm::Database::connect(db_opt).await?;
|
Some(db)
|
||||||
|
|
||||||
// TODO: if error, roll back
|
|
||||||
Migrator::up(&db_conn, None).await?;
|
|
||||||
|
|
||||||
Some(db_conn)
|
|
||||||
} else {
|
} else {
|
||||||
info!("no database");
|
info!("no database");
|
||||||
None
|
None
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
use argh::FromArgs;
|
|
||||||
use entities::{user, user_keys};
|
|
||||||
use fstrings::{format_args_f, println_f};
|
|
||||||
use sea_orm::ActiveModelTrait;
|
|
||||||
use web3_proxy::users::new_api_key;
|
|
||||||
|
|
||||||
#[derive(Debug, FromArgs)]
|
|
||||||
/// Command line interface for admins to interact with web3-proxy
|
|
||||||
pub struct TopConfig {
|
|
||||||
/// what host the client should connect to
|
|
||||||
#[argh(
|
|
||||||
option,
|
|
||||||
default = "\"mysql://root:dev_web3_proxy@127.0.0.1:3306/dev_web3_proxy\".to_string()"
|
|
||||||
)]
|
|
||||||
pub db_url: String,
|
|
||||||
|
|
||||||
/// this one cli can do multiple things
|
|
||||||
#[argh(subcommand)]
|
|
||||||
sub_command: SubCommand,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, PartialEq, Debug)]
|
|
||||||
#[argh(subcommand)]
|
|
||||||
enum SubCommand {
|
|
||||||
CreateUser(CreateUserSubCommand),
|
|
||||||
Two(SubCommandTwo),
|
|
||||||
// TODO: sub command to downgrade migrations?
|
|
||||||
// TODO: sub command to add new api keys to an existing user?
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, PartialEq, Debug)]
|
|
||||||
/// First subcommand.
|
|
||||||
#[argh(subcommand, name = "create_user")]
|
|
||||||
struct CreateUserSubCommand {
|
|
||||||
#[argh(option)]
|
|
||||||
/// the user's ethereum address
|
|
||||||
address: String,
|
|
||||||
|
|
||||||
#[argh(option)]
|
|
||||||
/// the user's optional email
|
|
||||||
email: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CreateUserSubCommand {
|
|
||||||
async fn main(self, db: &sea_orm::DatabaseConnection) -> anyhow::Result<()> {
|
|
||||||
let u = user::ActiveModel {
|
|
||||||
address: sea_orm::Set(self.address),
|
|
||||||
email: sea_orm::Set(self.email),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: proper error message
|
|
||||||
let u = u.insert(db).await?;
|
|
||||||
|
|
||||||
println_f!("user: {u:?}");
|
|
||||||
|
|
||||||
// create a key for the new user
|
|
||||||
let uk = user_keys::ActiveModel {
|
|
||||||
user_uuid: sea_orm::Set(u.uuid),
|
|
||||||
api_key: sea_orm::Set(new_api_key()),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
println_f!("user key: {uk:?}");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromArgs, PartialEq, Debug)]
|
|
||||||
/// Second subcommand.
|
|
||||||
#[argh(subcommand, name = "two")]
|
|
||||||
struct SubCommandTwo {
|
|
||||||
#[argh(switch)]
|
|
||||||
/// whether to fooey
|
|
||||||
fooey: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubCommandTwo {
|
|
||||||
async fn main(self) -> anyhow::Result<()> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> anyhow::Result<()> {
|
|
||||||
let cli_config: TopConfig = argh::from_env();
|
|
||||||
|
|
||||||
println!("hello, {}", cli_config.db_url);
|
|
||||||
|
|
||||||
match cli_config.sub_command {
|
|
||||||
SubCommand::CreateUser(x) => {
|
|
||||||
// TODO: more advanced settings
|
|
||||||
let db_conn = sea_orm::Database::connect(cli_config.db_url).await?;
|
|
||||||
|
|
||||||
x.main(&db_conn).await
|
|
||||||
}
|
|
||||||
SubCommand::Two(x) => x.main().await,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
use anyhow::Context;
|
||||||
|
use argh::FromArgs;
|
||||||
|
use entities::{user, user_keys};
|
||||||
|
use ethers::types::Address;
|
||||||
|
use fstrings::{format_args_f, println_f};
|
||||||
|
use sea_orm::ActiveModelTrait;
|
||||||
|
use web3_proxy::users::new_api_key;
|
||||||
|
|
||||||
|
#[derive(FromArgs, PartialEq, Debug)]
|
||||||
|
/// First subcommand.
|
||||||
|
#[argh(subcommand, name = "create_user")]
|
||||||
|
pub struct CreateUserSubCommand {
|
||||||
|
#[argh(option)]
|
||||||
|
/// the user's ethereum address
|
||||||
|
address: String,
|
||||||
|
|
||||||
|
#[argh(option)]
|
||||||
|
/// the user's optional email
|
||||||
|
email: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CreateUserSubCommand {
|
||||||
|
pub async fn main(self, db: &sea_orm::DatabaseConnection) -> anyhow::Result<()> {
|
||||||
|
let address = self
|
||||||
|
.address
|
||||||
|
.parse::<Address>()
|
||||||
|
.context("Failed parsing new user address")?
|
||||||
|
.to_fixed_bytes()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let u = user::ActiveModel {
|
||||||
|
address: sea_orm::Set(address),
|
||||||
|
email: sea_orm::Set(self.email),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let u = u.insert(db).await.context("Failed saving new user")?;
|
||||||
|
|
||||||
|
println_f!("user: {u:?}");
|
||||||
|
|
||||||
|
// create a key for the new user
|
||||||
|
let uk = user_keys::ActiveModel {
|
||||||
|
user_id: sea_orm::Set(u.id),
|
||||||
|
api_key: sea_orm::Set(new_api_key()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let uk = uk.insert(db).await.context("Failed saving new user key")?;
|
||||||
|
|
||||||
|
println_f!("user key: {uk:?}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
mod create_user;
|
||||||
|
mod two;
|
||||||
|
|
||||||
|
use argh::FromArgs;
|
||||||
|
use tracing::info;
|
||||||
|
use web3_proxy::app::get_migrated_db;
|
||||||
|
|
||||||
|
#[derive(Debug, FromArgs)]
|
||||||
|
/// Command line interface for admins to interact with web3-proxy
|
||||||
|
pub struct TopConfig {
|
||||||
|
/// what host the client should connect to
|
||||||
|
#[argh(
|
||||||
|
option,
|
||||||
|
default = "\"mysql://root:dev_web3_proxy@127.0.0.1:3306/dev_web3_proxy\".to_string()"
|
||||||
|
)]
|
||||||
|
pub db_url: String,
|
||||||
|
|
||||||
|
/// this one cli can do multiple things
|
||||||
|
#[argh(subcommand)]
|
||||||
|
sub_command: SubCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromArgs, PartialEq, Debug)]
|
||||||
|
#[argh(subcommand)]
|
||||||
|
enum SubCommand {
|
||||||
|
CreateUser(create_user::CreateUserSubCommand),
|
||||||
|
Two(two::SubCommandTwo),
|
||||||
|
// TODO: sub command to downgrade migrations?
|
||||||
|
// TODO: sub command to add new api keys to an existing user?
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
// if RUST_LOG isn't set, configure a default
|
||||||
|
// TODO: is there a better way to do this?
|
||||||
|
if std::env::var("RUST_LOG").is_err() {
|
||||||
|
// std::env::set_var("RUST_LOG", "info,web3_proxy=debug,web3_proxy_cli=debug");
|
||||||
|
std::env::set_var("RUST_LOG", "info,web3_proxy=debug,web3_proxy_cli=debug");
|
||||||
|
}
|
||||||
|
|
||||||
|
// install global collector configured based on RUST_LOG env var.
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
|
||||||
|
.compact()
|
||||||
|
.init();
|
||||||
|
|
||||||
|
// this probably won't matter for us in docker, but better safe than sorry
|
||||||
|
fdlimit::raise_fd_limit();
|
||||||
|
|
||||||
|
let cli_config: TopConfig = argh::from_env();
|
||||||
|
|
||||||
|
info!("hello, {}", cli_config.db_url);
|
||||||
|
|
||||||
|
match cli_config.sub_command {
|
||||||
|
SubCommand::CreateUser(x) => {
|
||||||
|
let db = get_migrated_db(cli_config.db_url, 1).await?;
|
||||||
|
|
||||||
|
x.main(&db).await
|
||||||
|
}
|
||||||
|
SubCommand::Two(x) => x.main().await,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
use argh::FromArgs;
|
||||||
|
|
||||||
|
#[derive(FromArgs, PartialEq, Debug)]
|
||||||
|
/// Second subcommand.
|
||||||
|
#[argh(subcommand, name = "two")]
|
||||||
|
pub struct SubCommandTwo {
|
||||||
|
#[argh(switch)]
|
||||||
|
/// whether to fooey
|
||||||
|
fooey: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubCommandTwo {
|
||||||
|
pub async fn main(self) -> anyhow::Result<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ pub async fn rate_limit_by_key(
|
||||||
// TODO: probably want a cache on this
|
// TODO: probably want a cache on this
|
||||||
match user_keys::Entity::find()
|
match user_keys::Entity::find()
|
||||||
.select_only()
|
.select_only()
|
||||||
.column(user_keys::Column::UserUuid)
|
.column(user_keys::Column::UserId)
|
||||||
.filter(user_keys::Column::ApiKey.eq(user_key))
|
.filter(user_keys::Column::ApiKey.eq(user_key))
|
||||||
.filter(user_keys::Column::Active.eq(true))
|
.filter(user_keys::Column::Active.eq(true))
|
||||||
.one(db)
|
.one(db)
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub async fn create_user(
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = user::ActiveModel {
|
let user = user::ActiveModel {
|
||||||
address: sea_orm::Set(payload.address.to_string()),
|
address: sea_orm::Set(payload.address.to_fixed_bytes().into()),
|
||||||
email: sea_orm::Set(payload.email),
|
email: sea_orm::Set(payload.email),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ use serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::value::RawValue;
|
use serde_json::value::RawValue;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use tracing::warn;
|
||||||
|
|
||||||
#[derive(Clone, serde::Deserialize)]
|
#[derive(Clone, serde::Deserialize)]
|
||||||
pub struct JsonRpcRequest {
|
pub struct JsonRpcRequest {
|
||||||
|
@ -166,6 +167,8 @@ impl JsonRpcForwardedResponse {
|
||||||
pub fn from_anyhow_error(err: anyhow::Error, id: Box<RawValue>) -> Self {
|
pub fn from_anyhow_error(err: anyhow::Error, id: Box<RawValue>) -> Self {
|
||||||
let err = format!("{:?}", err);
|
let err = format!("{:?}", err);
|
||||||
|
|
||||||
|
warn!("forwarding error. {:?}", err);
|
||||||
|
|
||||||
JsonRpcForwardedResponse {
|
JsonRpcForwardedResponse {
|
||||||
jsonrpc: "2.0".to_string(),
|
jsonrpc: "2.0".to_string(),
|
||||||
id,
|
id,
|
||||||
|
@ -173,7 +176,7 @@ impl JsonRpcForwardedResponse {
|
||||||
error: Some(JsonRpcErrorData {
|
error: Some(JsonRpcErrorData {
|
||||||
// TODO: set this jsonrpc error code to match the http status code
|
// TODO: set this jsonrpc error code to match the http status code
|
||||||
code: -32099,
|
code: -32099,
|
||||||
message: err,
|
message: "internal server error".to_string(),
|
||||||
data: None,
|
data: None,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue