use crate::error::{Error, Result}; use crate::{event::Event, nip05::Nip05Name}; use nauthz_grpc::authorization_client::AuthorizationClient; use nauthz_grpc::event::TagEntry; use nauthz_grpc::{Decision, Event as GrpcEvent, EventReply, EventRequest}; use tracing::{info, warn}; pub mod nauthz_grpc { tonic::include_proto!("nauthz"); } // A decision for the DB to act upon pub trait AuthzDecision: Send + Sync { fn permitted(&self) -> bool; fn message(&self) -> Option; } impl AuthzDecision for EventReply { fn permitted(&self) -> bool { self.decision == Decision::Permit as i32 } fn message(&self) -> Option { self.message.clone() } } // A connection to an event admission GRPC server pub struct EventAuthzService { server_addr: String, conn: Option>, } // conversion of Nip05Names into GRPC type impl std::convert::From for nauthz_grpc::event_request::Nip05Name { fn from(value: Nip05Name) -> Self { nauthz_grpc::event_request::Nip05Name { local: value.local.clone(), domain: value.domain.clone(), } } } // conversion of event tags into gprc struct fn tags_to_protobuf(tags: &Vec>) -> Vec { tags.iter() .map(|x| TagEntry { values: x.clone() }) .collect() } impl EventAuthzService { pub async fn connect(server_addr: &str) -> EventAuthzService { let mut eas = EventAuthzService { server_addr: server_addr.to_string(), conn: None, }; eas.ready_connection().await; eas } pub async fn ready_connection(self: &mut Self) { if self.conn.is_none() { let client = AuthorizationClient::connect(self.server_addr.to_string()).await; if let Err(ref msg) = client { warn!("could not connect to nostr authz GRPC server: {:?}", msg); } else { info!("connected to nostr authorization GRPC server"); } self.conn = client.ok(); } } pub async fn admit_event( self: &mut Self, event: &Event, ip: &str, origin: Option, user_agent: Option, nip05: Option, auth_pubkey: Option> ) -> Result> { self.ready_connection().await; let id_blob = hex::decode(&event.id)?; let pubkey_blob = hex::decode(&event.pubkey)?; let sig_blob = hex::decode(&event.sig)?; if let Some(ref mut c) = self.conn { let gevent = GrpcEvent { id: id_blob, pubkey: pubkey_blob, sig: sig_blob, created_at: event.created_at, kind: event.kind, content: event.content.clone(), tags: tags_to_protobuf(&event.tags), }; let svr_res = c .event_admit(EventRequest { event: Some(gevent), ip_addr: Some(ip.to_string()), origin, user_agent, auth_pubkey, nip05: nip05.map(|x| nauthz_grpc::event_request::Nip05Name::from(x)), }) .await?; let reply = svr_res.into_inner(); return Ok(Box::new(reply)); } else { return Err(Error::AuthzError); } } }