Re-enable the upstream authentication sessions cleanup job (#5439)

This commit is contained in:
Quentin Gliech
2026-01-23 18:17:11 +01:00
committed by GitHub
9 changed files with 79 additions and 51 deletions

View File

@@ -0,0 +1,11 @@
-- no-transaction
-- Copyright 2026 Element Creations Ltd.
--
-- SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
-- Please see LICENSE files in the repository root for full details.
-- Adds an index on the user_session_id column on the
-- upstream_oauth_authorization_sessions table
CREATE INDEX CONCURRENTLY IF NOT EXISTS
upstream_oauth_authorization_sessions_user_session_id_idx
ON upstream_oauth_authorization_sessions (user_session_id);

View File

@@ -0,0 +1,27 @@
-- Copyright 2026 Element Creations Ltd.
--
-- SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
-- Please see LICENSE files in the repository root for full details.
-- Adds a trigger which will backfill the user_session_id column when inserting
-- a new user_session_authentications row. This is to help supporting rolling
-- back to previous releases and should be dropped in a future version.
CREATE OR REPLACE FUNCTION upstream_oauth_authorization_sessions_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.upstream_oauth_authorization_session_id IS NOT NULL THEN
UPDATE upstream_oauth_authorization_sessions
SET user_session_id = NEW.user_session_id
WHERE upstream_oauth_authorization_sessions.upstream_oauth_authorization_session_id
= NEW.upstream_oauth_authorization_session_id
AND upstream_oauth_authorization_sessions.user_session_id IS NULL;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create the trigger
CREATE TRIGGER upstream_oauth_authorization_sessions_insert_trigger
AFTER INSERT ON user_session_authentications
FOR EACH ROW
EXECUTE FUNCTION upstream_oauth_authorization_sessions_insert_trigger();

View File

@@ -0,0 +1,13 @@
-- Copyright 2026 Element Creations Ltd.
--
-- SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
-- Please see LICENSE files in the repository root for full details.
-- Backfill the upstream_oauth_authorization_sessions.user_session_id column
-- based on session authentications
UPDATE upstream_oauth_authorization_sessions
SET user_session_id = user_session_authentications.user_session_id
FROM user_session_authentications
WHERE upstream_oauth_authorization_sessions.user_session_id IS NULL
AND upstream_oauth_authorization_sessions.upstream_oauth_authorization_session_id
= user_session_authentications.upstream_oauth_authorization_session_id;

View File

@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -18,18 +19,6 @@ pub enum UserSessions {
LastActiveIp,
}
#[derive(sea_query::Iden)]
#[expect(dead_code)]
pub enum UserSessionAuthentications {
Table,
UserSessionAuthenticationId,
UserSessionId,
CreatedAt,
UserPasswordId,
#[iden = "upstream_oauth_authorization_session_id"]
UpstreamOAuthAuthorizationSessionId,
}
#[derive(sea_query::Iden)]
pub enum Users {
Table,
@@ -204,6 +193,7 @@ pub enum UpstreamOAuthAuthorizationSessions {
CompletedAt,
ConsumedAt,
UnlinkedAt,
UserSessionId,
}
#[derive(sea_query::Iden)]

View File

@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
//
@@ -27,7 +28,7 @@ use uuid::Uuid;
use crate::{
DatabaseError, DatabaseInconsistencyError,
filter::StatementExt,
iden::{UpstreamOAuthAuthorizationSessions, UserSessionAuthentications, UserSessions, Users},
iden::{UpstreamOAuthAuthorizationSessions, UserSessions, Users},
pagination::QueryBuilderExt,
tracing::ExecuteExt,
};
@@ -154,26 +155,14 @@ impl crate::filter::Filter for BrowserSessionFilter<'_> {
.add_option(self.last_active_before().map(|last_active_before| {
Expr::col((UserSessions::Table, UserSessions::LastActiveAt)).lt(last_active_before)
}))
.add_option(self.authenticated_by_upstream_sessions().map(|filter| {
// For filtering by upstream sessions, we need to hop over the
// `user_session_authentications` table
let join_expr = Expr::col((
UserSessionAuthentications::Table,
UserSessionAuthentications::UpstreamOAuthAuthorizationSessionId,
))
.eq(Expr::col((
UpstreamOAuthAuthorizationSessions::Table,
UpstreamOAuthAuthorizationSessions::UpstreamOAuthAuthorizationSessionId,
)));
.add_option(self.linked_to_upstream_sessions().map(|filter| {
Expr::col((UserSessions::Table, UserSessions::UserSessionId)).in_subquery(
Query::select()
.expr(Expr::col((
UserSessionAuthentications::Table,
UserSessionAuthentications::UserSessionId,
UpstreamOAuthAuthorizationSessions::Table,
UpstreamOAuthAuthorizationSessions::UserSessionId,
)))
.from(UserSessionAuthentications::Table)
.inner_join(UpstreamOAuthAuthorizationSessions::Table, join_expr)
.from(UpstreamOAuthAuthorizationSessions::Table)
.apply_filter(filter)
.take(),
)

View File

@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
//
@@ -799,8 +800,8 @@ async fn test_user_session(pool: PgPool) {
// This will match all authorization sessions, which matches exactly that one
// authorization session
let upstream_oauth_session_filter = UpstreamOAuthSessionFilter::new();
let filter = BrowserSessionFilter::new()
.authenticated_by_upstream_sessions_only(upstream_oauth_session_filter);
let filter =
BrowserSessionFilter::new().linked_to_upstream_sessions_only(upstream_oauth_session_filter);
// Now try to look it up
let page = repo