From 0bf8e61981bee2a10e012a63765139ebc1d31d54 Mon Sep 17 00:00:00 2001 From: PolpOnline Date: Wed, 27 Nov 2024 15:37:08 +0100 Subject: [PATCH] Split apart some parts of app/mod.rs --- .idea/compiler.xml | 1 + src/backend/src/app/db.rs | 34 ++++ src/backend/src/app/mod.rs | 159 ++---------------- src/backend/src/app/openapi.rs | 38 +++++ src/backend/src/app/redis.rs | 46 +++++ src/backend/src/app/workers.rs | 44 +++++ src/backend/src/web/auth/login.rs | 2 +- src/backend/src/web/auth/logout.rs | 2 +- src/backend/src/web/protected/add_system.rs | 4 +- .../src/web/protected/change_visibility.rs | 4 +- .../src/web/protected/delete_system.rs | 2 +- .../src/web/protected/edit_system_name.rs | 2 +- src/backend/src/web/protected/list_systems.rs | 2 +- src/backend/src/web/public/healthcheck.rs | 2 +- src/backend/src/web/public/ping_status.rs | 2 +- .../web/public/public_systems/get_public.rs | 2 +- src/backend/src/web/public/sys_info.rs | 2 +- 17 files changed, 188 insertions(+), 160 deletions(-) create mode 100644 src/backend/src/app/db.rs create mode 100644 src/backend/src/app/openapi.rs create mode 100644 src/backend/src/app/redis.rs create mode 100644 src/backend/src/app/workers.rs diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 8ca546d..ec2703a 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,7 @@ + \ No newline at end of file diff --git a/src/backend/src/app/db.rs b/src/backend/src/app/db.rs new file mode 100644 index 0000000..8202083 --- /dev/null +++ b/src/backend/src/app/db.rs @@ -0,0 +1,34 @@ +use sqlx::{postgres::PgPoolOptions, PgPool}; +use tracing::info; + +use crate::app::App; + +impl App { + pub(super) async fn setup_db() -> color_eyre::Result { + info!("SQLx: Connecting to the database..."); + + let database_url = match std::env::var("DATABASE_PRIVATE_URL") { + Ok(url) => { + info!("SQLx: Using DATABASE_PRIVATE_URL"); + url + } + Err(_) => { + info!("SQLx: Using DATABASE_URL"); + std::env::var("DATABASE_URL")? + } + }; + + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await?; + + info!("SQLx: Connected to the database"); + + sqlx::migrate!().run(&pool).await?; + + info!("SQLx: Migrations run"); + + Ok(pool) + } +} diff --git a/src/backend/src/app/mod.rs b/src/backend/src/app/mod.rs index 091a4a2..96ad1f7 100644 --- a/src/backend/src/app/mod.rs +++ b/src/backend/src/app/mod.rs @@ -1,3 +1,8 @@ +mod db; +pub mod openapi; +mod redis; +mod workers; + use std::str::FromStr; use axum::{middleware, routing::get}; @@ -6,76 +11,27 @@ use axum_login::{ AuthManagerLayerBuilder, }; use http::StatusCode; -use sidekiq::{periodic, Processor, RedisConnectionManager}; -use sqlx::{postgres::PgPoolOptions, PgPool}; +use sqlx::PgPool; use tokio::{signal, task::AbortHandle}; use tower_http::{ compression::CompressionLayer, decompression::DecompressionLayer, trace::TraceLayer, }; use tower_sessions::cookie::Key; -use tower_sessions_redis_store::{ - fred::{ - prelude::{ClientLike, RedisConfig as RedisFredConfig, RedisPool as RedisFredPool}, - types::ReconnectPolicy, - }, - RedisStore, -}; +use tower_sessions_redis_store::{fred::prelude::RedisPool as RedisFredPool, RedisStore}; use tracing::info; -use utoipa::{ - openapi::security::{ApiKey, ApiKeyValue, SecurityScheme}, - Modify, OpenApi, -}; +use utoipa::OpenApi; use utoipa_axum::router::OpenApiRouter; use utoipa_scalar::{Scalar, Servable}; use crate::{ + app::{openapi::ApiDoc, redis::RedisLibPool}, custom_login_required, middleware::{set_cache_control::set_cache_control, set_user_info::set_user_info}, users::LoginBackend, web::{auth, protected, public}, - workers::{ - email_worker::{init_smtp_client, SmtpClient}, - register_workers, - }, - PRODUCTION, + workers::email_worker::{init_smtp_client, SmtpClient}, }; -pub const AUTH_TAG: &str = "Auth"; -pub const MONITORING_TAG: &str = "Monitoring"; -pub const USER_TAG: &str = "User"; -pub const SYSTEM_TAG: &str = "System"; -pub const DATA_TAG: &str = "Data"; -pub const PUBLIC_SYSTEM_TAG: &str = "Public systems"; - -#[derive(OpenApi)] -#[openapi( - modifiers(&ApiDocSecurityAddon), - tags( - (name = AUTH_TAG, description = "Endpoints to authenticate users"), - (name = MONITORING_TAG, description = "Endpoints to monitor the system (such as healthchecks)"), - (name = USER_TAG, description = "Endpoints related to users and their accounts"), - (name = SYSTEM_TAG, description = "Endpoints related to monitored systems"), - (name = DATA_TAG, description = "Endpoints that must be connected to by the monitored systems"), - (name = PUBLIC_SYSTEM_TAG, description = "Endpoints related to monitored systems that are public") - ) -)] -struct ApiDoc; - -struct ApiDocSecurityAddon; - -impl Modify for ApiDocSecurityAddon { - fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) { - if let Some(components) = openapi.components.as_mut() { - components.add_security_scheme( - "session", - SecurityScheme::ApiKey(ApiKey::Cookie(ApiKeyValue::new("monitor_id"))), - ) - } - } -} - -type RedisLibPool = bb8::Pool; - pub struct App { db: PgPool, redis_lib: RedisLibPool, @@ -167,101 +123,6 @@ impl App { Ok(()) } - - async fn setup_db() -> color_eyre::Result { - info!("SQLx: Connecting to the database..."); - - let database_url = match std::env::var("DATABASE_PRIVATE_URL") { - Ok(url) => { - info!("SQLx: Using DATABASE_PRIVATE_URL"); - url - } - Err(_) => { - info!("SQLx: Using DATABASE_URL"); - std::env::var("DATABASE_URL")? - } - }; - - let pool = PgPoolOptions::new() - .max_connections(5) - .connect(&database_url) - .await?; - - info!("SQLx: Connected to the database"); - - sqlx::migrate!().run(&pool).await?; - - info!("SQLx: Migrations run"); - - Ok(pool) - } - - async fn setup_redis_lib() -> color_eyre::Result { - info!("Redis Lib: Connecting to Redis (to manage workers)..."); - - let db_num = 1u8; - - let redis_url = std::env::var("REDIS_URL")?; - let redis_url = format!("{}/{}", redis_url, db_num); - let manager = RedisConnectionManager::new(redis_url)?; - let redis = bb8::Pool::builder().build(manager).await?; - - info!("Redis Lib: Connected to Redis (to manage workers)"); - - Ok(redis) - } - - async fn setup_redis_fred() -> color_eyre::Result { - info!("Redis Fred: Connecting to Redis (to manage sessions)..."); - - let db_num = 0u8; - - let redis_url = std::env::var("REDIS_URL")?; - let redis_url = format!("{}/{}", redis_url, db_num); - - let config = RedisFredConfig::from_url(&redis_url)?; - - let pool = RedisFredPool::new(config, None, None, Some(ReconnectPolicy::default()), 6)?; - - pool.init().await?; - - info!("Redis Fred: Connected to Redis (to manage sessions)"); - - Ok(pool) - } - - async fn start_workers(p: Processor) -> color_eyre::Result<()> { - info!( - "Sidekiq: Workers started in {} mode", - if *PRODUCTION { - "production" - } else { - "development" - } - ); - - // Start the server - p.run().await; - - Ok(()) - } - - async fn init_workers( - redis: RedisLibPool, - db: PgPool, - smtp_client: SmtpClient, - ) -> color_eyre::Result { - // Clear out all periodic jobs and their schedules - periodic::destroy_all(redis.clone()).await?; - - // Sidekiq server - let mut p = Processor::new(redis, vec!["down_emails".to_string()]); - - // Add known workers - register_workers(&mut p, db, smtp_client).await?; - - Ok(p) - } } async fn shutdown_signal(abort_handles: Vec) { diff --git a/src/backend/src/app/openapi.rs b/src/backend/src/app/openapi.rs new file mode 100644 index 0000000..9d8605e --- /dev/null +++ b/src/backend/src/app/openapi.rs @@ -0,0 +1,38 @@ +use utoipa::{ + openapi::security::{ApiKey, ApiKeyValue, SecurityScheme}, + Modify, OpenApi, +}; + +pub const AUTH_TAG: &str = "Auth"; +pub const MONITORING_TAG: &str = "Monitoring"; +pub const USER_TAG: &str = "User"; +pub const SYSTEM_TAG: &str = "System"; +pub const DATA_TAG: &str = "Data"; +pub const PUBLIC_SYSTEM_TAG: &str = "Public systems"; + +#[derive(OpenApi)] +#[openapi( + modifiers(&ApiDocSecurityAddon), + tags( + (name = AUTH_TAG, description = "Endpoints to authenticate users"), + (name = MONITORING_TAG, description = "Endpoints to monitor the system (such as healthchecks)"), + (name = USER_TAG, description = "Endpoints related to users and their accounts"), + (name = SYSTEM_TAG, description = "Endpoints related to monitored systems"), + (name = DATA_TAG, description = "Endpoints that must be connected to by the monitored systems"), + (name = PUBLIC_SYSTEM_TAG, description = "Endpoints related to monitored systems that are public") + ) +)] +pub(super) struct ApiDoc; + +struct ApiDocSecurityAddon; + +impl Modify for ApiDocSecurityAddon { + fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) { + if let Some(components) = openapi.components.as_mut() { + components.add_security_scheme( + "session", + SecurityScheme::ApiKey(ApiKey::Cookie(ApiKeyValue::new("monitor_id"))), + ) + } + } +} diff --git a/src/backend/src/app/redis.rs b/src/backend/src/app/redis.rs new file mode 100644 index 0000000..01a7e54 --- /dev/null +++ b/src/backend/src/app/redis.rs @@ -0,0 +1,46 @@ +use sidekiq::RedisConnectionManager; +use tower_sessions_redis_store::fred::{ + prelude::{ClientLike, RedisConfig as RedisFredConfig, RedisPool as RedisFredPool}, + types::ReconnectPolicy, +}; +use tracing::info; + +use crate::app::App; + +pub type RedisLibPool = bb8::Pool; + +impl App { + pub(super) async fn setup_redis_lib() -> color_eyre::Result { + info!("Redis Lib: Connecting to Redis (to manage workers)..."); + + let db_num = 1u8; + + let redis_url = std::env::var("REDIS_URL")?; + let redis_url = format!("{}/{}", redis_url, db_num); + let manager = RedisConnectionManager::new(redis_url)?; + let redis = bb8::Pool::builder().build(manager).await?; + + info!("Redis Lib: Connected to Redis (to manage workers)"); + + Ok(redis) + } + + pub(super) async fn setup_redis_fred() -> color_eyre::Result { + info!("Redis Fred: Connecting to Redis (to manage sessions)..."); + + let db_num = 0u8; + + let redis_url = std::env::var("REDIS_URL")?; + let redis_url = format!("{}/{}", redis_url, db_num); + + let config = RedisFredConfig::from_url(&redis_url)?; + + let pool = RedisFredPool::new(config, None, None, Some(ReconnectPolicy::default()), 6)?; + + pool.init().await?; + + info!("Redis Fred: Connected to Redis (to manage sessions)"); + + Ok(pool) + } +} diff --git a/src/backend/src/app/workers.rs b/src/backend/src/app/workers.rs new file mode 100644 index 0000000..36aa575 --- /dev/null +++ b/src/backend/src/app/workers.rs @@ -0,0 +1,44 @@ +use sidekiq::{periodic, Processor}; +use sqlx::PgPool; +use tracing::info; + +use crate::{ + app::{redis::RedisLibPool, App}, + workers::{email_worker::SmtpClient, register_workers}, + PRODUCTION, +}; + +impl App { + pub(super) async fn start_workers(p: Processor) -> color_eyre::Result<()> { + info!( + "Sidekiq: Workers started in {} mode", + if *PRODUCTION { + "production" + } else { + "development" + } + ); + + // Start the server + p.run().await; + + Ok(()) + } + + pub(super) async fn init_workers( + redis: RedisLibPool, + db: PgPool, + smtp_client: SmtpClient, + ) -> color_eyre::Result { + // Clear out all periodic jobs and their schedules + periodic::destroy_all(redis.clone()).await?; + + // Sidekiq server + let mut p = Processor::new(redis, vec!["down_emails".to_string()]); + + // Add known workers + register_workers(&mut p, db, smtp_client).await?; + + Ok(p) + } +} diff --git a/src/backend/src/web/auth/login.rs b/src/backend/src/web/auth/login.rs index b05312f..f8aa9ac 100644 --- a/src/backend/src/web/auth/login.rs +++ b/src/backend/src/web/auth/login.rs @@ -10,7 +10,7 @@ use tracing::{debug, info}; use utoipa::ToSchema; use crate::{ - app::AUTH_TAG, + app::openapi::AUTH_TAG, users::{AuthSession, Credentials, User}, }; diff --git a/src/backend/src/web/auth/logout.rs b/src/backend/src/web/auth/logout.rs index 36de0de..035ea37 100644 --- a/src/backend/src/web/auth/logout.rs +++ b/src/backend/src/web/auth/logout.rs @@ -1,7 +1,7 @@ use axum::response::IntoResponse; use http::StatusCode; -use crate::{app::AUTH_TAG, users::AuthSession}; +use crate::{app::openapi::AUTH_TAG, users::AuthSession}; #[utoipa::path( get, diff --git a/src/backend/src/web/protected/add_system.rs b/src/backend/src/web/protected/add_system.rs index af78b21..604ffdb 100644 --- a/src/backend/src/web/protected/add_system.rs +++ b/src/backend/src/web/protected/add_system.rs @@ -6,7 +6,9 @@ use sqlx::postgres::types::PgInterval; use utoipa::ToSchema; use uuid::Uuid; -use crate::{app::SYSTEM_TAG, users::AuthSession, web::protected::list_systems::Visibility}; +use crate::{ + app::openapi::SYSTEM_TAG, users::AuthSession, web::protected::list_systems::Visibility, +}; #[derive(Debug, Deserialize, Clone, ToSchema)] pub struct AddSystemRequest { diff --git a/src/backend/src/web/protected/change_visibility.rs b/src/backend/src/web/protected/change_visibility.rs index e76d0ef..ed50cd2 100644 --- a/src/backend/src/web/protected/change_visibility.rs +++ b/src/backend/src/web/protected/change_visibility.rs @@ -4,7 +4,9 @@ use serde::Deserialize; use utoipa::ToSchema; use uuid::Uuid; -use crate::{app::SYSTEM_TAG, users::AuthSession, web::protected::list_systems::Visibility}; +use crate::{ + app::openapi::SYSTEM_TAG, users::AuthSession, web::protected::list_systems::Visibility, +}; #[derive(Debug, Deserialize, ToSchema)] pub struct ChangeVisibilityRequest { diff --git a/src/backend/src/web/protected/delete_system.rs b/src/backend/src/web/protected/delete_system.rs index c935395..6046e6b 100644 --- a/src/backend/src/web/protected/delete_system.rs +++ b/src/backend/src/web/protected/delete_system.rs @@ -4,7 +4,7 @@ use serde::Deserialize; use utoipa::ToSchema; use uuid::Uuid; -use crate::{app::SYSTEM_TAG, users::AuthSession}; +use crate::{app::openapi::SYSTEM_TAG, users::AuthSession}; #[derive(Debug, Deserialize, ToSchema)] pub struct DeleteSystemRequest { diff --git a/src/backend/src/web/protected/edit_system_name.rs b/src/backend/src/web/protected/edit_system_name.rs index a697d48..7ef5a09 100644 --- a/src/backend/src/web/protected/edit_system_name.rs +++ b/src/backend/src/web/protected/edit_system_name.rs @@ -4,7 +4,7 @@ use serde::Deserialize; use utoipa::ToSchema; use uuid::Uuid; -use crate::{app::SYSTEM_TAG, users::AuthSession}; +use crate::{app::openapi::SYSTEM_TAG, users::AuthSession}; #[derive(Debug, Deserialize, ToSchema)] pub struct EditSystemNameRequest { diff --git a/src/backend/src/web/protected/list_systems.rs b/src/backend/src/web/protected/list_systems.rs index 5b73347..9afdd01 100644 --- a/src/backend/src/web/protected/list_systems.rs +++ b/src/backend/src/web/protected/list_systems.rs @@ -12,7 +12,7 @@ use utoipa::{IntoParams, ToSchema}; use uuid::Uuid; use crate::{ - app::SYSTEM_TAG, + app::openapi::SYSTEM_TAG, users::AuthSession, web::utils::{ time::{approx_expected_timestamp, naive_datetime_now}, diff --git a/src/backend/src/web/public/healthcheck.rs b/src/backend/src/web/public/healthcheck.rs index bca5c57..e207e98 100644 --- a/src/backend/src/web/public/healthcheck.rs +++ b/src/backend/src/web/public/healthcheck.rs @@ -1,7 +1,7 @@ use axum::response::IntoResponse; use http::StatusCode; -use crate::app::MONITORING_TAG; +use crate::app::openapi::MONITORING_TAG; #[utoipa::path( get, diff --git a/src/backend/src/web/public/ping_status.rs b/src/backend/src/web/public/ping_status.rs index 35876c9..ceaa923 100644 --- a/src/backend/src/web/public/ping_status.rs +++ b/src/backend/src/web/public/ping_status.rs @@ -3,7 +3,7 @@ use http::StatusCode; use tracing::info; use uuid::Uuid; -use crate::{app::DATA_TAG, users::AuthSession}; +use crate::{app::openapi::DATA_TAG, users::AuthSession}; #[utoipa::path( post, diff --git a/src/backend/src/web/public/public_systems/get_public.rs b/src/backend/src/web/public/public_systems/get_public.rs index 0217908..435c646 100644 --- a/src/backend/src/web/public/public_systems/get_public.rs +++ b/src/backend/src/web/public/public_systems/get_public.rs @@ -9,7 +9,7 @@ use utoipa::{IntoParams, ToSchema}; use uuid::Uuid; use crate::{ - app::PUBLIC_SYSTEM_TAG, + app::openapi::PUBLIC_SYSTEM_TAG, users::AuthSession, web::protected::list_systems::{SystemData, SystemRecord, Visibility, LIMIT_SYSTEM_REQUEST}, }; diff --git a/src/backend/src/web/public/sys_info.rs b/src/backend/src/web/public/sys_info.rs index 9f0bc53..2d14d1b 100644 --- a/src/backend/src/web/public/sys_info.rs +++ b/src/backend/src/web/public/sys_info.rs @@ -4,7 +4,7 @@ use sysinfo::System; use tokio::time::sleep; use utoipa::ToSchema; -use crate::app::MONITORING_TAG; +use crate::app::openapi::MONITORING_TAG; #[derive(Serialize, ToSchema)] pub struct MemInfo {