1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00

Remove the last authentication from the browser session model

This commit is contained in:
Quentin Gliech
2023-07-19 15:31:17 +02:00
parent 7e82ae845c
commit 802cf142fd
24 changed files with 325 additions and 204 deletions

View File

@@ -18,7 +18,7 @@ use mas_data_model::{Authentication, BrowserSession, Password, UpstreamOAuthLink
use mas_storage::{user::BrowserSessionRepository, Clock, Page, Pagination};
use rand::RngCore;
use sea_query::{Expr, IntoColumnRef, PostgresQueryBuilder};
use sqlx::{PgConnection, QueryBuilder};
use sqlx::PgConnection;
use ulid::Ulid;
use uuid::Uuid;
@@ -50,8 +50,6 @@ struct SessionLookup {
user_id: Uuid,
user_username: String,
user_primary_user_email_id: Option<Uuid>,
last_authentication_id: Option<Uuid>,
last_authd_at: Option<DateTime<Utc>>,
}
#[derive(sea_query::Iden)]
@@ -71,14 +69,6 @@ enum Users {
PrimaryUserEmailId,
}
#[derive(sea_query::Iden)]
enum SessionAuthentication {
Table,
UserSessionAuthenticationId,
UserSessionId,
CreatedAt,
}
impl TryFrom<SessionLookup> for BrowserSession {
type Error = DatabaseInconsistencyError;
@@ -91,25 +81,11 @@ impl TryFrom<SessionLookup> for BrowserSession {
primary_user_email_id: value.user_primary_user_email_id.map(Into::into),
};
let last_authentication = match (value.last_authentication_id, value.last_authd_at) {
(Some(id), Some(created_at)) => Some(Authentication {
id: id.into(),
created_at,
}),
(None, None) => None,
_ => {
return Err(DatabaseInconsistencyError::on(
"user_session_authentications",
))
}
};
Ok(BrowserSession {
id: value.user_session_id.into(),
user,
created_at: value.user_session_created_at,
finished_at: value.user_session_finished_at,
last_authentication,
})
}
}
@@ -132,21 +108,15 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
SessionLookup,
r#"
SELECT s.user_session_id
, s.created_at AS "user_session_created_at"
, s.finished_at AS "user_session_finished_at"
, s.created_at AS "user_session_created_at"
, s.finished_at AS "user_session_finished_at"
, u.user_id
, u.username AS "user_username"
, u.primary_user_email_id AS "user_primary_user_email_id"
, a.user_session_authentication_id AS "last_authentication_id?"
, a.created_at AS "last_authd_at?"
, u.username AS "user_username"
, u.primary_user_email_id AS "user_primary_user_email_id"
FROM user_sessions s
INNER JOIN users u
USING (user_id)
LEFT JOIN user_session_authentications a
USING (user_session_id)
WHERE s.user_session_id = $1
ORDER BY a.created_at DESC
LIMIT 1
"#,
Uuid::from(id),
)
@@ -199,7 +169,6 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
user: user.clone(),
created_at,
finished_at: None,
last_authentication: None,
};
Ok(session)
@@ -278,14 +247,6 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
Expr::col((Users::Table, Users::PrimaryUserEmailId)),
SessionLookupIden::UserPrimaryUserEmailId,
)
.expr_as(
Expr::value(None::<Uuid>),
SessionLookupIden::LastAuthenticationId,
)
.expr_as(
Expr::value(None::<DateTime<Utc>>),
SessionLookupIden::LastAuthdAt,
)
.from(UserSessions::Table)
.inner_join(
Users::Table,
@@ -324,6 +285,45 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
Ok(page)
}
#[tracing::instrument(
name = "db.browser_session.count",
skip_all,
fields(
db.statement,
),
err,
)]
async fn count(
&mut self,
filter: mas_storage::user::BrowserSessionFilter<'_>,
) -> Result<usize, Self::Error> {
let (sql, values) = sea_query::Query::select()
.expr(Expr::col((UserSessions::Table, UserSessions::UserSessionId)).count())
.from(UserSessions::Table)
.and_where_option(filter.user().map(|user| {
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(PostgresQueryBuilder);
let arguments = map_values(values);
let count: i64 = sqlx::query_scalar_with(&sql, arguments)
.traced()
.fetch_one(&mut *self.conn)
.await?;
count
.try_into()
.map_err(DatabaseError::to_invalid_operation)
}
#[tracing::instrument(
name = "db.browser_session.authenticate_with_password",
skip_all,
@@ -339,9 +339,9 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
&mut self,
rng: &mut (dyn RngCore + Send),
clock: &dyn Clock,
mut user_session: BrowserSession,
user_session: &BrowserSession,
user_password: &Password,
) -> Result<BrowserSession, Self::Error> {
) -> Result<Authentication, Self::Error> {
let _user_password = user_password;
let created_at = clock.now();
let id = Ulid::from_datetime_with_source(created_at.into(), rng);
@@ -364,9 +364,7 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
.execute(&mut *self.conn)
.await?;
user_session.last_authentication = Some(Authentication { id, created_at });
Ok(user_session)
Ok(Authentication { id, created_at })
}
#[tracing::instrument(
@@ -384,9 +382,9 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
&mut self,
rng: &mut (dyn RngCore + Send),
clock: &dyn Clock,
mut user_session: BrowserSession,
user_session: &BrowserSession,
upstream_oauth_link: &UpstreamOAuthLink,
) -> Result<BrowserSession, Self::Error> {
) -> Result<Authentication, Self::Error> {
let _upstream_oauth_link = upstream_oauth_link;
let created_at = clock.now();
let id = Ulid::from_datetime_with_source(created_at.into(), rng);
@@ -409,8 +407,38 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
.execute(&mut *self.conn)
.await?;
user_session.last_authentication = Some(Authentication { id, created_at });
Ok(Authentication { id, created_at })
}
Ok(user_session)
#[tracing::instrument(
name = "db.browser_session.get_last_authentication",
skip_all,
fields(
db.statement,
%user_session.id,
),
err,
)]
async fn get_last_authentication(
&mut self,
user_session: &BrowserSession,
) -> Result<Option<Authentication>, Self::Error> {
let authentication = sqlx::query_as!(
Authentication,
r#"
SELECT user_session_authentication_id AS id
, created_at
FROM user_session_authentications
WHERE user_session_id = $1
ORDER BY created_at DESC
LIMIT 1
"#,
Uuid::from(user_session.id),
)
.traced()
.fetch_optional(&mut *self.conn)
.await?;
Ok(authentication)
}
}