Include results based on identity proofs when searching profiles by wallet address

This commit is contained in:
silverpill 2022-04-27 11:05:46 +00:00
parent a1af35997c
commit 303827ffc6
4 changed files with 60 additions and 14 deletions

View file

@ -7,6 +7,7 @@ use serde::{
};
use crate::errors::ValidationError;
use crate::models::profiles::currencies::Currency;
use super::signatures::recover_address;
use super::utils::address_to_string;
@ -22,14 +23,10 @@ pub struct DidPkh {
}
impl DidPkh {
pub fn from_ethereum_address(address: &str) -> Self {
// Ethereum mainnet
// https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-3.md
Self {
network_id: "eip155".to_string(),
chain_id: "1".to_string(),
address: address.to_lowercase(),
}
pub fn from_address(currency: &Currency, address: &str) -> Self {
let (network_id, chain_id) = currency.caip2();
let address = currency.normalize_address(address);
Self { network_id, chain_id, address }
}
}
@ -133,10 +130,12 @@ mod tests {
use crate::ethereum::utils::address_to_string;
use super::*;
const ETHEREUM: Currency = Currency::Ethereum;
#[test]
fn test_did_string_conversion() {
let address = "0xB9C5714089478a327F09197987f16f9E5d936E8a";
let did = DidPkh::from_ethereum_address(address);
let did = DidPkh::from_address(&ETHEREUM, address);
assert_eq!(did.address, address.to_lowercase());
let did_str = did.to_string();
@ -156,7 +155,7 @@ mod tests {
let secret_key_ref = SecretKeyRef::new(&secret_key);
let secret_key_str = secret_key.display_secret().to_string();
let address = address_to_string(secret_key_ref.address());
let did = DidPkh::from_ethereum_address(&address);
let did = DidPkh::from_address(&ETHEREUM, &address);
let message = create_identity_claim(actor_id, &did).unwrap();
let signature = sign_message(&secret_key_str, message.as_bytes()).unwrap().to_string();
let result = verify_identity_proof(actor_id, &did, &signature);

View file

@ -227,7 +227,7 @@ async fn get_identity_claim(
let actor_id = current_user.profile.actor_id(&config.instance_url());
let wallet_address = current_user.wallet_address.as_ref()
.ok_or(HttpError::PermissionError)?;
let did = DidPkh::from_ethereum_address(wallet_address);
let did = DidPkh::from_address(&config.default_currency(), wallet_address);
let claim = create_identity_claim(&actor_id, &did)
.map_err(|_| HttpError::InternalError)?;
let response = IdentityClaim { claim };
@ -246,7 +246,7 @@ async fn create_identity_proof(
let actor_id = current_user.profile.actor_id(&config.instance_url());
let wallet_address = current_user.wallet_address.as_ref()
.ok_or(HttpError::PermissionError)?;
let did = DidPkh::from_ethereum_address(wallet_address);
let did = DidPkh::from_address(&config.default_currency(), wallet_address);
verify_identity_proof(
&actor_id,
&did,

View file

@ -10,6 +10,21 @@ impl Currency {
Self::Ethereum => "ETH",
}.to_string()
}
/// Network ID and chain ID according to CAIP-2 standard
/// https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md
pub fn caip2(&self) -> (String, String) {
let (network_id, chain_id) = match self {
Self::Ethereum => ("eip155", "1"),
};
(network_id.to_string(), chain_id.to_string())
}
pub fn normalize_address(&self, address: &str) -> String {
match self {
Self::Ethereum => address.to_lowercase(),
}
}
}
pub fn get_currency_field_name(currency: &Currency) -> String {

View file

@ -3,6 +3,7 @@ use uuid::Uuid;
use crate::database::catch_unique_violation;
use crate::errors::DatabaseError;
use crate::ethereum::identity::DidPkh;
use crate::models::cleanup::{
find_orphaned_files,
find_orphaned_ipfs_objects,
@ -374,6 +375,7 @@ pub async fn search_profile_by_wallet_address(
wallet_address: &str,
) -> Result<Vec<DbActorProfile>, DatabaseError> {
let field_name = get_currency_field_name(currency);
let did_str = DidPkh::from_address(currency, wallet_address).to_string();
// If currency is Ethereum,
// search over extra fields must be case insensitive
let rows = db_client.query(
@ -382,6 +384,11 @@ pub async fn search_profile_by_wallet_address(
FROM actor_profile LEFT JOIN user_account USING (id)
WHERE
user_account.wallet_address = $2
OR EXISTS (
SELECT 1
FROM jsonb_array_elements(actor_profile.identity_proofs) AS proof
WHERE proof ->> 'issuer' = $3
)
OR EXISTS (
SELECT 1
FROM jsonb_array_elements(actor_profile.extra_fields) AS field
@ -390,7 +397,7 @@ pub async fn search_profile_by_wallet_address(
AND field ->> 'value' ILIKE $2
)
",
&[&field_name, &wallet_address],
&[&field_name, &wallet_address, &did_str],
).await?;
let profiles: Vec<DbActorProfile> = rows.iter()
.map(|row| row.try_get("actor_profile"))
@ -481,7 +488,11 @@ mod tests {
use crate::activitypub::actor::Actor;
use crate::database::test_utils::create_test_database;
use crate::models::profiles::queries::create_profile;
use crate::models::profiles::types::{ExtraField, ProfileCreateData};
use crate::models::profiles::types::{
ExtraField,
IdentityProof,
ProfileCreateData,
};
use crate::models::users::queries::create_user;
use crate::models::users::types::UserCreateData;
use super::*;
@ -575,4 +586,25 @@ mod tests {
assert_eq!(profiles.len(), 1);
assert_eq!(profiles[0].id, profile.id);
}
#[tokio::test]
#[serial]
async fn test_search_profile_by_wallet_address_identity_proof() {
let db_client = &mut create_test_database().await;
let identity_proof = IdentityProof {
issuer: DidPkh::from_address(&ETHEREUM, "0x1234abcd"),
proof_type: "ethereum".to_string(),
value: "13590013185bdea963".to_string(),
};
let profile_data = ProfileCreateData {
identity_proofs: vec![identity_proof],
..Default::default()
};
let profile = create_profile(db_client, profile_data).await.unwrap();
let profiles = search_profile_by_wallet_address(
db_client, &ETHEREUM, "0x1234abcd").await.unwrap();
assert_eq!(profiles.len(), 1);
assert_eq!(profiles[0].id, profile.id);
}
}