diff --git a/README.md b/README.md index aba777e..b24ebea 100644 --- a/README.md +++ b/README.md @@ -45,16 +45,25 @@ Default configuration and credentials could be overriden by using `./config/cust #### Default configuration -Default configuration could be found in `./gov-portal-mocker/config/default.json` file. +Default configuration could be found in `./gov-portal-db/config/default.json` file. - `listenAddress`: host:port to run the gov portal database middleware at. Defaults to `localhost:10001` - `session`: session manager configuration - `secret`: secret to generate session tokens. Should be set before app start - `lifetime`: lifetime duration in seconds for which the session token will be valid to access database by using middleware. Defaults to 1 day -- `registration`: registration manager configuration +- `usersManager`: user's manager configuration - `secret`: secret to generate registration tokens to be sent to user specified email for verification. Should be set before app start - `lifetime`: lifetime duration in seconds for which the registration token will be valid to register user by using middleware. Defaults to 10 min - `userProfileAttributes`: restrictions to user profile attributes for data validation purpose, eg. max user name or bio length + - `emailVerification`: mailer configuration + - `mailerBaseUrl`: mailer service base http url + - `sendTimeout`: send mail request timeout in seconds + - `templateUrl`: link sent within verification email, must contain `{{VERIFICATION_TOKEN}}` token place holder + - `from`: sender's information + - `name`: sender's name + - `email`: sender's mail + - `subject`: mail subject + - `moderators`: comma separated array of moderator EVM-compatible wallet addresses, e.g. [`0xaAbB...445566`, `0xcCdD...778899`, ..] - `mongo`: MongoDB configuration - `url`: mongo connection url in format `mongodb://host:port`. Should be set before app start - `db`: database name with users collection. Defaults to `AirDAOGovPortal` diff --git a/gov-portal-db/config/default.json b/gov-portal-db/config/default.json index 0347336..9f05ff4 100644 --- a/gov-portal-db/config/default.json +++ b/gov-portal-db/config/default.json @@ -28,7 +28,8 @@ "email": "gwg@airdao.io" }, "subject": "Complete Your Governor Email Verification" - } + }, + "moderators": [] }, "mongo": { "url": null, diff --git a/gov-portal-db/src/server.rs b/gov-portal-db/src/server.rs index 02e5ae0..f3a6c46 100644 --- a/gov-portal-db/src/server.rs +++ b/gov-portal-db/src/server.rs @@ -228,13 +228,14 @@ async fn users_route( wallets = req.wallets.len() ); + let wallets_max_count = std::cmp::min(req.wallets.len(), USERS_MAX_WALLETS_REQ_LIMIT); + let res = match state.session_manager.verify_token(&req.session) { - Ok(_) => state + Ok(requestor) => state .users_manager - .get_users_by_wallets(&req.wallets[..USERS_MAX_WALLETS_REQ_LIMIT]) + .get_users_by_wallets(&requestor, &req.wallets[..wallets_max_count]) .await .map_err(|e| format!("Unable to acquire users profiles. Error: {e}")), - Err(e) => Err(format!("Users request failure. Error: {e}")), }; diff --git a/gov-portal-db/src/users_manager/error.rs b/gov-portal-db/src/users_manager/error.rs index 9ed7046..b65ec07 100644 --- a/gov-portal-db/src/users_manager/error.rs +++ b/gov-portal-db/src/users_manager/error.rs @@ -1,5 +1,7 @@ #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("Not authorized")] + Unauthorized, #[error("User is already registered")] UserAlreadyExist, #[error("User is not registered")] diff --git a/gov-portal-db/src/users_manager/mod.rs b/gov-portal-db/src/users_manager/mod.rs index b2d9d3e..ca8436e 100644 --- a/gov-portal-db/src/users_manager/mod.rs +++ b/gov-portal-db/src/users_manager/mod.rs @@ -37,6 +37,7 @@ pub struct UsersManagerConfig { /// User profile attributes verification settings pub user_profile_attributes: UserProfileAttributes, pub email_verification: EmailVerificationConfig, + pub moderators: Vec
, } #[derive(Deserialize, Debug, Clone)] @@ -193,8 +194,18 @@ impl UsersManager { /// Searches for multiple user profiles within MongoDB by provided EVM-like address [`Address`] list and returns [`Vec`] pub async fn get_users_by_wallets( &self, + requestor: &Address, wallets: &[Address], ) -> Result, error::Error> { + if !self + .config + .moderators + .iter() + .any(|wallet| wallet == requestor) + { + return Err(error::Error::Unauthorized); + } + if wallets.is_empty() { return Ok(vec![]); } @@ -570,7 +581,8 @@ mod tests { "email": "gwg@airdao.io" }, "subject": "Complete Your Governor Email Verification" - } + }, + "moderators": ["0xc0ffee254729296a45a3885639AC7E10F9d54979"] } "#, ) diff --git a/gov-portal-db/tests/test_db.rs b/gov-portal-db/tests/test_db.rs index 285164e..eb74aa9 100644 --- a/gov-portal-db/tests/test_db.rs +++ b/gov-portal-db/tests/test_db.rs @@ -33,6 +33,7 @@ async fn test_register_user() -> Result<(), anyhow::Error> { }, subject: "Complete Your Governor Email Verification".to_string(), }, + moderators: vec![], }, ) .await?; @@ -92,6 +93,12 @@ async fn test_users_endpoint() -> Result<(), anyhow::Error> { request_timeout: 10, }; + let moderators = vec![ + Address::from_low_u64_le(1_234_567), + Address::from_low_u64_le(1_234_568), + Address::from_low_u64_le(1_234_569), + ]; + let users_manager = std::sync::Arc::new( UsersManager::new( &mongo_config, @@ -109,6 +116,7 @@ async fn test_users_endpoint() -> Result<(), anyhow::Error> { }, subject: "Complete Your Governor Email Verification".to_string(), }, + moderators, }, ) .await?, @@ -136,17 +144,39 @@ async fn test_users_endpoint() -> Result<(), anyhow::Error> { })) .await; + assert_matches!( + users_manager + .get_users_by_wallets(&Address::from_low_u64_le(0), &[]) + .await, + Err(error::Error::Unauthorized) + ); + + assert_eq!( + users_manager + .get_users_by_wallets(&Address::from_low_u64_le(1_234_567), &[]) + .await + .and_then(|profiles| profiles + .into_iter() + .map(|profile| Ok(profile.info.email)) + .collect::, _>>()) + .unwrap(), + vec![] + ); + assert_eq!( users_manager - .get_users_by_wallets(&[ - Address::from_low_u64_le(10), - Address::from_low_u64_le(0), - Address::from_low_u64_le(1), - Address::from_low_u64_le(7), - Address::from_low_u64_le(8), - Address::from_low_u64_le(2), - Address::from_low_u64_le(9), - ]) + .get_users_by_wallets( + &Address::from_low_u64_le(1_234_568), + &[ + Address::from_low_u64_le(10), + Address::from_low_u64_le(0), + Address::from_low_u64_le(1), + Address::from_low_u64_le(7), + Address::from_low_u64_le(8), + Address::from_low_u64_le(2), + Address::from_low_u64_le(9), + ] + ) .await .and_then(|profiles| profiles .into_iter() @@ -238,6 +268,7 @@ async fn test_complete_profile() -> Result<(), anyhow::Error> { }, subject: "Complete Your Governor Email Verification".to_string(), }, + moderators: vec![], }, ) .await?;