diff --git a/.sqlx/query-4ee84adf4a01a20c49eb53336525708cde3d375c26458caed10dc17b9f899cd6.json b/.sqlx/query-4ee84adf4a01a20c49eb53336525708cde3d375c26458caed10dc17b9f899cd6.json new file mode 100644 index 0000000..3d9abf6 --- /dev/null +++ b/.sqlx/query-4ee84adf4a01a20c49eb53336525708cde3d375c26458caed10dc17b9f899cd6.json @@ -0,0 +1,27 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO discoveries VALUES ($1, $2, $3, $4)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + { + "Custom": { + "name": "discovery_type", + "kind": { + "Enum": [ + "instance", + "repository" + ] + } + } + }, + "Text" + ] + }, + "nullable": [] + }, + "hash": "4ee84adf4a01a20c49eb53336525708cde3d375c26458caed10dc17b9f899cd6" +} diff --git a/Cargo.lock b/Cargo.lock index 93b060a..48b5779 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -629,7 +629,7 @@ dependencies = [ [[package]] name = "giterated-daemon" -version = "0.0.2" +version = "0.0.3" dependencies = [ "aes-gcm", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 76378c2..52e27dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "giterated-daemon" -version = "0.0.2" +version = "0.0.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/backend/discovery.rs b/src/backend/discovery.rs index 03b120c..4c2af40 100644 --- a/src/backend/discovery.rs +++ b/src/backend/discovery.rs @@ -1,18 +1,108 @@ +use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, +}; + use anyhow::Error; +use base64::{engine::general_purpose::STANDARD, Engine as _}; +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use sqlx::PgPool; -use crate::{messages::discovery::DiscoveryMessage, model::repository::Repository}; +use crate::{ + messages::discovery::{DiscoveryMessage, DiscoveryMessageKind}, + model::{discovery::DiscoveryItem, repository::Repository}, +}; use super::DiscoveryBackend; -pub struct GiteratedDiscoveryProtocol {} +pub struct GiteratedDiscoveryProtocol { + pub pool: PgPool, +} + +#[derive(Debug, Hash, Serialize, Deserialize, Clone, sqlx::Type)] +#[sqlx(type_name = "discovery_type", rename_all = "lowercase")] +pub enum DiscoveryType { + Instance, + Repository, +} #[async_trait::async_trait] impl DiscoveryBackend for GiteratedDiscoveryProtocol { - async fn try_handle(&mut self, _request: &DiscoveryMessage) -> Result { - todo!() + async fn try_handle(&mut self, request: &DiscoveryMessage) -> Result { + if request + .message + .validate(&request.message.instance) + .await + .is_err() + { + return Ok(false); + } + + let inner = request.message.inner().await.clone(); + + match inner { + DiscoveryMessageKind::Discoveries(mut discoveries) => { + let discoveries = discoveries.discoveries.drain(..).map(|discovery| { + let hash = { + let mut hasher = DefaultHasher::new(); + discovery.hash(&mut hasher); + STANDARD.encode(hasher.finish().to_be_bytes()) + }; + + let (discovery_type, discovery) = match discovery { + DiscoveryItem::Instance { + instance, + signature, + } => (DiscoveryType::Instance, instance.to_string()), + DiscoveryItem::Repository { + repository, + signature, + } => (DiscoveryType::Repository, repository.to_string()), + }; + + DiscoveriesRow { + discovery_hash: hash, + discovery_time: Utc::now(), + discovery_type, + discovery, + } + }); + + for row in discoveries { + let result = sqlx::query!( + r#"INSERT INTO discoveries VALUES ($1, $2, $3, $4)"#, + row.discovery_hash, + row.discovery_time.to_string(), + row.discovery_type as _, + row.discovery + ) + .execute(&self.pool) + .await; + + match result { + Ok(_) => {}, + Err(err) => { + error!("Error inserting discovery. {:?}", err); + } + } + } + Ok(true) + } + DiscoveryMessageKind::Offer(offer) => Ok(true), + DiscoveryMessageKind::Request(request) => Ok(true), + } } async fn search(&mut self, _search: &str) -> Result, Error> { todo!() } } + +#[derive(Debug, sqlx::FromRow, sqlx::Type)] +pub struct DiscoveriesRow { + discovery_hash: String, + discovery_time: DateTime, + discovery_type: DiscoveryType, + discovery: String, +} \ No newline at end of file diff --git a/src/connection.rs b/src/connection.rs index 7d2f2fa..5f6e8f6 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, net::SocketAddr, str::FromStr, sync::Arc}; use anyhow::Error; use futures_util::{stream::StreamExt, SinkExt}; -use semver::{Version}; +use semver::Version; use serde::Serialize; use tokio::{ net::TcpStream, @@ -16,7 +16,7 @@ use tokio_tungstenite::{tungstenite::Message, WebSocketStream}; use crate::{ authentication::AuthenticationTokenGranter, - backend::{DiscoveryBackend, IssuesBackend, RepositoryBackend, UserBackend}, + backend::{DiscoveryBackend, RepositoryBackend, UserBackend}, handshake::{HandshakeFinalize, HandshakeMessage, HandshakeResponse}, listener::Listeners, messages::{ diff --git a/src/lib.rs b/src/lib.rs index caf9b5d..84268d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ pub fn version() -> Version { } pub fn validate_version(other: &Version) -> bool { - let version_req = VersionReq::from_str("=0.0.1").unwrap(); + let version_req = VersionReq::from_str("=0.0.3").unwrap(); version_req.matches(other) } diff --git a/src/main.rs b/src/main.rs index 00b5719..2b2c2df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,13 +64,15 @@ async fn main() -> Result<(), Error> { })); let user_backend: Arc> = Arc::new(Mutex::new(UserAuth::new( - db_pool, + db_pool.clone(), &Instance::from_str("giterated.dev").unwrap(), token_granter.clone(), ))); let discovery_backend: Arc> = - Arc::new(Mutex::new(GiteratedDiscoveryProtocol {})); + Arc::new(Mutex::new(GiteratedDiscoveryProtocol { + pool: db_pool.clone(), + })); info!("Connected"); diff --git a/src/messages/mod.rs b/src/messages/mod.rs index be40dcb..2e90cc9 100644 --- a/src/messages/mod.rs +++ b/src/messages/mod.rs @@ -40,7 +40,7 @@ pub enum MessageKind { #[derive(Serialize, Deserialize)] pub struct InstanceAuthenticated { message: T, - instance: Instance, + pub instance: Instance, signature: Vec, }