Skip to content

Commit c376790

Browse files
committed
syn2mas: Migrate threepids to MAS (#3878)
* Add a table to hold unsupported threepids * Migrate threepids from Synapse to MAS
1 parent 0a6048b commit c376790

15 files changed

+502
-96
lines changed

crates/cli/src/commands/syn2mas.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,51 @@ use tracing::{error, warn};
1212

1313
use crate::util::database_connection_from_config;
1414

15-
/// The exit code used by `syn2mas check` and `syn2mas migrate` when there are errors preventing migration.
15+
/// The exit code used by `syn2mas check` and `syn2mas migrate` when there are
16+
/// errors preventing migration.
1617
const EXIT_CODE_CHECK_ERRORS: u8 = 10;
1718

18-
/// The exit code used by `syn2mas check` when there are warnings which should be considered prior to migration.
19+
/// The exit code used by `syn2mas check` when there are warnings which should
20+
/// be considered prior to migration.
1921
const EXIT_CODE_CHECK_WARNINGS: u8 = 11;
2022

2123
#[derive(Parser, Debug)]
2224
pub(super) struct Options {
2325
#[command(subcommand)]
2426
subcommand: Subcommand,
2527

26-
/// This version of the syn2mas tool is EXPERIMENTAL and INCOMPLETE. It is only suitable for TESTING.
27-
/// If you want to use this tool anyway, please pass this argument.
28+
/// This version of the syn2mas tool is EXPERIMENTAL and INCOMPLETE. It is
29+
/// only suitable for TESTING. If you want to use this tool anyway,
30+
/// please pass this argument.
2831
///
29-
/// If you want to migrate from Synapse to MAS today, please use the Node.js-based tool in the MAS repository.
32+
/// If you want to migrate from Synapse to MAS today, please use the
33+
/// Node.js-based tool in the MAS repository.
3034
#[clap(long = "i-swear-i-am-just-testing-in-a-staging-environment")]
3135
experimental_accepted: bool,
3236

3337
/// Path to the Synapse configuration (in YAML format).
34-
/// May be specified multiple times if multiple Synapse configuration files are in use.
38+
/// May be specified multiple times if multiple Synapse configuration files
39+
/// are in use.
3540
#[clap(long = "synapse-config")]
3641
synapse_configuration_files: Vec<Utf8PathBuf>,
3742

3843
/// Override the Synapse database URI.
39-
/// syn2mas normally loads the Synapse database connection details from the Synapse configuration.
40-
/// However, it may sometimes be necessary to override the database URI and in that case this flag can be used.
44+
/// syn2mas normally loads the Synapse database connection details from the
45+
/// Synapse configuration. However, it may sometimes be necessary to
46+
/// override the database URI and in that case this flag can be used.
4147
///
4248
/// Should be a connection URI of the following general form:
4349
/// ```text
4450
/// postgresql://[user[:password]@][host][:port][/dbname][?param1=value1&...]
4551
/// ```
46-
/// To use a UNIX socket at a custom path, the host should be a path to a socket, but in the URI string
47-
/// it must be URI-encoded by replacing `/` with `%2F`.
52+
/// To use a UNIX socket at a custom path, the host should be a path to a
53+
/// socket, but in the URI string it must be URI-encoded by replacing
54+
/// `/` with `%2F`.
4855
///
49-
/// Finally, any missing values will be loaded from the libpq-compatible environment variables
50-
/// `PGHOST`, `PGPORT`, `PGUSER`, `PGDATABASE`, `PGPASSWORD`, etc.
51-
/// It is valid to specify the URL `postgresql:` and configure all values through those environment variables.
56+
/// Finally, any missing values will be loaded from the libpq-compatible
57+
/// environment variables `PGHOST`, `PGPORT`, `PGUSER`, `PGDATABASE`,
58+
/// `PGPASSWORD`, etc. It is valid to specify the URL `postgresql:` and
59+
/// configure all values through those environment variables.
5260
#[clap(long = "synapse-database-uri")]
5361
synapse_database_uri: Option<PgConnectOptions>,
5462
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-- Copyright 2025 New Vector Ltd.
2+
--
3+
-- SPDX-License-Identifier: AGPL-3.0-only
4+
-- Please see LICENSE in the repository root for full details.
5+
6+
7+
8+
-- Tracks third-party ID associations that have been verified but are
9+
-- not currently supported by MAS.
10+
-- This is currently used when importing third-party IDs from Synapse,
11+
-- which historically could verify at least phone numbers.
12+
-- E-mail associations will not be stored in this table because those are natively
13+
-- supported by MAS; see the `user_emails` table.
14+
15+
CREATE TABLE user_unsupported_third_party_ids(
16+
-- The owner of the third-party ID assocation
17+
user_id UUID NOT NULL
18+
REFERENCES users(user_id) ON DELETE CASCADE,
19+
20+
-- What type of association is this?
21+
medium TEXT NOT NULL,
22+
23+
-- The address of the associated ID, e.g. a phone number or other identifier.
24+
address TEXT NOT NULL,
25+
26+
-- When the association was created
27+
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
28+
29+
PRIMARY KEY (user_id, medium, address)
30+
);

crates/syn2mas/.sqlx/query-b11590549fdd4cdcd36c937a353b5b37ab50db3505712c35610b822cda322b5b.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/syn2mas/.sqlx/query-dfbd462f7874d3dae551f2a0328a853a8a7efccdc20b968d99d8c18deda8dd00.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/syn2mas/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ rand.workspace = true
2727
uuid = "1.10.0"
2828
ulid = { workspace = true, features = ["uuid"] }
2929

30+
mas-config.workspace = true
31+
3032
[dev-dependencies]
3133
mas-storage-pg.workspace = true
3234

3335
anyhow.workspace = true
3436
insta.workspace = true
3537
serde.workspace = true
3638

37-
mas-config.workspace = true
38-
3939
[lints]
4040
workspace = true

crates/syn2mas/src/lib.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ mod synapse_reader;
88

99
mod migration;
1010

11-
pub use self::mas_writer::locking::LockedMasDatabase;
12-
pub use self::mas_writer::{checks::mas_pre_migration_checks, MasWriter};
13-
pub use self::migration::migrate;
14-
pub use self::synapse_reader::checks::{
15-
synapse_config_check, synapse_config_check_against_mas_config, synapse_database_check,
11+
pub use self::{
12+
mas_writer::{checks::mas_pre_migration_checks, locking::LockedMasDatabase, MasWriter},
13+
migration::migrate,
14+
synapse_reader::{
15+
checks::{
16+
synapse_config_check, synapse_config_check_against_mas_config, synapse_database_check,
17+
},
18+
config as synapse_config, SynapseReader,
19+
},
1620
};
17-
pub use self::synapse_reader::config as synapse_config;
18-
pub use self::synapse_reader::SynapseReader;

crates/syn2mas/src/mas_writer/checks.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
//! # MAS Database Checks
77
//!
8-
//! This module provides safety checks to run against a MAS database before running the Synapse-to-MAS migration.
8+
//! This module provides safety checks to run against a MAS database before
9+
//! running the Synapse-to-MAS migration.
910
1011
use thiserror::Error;
1112
use thiserror_ext::ContextInto;
@@ -43,7 +44,8 @@ pub enum Error {
4344
///
4445
/// - If any database access error occurs.
4546
/// - If any MAS tables involved in the migration are not empty.
46-
/// - If we can't check whether syn2mas is already in progress on this database or not.
47+
/// - If we can't check whether syn2mas is already in progress on this database
48+
/// or not.
4749
#[tracing::instrument(skip_all)]
4850
pub async fn mas_pre_migration_checks<'a>(
4951
mas_connection: &mut LockedMasDatabase<'a>,
@@ -56,7 +58,8 @@ pub async fn mas_pre_migration_checks<'a>(
5658
return Ok(());
5759
}
5860

59-
// Check that the database looks like a MAS database and that it is also an empty database.
61+
// Check that the database looks like a MAS database and that it is also an
62+
// empty database.
6063

6164
for &table in MAS_TABLES_AFFECTED_BY_MIGRATION {
6265
let row_present = sqlx::query(&format!("SELECT 1 AS dummy FROM {table} LIMIT 1"))

crates/syn2mas/src/mas_writer/locking.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,19 @@ use sqlx::{
1313
static SYN2MAS_ADVISORY_LOCK: LazyLock<PgAdvisoryLock> =
1414
LazyLock::new(|| PgAdvisoryLock::new("syn2mas-maswriter"));
1515

16-
/// A wrapper around a Postgres connection which holds a session-wide advisory lock
17-
/// preventing concurrent access by other syn2mas instances.
16+
/// A wrapper around a Postgres connection which holds a session-wide advisory
17+
/// lock preventing concurrent access by other syn2mas instances.
1818
pub struct LockedMasDatabase<'conn> {
1919
inner: PgAdvisoryLockGuard<'static, &'conn mut PgConnection>,
2020
}
2121

2222
impl<'conn> LockedMasDatabase<'conn> {
23-
/// Attempts to lock the MAS database against concurrent access by other syn2mas instances.
23+
/// Attempts to lock the MAS database against concurrent access by other
24+
/// syn2mas instances.
2425
///
2526
/// If the lock can be acquired, returns a `LockedMasDatabase`.
26-
/// If the lock cannot be acquired, returns the connection back to the caller wrapped in `Either::Right`.
27+
/// If the lock cannot be acquired, returns the connection back to the
28+
/// caller wrapped in `Either::Right`.
2729
///
2830
/// # Errors
2931
///

0 commit comments

Comments
 (0)