diff --git a/src/activitypub/actors/attachments.rs b/src/activitypub/actors/attachments.rs index 4cac006..9bbcb14 100644 --- a/src/activitypub/actors/attachments.rs +++ b/src/activitypub/actors/attachments.rs @@ -12,13 +12,13 @@ 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, PaymentLink, PaymentOption, + ProofType, }; use super::types::ActorAttachment; @@ -30,7 +30,7 @@ pub fn attach_identity_proof( name: proof.issuer.to_string(), value: None, href: None, - signature_algorithm: Some(proof.proof_type), + signature_algorithm: Some(proof.proof_type.to_string()), signature_value: Some(proof.value), } } @@ -43,17 +43,19 @@ pub fn parse_identity_proof( return Err(ValidationError("invalid attachment type")); }; let proof_type = attachment.signature_algorithm.as_ref() - .ok_or(ValidationError("missing proof type"))?; + .ok_or(ValidationError("missing proof type"))? + .parse() + .map_err(|_| ValidationError("unsupported proof type"))?; let did = attachment.name.parse::() - .map_err(|_| ValidationError("invalid did"))?; + .map_err(|_| ValidationError("invalid DID"))?; let message = create_identity_claim(actor_id, &did) .map_err(|_| ValidationError("invalid claim"))?; let signature = attachment.signature_value.as_ref() .ok_or(ValidationError("missing signature"))?; match did { Did::Key(ref did_key) => { - if proof_type != PROOF_TYPE_ID_MINISIGN { - return Err(ValidationError("unknown proof type")); + if !matches!(proof_type, ProofType::LegacyMinisignIdentityProof) { + return Err(ValidationError("incorrect proof type")); }; verify_minisign_identity_proof( did_key, @@ -62,8 +64,8 @@ pub fn parse_identity_proof( ).map_err(|_| ValidationError("invalid identity proof"))?; }, Did::Pkh(ref did_pkh) => { - if proof_type != PROOF_TYPE_ID_EIP191 { - return Err(ValidationError("unknown proof type")); + if !matches!(proof_type, ProofType::LegacyEip191IdentityProof) { + return Err(ValidationError("incorrect proof type")); }; verify_eip191_identity_proof( did_pkh, @@ -74,7 +76,7 @@ pub fn parse_identity_proof( }; let proof = IdentityProof { issuer: did, - proof_type: proof_type.to_string(), + proof_type: proof_type, value: signature.to_string(), }; Ok(proof) diff --git a/src/mastodon_api/accounts/views.rs b/src/mastodon_api/accounts/views.rs index c7ab08e..58331ac 100644 --- a/src/mastodon_api/accounts/views.rs +++ b/src/mastodon_api/accounts/views.rs @@ -30,7 +30,6 @@ use crate::identity::{ parse_minisign_signature, verify_minisign_identity_proof, }, - signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN}, }; use crate::json_signatures::{ create::{add_integrity_proof, IntegrityProof}, @@ -53,6 +52,7 @@ use crate::models::profiles::queries::{ use crate::models::profiles::types::{ IdentityProof, ProfileUpdateData, + ProofType, }; use crate::models::relationships::queries::{ create_follow_request, @@ -389,7 +389,7 @@ async fn create_identity_proof( &message, &proof_data.signature, ).map_err(|_| ValidationError("invalid signature"))?; - PROOF_TYPE_ID_MINISIGN + ProofType::LegacyMinisignIdentityProof }, Did::Pkh(ref did_pkh) => { if did_pkh.chain_id != ChainId::ethereum_mainnet() { @@ -410,13 +410,13 @@ async fn create_identity_proof( &message, &proof_data.signature, ).map_err(|_| ValidationError("invalid signature"))?; - PROOF_TYPE_ID_EIP191 + ProofType::LegacyEip191IdentityProof }, }; let proof = IdentityProof { issuer: did, - proof_type: proof_type.to_string(), + proof_type: proof_type, value: proof_data.signature.clone(), }; let mut profile_data = ProfileUpdateData::from(¤t_user.profile); diff --git a/src/models/profiles/queries.rs b/src/models/profiles/queries.rs index 02d405d..43dd07f 100644 --- a/src/models/profiles/queries.rs +++ b/src/models/profiles/queries.rs @@ -647,6 +647,7 @@ mod tests { ExtraField, IdentityProof, ProfileCreateData, + ProofType, }; use crate::models::users::queries::create_user; use crate::models::users::types::UserCreateData; @@ -794,7 +795,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: "ethereum".to_string(), + proof_type: ProofType::LegacyEip191IdentityProof, value: "13590013185bdea963".to_string(), }; let profile_data = ProfileCreateData { diff --git a/src/models/profiles/types.rs b/src/models/profiles/types.rs index 6617694..9a36652 100644 --- a/src/models/profiles/types.rs +++ b/src/models/profiles/types.rs @@ -1,4 +1,6 @@ use std::convert::TryFrom; +use std::fmt; +use std::str::FromStr; use chrono::{DateTime, Duration, Utc}; use postgres_types::FromSql; @@ -14,7 +16,10 @@ use crate::activitypub::actors::types::{Actor, ActorAddress}; use crate::activitypub::identifiers::local_actor_id; use crate::database::json_macro::{json_from_sql, json_to_sql}; use crate::errors::{ConversionError, ValidationError}; -use crate::identity::did::Did; +use crate::identity::{ + did::Did, + signatures::{PROOF_TYPE_ID_EIP191, PROOF_TYPE_ID_MINISIGN}, +}; use crate::utils::caip2::ChainId; use super::validators::{ validate_username, @@ -23,10 +28,56 @@ use super::validators::{ clean_extra_fields, }; +#[derive(Clone, Debug)] +pub enum ProofType { + LegacyEip191IdentityProof, + LegacyMinisignIdentityProof, +} + +impl FromStr for ProofType { + type Err = ConversionError; + + fn from_str(value: &str) -> Result { + let proof_type = match value { + PROOF_TYPE_ID_EIP191 => Self::LegacyEip191IdentityProof, + PROOF_TYPE_ID_MINISIGN => Self::LegacyMinisignIdentityProof, + _ => return Err(ConversionError), + }; + 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 { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + String::deserialize(deserializer)? + .parse().map_err(DeserializerError::custom) + } +} + +impl Serialize for ProofType { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_str(&self.to_string()) + } +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IdentityProof { pub issuer: Did, - pub proof_type: String, + pub proof_type: ProofType, pub value: String, }