diff --git a/giterated-daemon/.sqlx/query-4707bb69d91fa6df545148c281bae53365c53011bea92e75996f030397ae6b07.json b/giterated-daemon/.sqlx/query-4707bb69d91fa6df545148c281bae53365c53011bea92e75996f030397ae6b07.json new file mode 100644 index 0000000..1067301 --- /dev/null +++ b/giterated-daemon/.sqlx/query-4707bb69d91fa6df545148c281bae53365c53011bea92e75996f030397ae6b07.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO repository_settings VALUES ($1, $2, $3) ON CONFLICT (repository, name) DO UPDATE SET value = $3", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "4707bb69d91fa6df545148c281bae53365c53011bea92e75996f030397ae6b07" +} diff --git a/giterated-daemon/.sqlx/query-d20bc04a9a3883bc2dbd9068d1a77264fff64d9f220f95b78f35e4f371cce160.json b/giterated-daemon/.sqlx/query-d20bc04a9a3883bc2dbd9068d1a77264fff64d9f220f95b78f35e4f371cce160.json new file mode 100644 index 0000000..cd3b660 --- /dev/null +++ b/giterated-daemon/.sqlx/query-d20bc04a9a3883bc2dbd9068d1a77264fff64d9f220f95b78f35e4f371cce160.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT * FROM repository_settings WHERE repository = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "repository", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "value", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "d20bc04a9a3883bc2dbd9068d1a77264fff64d9f220f95b78f35e4f371cce160" +} diff --git a/giterated-daemon/src/backend/user.rs b/giterated-daemon/src/backend/user.rs index dda7da2..fb0af00 100644 --- a/giterated-daemon/src/backend/user.rs +++ b/giterated-daemon/src/backend/user.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use anyhow::Error; use aes_gcm::{aead::Aead, AeadCore, Aes256Gcm, Key, KeyInit}; -use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; +use argon2::{password_hash::SaltString, Argon2, PasswordHasher, PasswordHash, PasswordVerifier}; use base64::{engine::general_purpose::STANDARD, Engine as _}; use giterated_models::{ messages::{ @@ -19,7 +19,7 @@ use giterated_models::{ model::{ instance::Instance, settings::{Setting, UserBio, UserDisplayImage, UserDisplayName}, - user::User, + user::User, authenticated::UserAuthenticationToken, }, }; use rsa::{ @@ -221,9 +221,29 @@ impl AuthBackend for UserAuth { async fn login( &mut self, - _request: AuthenticationTokenRequest, + request: AuthenticationTokenRequest, ) -> Result { - todo!() + let user = sqlx::query_as!(UserRow, r#"SELECT * FROM users WHERE username = $1"#, request.username).fetch_one(&self.pg_pool).await?; + + let hash = PasswordHash::new(&user.password).unwrap(); + + if !matches!(Argon2::default().verify_password(request.password.as_bytes(), &hash), Ok(())) { + // Invalid password! + return Err(Error::from(AuthenticationError::InvalidPassword)); + } + + let mut granter = self.auth_granter.lock().await; + let token = granter + .create_token_for( + &User { + username: user.username, + instance: self.this_instance.clone(), + }, + &request.issued_for.unwrap_or_else(|| self.this_instance.clone()), + ) + .await; + + Ok(AuthenticationTokenResponse { token: UserAuthenticationToken::from(token) }) } } @@ -236,3 +256,9 @@ struct UserRow { pub public_key: String, pub enc_private_key: Vec, } + +#[derive(Debug, thiserror::Error)] +pub enum AuthenticationError { + #[error("invalid password")] + InvalidPassword +} \ No newline at end of file diff --git a/giterated-daemon/src/connection/authentication.rs b/giterated-daemon/src/connection/authentication.rs index 2372239..b13c995 100644 --- a/giterated-daemon/src/connection/authentication.rs +++ b/giterated-daemon/src/connection/authentication.rs @@ -79,6 +79,8 @@ async fn authentication_token_request( // the user. TODO: Oauth-style flow let mut connections = connection_state.instance_connections.lock().await; + let issued_for = instance.inner().clone(); + let connection = connections.get_or_open(&request.instance).unwrap(); let private_key = { @@ -103,6 +105,11 @@ async fn authentication_token_request( private_key, }; + let request = AuthenticationTokenRequest { + issued_for: Some(issued_for), + ..request + }; + let response = giterated_api::request::request_local(request) .authenticate(authenticator) .execute_expect::(&connection) @@ -118,14 +125,9 @@ async fn authentication_token_request( return Ok(()); } - let issued_for = instance.inner().clone(); - - let mut token_granter = connection_state.auth_granter.lock().await; + let mut user_backend = connection_state.user_backend.lock().await; - let response = token_granter - .token_request(issued_for, request.username, request.password) - .await - .map_err(|e| AuthenticationConnectionError::TokenIssuance(e))?; + let response = user_backend.login(request).await.map_err(|e| AuthenticationConnectionError::TokenIssuance(e))?; connection_state .send(response) diff --git a/giterated-daemon/src/connection/wrapper.rs b/giterated-daemon/src/connection/wrapper.rs index b717548..c1f97ea 100644 --- a/giterated-daemon/src/connection/wrapper.rs +++ b/giterated-daemon/src/connection/wrapper.rs @@ -80,6 +80,7 @@ pub async fn connection_wrapper( Message::Close(_) => return, _ => continue, }; + info!("one payload"); let message = NetworkMessage(payload.clone()); @@ -94,19 +95,21 @@ pub async fn connection_wrapper( let raw = serde_json::from_slice::(&payload).unwrap(); if let Some(target_instance) = &raw.target_instance { - // Forward request - info!("Forwarding message to {}", target_instance.url); - let mut instance_connections = instance_connections.lock().await; - let pool = instance_connections.get_or_open(&target_instance).unwrap(); - let pool_clone = pool.clone(); - drop(pool); + if connection_state.instance != *target_instance { + // Forward request + info!("Forwarding message to {}", target_instance.url); + let mut instance_connections = instance_connections.lock().await; + let pool = instance_connections.get_or_open(&target_instance).unwrap(); + let pool_clone = pool.clone(); + drop(pool); - let result = wrap_forwarded(&pool_clone, raw).await; + let result = wrap_forwarded(&pool_clone, raw).await; - let mut socket = connection_state.socket.lock().await; - let _ = socket.send(result).await; + let mut socket = connection_state.socket.lock().await; + let _ = socket.send(result).await; - continue; + continue; + } } let message_type = &raw.message_type; diff --git a/giterated-daemon/src/main.rs b/giterated-daemon/src/main.rs index eb26a28..0ef5557 100644 --- a/giterated-daemon/src/main.rs +++ b/giterated-daemon/src/main.rs @@ -60,17 +60,17 @@ async fn main() -> Result<(), Error> { .as_str() .unwrap(), ), - instance: Instance::from_str("giterated.dev").unwrap(), + instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), })); let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter { config: config.clone(), - instance: Instance::from_str("giterated.dev").unwrap(), + instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), })); let user_backend: Arc> = Arc::new(Mutex::new(UserAuth::new( db_pool.clone(), - &Instance::from_str("giterated.dev").unwrap(), + &Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), token_granter.clone(), settings.clone(), ))); diff --git a/giterated-models/src/messages/authentication.rs b/giterated-models/src/messages/authentication.rs index 62305f4..27f75d2 100644 --- a/giterated-models/src/messages/authentication.rs +++ b/giterated-models/src/messages/authentication.rs @@ -41,6 +41,7 @@ pub struct RegisterAccountResponse { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AuthenticationTokenRequest { pub instance: Instance, + pub issued_for: Option, pub username: String, pub password: String, }