1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-09 04:22:45 +03:00

Use dynamic filters on browser sessions

This commit is contained in:
Quentin Gliech
2024-07-16 17:21:33 +02:00
parent aa992d31f8
commit c4e7cf1a27

View File

@@ -20,7 +20,10 @@ use mas_data_model::{
Authentication, AuthenticationMethod, BrowserSession, Password, Authentication, AuthenticationMethod, BrowserSession, Password,
UpstreamOAuthAuthorizationSession, User, UserAgent, UpstreamOAuthAuthorizationSession, User, UserAgent,
}; };
use mas_storage::{user::BrowserSessionRepository, Clock, Page, Pagination}; use mas_storage::{
user::{BrowserSessionFilter, BrowserSessionRepository},
Clock, Page, Pagination,
};
use rand::RngCore; use rand::RngCore;
use sea_query::{Expr, PostgresQueryBuilder}; use sea_query::{Expr, PostgresQueryBuilder};
use sea_query_binder::SqlxBinder; use sea_query_binder::SqlxBinder;
@@ -29,6 +32,7 @@ use ulid::Ulid;
use uuid::Uuid; use uuid::Uuid;
use crate::{ use crate::{
filter::StatementExt,
iden::{UserSessions, Users}, iden::{UserSessions, Users},
pagination::QueryBuilderExt, pagination::QueryBuilderExt,
tracing::ExecuteExt, tracing::ExecuteExt,
@@ -130,6 +134,22 @@ impl TryFrom<AuthenticationLookup> for Authentication {
} }
} }
impl crate::filter::Filter for BrowserSessionFilter<'_> {
fn generate_condition(&self, _has_joins: bool) -> impl sea_query::IntoCondition {
sea_query::Condition::all()
.add_option(self.user().map(|user| {
Expr::col((UserSessions::Table, UserSessions::UserId)).eq(Uuid::from(user.id))
}))
.add_option(self.state().map(|state| {
if state.is_active() {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_null()
} else {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_not_null()
}
}))
}
}
#[async_trait] #[async_trait]
impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> { impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
type Error = DatabaseError; type Error = DatabaseError;
@@ -270,22 +290,13 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
async fn finish_bulk( async fn finish_bulk(
&mut self, &mut self,
clock: &dyn Clock, clock: &dyn Clock,
filter: mas_storage::user::BrowserSessionFilter<'_>, filter: BrowserSessionFilter<'_>,
) -> Result<usize, Self::Error> { ) -> Result<usize, Self::Error> {
let finished_at = clock.now(); let finished_at = clock.now();
let (sql, arguments) = sea_query::Query::update() let (sql, arguments) = sea_query::Query::update()
.table(UserSessions::Table) .table(UserSessions::Table)
.value(UserSessions::FinishedAt, finished_at) .value(UserSessions::FinishedAt, finished_at)
.and_where_option(filter.user().map(|user| { .apply_filter(filter)
Expr::col((UserSessions::Table, UserSessions::UserId)).eq(Uuid::from(user.id))
}))
.and_where_option(filter.state().map(|state| {
if state.is_active() {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_null()
} else {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_not_null()
}
}))
.build_sqlx(PostgresQueryBuilder); .build_sqlx(PostgresQueryBuilder);
let res = sqlx::query_with(&sql, arguments) let res = sqlx::query_with(&sql, arguments)
@@ -306,7 +317,7 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
)] )]
async fn list( async fn list(
&mut self, &mut self,
filter: mas_storage::user::BrowserSessionFilter<'_>, filter: BrowserSessionFilter<'_>,
pagination: Pagination, pagination: Pagination,
) -> Result<Page<BrowserSession>, Self::Error> { ) -> Result<Page<BrowserSession>, Self::Error> {
let (sql, arguments) = sea_query::Query::select() let (sql, arguments) = sea_query::Query::select()
@@ -364,18 +375,7 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
Expr::col((UserSessions::Table, UserSessions::UserId)) Expr::col((UserSessions::Table, UserSessions::UserId))
.equals((Users::Table, Users::UserId)), .equals((Users::Table, Users::UserId)),
) )
.and_where_option( .apply_filter(filter)
filter
.user()
.map(|user| Expr::col((Users::Table, Users::UserId)).eq(Uuid::from(user.id))),
)
.and_where_option(filter.state().map(|state| {
if state.is_active() {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_null()
} else {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_not_null()
}
}))
.generate_pagination( .generate_pagination(
(UserSessions::Table, UserSessions::UserSessionId), (UserSessions::Table, UserSessions::UserSessionId),
pagination, pagination,
@@ -402,23 +402,11 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
), ),
err, err,
)] )]
async fn count( async fn count(&mut self, filter: BrowserSessionFilter<'_>) -> Result<usize, Self::Error> {
&mut self,
filter: mas_storage::user::BrowserSessionFilter<'_>,
) -> Result<usize, Self::Error> {
let (sql, arguments) = sea_query::Query::select() let (sql, arguments) = sea_query::Query::select()
.expr(Expr::col((UserSessions::Table, UserSessions::UserSessionId)).count()) .expr(Expr::col((UserSessions::Table, UserSessions::UserSessionId)).count())
.from(UserSessions::Table) .from(UserSessions::Table)
.and_where_option(filter.user().map(|user| { .apply_filter(filter)
Expr::col((UserSessions::Table, UserSessions::UserId)).eq(Uuid::from(user.id))
}))
.and_where_option(filter.state().map(|state| {
if state.is_active() {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_null()
} else {
Expr::col((UserSessions::Table, UserSessions::FinishedAt)).is_not_null()
}
}))
.build_sqlx(PostgresQueryBuilder); .build_sqlx(PostgresQueryBuilder);
let count: i64 = sqlx::query_scalar_with(&sql, arguments) let count: i64 = sqlx::query_scalar_with(&sql, arguments)