2021-04-09 00:22:17 +00:00
|
|
|
use chrono::{DateTime, Utc};
|
|
|
|
use postgres_types::FromSql;
|
|
|
|
use regex::Regex;
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
use crate::errors::ValidationError;
|
2022-11-08 21:59:45 +00:00
|
|
|
use crate::identity::did::Did;
|
2021-04-09 00:22:17 +00:00
|
|
|
use crate::models::profiles::types::DbActorProfile;
|
2022-08-15 19:25:31 +00:00
|
|
|
use crate::utils::currencies::Currency;
|
2021-04-09 00:22:17 +00:00
|
|
|
|
2022-05-26 10:04:52 +00:00
|
|
|
#[allow(dead_code)]
|
2021-04-09 00:22:17 +00:00
|
|
|
#[derive(FromSql)]
|
|
|
|
#[postgres(name = "user_account")]
|
|
|
|
pub struct DbUser {
|
2022-05-26 10:04:52 +00:00
|
|
|
id: Uuid,
|
|
|
|
wallet_address: Option<String>,
|
|
|
|
password_hash: Option<String>,
|
|
|
|
private_key: String,
|
|
|
|
invite_code: Option<String>,
|
|
|
|
created_at: DateTime<Utc>,
|
2021-04-09 00:22:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Represents local user
|
|
|
|
#[derive(Clone)]
|
2021-11-20 01:10:56 +00:00
|
|
|
#[cfg_attr(test, derive(Default))]
|
2021-04-09 00:22:17 +00:00
|
|
|
pub struct User {
|
|
|
|
pub id: Uuid,
|
2022-08-15 19:25:31 +00:00
|
|
|
pub wallet_address: Option<String>, // login address
|
2022-02-15 19:26:06 +00:00
|
|
|
pub password_hash: Option<String>,
|
2021-04-09 00:22:17 +00:00
|
|
|
pub private_key: String,
|
|
|
|
pub profile: DbActorProfile,
|
|
|
|
}
|
|
|
|
|
2021-11-12 22:05:31 +00:00
|
|
|
impl User {
|
|
|
|
pub fn new(
|
|
|
|
db_user: DbUser,
|
|
|
|
db_profile: DbActorProfile,
|
|
|
|
) -> Self {
|
|
|
|
assert_eq!(db_user.id, db_profile.id);
|
|
|
|
Self {
|
|
|
|
id: db_user.id,
|
|
|
|
wallet_address: db_user.wallet_address,
|
|
|
|
password_hash: db_user.password_hash,
|
|
|
|
private_key: db_user.private_key,
|
|
|
|
profile: db_profile,
|
|
|
|
}
|
|
|
|
}
|
2022-05-26 10:04:52 +00:00
|
|
|
|
2022-08-15 19:25:31 +00:00
|
|
|
/// Returns wallet address if it is verified
|
|
|
|
pub fn public_wallet_address(&self, currency: &Currency) -> Option<String> {
|
|
|
|
for proof in self.profile.identity_proofs.clone().into_inner() {
|
2022-11-09 01:51:44 +00:00
|
|
|
let did_pkh = match proof.issuer {
|
|
|
|
Did::Pkh(did_pkh) => did_pkh,
|
|
|
|
_ => continue,
|
|
|
|
};
|
2022-08-15 20:11:58 +00:00
|
|
|
// Return the first matching address, because only
|
|
|
|
// one proof per currency is allowed.
|
2022-11-08 21:59:45 +00:00
|
|
|
if let Some(ref address_currency) = did_pkh.currency() {
|
2022-08-15 19:25:31 +00:00
|
|
|
if address_currency == currency {
|
2022-11-08 21:59:45 +00:00
|
|
|
return Some(did_pkh.address);
|
2022-08-15 19:25:31 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
None
|
2022-05-26 10:04:52 +00:00
|
|
|
}
|
2021-11-12 22:05:31 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 11:20:48 +00:00
|
|
|
#[cfg_attr(test, derive(Default))]
|
2021-10-05 20:57:24 +00:00
|
|
|
pub struct UserCreateData {
|
2021-04-09 00:22:17 +00:00
|
|
|
pub username: String,
|
2022-02-15 19:26:06 +00:00
|
|
|
pub password_hash: Option<String>,
|
2022-01-06 19:06:35 +00:00
|
|
|
pub private_key_pem: String,
|
2021-12-24 17:46:01 +00:00
|
|
|
pub wallet_address: Option<String>,
|
2021-04-09 00:22:17 +00:00
|
|
|
pub invite_code: Option<String>,
|
|
|
|
}
|
|
|
|
|
2022-01-31 19:10:51 +00:00
|
|
|
pub fn validate_local_username(username: &str) -> Result<(), ValidationError> {
|
2021-11-21 14:38:27 +00:00
|
|
|
// The username regexp should not allow domain names and IP addresses
|
2021-04-09 00:22:17 +00:00
|
|
|
let username_regexp = Regex::new(r"^[a-z0-9_]+$").unwrap();
|
|
|
|
if !username_regexp.is_match(username) {
|
|
|
|
return Err(ValidationError("invalid username"));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
2022-05-26 10:04:52 +00:00
|
|
|
#[test]
|
2022-08-15 19:25:31 +00:00
|
|
|
fn test_public_wallet_address_login_address_not_exposed() {
|
2022-05-26 10:04:52 +00:00
|
|
|
let user = User {
|
|
|
|
wallet_address: Some("0x1234".to_string()),
|
|
|
|
..Default::default()
|
|
|
|
};
|
2022-08-15 19:25:31 +00:00
|
|
|
let ethereum = Currency::Ethereum;
|
|
|
|
assert_eq!(user.public_wallet_address(ðereum), None);
|
2022-05-26 10:04:52 +00:00
|
|
|
}
|
|
|
|
|
2021-04-09 00:22:17 +00:00
|
|
|
#[test]
|
2021-12-27 19:20:21 +00:00
|
|
|
fn test_validate_local_username() {
|
|
|
|
let result_1 = validate_local_username("name_1");
|
2021-04-09 00:22:17 +00:00
|
|
|
assert_eq!(result_1.is_ok(), true);
|
2021-12-27 19:20:21 +00:00
|
|
|
let result_2 = validate_local_username("name&");
|
2021-04-09 00:22:17 +00:00
|
|
|
assert_eq!(result_2.is_ok(), false);
|
|
|
|
}
|
|
|
|
}
|