diff --git a/crates/cli/src/commands/syn2mas.rs b/crates/cli/src/commands/syn2mas.rs index dfa835b95..4ea55a21f 100644 --- a/crates/cli/src/commands/syn2mas.rs +++ b/crates/cli/src/commands/syn2mas.rs @@ -61,6 +61,14 @@ pub(super) struct Options { /// configure all values through those environment variables. #[clap(long = "synapse-database-uri", global = true)] synapse_database_uri: Option, + + /// Make missing auth providers in Synapse config warnings instead of + /// errors. If this flag is set, and we find `auth_provider` values in + /// the Synapse `user_external_ids` table, that are not configured in + /// the Synapse OIDC configuration, instead of erroring we will just + /// output warnings. + #[clap(long = "ignore-missing-auth-providers", global = true)] + ignore_missing_auth_providers: bool, } #[derive(Parser, Debug)] @@ -169,8 +177,13 @@ impl Options { // Check databases syn2mas::mas_pre_migration_checks(&mut mas_connection).await?; { - let (extra_warnings, extra_errors) = - syn2mas::synapse_database_check(&mut syn_conn, &synapse_config, figment).await?; + let (extra_warnings, extra_errors) = syn2mas::synapse_database_check( + &mut syn_conn, + &synapse_config, + figment, + self.ignore_missing_auth_providers, + ) + .await?; check_warnings.extend(extra_warnings); check_errors.extend(extra_errors); } @@ -261,6 +274,7 @@ impl Options { &mut rng, provider_id_mappings, &progress, + self.ignore_missing_auth_providers, ) .await?; diff --git a/crates/syn2mas/src/migration.rs b/crates/syn2mas/src/migration.rs index e32bfd6b9..d71e8cd05 100644 --- a/crates/syn2mas/src/migration.rs +++ b/crates/syn2mas/src/migration.rs @@ -141,6 +141,7 @@ struct MigrationState { /// - An underlying database access error, either to MAS or to Synapse. /// - Invalid data in the Synapse database. #[expect(clippy::implicit_hasher)] +#[allow(clippy::too_many_arguments)] pub async fn migrate( mut synapse: SynapseReader<'_>, mas: MasWriter, @@ -149,6 +150,7 @@ pub async fn migrate( rng: &mut impl RngCore, provider_id_mapping: std::collections::HashMap, progress: &Progress, + ignore_missing_auth_providers: bool, ) -> Result<(), Error> { let counts = synapse.count_rows().await.into_synapse("counting users")?; @@ -171,8 +173,15 @@ pub async fn migrate( let (mas, state) = migrate_threepids(&mut synapse, mas, rng, state, progress_counter).await?; let progress_counter = progress.migrating_data(EntityType::ExternalIds, counts.external_ids); - let (mas, state) = - migrate_external_ids(&mut synapse, mas, rng, state, progress_counter).await?; + let (mas, state) = migrate_external_ids( + &mut synapse, + mas, + rng, + state, + progress_counter, + ignore_missing_auth_providers, + ) + .await?; let progress_counter = progress.migrating_data( EntityType::NonRefreshableAccessTokens, @@ -452,6 +461,7 @@ async fn migrate_external_ids( rng: &mut impl RngCore, state: MigrationState, progress_counter: ProgressCounter, + ignore_missing_auth_providers: bool, ) -> Result<(MasWriter, MigrationState), Error> { let start = Instant::now(); let progress_counter_ = progress_counter.clone(); @@ -489,6 +499,10 @@ async fn migrate_external_ids( let Some(&upstream_provider_id) = state.provider_id_mapping.get(&auth_provider) else { + if ignore_missing_auth_providers { + progress_counter.increment_skipped(); + continue; + } return Err(Error::MissingAuthProviderMapping { synapse_id: auth_provider, user: synapse_user_id, diff --git a/crates/syn2mas/src/synapse_reader/checks.rs b/crates/syn2mas/src/synapse_reader/checks.rs index aee91b62a..c50f1e9f3 100644 --- a/crates/syn2mas/src/synapse_reader/checks.rs +++ b/crates/syn2mas/src/synapse_reader/checks.rs @@ -130,6 +130,11 @@ pub enum CheckWarning { "Synapse database contains {num_non_email_3pids} non-email 3PIDs (probably phone numbers), which will be migrated but are not supported by MAS." )] NonEmailThreepidsInDatabase { num_non_email_3pids: i64 }, + + #[error( + "Synapse database contains {num_users} users associated to the OpenID Connect or OAuth2 provider '{provider}' but the Synapse configuration does not contain this provider." + )] + SynapseMissingOAuthProvider { provider: String, num_users: i64 }, } /// Check that the Synapse configuration is sane for migration. @@ -257,6 +262,7 @@ pub async fn synapse_database_check( synapse_connection: &mut PgConnection, synapse: &Config, mas: &Figment, + ignore_missing_auth_providers: bool, ) -> Result<(Vec, Vec), Error> { #[derive(FromRow)] struct UpstreamOAuthProvider { @@ -309,10 +315,17 @@ pub async fn synapse_database_check( let matching_syn = syn_oauth2.get(&row.auth_provider); let Some(matching_syn) = matching_syn else { - errors.push(CheckError::SynapseMissingOAuthProvider { - provider: row.auth_provider, - num_users: row.num_users, - }); + if ignore_missing_auth_providers { + warnings.push(CheckWarning::SynapseMissingOAuthProvider { + provider: row.auth_provider, + num_users: row.num_users, + }); + } else { + errors.push(CheckError::SynapseMissingOAuthProvider { + provider: row.auth_provider, + num_users: row.num_users, + }); + } continue; };