diff --git a/.sqlx/query-311137f954e7d0919262bcd8eac047577055879335c91c1935d2cd2f0565a086.json b/.sqlx/query-8b3673e18e4f773f3b52be4eda6af9e9dd10d52930399820da03c2057007df76.json similarity index 75% rename from .sqlx/query-311137f954e7d0919262bcd8eac047577055879335c91c1935d2cd2f0565a086.json rename to .sqlx/query-8b3673e18e4f773f3b52be4eda6af9e9dd10d52930399820da03c2057007df76.json index 61e4c9bdf..73a861f7a 100644 --- a/.sqlx/query-311137f954e7d0919262bcd8eac047577055879335c91c1935d2cd2f0565a086.json +++ b/.sqlx/query-8b3673e18e4f773f3b52be4eda6af9e9dd10d52930399820da03c2057007df76.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE wizard SET active_wizard = $1, completed = $2 WHERE is_singleton", + "query": "UPDATE wizard SET active_wizard = $1, completed = $2, last_version_migrated_to = $3 WHERE is_singleton", "describe": { "columns": [], "parameters": { @@ -18,10 +18,11 @@ } } }, - "Bool" + "Bool", + "Text" ] }, "nullable": [] }, - "hash": "311137f954e7d0919262bcd8eac047577055879335c91c1935d2cd2f0565a086" + "hash": "8b3673e18e4f773f3b52be4eda6af9e9dd10d52930399820da03c2057007df76" } diff --git a/.sqlx/query-75d092089964632abcf831388e1eb2b7b2626eee8c4426ba5c0797385f505b4d.json b/.sqlx/query-ffbab68d66d664f894995b26033489e61e0042f34ce0e892f4772960d3c2b1f0.json similarity index 70% rename from .sqlx/query-75d092089964632abcf831388e1eb2b7b2626eee8c4426ba5c0797385f505b4d.json rename to .sqlx/query-ffbab68d66d664f894995b26033489e61e0042f34ce0e892f4772960d3c2b1f0.json index 30021c7d1..6f4635174 100644 --- a/.sqlx/query-75d092089964632abcf831388e1eb2b7b2626eee8c4426ba5c0797385f505b4d.json +++ b/.sqlx/query-ffbab68d66d664f894995b26033489e61e0042f34ce0e892f4772960d3c2b1f0.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT active_wizard \"active_wizard!: ActiveWizard\", completed FROM wizard WHERE is_singleton LIMIT 1", + "query": "SELECT active_wizard \"active_wizard!: ActiveWizard\", completed, last_version_migrated_to FROM wizard WHERE is_singleton LIMIT 1", "describe": { "columns": [ { @@ -24,6 +24,11 @@ "ordinal": 1, "name": "completed", "type_info": "Bool" + }, + { + "ordinal": 2, + "name": "last_version_migrated_to", + "type_info": "Text" } ], "parameters": { @@ -31,8 +36,9 @@ }, "nullable": [ false, - false + false, + true ] }, - "hash": "75d092089964632abcf831388e1eb2b7b2626eee8c4426ba5c0797385f505b4d" + "hash": "ffbab68d66d664f894995b26033489e61e0042f34ce0e892f4772960d3c2b1f0" } diff --git a/crates/defguard/src/main.rs b/crates/defguard/src/main.rs index 2d45e63ba..03b517b2b 100644 --- a/crates/defguard/src/main.rs +++ b/crates/defguard/src/main.rs @@ -5,7 +5,7 @@ use std::{ use bytes::Bytes; use defguard_common::{ - VERSION, + CARGO_VERSION, VERSION, config::{Command, DefGuardConfig, SERVER_CONFIG}, db::{ init_db, @@ -139,7 +139,7 @@ async fn main() -> Result<(), anyhow::Error> { } let has_auto_adopt_flags = config.adopt_edge.is_some() && config.adopt_gateway.is_some(); - let wizard = Wizard::init(&pool, has_auto_adopt_flags, &config).await?; + let mut wizard = Wizard::init(&pool, has_auto_adopt_flags, &config).await?; Settings::initialize_runtime_defaults(&pool).await?; SERVER_CONFIG.set(config.clone()).ok(); @@ -178,6 +178,10 @@ async fn main() -> Result<(), anyhow::Error> { } } + wizard + .update_last_version_migrated_to(&pool, CARGO_VERSION) + .await?; + // Reload settings from database after setup completion to ensure any changes made during setup // are reflected in the in-memory settings. let settings = Settings::get(&pool).await?.ok_or_else(|| { diff --git a/crates/defguard_common/src/db/models/wizard.rs b/crates/defguard_common/src/db/models/wizard.rs index 7d47633ec..02c9d195d 100644 --- a/crates/defguard_common/src/db/models/wizard.rs +++ b/crates/defguard_common/src/db/models/wizard.rs @@ -45,6 +45,7 @@ impl fmt::Display for ActiveWizard { pub struct Wizard { pub active_wizard: ActiveWizard, pub completed: bool, + pub last_version_migrated_to: Option, } impl Wizard { @@ -53,10 +54,11 @@ impl Wizard { E: PgExecutor<'e>, { query!( - "UPDATE wizard SET active_wizard = $1, completed = $2 \ + "UPDATE wizard SET active_wizard = $1, completed = $2, last_version_migrated_to = $3 \ WHERE is_singleton", self.active_wizard as ActiveWizard, - self.completed + self.completed, + self.last_version_migrated_to ) .execute(executor) .await?; @@ -70,7 +72,7 @@ impl Wizard { { let row = query_as!( Wizard, - "SELECT active_wizard \"active_wizard!: ActiveWizard\", completed \ + "SELECT active_wizard \"active_wizard!: ActiveWizard\", completed, last_version_migrated_to \ FROM wizard WHERE is_singleton LIMIT 1", ) .fetch_one(executor) @@ -79,6 +81,7 @@ impl Wizard { Ok(Self { active_wizard: row.active_wizard, completed: row.completed, + last_version_migrated_to: row.last_version_migrated_to, }) } @@ -210,4 +213,16 @@ impl Wizard { _ => Ok(true), } } + + pub async fn update_last_version_migrated_to<'e, E>( + &mut self, + executor: E, + version: &str, + ) -> Result<(), sqlx::Error> + where + E: PgExecutor<'e>, + { + self.last_version_migrated_to = Some(version.to_string()); + self.save(executor).await + } } diff --git a/crates/defguard_core/src/enterprise/ldap/sync.rs b/crates/defguard_core/src/enterprise/ldap/sync.rs index 0e6996efb..cd4676e40 100644 --- a/crates/defguard_core/src/enterprise/ldap/sync.rs +++ b/crates/defguard_core/src/enterprise/ldap/sync.rs @@ -671,7 +671,7 @@ impl super::LDAPConnection { let mut sync_group_members = HashSet::new(); for sync_group in &sync_groups { let members = sync_group.members(pool).await?; - sync_group_members.extend(members.into_iter()); + sync_group_members.extend(members); } let mut all_ldap_users = self.get_all_users().await?; diff --git a/crates/defguard_core/src/lib.rs b/crates/defguard_core/src/lib.rs index ad0997577..90c0912a0 100644 --- a/crates/defguard_core/src/lib.rs +++ b/crates/defguard_core/src/lib.rs @@ -810,6 +810,7 @@ pub async fn init_dev_env(config: &DefGuardConfig) { let wizard = Wizard { active_wizard: ActiveWizard::None, completed: true, + last_version_migrated_to: None, }; // Ensure wizard is initialized, then overwrite with completed state let _ = Wizard::init(&pool, false, config).await; diff --git a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs index 726f87b36..51192362a 100644 --- a/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs +++ b/crates/defguard_proxy_manager/src/tests/proxy_manager/handler/polling.rs @@ -1,9 +1,8 @@ -use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; - use defguard_proto::{ client_types::InstanceInfoRequest, proxy::{CoreRequest, core_request, core_response}, }; +use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; use super::support::{ assert_error_response, clear_test_license, complete_proxy_handshake, create_device_for_user, diff --git a/migrations/20260416160025_store_last_migrated_version.down.sql b/migrations/20260416160025_store_last_migrated_version.down.sql new file mode 100644 index 000000000..a5856ab62 --- /dev/null +++ b/migrations/20260416160025_store_last_migrated_version.down.sql @@ -0,0 +1 @@ +ALTER TABLE wizard DROP COLUMN last_version_migrated_to; diff --git a/migrations/20260416160025_store_last_migrated_version.up.sql b/migrations/20260416160025_store_last_migrated_version.up.sql new file mode 100644 index 000000000..97cbf27a6 --- /dev/null +++ b/migrations/20260416160025_store_last_migrated_version.up.sql @@ -0,0 +1 @@ +ALTER TABLE wizard ADD COLUMN last_version_migrated_to TEXT;