Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syn2mas: migrate access tokens, refresh tokens and devices #3926

Merged
merged 11 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/cli/src/commands/syn2mas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ impl Options {
}
let mut writer = MasWriter::new(mas_connection, writer_mas_connections).await?;

let clock = SystemClock::default();
// TODO is this rng ok?
#[allow(clippy::disallowed_methods)]
let mut rng = thread_rng();
Expand All @@ -233,6 +234,7 @@ impl Options {
&mut reader,
&mut writer,
&mas_matrix.homeserver,
&clock,
&mut rng,
&provider_id_mappings,
)
Expand Down
1 change: 1 addition & 0 deletions crates/data-model/src/compat/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub struct CompatSession {
pub state: CompatSessionState,
pub user_id: Ulid,
pub device: Option<Device>,
pub human_name: Option<String>,
pub user_session_id: Option<Ulid>,
pub created_at: DateTime<Utc>,
pub is_synapse_admin: bool,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- Copyright 2025 New Vector Ltd.
--
-- SPDX-License-Identifier: AGPL-3.0-only
-- Please see LICENSE in the repository root for full details.

ALTER TABLE compat_sessions
-- Stores a human-readable name for the device.
-- syn2mas behaviour: Will be populated from the device name in Synapse.
ADD COLUMN human_name TEXT;
10 changes: 10 additions & 0 deletions crates/storage-pg/migrations/20250130170011_user_is_guest.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- Copyright 2025 New Vector Ltd.
--
-- SPDX-License-Identifier: AGPL-3.0-only
-- Please see LICENSE in the repository root for full details.

ALTER TABLE users
-- Track whether users are guests.
-- Although guest support is not present in MAS yet, syn2mas should import
-- these users and therefore we should track their state.
ADD COLUMN is_guest BOOLEAN NOT NULL DEFAULT FALSE;
8 changes: 8 additions & 0 deletions crates/storage-pg/src/app_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ mod priv_ {
pub(super) user_id: Option<Uuid>,
pub(super) scope_list: Option<Vec<String>>,
pub(super) device_id: Option<String>,
pub(super) human_name: Option<String>,
pub(super) created_at: DateTime<Utc>,
pub(super) finished_at: Option<DateTime<Utc>>,
pub(super) is_synapse_admin: Option<bool>,
Expand Down Expand Up @@ -91,6 +92,7 @@ impl TryFrom<AppSessionLookup> for AppSession {
user_id,
scope_list,
device_id,
human_name,
created_at,
finished_at,
is_synapse_admin,
Expand Down Expand Up @@ -141,6 +143,7 @@ impl TryFrom<AppSessionLookup> for AppSession {
state,
user_id: user_id.into(),
device,
human_name,
user_session_id,
created_at,
is_synapse_admin,
Expand Down Expand Up @@ -294,6 +297,7 @@ impl AppSessionRepository for PgAppSessionRepository<'_> {
AppSessionLookupIden::ScopeList,
)
.expr_as(Expr::cust("NULL"), AppSessionLookupIden::DeviceId)
.expr_as(Expr::cust("NULL"), AppSessionLookupIden::HumanName)
.expr_as(
Expr::col((OAuth2Sessions::Table, OAuth2Sessions::CreatedAt)),
AppSessionLookupIden::CreatedAt,
Expand Down Expand Up @@ -343,6 +347,10 @@ impl AppSessionRepository for PgAppSessionRepository<'_> {
Expr::col((CompatSessions::Table, CompatSessions::DeviceId)),
AppSessionLookupIden::DeviceId,
)
.expr_as(
Expr::col((CompatSessions::Table, CompatSessions::HumanName)),
AppSessionLookupIden::HumanName,
)
.expr_as(
Expr::col((CompatSessions::Table, CompatSessions::CreatedAt)),
AppSessionLookupIden::CreatedAt,
Expand Down
15 changes: 12 additions & 3 deletions crates/storage-pg/src/compat/refresh_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,25 @@ impl CompatRefreshTokenRepository for PgCompatRefreshTokenRepository<'_> {
r#"
UPDATE compat_refresh_tokens
SET consumed_at = $2
WHERE compat_refresh_token_id = $1
WHERE compat_session_id = $1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add AND consumed_at IS NULL, so that we don't update all the refresh tokens consumed ts

Also, you need to change/remove the DatabaseError::ensure_affected_rows(&res, 1) bellow, else it will error out if there are more than one row affected

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did that in 59e25c0

AND consumed_at IS NULL
"#,
Uuid::from(compat_refresh_token.id),
Uuid::from(compat_refresh_token.session_id),
consumed_at,
)
.traced()
.execute(&mut *self.conn)
.await?;

DatabaseError::ensure_affected_rows(&res, 1)?;
// This can affect multiple rows in case we've imported refresh tokens
// from Synapse. What we care about is that it at least affected one,
// which is what we're checking here
if res.rows_affected() == 0 {
return Err(DatabaseError::RowsAffected {
expected: 1,
actual: 0,
});
}

let compat_refresh_token = compat_refresh_token
.consume(consumed_at)
Expand Down
10 changes: 10 additions & 0 deletions crates/storage-pg/src/compat/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl<'c> PgCompatSessionRepository<'c> {
struct CompatSessionLookup {
compat_session_id: Uuid,
device_id: Option<String>,
human_name: Option<String>,
user_id: Uuid,
user_session_id: Option<Uuid>,
created_at: DateTime<Utc>,
Expand Down Expand Up @@ -85,6 +86,7 @@ impl TryFrom<CompatSessionLookup> for CompatSession {
user_id: value.user_id.into(),
user_session_id: value.user_session_id.map(Ulid::from),
device,
human_name: value.human_name,
created_at: value.created_at,
is_synapse_admin: value.is_synapse_admin,
user_agent: value.user_agent.map(UserAgent::parse),
Expand All @@ -101,6 +103,7 @@ impl TryFrom<CompatSessionLookup> for CompatSession {
struct CompatSessionAndSsoLoginLookup {
compat_session_id: Uuid,
device_id: Option<String>,
human_name: Option<String>,
user_id: Uuid,
user_session_id: Option<Uuid>,
created_at: DateTime<Utc>,
Expand Down Expand Up @@ -143,6 +146,7 @@ impl TryFrom<CompatSessionAndSsoLoginLookup> for (CompatSession, Option<CompatSs
state,
user_id: value.user_id.into(),
device,
human_name: value.human_name,
user_session_id: value.user_session_id.map(Ulid::from),
created_at: value.created_at,
is_synapse_admin: value.is_synapse_admin,
Expand Down Expand Up @@ -286,6 +290,7 @@ impl CompatSessionRepository for PgCompatSessionRepository<'_> {
r#"
SELECT compat_session_id
, device_id
, human_name
, user_id
, user_session_id
, created_at
Expand Down Expand Up @@ -356,6 +361,7 @@ impl CompatSessionRepository for PgCompatSessionRepository<'_> {
state: CompatSessionState::default(),
user_id: user.id,
device: Some(device),
human_name: None,
user_session_id: browser_session.map(|s| s.id),
created_at,
is_synapse_admin,
Expand Down Expand Up @@ -453,6 +459,10 @@ impl CompatSessionRepository for PgCompatSessionRepository<'_> {
Expr::col((CompatSessions::Table, CompatSessions::DeviceId)),
CompatSessionAndSsoLoginLookupIden::DeviceId,
)
.expr_as(
Expr::col((CompatSessions::Table, CompatSessions::HumanName)),
CompatSessionAndSsoLoginLookupIden::HumanName,
)
.expr_as(
Expr::col((CompatSessions::Table, CompatSessions::UserId)),
CompatSessionAndSsoLoginLookupIden::UserId,
Expand Down
1 change: 1 addition & 0 deletions crates/storage-pg/src/iden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub enum CompatSessions {
CompatSessionId,
UserId,
DeviceId,
HumanName,
UserSessionId,
CreatedAt,
FinishedAt,
Expand Down
8 changes: 7 additions & 1 deletion crates/storage/src/compat/refresh_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,13 @@ pub trait CompatRefreshTokenRepository: Send + Sync {
token: String,
) -> Result<CompatRefreshToken, Self::Error>;

/// Consume a compat refresh token
/// Consume a compat refresh token.
///
/// This also marks other refresh tokens in the same session as consumed.
/// This is desirable because the syn2mas migration process can import
/// multiple refresh tokens for one device (compat session).
/// But once the user uses one of those, the others should no longer
/// be valid.
///
/// Returns the consumed compat refresh token
///
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading