2023-02-11 14:26:08 -05:00
|
|
|
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<String>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AuthzDecision for EventReply {
|
|
|
|
fn permitted(&self) -> bool {
|
|
|
|
self.decision == Decision::Permit as i32
|
|
|
|
}
|
|
|
|
fn message(&self) -> Option<String> {
|
|
|
|
self.message.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A connection to an event admission GRPC server
|
|
|
|
pub struct EventAuthzService {
|
|
|
|
server_addr: String,
|
|
|
|
conn: Option<AuthorizationClient<tonic::transport::Channel>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
// conversion of Nip05Names into GRPC type
|
|
|
|
impl std::convert::From<Nip05Name> 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<String>>) -> Vec<TagEntry> {
|
|
|
|
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<String>,
|
|
|
|
user_agent: Option<String>,
|
|
|
|
nip05: Option<Nip05Name>,
|
2023-02-25 15:49:35 -05:00
|
|
|
auth_pubkey: Option<Vec<u8>>,
|
2023-02-11 14:26:08 -05:00
|
|
|
) -> Result<Box<dyn AuthzDecision>> {
|
|
|
|
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,
|
2023-02-14 22:17:48 -05:00
|
|
|
auth_pubkey,
|
2023-02-11 14:26:08 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|