From d4f701332f959f746f43af894a504de0e50ba983 Mon Sep 17 00:00:00 2001 From: silverpill Date: Mon, 13 Mar 2023 19:31:31 +0000 Subject: [PATCH] Use numbers to represent identity proof type in database --- ...or_profile__identity_proof_type_number.sql | 18 ++++++ src/activitypub/actors/attachments.rs | 24 +++++--- src/mastodon_api/accounts/views.rs | 6 +- src/models/profiles/queries.rs | 4 +- src/models/profiles/types.rs | 57 ++++++++----------- 5 files changed, 64 insertions(+), 45 deletions(-) create mode 100644 migrations/V0048__actor_profile__identity_proof_type_number.sql diff --git a/migrations/V0048__actor_profile__identity_proof_type_number.sql b/migrations/V0048__actor_profile__identity_proof_type_number.sql new file mode 100644 index 0000000..d79ed6b --- /dev/null +++ b/migrations/V0048__actor_profile__identity_proof_type_number.sql @@ -0,0 +1,18 @@ +UPDATE actor_profile +SET identity_proofs = replaced.identity_proofs +FROM ( + SELECT + actor_profile.id, + jsonb_agg( + CASE + WHEN identity_proof ->> 'proof_type' = 'ethereum-eip191-00' + THEN jsonb_set(identity_proof, '{proof_type}', '1') + WHEN identity_proof ->> 'proof_type' = 'MitraMinisignSignature2022A' + THEN jsonb_set(identity_proof, '{proof_type}', '2') + END + ) AS identity_proofs + FROM actor_profile + CROSS JOIN jsonb_array_elements(actor_profile.identity_proofs) AS identity_proof + GROUP BY actor_profile.id +) AS replaced +WHERE actor_profile.id = replaced.id; diff --git a/src/activitypub/actors/attachments.rs b/src/activitypub/actors/attachments.rs index 2cea244..2994bbb 100644 --- a/src/activitypub/actors/attachments.rs +++ b/src/activitypub/actors/attachments.rs @@ -11,13 +11,14 @@ use crate::identity::{ claims::create_identity_claim, did::Did, minisign::verify_minisign_identity_proof, + signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN}, }; use crate::models::profiles::types::{ ExtraField, IdentityProof, + IdentityProofType, PaymentLink, PaymentOption, - ProofType, }; use crate::web_client::urls::get_subscription_page_url; use super::types::ActorAttachment; @@ -25,12 +26,16 @@ use super::types::ActorAttachment; pub fn attach_identity_proof( proof: IdentityProof, ) -> ActorAttachment { + let proof_type_str = match proof.proof_type { + IdentityProofType::LegacyEip191IdentityProof => PROOF_TYPE_ID_EIP191, + IdentityProofType::LegacyMinisignIdentityProof => PROOF_TYPE_ID_MINISIGN, + }; ActorAttachment { object_type: IDENTITY_PROOF.to_string(), name: proof.issuer.to_string(), value: None, href: None, - signature_algorithm: Some(proof.proof_type.to_string()), + signature_algorithm: Some(proof_type_str.to_string()), signature_value: Some(proof.value), } } @@ -42,10 +47,13 @@ pub fn parse_identity_proof( if attachment.object_type != IDENTITY_PROOF { return Err(ValidationError("invalid attachment type")); }; - let proof_type = attachment.signature_algorithm.as_ref() - .ok_or(ValidationError("missing proof type"))? - .parse() - .map_err(|_| ValidationError("unsupported proof type"))?; + let proof_type_str = attachment.signature_algorithm.as_ref() + .ok_or(ValidationError("missing proof type"))?; + let proof_type = match proof_type_str.as_str() { + PROOF_TYPE_ID_EIP191 => IdentityProofType::LegacyEip191IdentityProof, + PROOF_TYPE_ID_MINISIGN => IdentityProofType::LegacyMinisignIdentityProof, + _ => return Err(ValidationError("unsupported proof type")), + }; let did = attachment.name.parse::() .map_err(|_| ValidationError("invalid DID"))?; let message = create_identity_claim(actor_id, &did) @@ -54,7 +62,7 @@ pub fn parse_identity_proof( .ok_or(ValidationError("missing signature"))?; match did { Did::Key(ref did_key) => { - if !matches!(proof_type, ProofType::LegacyMinisignIdentityProof) { + if !matches!(proof_type, IdentityProofType::LegacyMinisignIdentityProof) { return Err(ValidationError("incorrect proof type")); }; verify_minisign_identity_proof( @@ -64,7 +72,7 @@ pub fn parse_identity_proof( ).map_err(|_| ValidationError("invalid identity proof"))?; }, Did::Pkh(ref did_pkh) => { - if !matches!(proof_type, ProofType::LegacyEip191IdentityProof) { + if !matches!(proof_type, IdentityProofType::LegacyEip191IdentityProof) { return Err(ValidationError("incorrect proof type")); }; verify_eip191_identity_proof( diff --git a/src/mastodon_api/accounts/views.rs b/src/mastodon_api/accounts/views.rs index e20247b..8707a62 100644 --- a/src/mastodon_api/accounts/views.rs +++ b/src/mastodon_api/accounts/views.rs @@ -76,8 +76,8 @@ use crate::models::{ }, profiles::types::{ IdentityProof, + IdentityProofType, ProfileUpdateData, - ProofType, }, relationships::queries::{ get_followers_paginated, @@ -411,7 +411,7 @@ async fn create_identity_proof( &message, &proof_data.signature, ).map_err(|_| ValidationError("invalid signature"))?; - ProofType::LegacyMinisignIdentityProof + IdentityProofType::LegacyMinisignIdentityProof }, Did::Pkh(ref did_pkh) => { if did_pkh.chain_id != ChainId::ethereum_mainnet() { @@ -432,7 +432,7 @@ async fn create_identity_proof( &message, &proof_data.signature, ).map_err(|_| ValidationError("invalid signature"))?; - ProofType::LegacyEip191IdentityProof + IdentityProofType::LegacyEip191IdentityProof }, }; diff --git a/src/models/profiles/queries.rs b/src/models/profiles/queries.rs index c29945b..fc0ceed 100644 --- a/src/models/profiles/queries.rs +++ b/src/models/profiles/queries.rs @@ -819,8 +819,8 @@ mod tests { profiles::types::{ ExtraField, IdentityProof, + IdentityProofType, ProfileCreateData, - ProofType, }, users::queries::create_user, users::types::UserCreateData, @@ -993,7 +993,7 @@ mod tests { let db_client = &mut create_test_database().await; let identity_proof = IdentityProof { issuer: Did::Pkh(DidPkh::from_address(ÐEREUM, "0x1234abcd")), - proof_type: ProofType::LegacyEip191IdentityProof, + proof_type: IdentityProofType::LegacyEip191IdentityProof, value: "13590013185bdea963".to_string(), }; let profile_data = ProfileCreateData { diff --git a/src/models/profiles/types.rs b/src/models/profiles/types.rs index ed2e9fc..1c6813c 100644 --- a/src/models/profiles/types.rs +++ b/src/models/profiles/types.rs @@ -1,6 +1,3 @@ -use std::fmt; -use std::str::FromStr; - use chrono::{DateTime, Duration, Utc}; use postgres_types::FromSql; use serde::{ @@ -21,11 +18,8 @@ use crate::database::{ json_macro::{json_from_sql, json_to_sql}, DatabaseTypeError, }; -use crate::errors::{ConversionError, ValidationError}; -use crate::identity::{ - did::Did, - signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN}, -}; +use crate::errors::ValidationError; +use crate::identity::did::Did; use crate::models::emojis::types::DbEmoji; use crate::webfinger::types::ActorAddress; use super::validators::{ @@ -60,55 +54,54 @@ json_from_sql!(ProfileImage); json_to_sql!(ProfileImage); #[derive(Clone, Debug)] -pub enum ProofType { +pub enum IdentityProofType { LegacyEip191IdentityProof, LegacyMinisignIdentityProof, } -impl FromStr for ProofType { - type Err = ConversionError; +impl From<&IdentityProofType> for i16 { + fn from(proof_type: &IdentityProofType) -> i16 { + match proof_type { + IdentityProofType::LegacyEip191IdentityProof => 1, + IdentityProofType::LegacyMinisignIdentityProof => 2, + } + } +} - fn from_str(value: &str) -> Result { +impl TryFrom for IdentityProofType { + type Error = DatabaseTypeError; + + fn try_from(value: i16) -> Result { let proof_type = match value { - PROOF_TYPE_ID_EIP191 => Self::LegacyEip191IdentityProof, - PROOF_TYPE_ID_MINISIGN => Self::LegacyMinisignIdentityProof, - _ => return Err(ConversionError), + 1 => Self::LegacyEip191IdentityProof, + 2 => Self::LegacyMinisignIdentityProof, + _ => return Err(DatabaseTypeError), }; Ok(proof_type) } } -impl fmt::Display for ProofType { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - let proof_type_str = match self { - Self::LegacyEip191IdentityProof => PROOF_TYPE_ID_EIP191, - Self::LegacyMinisignIdentityProof => PROOF_TYPE_ID_MINISIGN, - }; - write!(formatter, "{}", proof_type_str) - } -} - -impl<'de> Deserialize<'de> for ProofType { +impl<'de> Deserialize<'de> for IdentityProofType { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - String::deserialize(deserializer)? - .parse().map_err(DeserializerError::custom) + i16::deserialize(deserializer)? + .try_into().map_err(DeserializerError::custom) } } -impl Serialize for ProofType { +impl Serialize for IdentityProofType { fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_str(&self.to_string()) + serializer.serialize_i16(self.into()) } } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IdentityProof { pub issuer: Did, - pub proof_type: ProofType, + pub proof_type: IdentityProofType, pub value: String, } @@ -551,7 +544,7 @@ mod tests { #[test] fn test_identity_proof_serialization() { - let json_data = r#"{"issuer":"did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a","proof_type":"ethereum-eip191-00","value":"dbfe"}"#; + let json_data = r#"{"issuer":"did:pkh:eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a","proof_type":1,"value":"dbfe"}"#; let proof: IdentityProof = serde_json::from_str(json_data).unwrap(); let did_pkh = match proof.issuer { Did::Pkh(ref did_pkh) => did_pkh,