lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

admission.rs (4070B)


      1 use core::fmt;
      2 
      3 use radroots_event::{
      4     contract::{EventContract, event_contract},
      5     envelope::EventEnvelope,
      6     envelope::kind::KIND_PROFILE,
      7 };
      8 
      9 use crate::profile::inbound::{
     10     RadrootsInboundProfileMetadata, RadrootsProfileMetadataParseError,
     11     parse_inbound_profile_metadata,
     12 };
     13 use crate::verification::{
     14     RadrootsNip01VerificationError, RadrootsSignatureVerifiedEvent, verify_nip01_event,
     15 };
     16 
     17 /// A verified kind-0 event bound to its tolerant metadata projection.
     18 #[derive(Clone, Debug, PartialEq)]
     19 pub struct RadrootsAdmittedProfileEvent {
     20     verified_event: RadrootsSignatureVerifiedEvent,
     21     metadata: RadrootsInboundProfileMetadata,
     22 }
     23 
     24 impl RadrootsAdmittedProfileEvent {
     25     pub fn verified_event(&self) -> &RadrootsSignatureVerifiedEvent {
     26         &self.verified_event
     27     }
     28 
     29     pub fn event(&self) -> &EventEnvelope {
     30         self.verified_event.event()
     31     }
     32 
     33     pub fn metadata(&self) -> &RadrootsInboundProfileMetadata {
     34         &self.metadata
     35     }
     36 
     37     pub fn contract(&self) -> &'static EventContract {
     38         event_contract("radroots.profile.metadata.v1")
     39             .expect("Profile metadata contract is registry-owned")
     40     }
     41 
     42     pub fn into_parts(
     43         self,
     44     ) -> (
     45         RadrootsSignatureVerifiedEvent,
     46         RadrootsInboundProfileMetadata,
     47     ) {
     48         (self.verified_event, self.metadata)
     49     }
     50 }
     51 
     52 #[non_exhaustive]
     53 #[derive(Clone, Debug, PartialEq, Eq)]
     54 pub enum RadrootsProfileAdmissionError {
     55     Nip01Verification(RadrootsNip01VerificationError),
     56     InvalidKind { expected: u32, actual: u32 },
     57     Metadata(RadrootsProfileMetadataParseError),
     58 }
     59 
     60 impl RadrootsProfileAdmissionError {
     61     pub const fn code(&self) -> &'static str {
     62         match self {
     63             Self::Nip01Verification(error) => error.code(),
     64             Self::InvalidKind { .. } => "invalid_kind",
     65             Self::Metadata(error) => error.code(),
     66         }
     67     }
     68 }
     69 
     70 impl fmt::Display for RadrootsProfileAdmissionError {
     71     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
     72         match self {
     73             Self::Nip01Verification(error) => write!(formatter, "{error}"),
     74             Self::InvalidKind { expected, actual } => {
     75                 write!(
     76                     formatter,
     77                     "Profile event kind must be {expected}, got {actual}"
     78                 )
     79             }
     80             Self::Metadata(error) => write!(formatter, "{error}"),
     81         }
     82     }
     83 }
     84 
     85 #[cfg(feature = "std")]
     86 impl std::error::Error for RadrootsProfileAdmissionError {
     87     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
     88         match self {
     89             Self::Nip01Verification(error) => Some(error),
     90             Self::Metadata(error) => Some(error),
     91             Self::InvalidKind { .. } => None,
     92         }
     93     }
     94 }
     95 
     96 impl From<RadrootsNip01VerificationError> for RadrootsProfileAdmissionError {
     97     fn from(value: RadrootsNip01VerificationError) -> Self {
     98         Self::Nip01Verification(value)
     99     }
    100 }
    101 
    102 impl From<RadrootsProfileMetadataParseError> for RadrootsProfileAdmissionError {
    103     fn from(value: RadrootsProfileMetadataParseError) -> Self {
    104         Self::Metadata(value)
    105     }
    106 }
    107 
    108 /// Admits an already verified Profile event and preserves its exact envelope.
    109 pub fn admit_verified_profile_event(
    110     verified_event: RadrootsSignatureVerifiedEvent,
    111 ) -> Result<RadrootsAdmittedProfileEvent, RadrootsProfileAdmissionError> {
    112     let actual = verified_event.event().kind_u32();
    113     if actual != KIND_PROFILE {
    114         return Err(RadrootsProfileAdmissionError::InvalidKind {
    115             expected: KIND_PROFILE,
    116             actual,
    117         });
    118     }
    119     let metadata = parse_inbound_profile_metadata(verified_event.event().content())?;
    120     Ok(RadrootsAdmittedProfileEvent {
    121         verified_event,
    122         metadata,
    123     })
    124 }
    125 
    126 /// Verifies id and signature before parsing and admitting exact kind-0 content.
    127 pub fn verify_and_admit_profile_event(
    128     event: EventEnvelope,
    129 ) -> Result<RadrootsAdmittedProfileEvent, RadrootsProfileAdmissionError> {
    130     admit_verified_profile_event(verify_nip01_event(event)?)
    131 }