From 324ff204802d7d38e13d4c6d4c77869654980bfb Mon Sep 17 00:00:00 2001 From: silverpill Date: Thu, 21 Oct 2021 11:55:27 +0000 Subject: [PATCH] Call manager contract to verify that user is allowed to sign up --- README.md | 1 + src/ethereum/gate.rs | 31 +++++++++++++++++++++++++++++++ src/ethereum/mod.rs | 1 + src/ethereum/nft.rs | 2 +- src/mastodon_api/users/views.rs | 8 ++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/ethereum/gate.rs diff --git a/README.md b/README.md index bce7aa3..6f9617d 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Federated social network with smart contracts. - Built on [ActivityPub](https://activitypub.rocks/) protocol. - Lightweight. - Sign-in with Ethereum. +- Proving membership with a token. - Converting posts into NFTs. - More crypto features in the future. diff --git a/src/ethereum/gate.rs b/src/ethereum/gate.rs new file mode 100644 index 0000000..6ac16f3 --- /dev/null +++ b/src/ethereum/gate.rs @@ -0,0 +1,31 @@ +use web3::contract::{Contract, Options}; + +use crate::config::Config; +use super::api::connect; +use super::nft::{MANAGER, load_abi, EthereumError}; +use super::utils::parse_address; + +pub async fn is_allowed_user( + config: &Config, + user_address: &str, +) -> Result { + let json_rpc_url = config.ethereum_json_rpc_url.as_ref() + .ok_or(EthereumError::ImproperlyConfigured)?; + let web3 = connect(json_rpc_url)?; + let ethereum_config = config.ethereum_contract.as_ref() + .ok_or(EthereumError::ImproperlyConfigured)?; + + let manager_abi = load_abi(&config.contract_dir, MANAGER)?; + let manager_address = parse_address(ðereum_config.address)?; + let manager = Contract::from_json( + web3.eth(), + manager_address, + &manager_abi, + )?; + let user_address = parse_address(user_address)?; + let result: bool = manager.query( + "isAllowedUser", (user_address,), + None, Options::default(), None, + ).await?; + Ok(result) +} diff --git a/src/ethereum/mod.rs b/src/ethereum/mod.rs index 90ba97a..e0ff91f 100644 --- a/src/ethereum/mod.rs +++ b/src/ethereum/mod.rs @@ -1,3 +1,4 @@ mod api; +pub mod gate; pub mod nft; pub mod utils; diff --git a/src/ethereum/nft.rs b/src/ethereum/nft.rs index 920a642..4ba4612 100644 --- a/src/ethereum/nft.rs +++ b/src/ethereum/nft.rs @@ -71,7 +71,7 @@ pub enum EthereumError { SigError(#[from] SignatureError), } -fn load_abi( +pub fn load_abi( contract_dir: &PathBuf, contract_name: &str, ) -> Result, EthereumError> { diff --git a/src/mastodon_api/users/views.rs b/src/mastodon_api/users/views.rs index 9e3f181..427d92a 100644 --- a/src/mastodon_api/users/views.rs +++ b/src/mastodon_api/users/views.rs @@ -6,6 +6,7 @@ use actix_web::{ use crate::config::Config; use crate::database::{Pool, get_database_client}; use crate::errors::{HttpError, ValidationError}; +use crate::ethereum::gate::is_allowed_user; use crate::mastodon_api::accounts::types::{Account, AccountCreateData}; use crate::models::users::queries::{ is_valid_invite_code, @@ -35,6 +36,13 @@ pub async fn create_user_view( Err(ValidationError("invalid invite code"))?; } } + if config.ethereum_contract.is_some() { + let is_allowed = is_allowed_user(&config, &user_data.wallet_address).await + .map_err(|_| HttpError::InternalError)?; + if !is_allowed { + Err(ValidationError("not allowed to sign up"))?; + } + } // Hash password and generate private key let password_hash = hash_password(&user_data.password) .map_err(|_| HttpError::InternalError)?;