From 27ac28e0ea3d61f9d60aa5768598a3542f623d57 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Mon, 26 Aug 2024 12:28:44 +0200 Subject: [PATCH 1/9] wip --- src/handlers/info.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/handlers/mod.rs | 9 +++++---- 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/handlers/info.rs diff --git a/src/handlers/info.rs b/src/handlers/info.rs new file mode 100644 index 0000000..3d999cd --- /dev/null +++ b/src/handlers/info.rs @@ -0,0 +1,44 @@ +use axum::{extract::State, routing::get, Json, Router}; +use axum_extra::extract::{cookie::Cookie, PrivateCookieJar}; +use time::OffsetDateTime; + +use crate::{ + error::ApiError, + handlers::get_core_response, + http::{AppState, ENROLLMENT_COOKIE_NAME}, + proto::{ + core_request, core_response, ActivateUserRequest, DeviceConfigResponse, DeviceInfo, + EnrollmentStartRequest, EnrollmentStartResponse, ExistingDevice, NewDevice, + }, +}; + +pub fn router() -> Router { + Router::new() + .route("/info", get(location_info)) +} + +#[instrument(level = "debug", skip(state))] +pub async fn location_info( + State(state): State, + private_cookies: PrivateCookieJar, +) -> Result, ApiError> { + // let pubkey = req.pubkey.clone(); + info!("Getting network info for device {pubkey}"); + + // set auth info + req.token = private_cookies + .get(ENROLLMENT_COOKIE_NAME) + .map(|cookie| cookie.value().to_string()); + + let rx = state + .grpc_server + .send(Some(core_request::Payload::ExistingDevice(req)), None)?; + let payload = get_core_response(rx).await?; + if let core_response::Payload::DeviceConfig(response) = payload { + info!("Got network info for device {pubkey}"); + Ok(Json(response)) + } else { + error!("Received invalid gRPC response type: {payload:#?}"); + Err(ApiError::InvalidResponseType) + } +} diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 1fb53e9..9017693 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,7 +1,3 @@ -pub(crate) mod desktop_client_mfa; -pub(crate) mod enrollment; -pub(crate) mod password_reset; - use crate::{error::ApiError, proto::core_response::Payload}; use axum::{extract::FromRequestParts, http::request::Parts}; use axum_client_ip::{InsecureClientIp, LeftmostXForwardedFor}; @@ -11,6 +7,11 @@ use tokio::{sync::oneshot::Receiver, time::timeout}; use super::proto::DeviceInfo; +pub(crate) mod desktop_client_mfa; +pub(crate) mod enrollment; +pub(crate) mod info; +pub(crate) mod password_reset; + // timeout in seconds for awaiting core response const CORE_RESPONSE_TIMEOUT: u64 = 5; From be1117dc78dceb3aec29faefb9781272b0d1d3dd Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Tue, 27 Aug 2024 12:48:00 +0200 Subject: [PATCH 2/9] Activate user endpoint returns auth token --- src/handlers/enrollment.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/handlers/enrollment.rs b/src/handlers/enrollment.rs index 9a7c4ec..16f13ab 100644 --- a/src/handlers/enrollment.rs +++ b/src/handlers/enrollment.rs @@ -7,8 +7,9 @@ use crate::{ handlers::get_core_response, http::{AppState, ENROLLMENT_COOKIE_NAME}, proto::{ - core_request, core_response, ActivateUserRequest, DeviceConfigResponse, DeviceInfo, - EnrollmentStartRequest, EnrollmentStartResponse, ExistingDevice, NewDevice, + core_request, core_response, ActivateUserRequest, ActivateUserResponse, + DeviceConfigResponse, DeviceInfo, EnrollmentStartRequest, EnrollmentStartResponse, + ExistingDevice, NewDevice, }, }; @@ -65,7 +66,7 @@ pub async fn activate_user( device_info: Option, mut private_cookies: PrivateCookieJar, Json(mut req): Json, -) -> Result { +) -> Result<(PrivateCookieJar, Json), ApiError> { let phone = req.phone_number.clone(); info!("Activating user - phone number {phone:?}"); @@ -81,14 +82,13 @@ pub async fn activate_user( .send(Some(core_request::Payload::ActivateUser(req)), device_info)?; let payload = get_core_response(rx).await?; debug!("Receving payload from the core service. Trying to remove private cookie..."); - if let core_response::Payload::Empty(()) = payload { + if let core_response::Payload::ActivateUserResponse(response) = payload { + info!("Activated user - phone number {phone:?}"); if let Some(cookie) = private_cookies.get(ENROLLMENT_COOKIE_NAME) { - info!("Activated user - phone number {phone:?}"); debug!("Enrollment finished. Removing session cookie"); private_cookies = private_cookies.remove(cookie); } - - Ok(private_cookies) + Ok((private_cookies, Json(response))) } else { error!("Received invalid gRPC response type: {payload:#?}"); Err(ApiError::InvalidResponseType) From 12953faf75ef693aae4ee720f9e64da9bbfb9ab4 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Tue, 27 Aug 2024 13:11:49 +0200 Subject: [PATCH 3/9] wip: info handler --- src/handlers/info.rs | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/handlers/info.rs b/src/handlers/info.rs index 3d999cd..3082549 100644 --- a/src/handlers/info.rs +++ b/src/handlers/info.rs @@ -12,33 +12,33 @@ use crate::{ }, }; -pub fn router() -> Router { - Router::new() - .route("/info", get(location_info)) -} +// pub fn router() -> Router { +// Router::new() +// .route("/info", get(location_info)) +// } -#[instrument(level = "debug", skip(state))] -pub async fn location_info( - State(state): State, - private_cookies: PrivateCookieJar, -) -> Result, ApiError> { - // let pubkey = req.pubkey.clone(); - info!("Getting network info for device {pubkey}"); +// #[instrument(level = "debug", skip(state))] +// pub async fn location_info( +// State(state): State, +// private_cookies: PrivateCookieJar, +// ) -> Result, ApiError> { +// // let pubkey = req.pubkey.clone(); +// info!("Getting network info for device {pubkey}"); - // set auth info - req.token = private_cookies - .get(ENROLLMENT_COOKIE_NAME) - .map(|cookie| cookie.value().to_string()); +// // set auth info +// req.token = private_cookies +// .get(ENROLLMENT_COOKIE_NAME) +// .map(|cookie| cookie.value().to_string()); - let rx = state - .grpc_server - .send(Some(core_request::Payload::ExistingDevice(req)), None)?; - let payload = get_core_response(rx).await?; - if let core_response::Payload::DeviceConfig(response) = payload { - info!("Got network info for device {pubkey}"); - Ok(Json(response)) - } else { - error!("Received invalid gRPC response type: {payload:#?}"); - Err(ApiError::InvalidResponseType) - } -} +// let rx = state +// .grpc_server +// .send(Some(core_request::Payload::ExistingDevice(req)), None)?; +// let payload = get_core_response(rx).await?; +// if let core_response::Payload::DeviceConfig(response) = payload { +// info!("Got network info for device {pubkey}"); +// Ok(Json(response)) +// } else { +// error!("Received invalid gRPC response type: {payload:#?}"); +// Err(ApiError::InvalidResponseType) +// } +// } From 6692cd7a077307ae3e8ecf773673dc238068174f Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 30 Aug 2024 10:54:55 +0200 Subject: [PATCH 4/9] Add polling endpoint --- src/handlers/info.rs | 44 ----------------------------------------- src/handlers/mod.rs | 2 +- src/handlers/polling.rs | 28 ++++++++++++++++++++++++++ src/http.rs | 5 +++-- web/vite.config.ts | 2 +- 5 files changed, 33 insertions(+), 48 deletions(-) delete mode 100644 src/handlers/info.rs create mode 100644 src/handlers/polling.rs diff --git a/src/handlers/info.rs b/src/handlers/info.rs deleted file mode 100644 index 3082549..0000000 --- a/src/handlers/info.rs +++ /dev/null @@ -1,44 +0,0 @@ -use axum::{extract::State, routing::get, Json, Router}; -use axum_extra::extract::{cookie::Cookie, PrivateCookieJar}; -use time::OffsetDateTime; - -use crate::{ - error::ApiError, - handlers::get_core_response, - http::{AppState, ENROLLMENT_COOKIE_NAME}, - proto::{ - core_request, core_response, ActivateUserRequest, DeviceConfigResponse, DeviceInfo, - EnrollmentStartRequest, EnrollmentStartResponse, ExistingDevice, NewDevice, - }, -}; - -// pub fn router() -> Router { -// Router::new() -// .route("/info", get(location_info)) -// } - -// #[instrument(level = "debug", skip(state))] -// pub async fn location_info( -// State(state): State, -// private_cookies: PrivateCookieJar, -// ) -> Result, ApiError> { -// // let pubkey = req.pubkey.clone(); -// info!("Getting network info for device {pubkey}"); - -// // set auth info -// req.token = private_cookies -// .get(ENROLLMENT_COOKIE_NAME) -// .map(|cookie| cookie.value().to_string()); - -// let rx = state -// .grpc_server -// .send(Some(core_request::Payload::ExistingDevice(req)), None)?; -// let payload = get_core_response(rx).await?; -// if let core_response::Payload::DeviceConfig(response) = payload { -// info!("Got network info for device {pubkey}"); -// Ok(Json(response)) -// } else { -// error!("Received invalid gRPC response type: {payload:#?}"); -// Err(ApiError::InvalidResponseType) -// } -// } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 9017693..6531087 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -9,8 +9,8 @@ use super::proto::DeviceInfo; pub(crate) mod desktop_client_mfa; pub(crate) mod enrollment; -pub(crate) mod info; pub(crate) mod password_reset; +pub(crate) mod polling; // timeout in seconds for awaiting core response const CORE_RESPONSE_TIMEOUT: u64 = 5; diff --git a/src/handlers/polling.rs b/src/handlers/polling.rs new file mode 100644 index 0000000..3820196 --- /dev/null +++ b/src/handlers/polling.rs @@ -0,0 +1,28 @@ +use axum::{extract::State, Json}; + +use crate::{ + error::ApiError, + handlers::get_core_response, + http::AppState, + proto::{core_request, core_response, InstanceInfoRequest, InstanceInfoResponse}, +}; + +#[instrument(level = "debug", skip(state))] +pub async fn info( + State(state): State, + Json(req): Json, +) -> Result, ApiError> { + debug!("Retrieving info for polling request"); + let rx = state + .grpc_server + .send(Some(core_request::Payload::InstanceInfo(req.clone())), None)?; + let payload = get_core_response(rx).await?; + + if let core_response::Payload::InstanceInfo(response) = payload { + info!("Retrieved info for polling request"); + Ok(Json(response)) + } else { + error!("Received invalid gRPC response type: {payload:#?}"); + Err(ApiError::InvalidResponseType) + } +} diff --git a/src/http.rs b/src/http.rs index 3bdfa7a..a6be8d3 100644 --- a/src/http.rs +++ b/src/http.rs @@ -10,7 +10,7 @@ use axum::{ body::Body, extract::{ConnectInfo, FromRef, State}, http::{Request, StatusCode}, - routing::get, + routing::{get, post}, serve, Json, Router, }; use axum_extra::extract::cookie::Key; @@ -29,7 +29,7 @@ use crate::{ config::Config, error::ApiError, grpc::ProxyServer, - handlers::{desktop_client_mfa, enrollment, password_reset}, + handlers::{desktop_client_mfa, enrollment, password_reset, polling}, proto::proxy_server, }; @@ -188,6 +188,7 @@ pub async fn run_server(config: Config) -> anyhow::Result<()> { .nest("/enrollment", enrollment::router()) .nest("/password-reset", password_reset::router()) .nest("/client-mfa", desktop_client_mfa::router()) + .route("/poll", post(polling::info)) .route("/health", get(healthcheck)) .route("/health-grpc", get(healthcheckgrpc)) .route("/info", get(app_info)), diff --git a/web/vite.config.ts b/web/vite.config.ts index 999e582..0ad35bc 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -8,7 +8,7 @@ export default defineConfig({ plugins: [react()], server: { strictPort: true, - port: 3000, + port: 3002, proxy: { '/api': { target: 'http://127.0.0.1:8080/', From b33a1d9f2afb6f5f29cef3a95643856390ba1361 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 5 Sep 2024 07:47:44 +0200 Subject: [PATCH 5/9] Activate user doesn't return auth token, create_device does --- proto | 2 +- src/handlers/enrollment.rs | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/proto b/proto index c71f378..d9c2c61 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit c71f37847279ee23220fcf9e0e45d2c365b3b8ee +Subproject commit d9c2c61b1aad1b12ab6f1461badba4f072a341e2 diff --git a/src/handlers/enrollment.rs b/src/handlers/enrollment.rs index 16f13ab..bb8d5da 100644 --- a/src/handlers/enrollment.rs +++ b/src/handlers/enrollment.rs @@ -7,9 +7,8 @@ use crate::{ handlers::get_core_response, http::{AppState, ENROLLMENT_COOKIE_NAME}, proto::{ - core_request, core_response, ActivateUserRequest, ActivateUserResponse, - DeviceConfigResponse, DeviceInfo, EnrollmentStartRequest, EnrollmentStartResponse, - ExistingDevice, NewDevice, + core_request, core_response, ActivateUserRequest, DeviceConfigResponse, DeviceInfo, + EnrollmentStartRequest, EnrollmentStartResponse, ExistingDevice, NewDevice, }, }; @@ -66,7 +65,7 @@ pub async fn activate_user( device_info: Option, mut private_cookies: PrivateCookieJar, Json(mut req): Json, -) -> Result<(PrivateCookieJar, Json), ApiError> { +) -> Result { let phone = req.phone_number.clone(); info!("Activating user - phone number {phone:?}"); @@ -82,13 +81,13 @@ pub async fn activate_user( .send(Some(core_request::Payload::ActivateUser(req)), device_info)?; let payload = get_core_response(rx).await?; debug!("Receving payload from the core service. Trying to remove private cookie..."); - if let core_response::Payload::ActivateUserResponse(response) = payload { + if let core_response::Payload::Empty(()) = payload { info!("Activated user - phone number {phone:?}"); if let Some(cookie) = private_cookies.get(ENROLLMENT_COOKIE_NAME) { debug!("Enrollment finished. Removing session cookie"); private_cookies = private_cookies.remove(cookie); } - Ok((private_cookies, Json(response))) + Ok(private_cookies) } else { error!("Received invalid gRPC response type: {payload:#?}"); Err(ApiError::InvalidResponseType) From 9e2dbcfe0f432d80287156c930abbeee96fb0a3a Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 5 Sep 2024 08:55:49 +0200 Subject: [PATCH 6/9] Update protos --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index d9c2c61..af18eaf 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit d9c2c61b1aad1b12ab6f1461badba4f072a341e2 +Subproject commit af18eaffb5a5800ac068040fd1fcd0414843f204 From b87adc854bb26628eca9f31177330a8e099cbe4f Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 5 Sep 2024 17:28:44 +0200 Subject: [PATCH 7/9] Update protos --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index af18eaf..6c89f19 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit af18eaffb5a5800ac068040fd1fcd0414843f204 +Subproject commit 6c89f195e6d9de08a13c97ccf09550873a845d4f From 29c925518e260b5b0eb44e5ff85851e7ff352a39 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 6 Sep 2024 14:30:08 +0200 Subject: [PATCH 8/9] Update protos --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index 6c89f19..57654ba 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 6c89f195e6d9de08a13c97ccf09550873a845d4f +Subproject commit 57654ba89d5a1675c0c2d6bac8f7910cb28257f5 From 430c1718f6f8a71c317dddf73c71bacc65b545a7 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Fri, 6 Sep 2024 14:51:19 +0200 Subject: [PATCH 9/9] Update protos --- proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto b/proto index 57654ba..d069a0e 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 57654ba89d5a1675c0c2d6bac8f7910cb28257f5 +Subproject commit d069a0e5304281cfc8b09e949a8e7a9feb5fc115