diff --git a/src/backend/discovery.rs b/src/backend/discovery.rs index 4c2af40..5d81dfb 100644 --- a/src/backend/discovery.rs +++ b/src/backend/discovery.rs @@ -81,7 +81,7 @@ impl DiscoveryBackend for GiteratedDiscoveryProtocol { .await; match result { - Ok(_) => {}, + Ok(_) => {} Err(err) => { error!("Error inserting discovery. {:?}", err); } @@ -105,4 +105,4 @@ pub struct DiscoveriesRow { discovery_time: DateTime, discovery_type: DiscoveryType, discovery: String, -} \ No newline at end of file +} diff --git a/src/backend/git.rs b/src/backend/git.rs index 901afcb..ba435da 100644 --- a/src/backend/git.rs +++ b/src/backend/git.rs @@ -1,14 +1,16 @@ use anyhow::Error; use async_trait::async_trait; +use futures_util::StreamExt; use git2::ObjectType; -use sqlx::PgPool; +use sqlx::{Either, PgPool}; use std::path::{Path, PathBuf}; use thiserror::Error; use crate::messages::ValidatedUserAuthenticated; +use crate::model::instance::Instance; use crate::model::repository::{ - Commit, RepositoryObjectType, RepositoryTreeEntry, RepositoryVisibility, + Commit, Repository, RepositoryObjectType, RepositoryTreeEntry, RepositoryVisibility, }; use crate::model::user::User; use crate::{ @@ -29,6 +31,7 @@ use super::{IssuesBackend, RepositoryBackend}; /// Repository in the database #[derive(Debug, sqlx::FromRow)] pub struct GitRepository { + #[sqlx(try_from = "String")] pub owner_user: User, pub name: String, pub description: Option, @@ -94,13 +97,19 @@ pub enum GitBackendError { pub struct GitBackend { pub pg_pool: PgPool, pub repository_folder: String, + pub instance: Instance, } impl GitBackend { - pub fn new(pg_pool: &PgPool, repository_folder: &str) -> Self { + pub fn new( + pg_pool: &PgPool, + repository_folder: &str, + instance: impl ToOwned, + ) -> Self { Self { pg_pool: pg_pool.clone(), repository_folder: repository_folder.to_string(), + instance: instance.to_owned(), } } @@ -442,6 +451,27 @@ impl RepositoryBackend for GitBackend { ) -> Result { todo!() } + + async fn repositories_for_user(&mut self, user: &User) -> Result, Error> { + let mut repositories = sqlx::query_as!( + GitRepository, + r#"SELECT visibility as "visibility: _", owner_user, name, description, default_branch FROM repositories WHERE owner_user = $1"#, + user.to_string() + ) + .fetch_many(&self.pg_pool); + + let mut result = vec![]; + + while let Some(Ok(Either::Right(repository))) = repositories.next().await { + result.push(Repository { + owner: repository.owner_user, + name: repository.name, + instance: self.instance.clone(), + }); + } + + Ok(result) + } } impl IssuesBackend for GitBackend { diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 40ed8c4..cdf7676 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -25,7 +25,10 @@ use crate::{ }, ValidatedUserAuthenticated, }, - model::repository::{Repository, RepositoryView}, + model::{ + repository::{Repository, RepositoryView}, + user::User, + }, }; #[async_trait] @@ -42,6 +45,7 @@ pub trait RepositoryBackend: IssuesBackend { &mut self, request: &ValidatedUserAuthenticated, ) -> Result; + async fn repositories_for_user(&mut self, user: &User) -> Result, Error>; } pub trait IssuesBackend { diff --git a/src/connection.rs b/src/connection.rs index 5f6e8f6..28ead95 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -27,6 +27,10 @@ use crate::{ repository::{ RepositoryMessage, RepositoryMessageKind, RepositoryRequest, RepositoryResponse, }, + user::{ + UserMessage, UserMessageKind, UserMessageRequest, UserMessageResponse, + UserRepositoriesResponse, + }, MessageKind, }, model::{ @@ -453,6 +457,126 @@ pub async fn connection_worker( continue; } + + if let MessageKind::User(message) = &message { + match &message.message { + UserMessageKind::Request(request) => match request { + UserMessageRequest::DisplayName(request) => { + let mut user_backend = user_backend.lock().await; + + let response = user_backend.display_name(request.clone()).await; + + let response = match response { + Ok(response) => response, + Err(err) => { + error!("Error handling request: {:?}", err); + continue; + } + }; + drop(user_backend); + + let _result = send( + &mut socket, + MessageKind::User(UserMessage { + instance: message.instance.clone(), + message: UserMessageKind::Response( + UserMessageResponse::DisplayName(response), + ), + }), + ) + .await; + + continue; + } + UserMessageRequest::DisplayImage(request) => { + let mut user_backend = user_backend.lock().await; + + let response = user_backend.display_image(request.clone()).await; + + let response = match response { + Ok(response) => response, + Err(err) => { + error!("Error handling request: {:?}", err); + continue; + } + }; + drop(user_backend); + + let _result = send( + &mut socket, + MessageKind::User(UserMessage { + instance: message.instance.clone(), + message: UserMessageKind::Response( + UserMessageResponse::DisplayImage(response), + ), + }), + ) + .await; + + continue; + } + UserMessageRequest::Bio(request) => { + let mut user_backend = user_backend.lock().await; + + let response = user_backend.bio(request.clone()).await; + + let response = match response { + Ok(response) => response, + Err(err) => { + error!("Error handling request: {:?}", err); + continue; + } + }; + drop(user_backend); + + let _result = send( + &mut socket, + MessageKind::User(UserMessage { + instance: message.instance.clone(), + message: UserMessageKind::Response(UserMessageResponse::Bio( + response, + )), + }), + ) + .await; + + continue; + } + UserMessageRequest::Repositories(request) => { + let mut repository_backend = backend.lock().await; + + let repositories = repository_backend + .repositories_for_user(&request.user) + .await; + + let repositories = match repositories { + Ok(repositories) => repositories, + Err(err) => { + error!("Error handling request: {:?}", err); + continue; + } + }; + drop(repository_backend); + + let response = UserRepositoriesResponse { repositories }; + + let _result = send( + &mut socket, + MessageKind::User(UserMessage { + instance: message.instance.clone(), + message: UserMessageKind::Response( + UserMessageResponse::Repositories(response), + ), + }), + ) + .await; + + continue; + } + }, + UserMessageKind::Response(_) => unreachable!(), + } + } } info!("Connection closed"); @@ -471,6 +595,7 @@ async fn send_and_get_listener( MessageKind::Repository(repository) => (None, None, Some(repository.target.clone())), MessageKind::Authentication(_) => todo!(), MessageKind::Discovery(_) => todo!(), + MessageKind::User(user) => todo!(), }; let target = match (&instance, &user, &repository) { diff --git a/src/main.rs b/src/main.rs index 2b2c2df..b8aa26e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,6 +57,7 @@ async fn main() -> Result<(), Error> { .as_str() .unwrap(), ), + instance: Instance::from_str("giterated.dev").unwrap(), })); let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter { diff --git a/src/messages/mod.rs b/src/messages/mod.rs index 1222c46..5753f79 100644 --- a/src/messages/mod.rs +++ b/src/messages/mod.rs @@ -18,7 +18,7 @@ use crate::{ use self::{ authentication::AuthenticationMessage, discovery::DiscoveryMessage, - repository::RepositoryMessage, + repository::RepositoryMessage, user::UserMessage, }; pub mod authentication; @@ -33,6 +33,7 @@ pub enum MessageKind { Repository(RepositoryMessage), Authentication(AuthenticationMessage), Discovery(DiscoveryMessage), + User(UserMessage), } /// An authenticated message, where the instance is authenticating diff --git a/src/messages/user.rs b/src/messages/user.rs index bfcd5c4..bf34fd8 100644 --- a/src/messages/user.rs +++ b/src/messages/user.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use crate::model::{instance::Instance, user::User}; +use crate::model::{instance::Instance, repository::Repository, user::User}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct UserMessage { @@ -19,13 +19,15 @@ pub enum UserMessageRequest { DisplayName(UserDisplayNameRequest), DisplayImage(UserDisplayImageRequest), Bio(UserBioRequest), + Repositories(UserRepositoriesRequest), } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum UserMessageResponse { - DisplayName(UserDisplayImageResponse), + DisplayName(UserDisplayNameResponse), DisplayImage(UserDisplayImageResponse), Bio(UserBioResponse), + Repositories(UserRepositoriesResponse), } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -57,3 +59,13 @@ pub struct UserBioRequest { pub struct UserBioResponse { pub bio: Option, } + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct UserRepositoriesRequest { + pub user: User, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct UserRepositoriesResponse { + pub repositories: Vec, +}