From 333f90e2931a5852027a440201ef90027d7243d6 Mon Sep 17 00:00:00 2001 From: silverpill Date: Mon, 31 Jan 2022 19:10:51 +0000 Subject: [PATCH] Validate wallet address when creating new user --- src/mastodon_api/accounts/types.rs | 19 ++++++++++++++++++- src/mastodon_api/accounts/views.rs | 3 +-- src/mastodon_api/oauth/views.rs | 1 + src/models/users/types.rs | 28 +++++++++++++++++++--------- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/mastodon_api/accounts/types.rs b/src/mastodon_api/accounts/types.rs index 44b8c3b..e154330 100644 --- a/src/mastodon_api/accounts/types.rs +++ b/src/mastodon_api/accounts/types.rs @@ -4,12 +4,19 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use uuid::Uuid; +use crate::errors::ValidationError; use crate::models::profiles::types::{ DbActorProfile, ExtraField, ProfileUpdateData, }; -use crate::models::users::types::{User, UserCreateData}; +use crate::models::profiles::validators::validate_username; +use crate::models::users::types::{ + validate_local_username, + validate_wallet_address, + User, + UserCreateData, +}; use crate::utils::files::{FileError, save_validated_b64_file, get_file_url}; #[derive(Serialize)] @@ -106,6 +113,16 @@ pub struct AccountCreateData { } impl AccountCreateData { + + pub fn clean(&self) -> Result<(), ValidationError> { + validate_username(&self.username)?; + validate_local_username(&self.username)?; + if let Some(wallet_address) = self.wallet_address.as_ref() { + validate_wallet_address(wallet_address)?; + }; + Ok(()) + } + pub fn into_user_data( self, password_hash: String, diff --git a/src/mastodon_api/accounts/views.rs b/src/mastodon_api/accounts/views.rs index 7fe579a..58d6601 100644 --- a/src/mastodon_api/accounts/views.rs +++ b/src/mastodon_api/accounts/views.rs @@ -40,7 +40,6 @@ use crate::models::users::queries::{ is_valid_invite_code, create_user, }; -use crate::models::users::types::UserCreateData; use crate::utils::crypto::{ hash_password, generate_private_key, @@ -62,7 +61,7 @@ pub async fn create_account( ) -> Result { let db_client = &mut **get_database_client(&db_pool).await?; // Validate - UserCreateData::clean(&account_data.username)?; + account_data.clean()?; if !config.registrations_open { let invite_code = account_data.invite_code.as_ref() .ok_or(ValidationError("invite code is required"))?; diff --git a/src/mastodon_api/oauth/views.rs b/src/mastodon_api/oauth/views.rs index ca96eb5..8fd917e 100644 --- a/src/mastodon_api/oauth/views.rs +++ b/src/mastodon_api/oauth/views.rs @@ -31,6 +31,7 @@ async fn token_view( "ethereum" => { let wallet_address = request_data.wallet_address.as_ref() .ok_or(ValidationError("wallet address is required"))?; + // Wallet address must be in lowercase get_user_by_wallet_address(db_client, wallet_address).await? }, _ => { diff --git a/src/models/users/types.rs b/src/models/users/types.rs index 6792c74..965a7aa 100644 --- a/src/models/users/types.rs +++ b/src/models/users/types.rs @@ -5,7 +5,6 @@ use uuid::Uuid; use crate::errors::ValidationError; use crate::models::profiles::types::DbActorProfile; -use crate::models::profiles::validators::validate_username; #[derive(FromSql)] #[postgres(name = "user_account")] @@ -54,7 +53,7 @@ pub struct UserCreateData { pub invite_code: Option, } -fn validate_local_username(username: &str) -> Result<(), ValidationError> { +pub fn validate_local_username(username: &str) -> Result<(), ValidationError> { // The username regexp should not allow domain names and IP addresses let username_regexp = Regex::new(r"^[a-z0-9_]+$").unwrap(); if !username_regexp.is_match(username) { @@ -63,13 +62,14 @@ fn validate_local_username(username: &str) -> Result<(), ValidationError> { Ok(()) } -impl UserCreateData { - /// Validate and clean. - pub fn clean(username: &str) -> Result<(), ValidationError> { - validate_username(username)?; - validate_local_username(username)?; - Ok(()) - } +/// Verifies that wallet address is valid ethereum address +pub fn validate_wallet_address(wallet_address: &str) -> Result<(), ValidationError> { + // Address should be lowercase + let address_regexp = Regex::new(r"^0x[a-f0-9]{40}$").unwrap(); + if !address_regexp.is_match(wallet_address) { + return Err(ValidationError("address is not lowercase")); + }; + Ok(()) } #[cfg(test)] @@ -83,4 +83,14 @@ mod tests { let result_2 = validate_local_username("name&"); assert_eq!(result_2.is_ok(), false); } + + #[test] + fn test_validate_wallet_address() { + let result_1 = validate_wallet_address("0xab5801a7d398351b8be11c439e05c5b3259aec9b"); + assert_eq!(result_1.is_ok(), true); + let result_2 = validate_wallet_address("ab5801a7d398351b8be11c439e05c5b3259aec9b"); + assert_eq!(result_2.is_ok(), false); + let result_3 = validate_wallet_address("0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"); + assert_eq!(result_3.is_ok(), false); + } }