diff --git a/migrations/20230829104151_create_users.sql b/migrations/20230829104151_create_users.sql new file mode 100644 index 0000000..c0071ef --- /dev/null +++ b/migrations/20230829104151_create_users.sql @@ -0,0 +1,13 @@ +-- Add migration script here + +CREATE TABLE IF NOT EXISTS users +( + username TEXT NOT NULL, + display_name TEXT, + image_url TEXT NOT NULL, + bio TEXT, + email TEXT, + password TEXT NOT NULL +) + +CREATE UNIQUE INDEX unique_username ON users (username); \ No newline at end of file diff --git a/src/backend/git.rs b/src/backend/git.rs index 6ca26ad..6d49429 100644 --- a/src/backend/git.rs +++ b/src/backend/git.rs @@ -309,8 +309,10 @@ impl RepositoryBackend for GitBackend { async fn repository_info( &mut self, - request: &RepositoryInfoRequest, + raw_request: &UserAuthenticated, ) -> Result> { + let request = raw_request.inner().await; + let repository = match self .find_by_instance_username_name( // &request.owner.instance.url, @@ -323,16 +325,16 @@ impl RepositoryBackend for GitBackend { Err(err) => return Err(Box::new(err)), }; - // if !repository.can_user_view_repository( - // request.owner.instance.url.as_str(), - // Some(request.owner.username.as_str()), - // ) { - // return Err(Box::new(GitBackendError::RepositoryNotFound { - // instance_url: request.owner.instance.url.clone(), - // username: request.owner.username.clone(), - // name: request.name.clone(), - // })); - // } + if !repository.can_user_view_repository( + request.owner.instance.url.as_str(), + Some(request.owner.username.as_str()), + ) { + return Err(Box::new(GitBackendError::RepositoryNotFound { + instance_url: request.owner.instance.url.clone(), + username: request.owner.username.clone(), + name: request.name.clone(), + })); + } let git = match repository.open_git2_repository(&self.repository_folder) { Ok(git) => git, diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 0800cde..193f6a9 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,5 +1,6 @@ pub mod git; pub mod github; +pub mod user; use async_trait::async_trait; use std::error::Error; @@ -52,22 +53,27 @@ pub trait IssuesBackend { ) -> Result>; } +#[async_trait::async_trait] pub trait AuthBackend { - fn register(&mut self, request: ()) -> Result<(), Box>; + async fn register(&mut self, request: ()) -> Result<(), Box>; - fn login(&mut self, request: ()) -> Result<(), Box>; + async fn login(&mut self, request: ()) -> Result<(), Box>; } -pub trait UserBackend { - fn display_name( +#[async_trait::async_trait] +pub trait UserBackend: AuthBackend { + async fn display_name( &mut self, request: UserDisplayNameRequest, ) -> Result>; - fn display_image( + async fn display_image( &mut self, request: UserDisplayImageRequest, ) -> Result>; - fn bio(&mut self, request: UserBioRequest) -> Result>; + async fn bio( + &mut self, + request: UserBioRequest, + ) -> Result>; } diff --git a/src/backend/user.rs b/src/backend/user.rs new file mode 100644 index 0000000..6753f42 --- /dev/null +++ b/src/backend/user.rs @@ -0,0 +1,89 @@ +use std::error::Error; + +use sqlx::PgPool; + +use crate::messages::user::{ + UserBioRequest, UserBioResponse, UserDisplayImageRequest, UserDisplayImageResponse, + UserDisplayNameRequest, UserDisplayNameResponse, +}; + +use super::{AuthBackend, UserBackend}; + +pub struct UserAuth { + pub pg_pool: PgPool, +} + +impl UserAuth { + pub fn new(pool: PgPool) -> Self { + Self { pg_pool: pool } + } +} + +#[async_trait::async_trait] +impl UserBackend for UserAuth { + async fn display_name( + &mut self, + request: UserDisplayNameRequest, + ) -> Result> { + let db_row = sqlx::query_as!( + UserRow, + r#"SELECT * FROM users WHERE username = $1"#, + request.user.username + ) + .await?; + + Ok(UserDisplayNameResponse { + display_name: db_row.display_name, + }) + } + + async fn display_image( + &mut self, + request: UserDisplayImageRequest, + ) -> Result> { + let db_row = sqlx::query_as!( + UserRow, + r#"SELECT * FROM users WHERE username = $1"#, + request.user.username + ) + .await?; + + Ok(UserDisplayImageResponse { + image_url: db_row.image_url, + }) + } + + async fn bio( + &mut self, + request: UserBioRequest, + ) -> Result> { + let db_row = sqlx::query_as!( + UserRow, + r#"SELECT * FROM users WHERE username = $1"#, + request.user.username + ) + .await?; + + Ok(UserBioResponse { bio: db_row.bio }) + } +} + +#[async_trait::async_trait] +impl AuthBackend for UserAuth { + async fn register(&mut self, request: ()) -> Result<(), Box> { + todo!() + } + + async fn login(&mut self, request: ()) -> Result<(), Box> { + todo!() + } +} + +#[derive(Debug, sqlx::FromRow)] +struct UserRow { + pub username: String, + pub display_name: Option, + pub bio: Option, + pub email: Option, + pub password: String, +} diff --git a/src/connection.rs b/src/connection.rs index 2886d4f..6ca4152 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -13,7 +13,7 @@ use tokio_tungstenite::{tungstenite::Message, WebSocketStream}; use crate::{ authentication::AuthenticationTokenGranter, - backend::{IssuesBackend, RepositoryBackend}, + backend::{IssuesBackend, RepositoryBackend, UserBackend}, handshake::{HandshakeFinalize, HandshakeMessage, HandshakeResponse}, listener::Listeners, messages::{ @@ -56,6 +56,7 @@ pub async fn connection_worker( listeners: Arc>, connections: Arc>, backend: Arc>, + user_backend: Arc>, auth_granter: Arc>, addr: SocketAddr, ) { diff --git a/src/main.rs b/src/main.rs index 3674cba..558c8ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::{error::Error, net::SocketAddr, sync::Arc}; use connection::{connection_worker, Connections, RawConnection}; use giterated_daemon::{ authentication::AuthenticationTokenGranter, - backend::{git::GitBackend, RepositoryBackend}, + backend::{git::GitBackend, user::UserAuth, RepositoryBackend, UserBackend}, connection, listener, }; use listener::Listeners; @@ -47,7 +47,7 @@ async fn main() -> Result<(), Box> { let repository_backend: Arc> = Arc::new(Mutex::new({ let foo: GitBackend = GitBackend { - pg_pool: db_pool, + pg_pool: db_pool.clone(), repository_folder: String::from( config["repository"]["backend"]["git"]["root"] .as_str() @@ -57,6 +57,9 @@ async fn main() -> Result<(), Box> { foo })); + let user_backend: Arc> = + Arc::new(Mutex::new(UserAuth::new(db_pool))); + let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter { config: config.clone(), })); @@ -98,6 +101,7 @@ async fn main() -> Result<(), Box> { listeners.clone(), connections.clone(), repository_backend.clone(), + user_backend.clone(), token_granter.clone(), address, )),