more work on identity->chat hello/handshake

This commit is contained in:
sam 2024-01-18 21:44:53 +01:00
parent 1e53661b0a
commit 041531e88a
12 changed files with 96 additions and 40 deletions

21
chat/src/http/hello.rs Normal file
View file

@ -0,0 +1,21 @@
use std::sync::Arc;
use axum::{Extension, Json};
use foxchat::{
http::ApiError,
s2s::http::{HelloRequest, HelloResponse, NodeResponse}, fed,
};
use crate::{app_state::AppState, model::instance::Instance};
pub async fn post_hello(
Extension(state): Extension<Arc<AppState>>,
Json(data): Json<HelloRequest>,
) -> Result<Json<HelloResponse>, ApiError> {
let instance = Instance::get(&state.pool).await?;
let node = fed::get::<NodeResponse>(&instance.private_key, &state.config.domain, &data.host, "/_fox/ident/node", None).await?;
// TODO: validate identity server's signature, probably adapt FoxRequestData.from_request_parts() (or extract it into a separate function? not sure if that's possible though)
todo!()
}

18
chat/src/http/mod.rs Normal file
View file

@ -0,0 +1,18 @@
mod hello;
use crate::{app_state::AppState, config::Config};
use axum::{routing::post, Extension, Router};
use sqlx::{Pool, Postgres};
use std::sync::Arc;
use tower_http::trace::TraceLayer;
pub fn new(pool: Pool<Postgres>, config: Config) -> Router {
let app_state = Arc::new(AppState { pool, config });
let app = Router::new()
.route("/_fox/chat/hello", post(hello::post_hello))
.layer(TraceLayer::new_for_http())
.layer(Extension(app_state));
return app;
}

View file

@ -1,12 +1,15 @@
mod app_state;
mod config; mod config;
mod db; mod db;
mod fed; mod fed;
mod app_state; mod http;
mod model; mod model;
use crate::config::Config; use crate::config::Config;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use eyre::Result; use eyre::Result;
use std::net::{Ipv4Addr, SocketAddrV4};
use tokio::net::TcpListener;
use tracing::info; use tracing::info;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
@ -61,5 +64,12 @@ async fn main_web(config: Config) -> Result<()> {
db::init_instance(&pool).await?; db::init_instance(&pool).await?;
info!("Initialized instance data!"); info!("Initialized instance data!");
let port = config.port;
let app = http::new(pool, config);
let listener = TcpListener::bind(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)).await?;
axum::serve(listener, app).await?;
Ok(()) Ok(())
} }

View file

@ -27,15 +27,15 @@ pub fn is_valid_domain(domain: &str) -> bool {
pub async fn get<R: DeserializeOwned>( pub async fn get<R: DeserializeOwned>(
private_key: &RsaPrivateKey, private_key: &RsaPrivateKey,
self_domain: String, self_domain: &str,
host: String, host: &str,
path: String, path: &str,
user_id: Option<&str>, user_id: Option<&str>,
) -> Result<R> { ) -> Result<R> {
let (signature, date) = build_signature( let (signature, date) = build_signature(
private_key, private_key,
host.clone(), host,
path.clone(), path,
None, None,
user_id.clone(), user_id.clone(),
); );
@ -58,9 +58,9 @@ pub async fn get<R: DeserializeOwned>(
pub async fn post<T: Serialize, R: DeserializeOwned>( pub async fn post<T: Serialize, R: DeserializeOwned>(
private_key: &RsaPrivateKey, private_key: &RsaPrivateKey,
self_domain: String, self_domain: &str,
host: String, host: &str,
path: String, path: &str,
user_id: Option<&str>, user_id: Option<&str>,
body: &T, body: &T,
) -> Result<R> { ) -> Result<R> {
@ -68,8 +68,8 @@ pub async fn post<T: Serialize, R: DeserializeOwned>(
let (signature, date) = build_signature( let (signature, date) = build_signature(
private_key, private_key,
host.clone(), host,
path.clone(), path,
Some(body.len()), Some(body.len()),
user_id.clone(), user_id.clone(),
); );

View file

@ -10,8 +10,8 @@ use crate::FoxError;
pub fn build_signature( pub fn build_signature(
private_key: &RsaPrivateKey, private_key: &RsaPrivateKey,
host: String, host: &str,
request_path: String, request_path: &str,
content_length: Option<usize>, content_length: Option<usize>,
user_id: Option<&str>, user_id: Option<&str>,
) -> (String, DateTime<Utc>) { ) -> (String, DateTime<Utc>) {

View file

@ -0,0 +1,18 @@
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct HelloRequest {
pub host: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct HelloResponse {
pub public_key: String,
pub host: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeResponse {
pub software: String,
pub public_key: String,
}

View file

@ -0,0 +1,3 @@
mod hello;
pub use hello::{HelloRequest, HelloResponse, NodeResponse};

View file

@ -1,3 +1,4 @@
mod event; mod event;
pub mod http;
pub use event::{DispatchEvent, Payload}; pub use event::{DispatchEvent, Payload};

View file

@ -1,5 +1,5 @@
mod node;
mod account; mod account;
mod node;
use std::sync::Arc; use std::sync::Arc;

View file

@ -2,9 +2,8 @@ use std::sync::Arc;
use axum::{Extension, Json, extract::Path}; use axum::{Extension, Json, extract::Path};
use eyre::{Context, Result}; use eyre::{Context, Result};
use foxchat::http::ApiError; use foxchat::{http::ApiError, s2s::http::NodeResponse};
use rsa::pkcs1::EncodeRsaPublicKey; use rsa::pkcs1::EncodeRsaPublicKey;
use serde::Serialize;
use crate::{app_state::AppState, model::{instance::Instance, chat_instance::ChatInstance}}; use crate::{app_state::AppState, model::{instance::Instance, chat_instance::ChatInstance}};
@ -19,19 +18,13 @@ pub async fn get_node(
.wrap_err("serializing public key")?; .wrap_err("serializing public key")?;
Ok(Json(NodeResponse { Ok(Json(NodeResponse {
software: NODE_SOFTWARE, software: NODE_SOFTWARE.into(),
public_key, public_key,
})) }))
} }
const NODE_SOFTWARE: &str = "foxchat_ident"; const NODE_SOFTWARE: &str = "foxchat_ident";
#[derive(Serialize)]
pub struct NodeResponse {
pub software: &'static str,
pub public_key: String,
}
pub async fn get_chat_node( pub async fn get_chat_node(
Extension(state): Extension<Arc<AppState>>, Extension(state): Extension<Arc<AppState>>,
Path(domain): Path<String>, Path(domain): Path<String>,

View file

@ -4,11 +4,10 @@ mod db;
mod http; mod http;
mod model; mod model;
use std::net::{Ipv4Addr, SocketAddrV4};
use crate::config::Config; use crate::config::Config;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use std::net::{Ipv4Addr, SocketAddrV4};
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tracing::info; use tracing::info;

View file

@ -1,7 +1,11 @@
use std::sync::Arc; use std::sync::Arc;
use eyre::Result; use eyre::Result;
use foxchat::{fed::{self, request::is_valid_domain}, FoxError}; use foxchat::{
fed::{self, request::is_valid_domain},
s2s::http::{HelloRequest, HelloResponse},
FoxError,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ulid::Ulid; use ulid::Ulid;
@ -47,9 +51,9 @@ impl ChatInstance {
let resp: HelloResponse = fed::post( let resp: HelloResponse = fed::post(
&current_instance.private_key, &current_instance.private_key,
state.config.domain.clone(), &state.config.domain,
domain.clone(), &domain,
"/_fox/chat/hello".into(), "/_fox/chat/hello",
None, None,
&HelloRequest { &HelloRequest {
host: state.config.domain.clone(), host: state.config.domain.clone(),
@ -78,14 +82,3 @@ impl ChatInstance {
Ok(instance) Ok(instance)
} }
} }
#[derive(Serialize, Debug)]
struct HelloRequest {
pub host: String,
}
#[derive(Deserialize, Debug)]
struct HelloResponse {
pub public_key: String,
pub host: String,
}