Use the user_session_id on upstream authorisations for filtering instead
of authentications This makes it one less table to read
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Copyright 2025, 2026 Element Creations Ltd.
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
@@ -249,14 +250,14 @@ pub(crate) async fn post(
|
||||
}
|
||||
UpstreamOAuthProviderOnBackchannelLogout::LogoutBrowserOnly => {
|
||||
let filter = BrowserSessionFilter::new()
|
||||
.authenticated_by_upstream_sessions_only(auth_session_filter)
|
||||
.linked_to_upstream_sessions_only(auth_session_filter)
|
||||
.active_only();
|
||||
let affected = repo.browser_session().finish_bulk(&clock, filter).await?;
|
||||
tracing::info!("Finished {affected} browser sessions");
|
||||
}
|
||||
UpstreamOAuthProviderOnBackchannelLogout::LogoutAll => {
|
||||
let browser_session_filter = BrowserSessionFilter::new()
|
||||
.authenticated_by_upstream_sessions_only(auth_session_filter);
|
||||
let browser_session_filter =
|
||||
BrowserSessionFilter::new().linked_to_upstream_sessions_only(auth_session_filter);
|
||||
|
||||
// We need to loop through all the browser sessions to find all the
|
||||
// users affected so that we can trigger a device sync job for them
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
//
|
||||
@@ -41,7 +42,7 @@ pub struct BrowserSessionFilter<'a> {
|
||||
state: Option<BrowserSessionState>,
|
||||
last_active_before: Option<DateTime<Utc>>,
|
||||
last_active_after: Option<DateTime<Utc>>,
|
||||
authenticated_by_upstream_sessions: Option<UpstreamOAuthSessionFilter<'a>>,
|
||||
linked_to_upstream_sessions: Option<UpstreamOAuthSessionFilter<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> BrowserSessionFilter<'a> {
|
||||
@@ -114,21 +115,20 @@ impl<'a> BrowserSessionFilter<'a> {
|
||||
self.state
|
||||
}
|
||||
|
||||
/// Only return browser sessions authenticated by the given upstream OAuth
|
||||
/// sessions
|
||||
/// Only return browser sessions linked to the given upstream OAuth sessions
|
||||
#[must_use]
|
||||
pub fn authenticated_by_upstream_sessions_only(
|
||||
pub fn linked_to_upstream_sessions_only(
|
||||
mut self,
|
||||
filter: UpstreamOAuthSessionFilter<'a>,
|
||||
) -> Self {
|
||||
self.authenticated_by_upstream_sessions = Some(filter);
|
||||
self.linked_to_upstream_sessions = Some(filter);
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the upstream OAuth session filter
|
||||
#[must_use]
|
||||
pub fn authenticated_by_upstream_sessions(&self) -> Option<UpstreamOAuthSessionFilter<'a>> {
|
||||
self.authenticated_by_upstream_sessions
|
||||
pub fn linked_to_upstream_sessions(&self) -> Option<UpstreamOAuthSessionFilter<'a>> {
|
||||
self.linked_to_upstream_sessions
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user